mirror of https://github.com/rancher/ui.git
commit
cb5653835b
|
|
@ -204,6 +204,16 @@ export default Controller.extend({
|
|||
this.set('expandedInstances',[]);
|
||||
},
|
||||
|
||||
publicEndpoints: computed('model.app.workloads.@each.publicEndpoints', function() {
|
||||
let out = [];
|
||||
get(this, 'model.app.workloads').forEach((workload) => {
|
||||
(get(workload, 'publicEndpoints') || []).forEach((endpoint) => {
|
||||
out.push(endpoint);
|
||||
});
|
||||
});
|
||||
return out;
|
||||
}),
|
||||
|
||||
workloadsAndPods: computed('model.app.workloads', 'model.app.pods', function() {
|
||||
let out = [];
|
||||
out = this.get('model.app.pods').filter(obj => !obj.get('workloadId'));
|
||||
|
|
|
|||
|
|
@ -54,6 +54,18 @@
|
|||
expandOnInit=false
|
||||
}}
|
||||
|
||||
{{#accordion-list-item
|
||||
title=(t 'appDetailPage.endpoints.title')
|
||||
detail=(t 'appDetailPage.endpoints.detail')
|
||||
expandAll=al.expandAll
|
||||
expand=(action expandFn)
|
||||
expandOnInit=true
|
||||
}}
|
||||
{{form-endpoints
|
||||
model=publicEndpoints
|
||||
}}
|
||||
{{/accordion-list-item}}
|
||||
|
||||
{{#accordion-list-item
|
||||
title=(t 'appDetailPage.workloads.title')
|
||||
detail=(t 'appDetailPage.workloads.detail')
|
||||
|
|
|
|||
|
|
@ -24,8 +24,11 @@ export default Controller.extend({
|
|||
return get(this,'model.projects').filterBy('clusterId', get(this,'scope.currentCluster.id'));
|
||||
}),
|
||||
|
||||
projectsWithoutNamespaces: computed('projects.@each.{id,state,clusterId}', 'rows.@each.namespaces', function(){
|
||||
return get(this, 'projects').filter(p => get(p, 'namespaces.length') <= 0);
|
||||
projectsWithoutNamespaces: computed('projects.@each.{id,state,clusterId}', 'rows.@each.projectId', function(){
|
||||
return get(this, 'projects').filter(p => {
|
||||
const namespaces = get(this, 'rows').filterBy('projectId', get(p, 'id')) || [];
|
||||
return get(namespaces, 'length') <= 0;
|
||||
});
|
||||
}),
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export default Route.extend(Preload,{
|
|||
this.preload('dnsRecord'),
|
||||
this.preload('secret'),
|
||||
this.preload('service'),
|
||||
this.preload('configmap'),
|
||||
this.preload('namespacedSecret'),
|
||||
this.preload('persistentVolumeClaim'),
|
||||
]).then(() => {
|
||||
|
|
|
|||
|
|
@ -98,19 +98,14 @@ export default Route.extend({
|
|||
});
|
||||
});
|
||||
},
|
||||
setupController(controller, model) {
|
||||
this._super(controller, model);
|
||||
if (model.upgradeTemplate) {
|
||||
controller.set('showName', false);
|
||||
}
|
||||
},
|
||||
resetController: function (controller, isExiting/*, transition*/) {
|
||||
if (isExiting)
|
||||
{
|
||||
controller.set('namespaceId', null);
|
||||
controller.set('template', null);
|
||||
controller.set('upgrade', null);
|
||||
controller.set('catalog', null);
|
||||
controller.set('namespaceId', null);
|
||||
controller.set('appId', null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
catalogApp=model.catalogApp
|
||||
namespaceResource=model.namespace
|
||||
parentRoute=parentRoute
|
||||
showName=showName
|
||||
upgrade=model.upgradeTemplate
|
||||
templateResource=model.tpl
|
||||
templateKind=model.tplKind
|
||||
|
|
|
|||
|
|
@ -152,6 +152,9 @@ const rootNav = [
|
|||
ctx: [getClusterId],
|
||||
resource: ['project'],
|
||||
resourceScope: 'global',
|
||||
condition: function() {
|
||||
return this.get('cluster.isReady');
|
||||
}
|
||||
},
|
||||
{
|
||||
scope: 'cluster',
|
||||
|
|
|
|||
|
|
@ -46,14 +46,16 @@ var Namespace = Resource.extend(StateCounts, {
|
|||
catalog: service(),
|
||||
scope: service(),
|
||||
router: service(),
|
||||
projectStore: service('store'),
|
||||
globalStore: service(),
|
||||
clusterStore: service(),
|
||||
|
||||
pods: hasMany('id', 'pod', 'namespaceId', 'store'),
|
||||
workloads: hasMany('id', 'workload', 'namespaceId', 'store'),
|
||||
services: hasMany('id', 'service', 'namespaceId', 'store'),
|
||||
secrets: hasMany('id', 'namespacedSecret', 'namespaceId', 'store'),
|
||||
ingress: hasMany('id', 'ingress', 'namespaceId', 'store'),
|
||||
volumes: hasMany('id', 'persistentVolumeClaim', 'namespaceId', 'store'),
|
||||
pods: hasMany('id', 'pod', 'namespaceId', 'projectStore', null, 'clusterStore'),
|
||||
workloads: hasMany('id', 'workload', 'namespaceId', 'projectStore', null, 'clusterStore'),
|
||||
services: hasMany('id', 'service', 'namespaceId', 'projectStore', null, 'clusterStore'),
|
||||
secrets: hasMany('id', 'namespacedSecret', 'namespaceId', 'projectStore', null, 'clusterStore'),
|
||||
ingress: hasMany('id', 'ingress', 'namespaceId', 'projectStore', null, 'clusterStore'),
|
||||
volumes: hasMany('id', 'persistentVolumeClaim', 'namespaceId', 'projectStore', null, 'clusterStore'),
|
||||
project: reference('projectId', 'project', 'globalStore'),
|
||||
|
||||
init() {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ export default Resource.extend({
|
|||
});
|
||||
},
|
||||
|
||||
resetDefault() {
|
||||
this.setDefault(false)
|
||||
},
|
||||
|
||||
edit() {
|
||||
get(this, 'router').transitionTo('authenticated.cluster.storage.classes.detail.edit', get(this, 'id'));
|
||||
},
|
||||
|
|
@ -80,8 +84,8 @@ export default Resource.extend({
|
|||
annotations[DEFAULT_ANNOTATION] = 'true';
|
||||
annotations[BETA_ANNOTATION] = 'true';
|
||||
} else {
|
||||
delete annotations[DEFAULT_ANNOTATION];
|
||||
delete annotations[BETA_ANNOTATION];
|
||||
annotations[DEFAULT_ANNOTATION] = 'false';
|
||||
annotations[BETA_ANNOTATION] = 'false';
|
||||
}
|
||||
|
||||
this.save();
|
||||
|
|
@ -92,6 +96,7 @@ export default Resource.extend({
|
|||
|
||||
let out = [
|
||||
{ label: 'action.makeDefault', icon: 'icon icon-star-fill', action: 'makeDefault', enabled: !isDefault },
|
||||
{ label: 'action.resetDefault', icon: 'icon icon-star-line', action: 'resetDefault', enabled: isDefault },
|
||||
];
|
||||
|
||||
return out;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ const Template = Resource.extend({
|
|||
}.property('category','categories.[]'),
|
||||
|
||||
categoryLowerArray: function() {
|
||||
return this.get('categoryArray').map(x => (x||'').toLowerCase());
|
||||
return this.get('categoryArray').map(x => (x||'').underscore().toLowerCase());
|
||||
}.property('categoryArray.[]'),
|
||||
|
||||
supported: function() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
$container-height: 300px;
|
||||
$container-height: 321px;
|
||||
$container-width: 283px;
|
||||
$font-size: 12px;
|
||||
$line-height: 1.4;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import Controller from '@ember/controller';
|
||||
import C from 'ui/utils/constants';
|
||||
import { computed, get } from '@ember/object';
|
||||
import { computed, get, set } from '@ember/object';
|
||||
import { send } from 'ember-metal/events';
|
||||
|
||||
export default Controller.extend({
|
||||
|
|
@ -11,15 +11,30 @@ export default Controller.extend({
|
|||
settings: service(),
|
||||
catalog: service(),
|
||||
|
||||
togglingHelmIncubator: false,
|
||||
togglingHelmStable: false,
|
||||
togglingLibrary: false,
|
||||
|
||||
actions: {
|
||||
disableLibrary() {
|
||||
if( get(this, 'togglingLibrary') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(this, 'togglingLibrary', true);
|
||||
get(this, 'library').delete().catch((err) => {
|
||||
get(this, 'growl').fromError('Error removing Library', err);
|
||||
}).finally(() => {
|
||||
send(this, 'refresh')
|
||||
set(this, 'togglingLibrary', false);
|
||||
send(this, 'refresh');
|
||||
});
|
||||
},
|
||||
enableLibrary() {
|
||||
if( get(this, 'togglingLibrary') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(this, 'togglingLibrary', true);
|
||||
get(this, 'globalStore').createRecord({
|
||||
type: 'catalog',
|
||||
name: C.CATALOG.LIBRARY_KEY,
|
||||
|
|
@ -29,18 +44,30 @@ export default Controller.extend({
|
|||
}).save().catch((err) => {
|
||||
get(this, 'growl').fromError('Error saving Library', err);
|
||||
}).finally(() => {
|
||||
send(this, 'refresh')
|
||||
set(this, 'togglingLibrary', false);
|
||||
send(this, 'refresh');
|
||||
});
|
||||
},
|
||||
|
||||
disableHelmIncubator() {
|
||||
if( get(this, 'togglingHelmIncubator') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(this, 'togglingHelmIncubator', true);
|
||||
get(this, 'helmIncubator').delete().catch((err) => {
|
||||
get(this, 'growl').fromError('Error removing Incubator', err);
|
||||
}).finally(() => {
|
||||
send(this, 'refresh')
|
||||
set(this, 'togglingHelmIncubator', false);
|
||||
send(this, 'refresh');
|
||||
});
|
||||
},
|
||||
enableHelmIncubator() {
|
||||
if( get(this, 'togglingHelmIncubator') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(this, 'togglingHelmIncubator', true);
|
||||
get(this, 'globalStore').createRecord({
|
||||
type: 'catalog',
|
||||
name: C.CATALOG.HELM_INCUBATOR_KEY,
|
||||
|
|
@ -50,18 +77,30 @@ export default Controller.extend({
|
|||
}).save().catch((err) => {
|
||||
get(this, 'growl').fromError('Error saving Incubator', err);
|
||||
}).finally(() => {
|
||||
send(this, 'refresh')
|
||||
set(this, 'togglingHelmIncubator', false);
|
||||
send(this, 'refresh');
|
||||
});
|
||||
},
|
||||
|
||||
disableHelmStable() {
|
||||
if( get(this, 'togglingHelmStable') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(this, 'togglingHelmStable', true);
|
||||
get(this, 'helmStable').delete().catch((err) => {
|
||||
get(this, 'growl').fromError('Error removing Stable', err);
|
||||
}).finally(() => {
|
||||
send(this, 'refresh')
|
||||
set(this, 'togglingHelmStable', false);
|
||||
send(this, 'refresh');
|
||||
});
|
||||
},
|
||||
enableHelmStable() {
|
||||
if( get(this, 'togglingHelmStable') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(this, 'togglingHelmStable', true);
|
||||
get(this, 'globalStore').createRecord({
|
||||
type: 'catalog',
|
||||
name: C.CATALOG.HELM_STABLE_KEY,
|
||||
|
|
@ -71,28 +110,8 @@ export default Controller.extend({
|
|||
}).save().catch((err) => {
|
||||
get(this, 'growl').fromError('Error saving Stable', err);
|
||||
}).finally(() => {
|
||||
send(this, 'refresh')
|
||||
});
|
||||
},
|
||||
|
||||
enableLibrary() {
|
||||
get(this, 'globalStore').createRecord({
|
||||
type: 'catalog',
|
||||
name: C.CATALOG.LIBRARY_KEY,
|
||||
url: C.CATALOG.LIBRARY_VALUE,
|
||||
branch: C.CATALOG.LIBRARY_BRANCH,
|
||||
}).save().catch((err) => {
|
||||
get(this, 'growl').fromError('Error saving Library', err);
|
||||
}).finally(() => {
|
||||
send(this, 'refresh')
|
||||
});
|
||||
},
|
||||
|
||||
disableLibrary() {
|
||||
get(this, 'stdLibrary').delete().catch((err) => {
|
||||
get(this, 'growl').fromError('Error removing Library', err);
|
||||
}).finally(() => {
|
||||
send(this, 'refresh')
|
||||
set(this, 'togglingHelmStable', false);
|
||||
send(this, 'refresh');
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@
|
|||
<div>
|
||||
{{#if library}}
|
||||
<div class="btn-group no-inline-space">
|
||||
<button class="btn btn-link btn-sm bg-default" {{action "disableLibrary"}}>{{t 'generic.disable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-default" {{action "disableLibrary"}} disabled={{togglingLibrary}}>{{#if togglingLibrary}}<i class="icon icon-spinner icon-spin"></i> {{/if}}{{t 'generic.disable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-success">{{t 'generic.enabled'}}</button>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="btn-group no-inline-space">
|
||||
<button class="btn btn-link btn-sm bg-primary">{{t 'generic.disabled'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-defualt" {{action "enableLibrary"}}>{{t 'generic.enable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-defualt" {{action "enableLibrary"}} disabled={{togglingLibrary}}>{{#if togglingLibrary}}<i class="icon icon-spinner icon-spin"></i> {{/if}}{{t 'generic.enable'}}</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
@ -34,13 +34,13 @@
|
|||
<div>
|
||||
{{#if helmStable}}
|
||||
<div class="btn-group no-inline-space">
|
||||
<button class="btn btn-link btn-sm bg-default" {{action "disableHelmStable"}}>{{t 'generic.disable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-default" {{action "disableHelmStable"}} disabled={{togglingHelmStable}}>{{#if togglingHelmStable}}<i class="icon icon-spinner icon-spin"></i> {{/if}}{{t 'generic.disable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-success">{{t 'generic.enabled'}}</button>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="btn-group no-inline-space">
|
||||
<button class="btn btn-link btn-sm bg-primary">{{t 'generic.disabled'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-defualt" {{action "enableHelmStable"}}>{{t 'generic.enable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-defualt" {{action "enableHelmStable"}} disabled={{togglingHelmStable}}>{{#if togglingHelmStable}}<i class="icon icon-spinner icon-spin"></i> {{/if}}{{t 'generic.enable'}}</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
@ -54,13 +54,13 @@
|
|||
<div>
|
||||
{{#if helmIncubator}}
|
||||
<div class="btn-group no-inline-space">
|
||||
<button class="btn btn-link btn-sm bg-default" {{action "disableHelmIncubator"}}>{{t 'generic.disable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-default" {{action "disableHelmIncubator"}} disabled={{togglingHelmIncubator}}>{{#if togglingHelmIncubator}}<i class="icon icon-spinner icon-spin"></i> {{/if}}{{t 'generic.disable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-success">{{t 'generic.enabled'}}</button>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="btn-group no-inline-space">
|
||||
<button class="btn btn-link btn-sm bg-primary">{{t 'generic.disabled'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-defualt" {{action "enableHelmIncubator"}}>{{t 'generic.enable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-defualt" {{action "enableHelmIncubator"}} disabled={{togglingHelmIncubator}}>{{#if togglingHelmIncubator}}<i class="icon icon-spinner icon-spin"></i> {{/if}}{{t 'generic.enable'}}</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { get, set, computed } from '@ember/object';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import Service, { inject as service } from '@ember/service';
|
||||
|
||||
export default Service.extend({
|
||||
clusterStore: service(),
|
||||
|
||||
_allStorageClasses: null,
|
||||
|
||||
init() {
|
||||
const clusterStore = get(this, 'clusterStore');
|
||||
set(this, '_allStorageClasses', clusterStore.all('storageclass'));
|
||||
},
|
||||
|
||||
storageClasses: computed('_allStorageClasses.[]', function () {
|
||||
return get(this, '_allStorageClasses').sortBy('name');
|
||||
}),
|
||||
|
||||
list: alias('storageClasses'),
|
||||
|
||||
byId(id) {
|
||||
return get(this, '_allStorageClasses').findBy('id', id);
|
||||
},
|
||||
});
|
||||
|
|
@ -3,7 +3,7 @@ import Service, { inject as service } from '@ember/service';
|
|||
import { addQueryParams, uniqKeys } from 'shared/utils/util';
|
||||
import C from 'shared/utils/constants';
|
||||
import EmberObject from '@ember/object'
|
||||
import { get } from '@ember/object';
|
||||
import { set, get, observer } from '@ember/object';
|
||||
import { /* parseExternalId, */ parseHelmExternalId } from 'ui/utils/parse-externalid';
|
||||
import { allSettled } from 'rsvp';
|
||||
|
||||
|
|
@ -19,6 +19,32 @@ export default Service.extend({
|
|||
templateCache: null,
|
||||
catalogs: null,
|
||||
|
||||
_allCatalogs: null,
|
||||
_refreshMap: null,
|
||||
|
||||
init() {
|
||||
const store = get(this,'globalStore');
|
||||
set(this, '_allCatalogs', store.all('catalog'));
|
||||
set(this, '_refreshMap', {});
|
||||
},
|
||||
|
||||
catalogsDidChange: observer('_allCatalogs.@each.state', '_refreshMap', function() {
|
||||
if ( get(this, 'templateCache') !== null ) {
|
||||
const oldRefreshMap = get(this, '_refreshMap');
|
||||
const newRefreshMap = {};
|
||||
(get(this, '_allCatalogs') || []).forEach((c) => {
|
||||
newRefreshMap[get(c, 'id')] = get(c, 'lastRefreshTimestamp');
|
||||
});
|
||||
let needRefresh = false;
|
||||
for (let k of new Set([...Object.keys(newRefreshMap), ...Object.keys(oldRefreshMap)])) {
|
||||
if ( !oldRefreshMap.hasOwnProperty(k) || !newRefreshMap.hasOwnProperty(k) || oldRefreshMap[k] !== newRefreshMap[k] ) {
|
||||
needRefresh = true;
|
||||
}
|
||||
}
|
||||
set(this, 'needRefresh', needRefresh);
|
||||
}
|
||||
}),
|
||||
|
||||
reset() {
|
||||
this.setProperties({
|
||||
templateCache: null,
|
||||
|
|
@ -99,11 +125,18 @@ export default Service.extend({
|
|||
}
|
||||
|
||||
// If the catalogIds dont match we need to go get the other catalog from the store since we do not cache all catalogs
|
||||
if ( cache && cache.catalogId === catalogId)
|
||||
if ( cache && cache.catalogId === catalogId && !get(this, 'needRefresh') )
|
||||
{
|
||||
return resolve(this.filter(cache, params.category));
|
||||
}
|
||||
|
||||
const catalogs = get(this, '_allCatalogs');
|
||||
const refreshMap = {};
|
||||
catalogs.forEach((c) => {
|
||||
refreshMap[get(c, 'id')] = get(c, 'lastRefreshTimestamp');
|
||||
});
|
||||
set(this, '_refreshMap', refreshMap);
|
||||
|
||||
let url = this._addLimits(`${get(this,'app.apiEndpoint')}/templates`, qp);
|
||||
return get(this,'store').request({url: url, headers: {[C.HEADER.PROJECT_ID]: get(this,'scope.currentProject.id')}}).then((res) => {
|
||||
res.catalogId = catalogId;
|
||||
|
|
@ -132,15 +165,15 @@ export default Service.extend({
|
|||
},
|
||||
|
||||
filter(data, category) {
|
||||
category = (category||'all').toLowerCase();
|
||||
category = (category||'').toLowerCase();
|
||||
|
||||
let categories = [];
|
||||
data.forEach((obj) => { categories.pushObjects(obj.get('categoryArray')); });
|
||||
categories = uniqKeys(categories);
|
||||
categories.unshift('all');
|
||||
categories.unshift('');
|
||||
|
||||
data = data.filter((tpl) => {
|
||||
if ( category !== 'all' && !tpl.get('categoryLowerArray').includes(category) ) {
|
||||
if ( category !== '' && !tpl.get('categoryLowerArray').includes(category) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export default Component.extend({
|
|||
categories.sort().forEach((ctgy) => {
|
||||
let normalized = ctgy.underscore();
|
||||
|
||||
if (out[normalized] && ctgy !== 'all') {
|
||||
if (out[normalized] && ctgy) {
|
||||
out[normalized].count++;
|
||||
} else {
|
||||
out[normalized] = {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
{{#if opt.localizedLabel}}
|
||||
{{t opt.localizedLabel}}
|
||||
{{else}}
|
||||
{{opt.label}}
|
||||
<div class="text-capitalize">{{opt.label}}</div>
|
||||
{{/if}}
|
||||
</a>
|
||||
</li>
|
||||
|
|
@ -92,9 +92,10 @@
|
|||
{{#each arrangedContent as |catalogItem|}}
|
||||
{{#catalog-box model=catalogItem showSource=showCatalogDropdown as |section|}}
|
||||
{{#if (eq section 'body')}}
|
||||
<h3>
|
||||
<a {{action (action launch catalogItem.id )}}>{{catalogItem.displayName}}</a>
|
||||
<h3 class="mb-0">
|
||||
<a class="pointer" {{action (action launch catalogItem.id )}}>{{catalogItem.displayName}}</a>
|
||||
</h3>
|
||||
<div>({{t 'generic.from'}} <span class="text-capitalize">{{catalogItem.catalogId}}</span>)</div>
|
||||
<div class="mt-10 description">{{catalogItem.description}}</div>
|
||||
{{else if (eq section 'footer')}}
|
||||
<button type="button" class="btn btn-sm bg-primary" {{action (action launch catalogItem.id )}}>{{t 'catalogPage.index.action.launch'}}</button>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
{{#if (eq step 1)}}
|
||||
{{top-errors errors=errors}}
|
||||
{{top-errors errors=otherErrors}}
|
||||
{{top-errors errors=clusterErrors}}
|
||||
{{save-cancel
|
||||
save="awsLogin"
|
||||
cancel=close
|
||||
|
|
@ -95,6 +96,7 @@
|
|||
|
||||
{{top-errors errors=errors}}
|
||||
{{top-errors errors=otherErrors}}
|
||||
{{top-errors errors=clusterErrors}}
|
||||
{{save-cancel editing=(eq mode 'edit') save="driverSave" cancel=close}}
|
||||
{{/if}}
|
||||
{{/accordion-list}}
|
||||
|
|
|
|||
|
|
@ -190,4 +190,5 @@
|
|||
|
||||
{{top-errors errors=errors}}
|
||||
{{top-errors errors=otherErrors}}
|
||||
{{top-errors errors=clusterErrors}}
|
||||
{{save-cancel editing=(eq mode 'edit') save="driverSave" cancel=close}}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
{{top-errors errors=errors}}
|
||||
{{top-errors errors=otherErrors}}
|
||||
{{top-errors errors=clusterErrors}}
|
||||
{{save-cancel
|
||||
createLabel="clusterNew.googlegke.checkServiceAccount"
|
||||
savingLabel="clusterNew.googlegke.checkingServiceAccount"
|
||||
|
|
@ -138,5 +139,6 @@
|
|||
|
||||
{{top-errors errors=errors}}
|
||||
{{top-errors errors=otherErrors}}
|
||||
{{top-errors errors=clusterErrors}}
|
||||
{{save-cancel editing=(eq mode 'edit') save="driverSave" cancel=close}}
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,13 @@ export default Component.extend(ClusterDriver, {
|
|||
|
||||
set(this, 'token', token);
|
||||
set(this, 'loading', false);
|
||||
}).catch((err) => {
|
||||
if ( this.isDestroyed || this.isDestroying ) {
|
||||
return;
|
||||
}
|
||||
|
||||
get(this,'growl').fromError('Error getting command', err);
|
||||
set(this, 'loading', false);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
{{#if isEdit}}
|
||||
{{top-errors errors=otherErrors}}
|
||||
{{top-errors errors=clusterErrors}}
|
||||
{{save-cancel save="driverSave" editing=true cancel="close"}}
|
||||
{{else}}
|
||||
<div class="footer-actions">
|
||||
|
|
@ -43,5 +44,6 @@
|
|||
{{/if}}
|
||||
{{else}}
|
||||
{{top-errors errors=otherErrors}}
|
||||
{{top-errors errors=clusterErrors}}
|
||||
{{save-cancel save="driverSave" editing=isEdit cancel="close"}}
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export default Component.extend(ClusterDriver, {
|
|||
layout,
|
||||
globalStore: service(),
|
||||
settings: service(),
|
||||
growl: service(),
|
||||
intl: service(),
|
||||
|
||||
configField: 'rancherKubernetesEngineConfig',
|
||||
|
|
@ -100,6 +101,9 @@ export default Component.extend(ClusterDriver, {
|
|||
}),
|
||||
});
|
||||
set(this, 'cluster.rancherKubernetesEngineConfig', config);
|
||||
}
|
||||
|
||||
if ( get(this, 'isNew') ) {
|
||||
this.driverDidChange();
|
||||
}
|
||||
},
|
||||
|
|
@ -181,6 +185,13 @@ export default Component.extend(ClusterDriver, {
|
|||
}
|
||||
set(this, 'token', token);
|
||||
set(this, 'loading', false);
|
||||
}).catch((err) => {
|
||||
if ( this.isDestroyed || this.isDestroying ) {
|
||||
return;
|
||||
}
|
||||
|
||||
get(this,'growl').fromError('Error getting command', err);
|
||||
set(this, 'loading', false);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -223,11 +234,11 @@ export default Component.extend(ClusterDriver, {
|
|||
}),
|
||||
|
||||
isAddressValid: computed('address', function() {
|
||||
return get(this, 'address.length') === 0 || validateEndpoint(get(this, 'address'));
|
||||
return get(this, 'address') === undefined || get(this, 'address.length') === 0 || validateEndpoint(get(this, 'address'));
|
||||
}),
|
||||
|
||||
isInternalAddressValid: computed('internalAddress', function() {
|
||||
return get(this, 'internalAddress.length') === 0 || validateEndpoint(get(this, 'internalAddress'));
|
||||
return get(this, 'internalAddress') === undefined || get(this, 'internalAddress.length') === 0 || validateEndpoint(get(this, 'internalAddress'));
|
||||
}),
|
||||
|
||||
// Custom stuff
|
||||
|
|
@ -271,6 +282,10 @@ export default Component.extend(ClusterDriver, {
|
|||
command: computed(`settings.${C.SETTING.AGENT_IMAGE}`, 'labels', 'token.nodeCommand', 'etcd', 'controlplane', 'worker', 'address', 'internalAddress', function() {
|
||||
let out = get(this, 'token.nodeCommand');
|
||||
|
||||
if ( !out ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const address = get(this, 'address');
|
||||
if(address) {
|
||||
out += ` --address ${address}`;
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@
|
|||
<div class="copy-pre mt-20 mb-20">
|
||||
{{#if loading}}
|
||||
<div class="text-center"><i class="icon icon-spinner icon-spin"></i> {{t 'generic.loading'}}</div>
|
||||
{{else}}
|
||||
{{else if command}}
|
||||
{{copy-to-clipboard clipboardText=command tagName="div" classNames="copy-to-pre"}}
|
||||
<pre id="registration-command" style="font-size: 14px;">{{command}}</pre>
|
||||
{{/if}}
|
||||
|
|
@ -241,6 +241,7 @@
|
|||
{{/if}}
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{top-errors errors=clusterErrors}}
|
||||
{{top-errors errors=otherErrors}}
|
||||
{{#if (or isEdit (eq step 1))}}
|
||||
{{save-cancel createLabel=(if isCustom 'saveCancel.next' 'saveCancel.create') editing=isEdit save="driverSave" cancel="close"}}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { next } from '@ember/runloop';
|
||||
import { get } from '@ember/object';
|
||||
import { set, get, observer } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import Component from '@ember/component';
|
||||
import Util from 'ui/utils/util';
|
||||
|
|
@ -18,6 +18,7 @@ export default Component.extend({
|
|||
showProtip: true,
|
||||
|
||||
status: 'connecting',
|
||||
containerName: null,
|
||||
socket: null,
|
||||
|
||||
actions: {
|
||||
|
|
@ -42,6 +43,13 @@ export default Component.extend({
|
|||
},
|
||||
},
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
const containerName = get(this, 'instance.containers.firstObject.name');
|
||||
set(this, 'containerName', containerName);
|
||||
},
|
||||
|
||||
didInsertElement: function () {
|
||||
this._super();
|
||||
next(this, () => {
|
||||
|
|
@ -54,11 +62,11 @@ export default Component.extend({
|
|||
},
|
||||
|
||||
exec: function () {
|
||||
var instance = this.get('instance');
|
||||
var instance = get(this, 'instance');
|
||||
const clusterId = get(this, 'scope.currentCluster.id');
|
||||
const namespaceId = get(instance, 'namespaceId');
|
||||
const podName = get(instance, 'name');
|
||||
const containerName = get(instance, 'containers.firstObject.name');
|
||||
const containerName = get(this, 'containerName');
|
||||
const scheme = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
||||
let url = `${scheme}${window.location.host}/k8s/clusters/${clusterId}/api/v1/namespaces/${namespaceId}/pods/${podName}/log`;
|
||||
url += `?container=${encodeURIComponent(containerName)}&tailLines=${LINES}&follow=true×tamps=true`;
|
||||
|
|
@ -68,20 +76,20 @@ export default Component.extend({
|
|||
|
||||
connect: function (url) {
|
||||
var socket = new WebSocket(url, 'base64.binary.k8s.io');
|
||||
this.set('socket', socket);
|
||||
set(this, 'socket', socket);
|
||||
|
||||
var body = this.$('.log-body')[0];
|
||||
var $body = $(body);
|
||||
|
||||
this.set('status', 'initializing');
|
||||
set(this, 'status', 'initializing');
|
||||
|
||||
socket.onopen = () => {
|
||||
this.set('status', 'connected');
|
||||
set(this, 'status', 'connected');
|
||||
};
|
||||
|
||||
socket.onmessage = (message) => {
|
||||
let ansiup = new AnsiUp.default;
|
||||
this.set('status', 'connected');
|
||||
set(this, 'status', 'connected');
|
||||
var isFollow = ($body.scrollTop() + $body.outerHeight() + 10) >= body.scrollHeight;
|
||||
const data = decodeURIComponent(window.escape(AWS.util.base64.decode(message.data)));
|
||||
|
||||
|
|
@ -119,17 +127,17 @@ export default Component.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
this.set('status', 'disconnected');
|
||||
set(this, 'status', 'disconnected');
|
||||
};
|
||||
},
|
||||
|
||||
disconnect: function () {
|
||||
this.set('status', 'closed');
|
||||
set(this, 'status', 'closed');
|
||||
|
||||
var socket = this.get('socket');
|
||||
var socket = get(this, 'socket');
|
||||
if (socket) {
|
||||
socket.close();
|
||||
this.set('socket', null);
|
||||
set(this, 'socket', null);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -138,6 +146,12 @@ export default Component.extend({
|
|||
this._super();
|
||||
},
|
||||
|
||||
containerDidChange: observer('containerName', function() {
|
||||
this.disconnect();
|
||||
this.send('clear');
|
||||
this.exec();
|
||||
}),
|
||||
|
||||
isDate(date) {
|
||||
return new Date(date) !== "Invalid Date" && !isNaN(new Date(date))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,20 @@
|
|||
<h2>
|
||||
<i class="icon icon-file"></i> {{t 'containerLogs.title' instanceName=instance.displayName}}
|
||||
<i class="icon icon-file"></i> {{t 'containerLogs.title'}}
|
||||
{{#if displayName}}
|
||||
{{displayName}}
|
||||
{{else if (gt instance.containers.length 1)}}
|
||||
<div class="container-select">
|
||||
{{new-select
|
||||
classNames="form-control"
|
||||
optionValuePath="name"
|
||||
optionLabelPath="name"
|
||||
content=instance.containers
|
||||
value=containerName
|
||||
}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{containerName}}
|
||||
{{/if}}
|
||||
<div class="console-status text-muted pull-right">{{t (concat 'containerLogs.status.' status)}}</div>
|
||||
</h2>
|
||||
{{#if showProtip}}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
model=model
|
||||
originalCluster=originalCluster
|
||||
otherErrors=memberErrors
|
||||
clusterErrors=errors
|
||||
save=(action 'save')
|
||||
close=(action 'close')
|
||||
registerHook=(action "registerHook")
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@
|
|||
{{radio-button selection=useStorageClass value=true disabled=(not canUseStorageClass)}}
|
||||
{{t 'cruPersistentVolumeClaim.source.storageClass'}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
{{radio-button selection=useStorageClass value=false}}
|
||||
{{t 'cruPersistentVolumeClaim.source.pv'}}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import Component from '@ember/component';
|
||||
import layout from './template';
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
tagName: '',
|
||||
model: null,
|
||||
expandAll: null,
|
||||
expandFn: null,
|
||||
sortBy: 'linkEndpoint',
|
||||
descending: true,
|
||||
headers: [
|
||||
{
|
||||
name: 'linkEndpoint',
|
||||
sort: ['linkEndpoint'],
|
||||
translationKey: 'appDetailPage.endpoints.endpoint',
|
||||
searchField: 'linkEndpoint',
|
||||
},
|
||||
{
|
||||
name: 'protocol',
|
||||
sort: ['linkEndpoint', 'protocol'],
|
||||
translationKey: 'appDetailPage.endpoints.protocol',
|
||||
searchField: 'protocol',
|
||||
}
|
||||
],
|
||||
});
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
{{#sortable-table
|
||||
classNames="grid fixed mb-0 sortable-table"
|
||||
bulkActions=false
|
||||
rowActions=false
|
||||
paging=false
|
||||
search=true
|
||||
sortBy=sortBy
|
||||
stickyHeader=false
|
||||
descending=descending
|
||||
headers=headers
|
||||
body=model
|
||||
as |sortable kind endpoint|
|
||||
}}
|
||||
{{#if (eq kind "row")}}
|
||||
<tr>
|
||||
<td data-title="{{t 'appDetailPage.endpoints.endpoint'}}:" class="force-wrap">
|
||||
{{#if endpoint.linkEndpoint}}
|
||||
<a target="_blank" rel="noreferrer nofollow" href="{{endpoint.linkEndpoint}}">{{endpoint.linkEndpoint}}</a>
|
||||
{{else}}
|
||||
{{endpoint.linkEndpoint}}
|
||||
{{/if}}
|
||||
</td>
|
||||
<td data-title="{{t 'appDetailPage.endpoints.protocol'}}:" class="force-wrap">
|
||||
<div class="text-uppercase">{{endpoint.protocol}}</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{else if (eq kind "nomatch")}}
|
||||
<tr>
|
||||
<td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'appDetailPage.endpoints.noMatch'}}</td>
|
||||
</tr>
|
||||
{{else if (eq kind "norows")}}
|
||||
<tr>
|
||||
<td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'appDetailPage.endpoints.noData'}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{/sortable-table}}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { observer, get } from '@ember/object';
|
||||
import { observer, get, set } from '@ember/object';
|
||||
import { next } from '@ember/runloop';
|
||||
import { alias, equal } from '@ember/object/computed';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
|
@ -13,6 +13,7 @@ export default Component.extend({
|
|||
layout,
|
||||
intl: service(),
|
||||
scope: service(),
|
||||
clusterStore: service(),
|
||||
|
||||
createLabel: 'formNamespace.label.create',
|
||||
reuseLabel: 'formNamespace.label.reuse',
|
||||
|
|
@ -31,13 +32,14 @@ export default Component.extend({
|
|||
hookName: 'saveNamespace',
|
||||
|
||||
classNames: ['inline-form'],
|
||||
choices: alias('scope.currentProject.namespaces'),
|
||||
choices: null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
let all = this.get('choices');
|
||||
set(this, 'choices', get(this, 'clusterStore').all('namespace').filterBy('projectId', get(this, 'scope.currentProject.id')));
|
||||
let all = get(this, 'choices');
|
||||
|
||||
this.set('createNamespace', this.get('clusterStore').createRecord({
|
||||
set(this, 'createNamespace', get(this, 'clusterStore').createRecord({
|
||||
type: 'namespace',
|
||||
name: '',
|
||||
projectId: get(this, 'scope.currentProject.id'),
|
||||
|
|
@ -45,21 +47,21 @@ export default Component.extend({
|
|||
|
||||
// TODO
|
||||
// Find a namespace
|
||||
if ( this.get('mode') === REUSE ) {
|
||||
if ( get(this, 'mode') === REUSE ) {
|
||||
let namespace = get(this,'namespace') || // Passed in
|
||||
all.findBy('isDefault', true) || // The default one
|
||||
all.objectAt(0); // Ok any one
|
||||
|
||||
if ( namespace && namespace.id) {
|
||||
this.set('reuseNamespaceId', get(namespace, 'id'));
|
||||
set(this, 'reuseNamespaceId', get(namespace, 'id'));
|
||||
} else if (namespace){
|
||||
this.set('createNamespace', namespace);
|
||||
this.set('mode', CREATE);
|
||||
set(this, 'createNamespace', namespace);
|
||||
set(this, 'mode', CREATE);
|
||||
return;
|
||||
} else {
|
||||
next(() => {
|
||||
this.set('mode', CREATE);
|
||||
this.get('createNamespace.name', 'default')
|
||||
set(this, 'mode', CREATE);
|
||||
get(this, 'createNamespace.name', 'default')
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -73,8 +75,8 @@ export default Component.extend({
|
|||
|
||||
actions: {
|
||||
toggle() {
|
||||
let mode = (this.get('mode') === REUSE ? CREATE : REUSE);
|
||||
this.set('mode', mode);
|
||||
let mode = (get(this, 'mode') === REUSE ? CREATE : REUSE);
|
||||
set(this, 'mode', mode);
|
||||
if ( mode === CREATE ) {
|
||||
next(() => {
|
||||
let elem = this.$('.new-name')[0];
|
||||
|
|
@ -89,23 +91,23 @@ export default Component.extend({
|
|||
|
||||
updateNamespace: observer('reuseNamespaceId','mode', function() {
|
||||
let namespace;
|
||||
if ( this.get('mode') === REUSE ) {
|
||||
namespace = this.get('choices').findBy('id', this.get('reuseNamespaceId'));
|
||||
if ( get(this, 'mode') === REUSE ) {
|
||||
namespace = get(this, 'choices').findBy('id', get(this, 'reuseNamespaceId'));
|
||||
}
|
||||
|
||||
if ( !namespace ) {
|
||||
namespace = this.get('createNamespace');
|
||||
namespace = get(this, 'createNamespace');
|
||||
}
|
||||
|
||||
this.set('namespace', namespace);
|
||||
set(this, 'namespace', namespace);
|
||||
}),
|
||||
|
||||
validate: observer('namespace.{id,name}', function() {
|
||||
let intl = this.get('intl');
|
||||
let intl = get(this, 'intl');
|
||||
let errors = [];
|
||||
|
||||
let namespace = this.get('namespace');
|
||||
if ( namespace && namespace.get('name') ) {
|
||||
let namespace = get(this, 'namespace');
|
||||
if ( namespace && get(namespace, 'name') ) {
|
||||
namespace.validationErrors().forEach((err) => {
|
||||
errors.push(intl.t('formNamespace.errors.validation', {error: err}))
|
||||
});
|
||||
|
|
@ -114,9 +116,9 @@ export default Component.extend({
|
|||
}
|
||||
|
||||
if ( errors.length ) {
|
||||
this.set('errors', errors);
|
||||
set(this, 'errors', errors);
|
||||
} else {
|
||||
this.set('errors', null);
|
||||
set(this, 'errors', null);
|
||||
}
|
||||
}),
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export default Component.extend({
|
|||
layout,
|
||||
originQuestions: alias('selectedTemplate.questions'),
|
||||
pasteOrUpload: false,
|
||||
accept : '.yml, .yaml',
|
||||
accept: '*',
|
||||
showHeader: true,
|
||||
answerGroups: null,
|
||||
_boundChange : null,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<form class="{{if getTemplate.isRunning 'hide'}}">
|
||||
<div class="btn-group pull-right">
|
||||
<button class="btn btn-sm bg-primary" {{action 'showPaste'}}>{{t 'generic.paste'}} <span class="icon icon-copy"></span></button>
|
||||
<button class="btn btn-sm bg-primary" {{action 'upload'}}>{{t 'generic.upload'}} <span class="icon icon-upload"></span></button>
|
||||
<button class="btn btn-sm bg-primary" {{action 'upload'}}>{{t 'uploadFile.label'}} <span class="icon icon-upload"></span></button>
|
||||
</div>
|
||||
<div>
|
||||
{{#if showHeader}}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { compare as compareVersion } from 'ui/utils/parse-version';
|
|||
import { task } from 'ember-concurrency';
|
||||
import YAML from 'npm:yamljs';
|
||||
import layout from './template';
|
||||
import { isEmpty } from '@ember/utils';
|
||||
|
||||
|
||||
export default Component.extend(NewOrEdit, {
|
||||
|
|
@ -31,7 +30,7 @@ export default Component.extend(NewOrEdit, {
|
|||
actuallySave: true,
|
||||
showHeader: true,
|
||||
showPreview: true,
|
||||
showName: isEmpty('catalogApp.id'),
|
||||
customizeNamespace: false,
|
||||
titleAdd: 'newCatalog.titleAdd',
|
||||
titleUpgrade: 'newCatalog.titleUpgrade',
|
||||
selectVersionAdd: 'newCatalog.selectVersionAdd',
|
||||
|
|
@ -48,6 +47,7 @@ export default Component.extend(NewOrEdit, {
|
|||
decoded: false,
|
||||
srcSet: false,
|
||||
|
||||
detailExpanded: false,
|
||||
previewOpen: false,
|
||||
previewTab: null,
|
||||
questionsArray: null,
|
||||
|
|
@ -59,6 +59,14 @@ export default Component.extend(NewOrEdit, {
|
|||
noAppReadme: null,
|
||||
|
||||
actions: {
|
||||
toogleDetailedDescriptions: function () {
|
||||
set(this, 'detailExpanded', true);
|
||||
},
|
||||
|
||||
toogleNamespace: function () {
|
||||
set(this, 'customizeNamespace', true);
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this.sendAction('cancel');
|
||||
},
|
||||
|
|
@ -84,6 +92,8 @@ export default Component.extend(NewOrEdit, {
|
|||
this.decodeFiles();
|
||||
}
|
||||
|
||||
debugger
|
||||
|
||||
scheduleOnce('afterRender', () => {
|
||||
if ( get(this, 'selectedTemplateUrl') ) {
|
||||
|
||||
|
|
@ -283,6 +293,9 @@ export default Component.extend(NewOrEdit, {
|
|||
|
||||
(get(this, 'selectedTemplateModel.questions') || []).forEach((item) => {
|
||||
out[item.variable] = item.answer;
|
||||
(get(item, 'subquestions') || []).forEach((sub) => {
|
||||
out[sub.variable] = sub.answer;
|
||||
});
|
||||
});
|
||||
|
||||
return out;
|
||||
|
|
|
|||
|
|
@ -16,15 +16,23 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
<div class="col span-8">
|
||||
{{#unless appReadmeContent}}
|
||||
{{#unless noAppReadme}}
|
||||
{{#if appReadmeContent}}
|
||||
{{marked-down markdown=appReadmeContent}}
|
||||
{{else if (not noAppReadme)}}
|
||||
<div class="text-center">
|
||||
<i class="icon icon-spinner icon-spin" style="font-size:36px;"></i>
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{else}}
|
||||
{{marked-down markdown=appReadmeContent}}
|
||||
{{/unless}}
|
||||
{{else if noAppReadme}}
|
||||
<h1 class="mb-10 text-capitalize">
|
||||
{{templateResource.name}}
|
||||
</h1>
|
||||
<p>{{templateResource.description}}</p>
|
||||
<div class="row">
|
||||
<button class="btn btn-sm bg-transparent pl-0" {{action 'toogleDetailedDescriptions'}}>
|
||||
{{t 'newCatalog.seeMore'}}
|
||||
</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -35,6 +43,7 @@
|
|||
detail=(t 'newCatalog.appInfoDetail')
|
||||
expandAll=al.expandAll
|
||||
expand=(action expandFn)
|
||||
expanded=detailExpanded
|
||||
}}
|
||||
<div class="row">
|
||||
{{#if readmeContent}}
|
||||
|
|
@ -65,7 +74,7 @@
|
|||
model=catalogApp
|
||||
nameRequired=true
|
||||
descriptionShow=false
|
||||
nameDisabled=showName
|
||||
nameDisabled=editing
|
||||
bothColClass="col span-12"
|
||||
colClass="col span-12"
|
||||
}}
|
||||
|
|
@ -86,9 +95,18 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{#unless customizeNamespace}}
|
||||
<div class="col span-12">
|
||||
{{#if showName}}
|
||||
{{#advanced-section}}
|
||||
{{t 'newCatalog.customizeNamespace' namespaceId=primaryResource.name htmlSafe=true}}
|
||||
{{#unless editing}}
|
||||
<button class="btn btn-sm bg-transparent pl-0" {{action 'toogleNamespace'}}>
|
||||
{{t 'generic.customize'}}
|
||||
</button>
|
||||
{{/unless}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
<div class="col span-12">
|
||||
{{#if customizeNamespace}}
|
||||
<hr class="mt-20 mb-20"/>
|
||||
|
||||
{{form-namespace
|
||||
|
|
@ -96,7 +114,6 @@
|
|||
mode='reuse'
|
||||
errors=namespaceErrors
|
||||
}}
|
||||
{{/advanced-section}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ export default Component.extend(HoverDropdown, {
|
|||
}.observes(
|
||||
'pageScope',
|
||||
'clusterId',
|
||||
'cluster.isReady',
|
||||
'projectId',
|
||||
'stacks.@each.group',
|
||||
`prefs.${C.PREFS.ACCESS_WARNING}`,
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ export default Component.extend({
|
|||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
set(this,'projectSecrets', get(this,'store').all('secret'));
|
||||
set(this,'namespaceSecrets', get(this,'store').all('namespacedSecret'));
|
||||
set(this,'projectSecrets', get(this,'store').all('secret').filterBy('type','secret'));
|
||||
set(this,'namespaceSecrets', get(this,'store').all('namespacedSecret').filterBy('type','namespacedSecret'));
|
||||
|
||||
let def = get(this,'value') || get(this,'field.default');
|
||||
if ( def && !get(this,'selected') ) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
import { alias } from '@ember/object/computed';
|
||||
import { get, set, observer} from '@ember/object';
|
||||
import { next } from '@ember/runloop';
|
||||
import { inject as service } from '@ember/service';
|
||||
import Component from '@ember/component';
|
||||
import layout from './template';
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
allStorageClasses: service(),
|
||||
|
||||
field: null,
|
||||
value: null,
|
||||
|
||||
selected: null,
|
||||
disabled: false,
|
||||
|
||||
storageClassesOptions: alias('allStorageClasses.list'),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
const def = get(this,'value') || get(this,'field.default');
|
||||
if ( def && !get(this,'selected') ) {
|
||||
const exact = get(this, 'storageClassesOptions').findBy('id', def);
|
||||
|
||||
next(() => {
|
||||
if ( exact ) {
|
||||
set(this, 'selected', get(exact, 'id') || null);
|
||||
} else {
|
||||
set(this, 'selected', null);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
selectedChanged: observer('selected', function() {
|
||||
let id = get(this,'selected');
|
||||
let str = null;
|
||||
|
||||
if ( id ) {
|
||||
const storageClass = get(this, 'storageClassesOptions').findBy('id', id);
|
||||
if ( storageClass ) {
|
||||
str = get(storageClass, 'id');
|
||||
}
|
||||
}
|
||||
|
||||
set(this,'value', str);
|
||||
}),
|
||||
});
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{{searchable-select
|
||||
content=storageClassesOptions
|
||||
class="form-control"
|
||||
value=selected
|
||||
prompt=(t 'schema.inputStorageClass.prompt')
|
||||
optionValuePath="id"
|
||||
optionLabelPath="displayName"
|
||||
placeholder=(t 'schema.inputStorageClass.prompt')
|
||||
}}
|
||||
|
|
@ -574,6 +574,7 @@ C.SUPPORTED_SCHEMA_INPUTS= [
|
|||
'multiline',
|
||||
'password',
|
||||
'service',
|
||||
'storageclass',
|
||||
'string',
|
||||
'masked',
|
||||
'secret',
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ export function absoluteUrl(url) {
|
|||
}
|
||||
|
||||
export function validateEndpoint(str) {
|
||||
//credit to https://stackoverflow.com/questions/9208814/validate-ipv4-ipv6-and-hostname
|
||||
return /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/.test(str);
|
||||
//credit to https://stackoverflow.com/questions/4460586/javascript-regular-expression-to-check-for-ip-addresses
|
||||
return /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(str);
|
||||
}
|
||||
|
||||
export function addAuthorization(url, user, pass) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
export { default } from 'shared/all-storage-classes/service';
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from 'shared/components/form-endpoints/component';
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from 'shared/components/schema/input-storageclass/component';
|
||||
|
|
@ -22,6 +22,7 @@ generic:
|
|||
containers: Containers
|
||||
created: Created
|
||||
createdDate: "Created {date}"
|
||||
customize: Customize
|
||||
default: Default
|
||||
description: Description
|
||||
details: Details
|
||||
|
|
@ -39,6 +40,7 @@ generic:
|
|||
entrypoint: Entrypoint
|
||||
environment: Environment
|
||||
expandAll: Expand All
|
||||
from: from
|
||||
gigabyte: 'GB'
|
||||
generic: 'Generic'
|
||||
hardware: Hardware
|
||||
|
|
@ -178,6 +180,13 @@ accountsPage:
|
|||
|
||||
appDetailPage:
|
||||
header: "App: {appName}"
|
||||
endpoints:
|
||||
title: Endpoints
|
||||
detail: 'Public Endpoints of this application'
|
||||
endpoint: Endpoint
|
||||
protocol: Protocol
|
||||
noData: No public endpoints were created for this application.
|
||||
noMatch: No public endpoints match the current search.
|
||||
notes:
|
||||
title: Notes
|
||||
detail: 'Instructions on how to use this application'
|
||||
|
|
@ -1957,7 +1966,7 @@ confirmDelete:
|
|||
largeDeleteText: '{key} and {othersCount} others'
|
||||
|
||||
containerLogs:
|
||||
title: "Logs: {instanceName}"
|
||||
title: "Logs: "
|
||||
onlyCombined: "<b>Note:</b> Only combined stdout/stderr logs are available for this container because it was run with the TTY (-t) flag."
|
||||
combined: Combined
|
||||
stdout: Standard Out
|
||||
|
|
@ -3934,6 +3943,9 @@ inputPassword:
|
|||
inputTextFile:
|
||||
tooltip: Read from a file
|
||||
|
||||
uploadFile:
|
||||
label: Read from File
|
||||
|
||||
podsSection:
|
||||
title: Pods
|
||||
detail: Pods in this workload
|
||||
|
|
@ -4277,12 +4289,14 @@ newCatalog:
|
|||
maintainedBy: Maintained by community members
|
||||
maintainer: "Maintainer:"
|
||||
newNamespace: New Namespace
|
||||
customizeNamespace: "This application will be deployed into the <code>{namespaceId}</code> namespace"
|
||||
newAppDetail: Choose application version and namespace for the application
|
||||
appInfo: Detailed Descriptions
|
||||
appInfoDetail: Application information and user guid
|
||||
noConfig: This template has no configuration options
|
||||
official: Officially Certified
|
||||
preview: Preview
|
||||
seeMore: More information...
|
||||
saveConfigure: Configure
|
||||
saveNew: Launch
|
||||
saveUpgrade: Upgrade
|
||||
|
|
@ -5064,6 +5078,8 @@ schema:
|
|||
custom: Custom
|
||||
inputDnsRecord:
|
||||
prompt: Choose a Service...
|
||||
inputStorageClass:
|
||||
prompt: Use the default class...
|
||||
inputSecret:
|
||||
prompt: Choose a Secret...
|
||||
|
||||
|
|
@ -5334,6 +5350,7 @@ action:
|
|||
garbageCollect: Cleanup
|
||||
logs: View Logs
|
||||
makeDefault: Set as default
|
||||
resetDefault: Reset default
|
||||
nodeConfig: Download Keys
|
||||
move: Move
|
||||
pause: Pause Orchestration
|
||||
|
|
|
|||
|
|
@ -1076,7 +1076,7 @@ confirmDelete:
|
|||
cancelAction: Cancelar
|
||||
largeDeleteText: '{key} y {othersCount} otros'
|
||||
containerLogs:
|
||||
title: 'Registros: {instanceName}'
|
||||
title: 'Registros: '
|
||||
onlyCombined: "<b>Nota:</b> Solo estarán disponibles los registros combinados de stdout y stderr para este contenedor porque fue lanzado son la instrucción TTY (-t)."
|
||||
combined: Combinado
|
||||
stdout: Standard Out
|
||||
|
|
|
|||
|
|
@ -990,7 +990,7 @@ confirmDelete:
|
|||
cancelAction: Annuler
|
||||
largeDeleteText: '{key} et {othersCount} d’autres'
|
||||
containerLogs:
|
||||
title: 'Journaux : {instanceName}'
|
||||
title: 'Journaux : '
|
||||
onlyCombined: "<b>Remarque :</b> Seuls les journaux combinés des sorties standard et d'erreurs est disponible pour ce conteneur parce qu’il a été exécuté avec l'option TTY (-t) ."
|
||||
combined: Combiné
|
||||
stdout: Sortie Standard
|
||||
|
|
|
|||
|
|
@ -830,7 +830,7 @@ confirmDelete:
|
|||
cancelAction: Mégsem
|
||||
largeDeleteText: '{key} és {othersCount} mások'
|
||||
containerLogs:
|
||||
title: 'Naplók: {instanceName}'
|
||||
title: 'Naplók: '
|
||||
combined: Kombinált
|
||||
stdout: Szabványos kimenet
|
||||
stderr: Standard hiba
|
||||
|
|
|
|||
|
|
@ -1086,7 +1086,7 @@ confirmDelete:
|
|||
confirmAction: 削除
|
||||
cancelAction: キャンセル
|
||||
containerLogs:
|
||||
title: 'ログ: {instanceName}'
|
||||
title: 'ログ: '
|
||||
onlyCombined: "<b>Note:</b> このコンテナでは TTY (-t) フラグが有効なため、標準出力/標準エラー出力が結合されたログのみが利用可能です。"
|
||||
combined: 結合された出力
|
||||
stdout: 標準出力
|
||||
|
|
|
|||
|
|
@ -929,7 +929,7 @@ confirmDelete:
|
|||
confirmAction: Удалить
|
||||
cancelAction: Отмена
|
||||
containerLogs:
|
||||
title: 'Логи: {instanceName}'
|
||||
title: 'Логи: '
|
||||
combined: Комбинированный
|
||||
stderr: Ошибки
|
||||
protip: 'Подсказка: удерживайте клавишу {key}, чтобы открыть журнал событий в новом окне.'
|
||||
|
|
|
|||
|
|
@ -1105,7 +1105,7 @@ confirmDelete:
|
|||
confirmAction: Видалити
|
||||
cancelAction: Відміна
|
||||
containerLogs:
|
||||
title: 'Логи: {instanceName}'
|
||||
title: 'Логи: '
|
||||
onlyCombined: "<b>Примітка:</b> Для цього контейнера доступні комбіновані stdout/stderr журнали, тому що він був запущений з TTY (-t)."
|
||||
combined: Комбіновані
|
||||
stdout: Стандартний вивід
|
||||
|
|
|
|||
|
|
@ -1137,7 +1137,7 @@ confirmDelete:
|
|||
cancelAction: 取消
|
||||
largeDeleteText: '{key} 及 {othersCount} 其他'
|
||||
containerLogs:
|
||||
title: '日志: {instanceName}'
|
||||
title: '日志: '
|
||||
onlyCombined: "<b>注意:</b> 此容器运行时带有TTY(-t)参数,仅有合并的标准输出和标准错误日志可见"
|
||||
combined: 合并日志
|
||||
stdout: 标准输出
|
||||
|
|
|
|||
Loading…
Reference in New Issue