Merge pull request #1517 from vincent99/master

Secrets
This commit is contained in:
Vincent Fiduccia 2017-12-29 18:45:26 -07:00 committed by GitHub
commit 7ef3d78a1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 539 additions and 215 deletions

View File

@ -19,7 +19,6 @@
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
subRows=true subRows=true
fullRows=true
pagingLabel="pagination.node" pagingLabel="pagination.node"
extraSearchFields=extraSearchFields extraSearchFields=extraSearchFields
headers=headers as |sortable kind node dt|}} headers=headers as |sortable kind node dt|}}

View File

@ -20,7 +20,6 @@
bulkActions=true bulkActions=true
body=rows body=rows
sortBy=sortBy sortBy=sortBy
fullRows=true
as |sortable kind obj dt| as |sortable kind obj dt|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -36,7 +36,6 @@
sortBy=sortBy sortBy=sortBy
headers=headers headers=headers
body=filtered body=filtered
fullRows=true
as |sortable kind key| as |sortable kind key|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -35,7 +35,6 @@
sortBy=sortBy sortBy=sortBy
headers=headers headers=headers
body=arranged body=arranged
fullRows=true
as |sortable kind key| as |sortable kind key|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -19,7 +19,6 @@
sortBy=sortBy sortBy=sortBy
headers=headers headers=headers
body=model.receivers body=model.receivers
fullRows=true
as |sortable kind row| as |sortable kind row|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -15,7 +15,6 @@
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
subRows=true subRows=true
fullRows=true
groupByKey=groupTableBy groupByKey=groupTableBy
groupByRef="stack" groupByRef="stack"
pagingLabel="pagination.loadBalancer" pagingLabel="pagination.loadBalancer"

View File

@ -18,7 +18,6 @@
sortBy=sortBy sortBy=sortBy
headers=headers headers=headers
body=model body=model
fullRows=true
as |sortable kind cert| as |sortable kind cert|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -16,7 +16,6 @@
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
subRows=true subRows=true
fullRows=true
groupByKey=groupTableBy groupByKey=groupTableBy
groupByRef="namespace" groupByRef="namespace"
extraGroups=emptyNamespaces extraGroups=emptyNamespaces

View File

@ -15,7 +15,6 @@
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
subRows=true subRows=true
fullRows=true
groupByKey=groupTableBy groupByKey=groupTableBy
groupByRef="namespace" groupByRef="namespace"
pagingLabel="pagination.dnsRecord" pagingLabel="pagination.dnsRecord"

View File

@ -253,7 +253,6 @@
descending=descending descending=descending
headers=storageHeaders headers=storageHeaders
body=nonRootVolumes body=nonRootVolumes
fullRows=true
as |sortable kind volume| as |sortable kind volume|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -34,7 +34,6 @@
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
subRows=true subRows=true
fullRows=true
pagingLabel="pagination.host" pagingLabel="pagination.host"
subHeaders=containerHeaders subHeaders=containerHeaders
subSearchField="arrangedInstances" subSearchField="arrangedInstances"

View File

@ -11,7 +11,7 @@ export function initialize(/*application */) {
// Disable iOS auto-capitalization // Disable iOS auto-capitalization
TextField.reopen({ TextField.reopen({
attributeBindings: ['autocapitalize'], attributeBindings: ['autocapitalize','spellcheck','autocomplete'],
autocapitalize: 'none', autocapitalize: 'none',
}); });
} }

View File

@ -6,6 +6,7 @@ import { formatSi, parseSi, exponentNeeded } from 'shared/utils/parse-unit';
import C from 'ui/utils/constants'; import C from 'ui/utils/constants';
import StateCounts from 'ui/mixins/state-counts'; import StateCounts from 'ui/mixins/state-counts';
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
import { reference } from 'ember-api-store/utils/denormalize';
var Machine = Resource.extend(StateCounts,{ var Machine = Resource.extend(StateCounts,{
@ -16,6 +17,8 @@ var Machine = Resource.extend(StateCounts,{
router: service(), router: service(),
clusterStore: service(), clusterStore: service(),
cluster: reference('clusterId','cluster'),
init() { init() {
this._super(...arguments); this._super(...arguments);
this.defineStateCounts('arrangedInstances', 'instanceStates', 'instanceCountSort'); this.defineStateCounts('arrangedInstances', 'instanceStates', 'instanceCountSort');
@ -92,7 +95,11 @@ var Machine = Resource.extend(StateCounts,{
name = this.get('nodeName'); name = this.get('nodeName');
if ( name ) { if ( name ) {
return name.replace(/\..*$/,''); if ( name.match(/[a-z]/i) ) {
name = name.replace(/\..*$/,'');
}
return name;
} }
name = this.get('requestedHostname'); name = this.get('requestedHostname');

View File

@ -1,19 +1,32 @@
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import { alias } from '@ember/object/computed';
import { computed, get } from '@ember/object';
import Resource from 'ember-api-store/models/resource'; import Resource from 'ember-api-store/models/resource';
export default Resource.extend({ export default Resource.extend({
modalService: service('modal'), modalService: service('modal'),
router: service(),
state: 'active',
actions: { actions: {
edit: function() { edit: function(act) {
this.get('modalService').toggleModal('modal-edit-secret', this); this.get('router').transitionTo('secrets.detail.edit', this.get('id'));
}, },
}, },
keys: computed('data', function() {
return Object.keys(get(this, 'data')).sort();
}),
firstKey: alias('keys.firstObject'),
availableActions: function() { availableActions: function() {
var l = this.get('links'); var l = this.get('links');
var choices = [ var choices = [
{ label: 'action.edit', icon: 'icon icon-edit', action: 'edit', enabled: !!l.update },
{ divider: true },
{ label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: !!l.remove, altAction: 'delete', bulkable: true }, { label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: !!l.remove, altAction: 'delete', bulkable: true },
{ divider: true }, { divider: true },
{ label: 'action.viewInApi', icon: 'icon icon-external-link', action: 'goToApi', enabled: true }, { label: 'action.viewInApi', icon: 'icon icon-external-link', action: 'goToApi', enabled: true },

View File

@ -18,7 +18,6 @@
sortBy=sortBy sortBy=sortBy
headers=headers headers=headers
body=model body=model
fullRows=true
as |sortable kind registry| as |sortable kind registry|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -144,7 +144,9 @@ Router.map(function() {
this.route('secrets', {path: '/secrets', resetNamespace: true}, function() { this.route('secrets', {path: '/secrets', resetNamespace: true}, function() {
this.route('new', {path: '/add'}); this.route('new', {path: '/add'});
this.route('index', {path: '/'}); this.route('index', {path: '/'});
this.route('detail', {path: '/:secret_id'}); this.route('detail', {path: '/:secret_id'}, function() {
this.route('edit');
});
}); });
}); });

View File

@ -0,0 +1,13 @@
import Controller from '@ember/controller';
export default Controller.extend({
actions: {
done() {
this.send('goToPrevious');
},
cancel() {
this.send('goToPrevious');
}
},
});

View File

@ -0,0 +1,16 @@
import Route from '@ember/routing/route';
import { get, set } from '@ember/object';
export default Route.extend({
model: function(params) {
const original = this.modelFor('secrets.detail');
set(this, 'originalModel', original);
return original.clone();
},
setupController(controller, model) {
this._super(...arguments);
set(controller,'originalModel', this.modelFor('secrets.detail'));
}
});

View File

@ -0,0 +1,7 @@
{{new-edit-secret
originalModel=originalModel
model=model
mode="edit"
done=(action "done")
cancel=(action "cancel")
}}

View File

@ -0,0 +1,4 @@
{{new-edit-secret
mode="view"
model=model
}}

View File

@ -0,0 +1,20 @@
import Route from '@ember/routing/route';
import { get } from '@ember/object';
export default Route.extend({
model: function(params) {
const all = this.modelFor('secrets');
let secret = all.projectSecrets.findBy('id', params.secret_id);
if ( secret ) {
return secret;
}
secret = all.namespacedSecrets.findBy('id', params.secret_id);
if ( secret ) {
return secret;
}
return get(this, 'store').find('secret', params.secret_id);
},
});

View File

@ -37,12 +37,25 @@ export default Controller.extend({
translationKey: 'generic.description', translationKey: 'generic.description',
sort: ['description','name','id'], sort: ['description','name','id'],
}, },
{
name: 'namespace',
translationKey: 'generic.namespace',
searchField: 'namespace.displayName',
sort: ['namespace.displayName','name','id'],
},
{
name: 'keys',
translationKey: 'secretsPage.table.keys',
searchField: 'keys',
sort: ['firstKey','name','id'],
},
{ {
name: 'created', name: 'created',
translationKey: 'generic.created', translationKey: 'generic.created',
sort: ['created:desc','name','id'], sort: ['created:desc','name','id'],
searchField: false, searchField: false,
type: 'string', type: 'string',
width: 150,
}, },
], ],

View File

@ -4,6 +4,16 @@
</div> </div>
<div class="right-buttons"> <div class="right-buttons">
<div class="btn-group p-0 mr-10">
{{#tooltip-element type="tooltip-basic" model=(t 'nav.group.none') tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="tooltipLink"}}
{{#link-to (query-params group="none") classNames="btn btn-sm bg-default"}}<i class="icon icon-secrets"></i>{{/link-to}}
{{/tooltip-element}}
{{#tooltip-element type="tooltip-basic" model=(t 'nav.group.namespace') tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="tooltipLink"}}
{{#link-to (query-params group="namespace") classNames="btn btn-sm bg-default"}}<i class="icon icon-list-nested"></i>{{/link-to}}
{{/tooltip-element}}
</div>
{{#link-to "secrets.new" classNames="btn btn-sm bg-primary" disabled=scope.current.isKubernetes}}{{t 'secretsPage.index.linkTo'}}{{/link-to}} {{#link-to "secrets.new" classNames="btn btn-sm bg-primary" disabled=scope.current.isKubernetes}}{{t 'secretsPage.index.linkTo'}}{{/link-to}}
</div> </div>
</section> </section>
@ -21,7 +31,7 @@
{{#if (eq kind "row")}} {{#if (eq kind "row")}}
{{secret-row model=row}} {{secret-row model=row}}
{{else if (eq kind "group")}} {{else if (eq kind "group")}}
{{namespace-group model=inst.ref fullColspan=sortable.fullColspan showState=true}} {{namespace-group model=row.ref noGroup="namespaceGroup.project" fullColspan=sortable.fullColspan}}
{{else if (eq kind "nomatch")}} {{else if (eq kind "nomatch")}}
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'secretsPage.index.noMatch'}}</td></tr> <tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'secretsPage.index.noMatch'}}</td></tr>
{{else if (eq kind "norows")}} {{else if (eq kind "norows")}}

View File

@ -1,5 +1,5 @@
{{new-edit-secret {{new-edit-secret
editing=false mode="new"
model=model model=model
cancel=(action "cancel") cancel=(action "cancel")
}} }}

View File

@ -37,7 +37,6 @@
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
subRows=true subRows=true
fullRows=true
pagingLabel="pagination.workload" pagingLabel="pagination.workload"
subSearchField="instances" subSearchField="instances"
extraSearchFields=extraSearchFields extraSearchFields=extraSearchFields
@ -84,7 +83,6 @@
body=loadBalancers body=loadBalancers
bulkActions=true bulkActions=true
classNames="grid sortable-table" classNames="grid sortable-table"
fullRows=true
pagingLabel="pagination.container" pagingLabel="pagination.container"
searchText=searchText searchText=searchText
sortBy=sortBy sortBy=sortBy
@ -131,7 +129,6 @@
subHeaders=containerHeaders subHeaders=containerHeaders
subSearchField="instances" subSearchField="instances"
bulkActions=true bulkActions=true
fullRows=true
pagingLabel="pagination.container" pagingLabel="pagination.container"
headers=dnsHeaders headers=dnsHeaders
as |sortable kind serv dt|}} as |sortable kind serv dt|}}
@ -165,7 +162,6 @@
body=model.volumes body=model.volumes
bulkActions=true bulkActions=true
classNames="grid sortable-table" classNames="grid sortable-table"
fullRows=true
isVisible=parent.expanded isVisible=parent.expanded
pagingLabel="pagination.volume" pagingLabel="pagination.volume"
searchText=searchText searchText=searchText

View File

@ -9,6 +9,7 @@
@import "app/styles/fonts/prompt"; @import "app/styles/fonts/prompt";
@import "app/styles/fonts/icons"; @import "app/styles/fonts/icons";
@import "app/styles/fonts/zerowidthspace"; @import "app/styles/fonts/zerowidthspace";
@import "app/styles/fonts/dots";
@import "app/styles/base/base"; @import "app/styles/base/base";
@import "app/styles/base/color"; @import "app/styles/base/color";
@import "app/styles/base/typography"; @import "app/styles/base/typography";

View File

@ -266,8 +266,11 @@ input.input-sm,
.input-group.input-sm .input-group-addon { .input-group.input-sm .input-group-addon {
padding: 3px 8px; padding: 3px 8px;
font-size: 0.87em; font-size: 0.87em;
&:not(textarea) {
max-height: 32px; max-height: 32px;
} }
}
.input-lg, .input-lg,
input.input-lg, input.input-lg,

View File

@ -0,0 +1,12 @@
@font-face {
font-family: 'dotsfont';
font-weight: normal;
font-style: normal;
src: url(data:application/font-woff;charset=utf-8;base64,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) format('woff');
}
.conceal:not(:invalid):not(:active):not(:focus) {
font-family: 'dotsfont';
}

View File

@ -79,7 +79,6 @@
classNames="grid fixed mb-0 sortable-table" classNames="grid fixed mb-0 sortable-table"
bulkActions=false bulkActions=false
pagingLabel="pagination.mount" pagingLabel="pagination.mount"
fullRows=true
rowActions=false rowActions=false
search=true search=true
sortBy=sortBy sortBy=sortBy

View File

@ -15,7 +15,6 @@
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
subRows=true subRows=true
fullRows=true
groupByKey=groupTableBy groupByKey=groupTableBy
groupByRef="stack" groupByRef="stack"
pagingLabel="pagination.volume" pagingLabel="pagination.volume"

View File

@ -74,7 +74,6 @@
search=false search=false
sortBy=sortBy sortBy=sortBy
bulkActions=false bulkActions=false
fullRows=true
pagingLabel="pagination.node" pagingLabel="pagination.node"
headers=projectHeaders as |sortable kind role dt|}} headers=projectHeaders as |sortable kind role dt|}}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}
@ -107,7 +106,6 @@
search=false search=false
sortBy=sortBy sortBy=sortBy
bulkActions=false bulkActions=false
fullRows=true
pagingLabel="pagination.node" pagingLabel="pagination.node"
headers=clusterHeaders as |sortable kind role dt|}} headers=clusterHeaders as |sortable kind role dt|}}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -61,7 +61,6 @@
search=false search=false
sortBy=sortBy sortBy=sortBy
bulkActions=false bulkActions=false
fullRows=true
pagingLabel="pagination.node" pagingLabel="pagination.node"
headers=headers as |sortable kind role dt|}} headers=headers as |sortable kind role dt|}}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -9,7 +9,6 @@
<section class="instances"> <section class="instances">
{{#sortable-table {{#sortable-table
classNames="grid sortable-table" classNames="grid sortable-table"
fullRows=true
sortBy=sortBy sortBy=sortBy
headers=headers headers=headers
body=model body=model

View File

@ -59,7 +59,6 @@
search=false search=false
sortBy=sortBy sortBy=sortBy
bulkActions=false bulkActions=false
fullRows=true
pagingLabel="pagination.node" pagingLabel="pagination.node"
headers=headers as |sortable kind role dt|}} headers=headers as |sortable kind role dt|}}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -55,7 +55,6 @@
headers=headers headers=headers
body=custom body=custom
sortBy=sortBy sortBy=sortBy
fullRows=true
rightActions=true rightActions=true
as |sortable kind row dt| as |sortable kind row dt|
}} }}

View File

@ -15,7 +15,6 @@
searchText=searchText searchText=searchText
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
fullRows=true
pagingLabel="pagination.cluster" pagingLabel="pagination.cluster"
headers=headers as |sortable kind inst dt| headers=headers as |sortable kind inst dt|
}} }}

View File

@ -26,12 +26,12 @@
<div class="bubble bg-body round p-10"><img src="{{app.baseAssets}}assets/images/cluster-create.svg" class="mt-5" /></div> <div class="bubble bg-body round p-10"><img src="{{app.baseAssets}}assets/images/cluster-create.svg" class="mt-5" /></div>
</div> </div>
<div class="col span-4 text-center option"> <div class="col span-4 text-center option option-disabled">
<h2>{{t 'clustersPage.indexPage.import.header'}}</h2> <h2>{{t 'clustersPage.indexPage.import.header'}}</h2>
<div class="box-sm"> <div class="box-sm">
<p>{{t 'clustersPage.indexPage.import.desc'}}</p> <p>{{t 'clustersPage.indexPage.import.desc'}}</p>
<div class="links" style="top: auto; bottom: 30px;"> <div class="links" style="top: auto; bottom: 30px;">
{{#link-to "clusters.new.import" class="btn bg-primary"}}{{t 'clusterWelcome.select'}}{{/link-to}} {{#link-to "clusters.new.import" class="btn bg-disabled"}}Coming Soon{{/link-to}}
</div> </div>
</div> </div>
<div class="bubble bg-body round p-10"><img src="{{app.baseAssets}}assets/images/cluster-import.svg" class="mt-5" /></div> <div class="bubble bg-body round p-10"><img src="{{app.baseAssets}}assets/images/cluster-import.svg" class="mt-5" /></div>

View File

@ -23,9 +23,9 @@
}} }}
<div class="row"> <div class="row">
<div class="col span-6"> <div class="col span-6">
<div class="radio"> <div class="radio text-muted">
<label>{{radio-button selection=scope value="embedded"}} {{t 'clustersPage.addPage.rke.new.radio.embedded.label'}}</label> <label>{{radio-button selection=scope value="embedded" disabled=true}} {{t 'clustersPage.addPage.rke.new.radio.embedded.label'}}</label>
<p class="text-info">{{t 'clustersPage.addPage.rke.new.radio.embedded.detail' appName=settings.appName}}</p> <p class="text-info">{{t 'clustersPage.addPage.rke.new.radio.embedded.detail' appName=settings.appName}} &mdash; Coming Soon</p>
</div> </div>
</div> </div>
<div class="col span-6"> <div class="col span-6">
@ -50,7 +50,6 @@
body=filteredMachines body=filteredMachines
searchText=searchText searchText=searchText
sortBy=sortBy sortBy=sortBy
fullRows=true
suffix=true suffix=true
bulkActions=false bulkActions=false
rowActions=false rowActions=false

View File

@ -16,12 +16,11 @@
searchText=searchText searchText=searchText
sortBy=sortBy sortBy=sortBy
bulkActions=true bulkActions=true
fullRows=true
pagingLabel="pagination.node" pagingLabel="pagination.node"
headers=headers as |sortable kind nodes dt|}} headers=headers as |sortable kind nodes dt|}}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}
{{node-row {{node-row
view="cluster" view="global"
model=nodes model=nodes
fullColspan=sortable.fullColspan fullColspan=sortable.fullColspan
dt=dt dt=dt

View File

@ -5,7 +5,6 @@
<section class="instances"> <section class="instances">
{{#sortable-table {{#sortable-table
classNames="grid sortable-table" classNames="grid sortable-table"
fullRows=true
sortBy=sortBy sortBy=sortBy
headers=headers headers=headers
searchText=searchText searchText=searchText

View File

@ -5,7 +5,6 @@
<section class="instances"> <section class="instances">
{{#sortable-table {{#sortable-table
classNames="grid sortable-table" classNames="grid sortable-table"
fullRows=true
sortBy=sortBy sortBy=sortBy
headers=headers headers=headers
searchText=searchText searchText=searchText

View File

@ -7,6 +7,7 @@ export default Component.extend({
model : null, model : null,
size : 'xs', size : 'xs',
inTooltip : false, inTooltip : false,
context : null,
resourceActions : service('resource-actions'), resourceActions : service('resource-actions'),
@ -39,12 +40,7 @@ export default Component.extend({
this.get('resourceActions').set('tooltipActions', false); this.get('resourceActions').set('tooltipActions', false);
} }
this.get('resourceActions').show(this.get('model'), more, this.$(), offsets); this.get('resourceActions').show(this.get('model'), more, this.$(), offsets, this.get('context'));
} }
}, },
sendToModel(action) {
this.get('tooltipService').leave();
this.get('model').send(action);
},
}); });

View File

@ -12,7 +12,6 @@
subRow=subRow subRow=subRow
subRows=subRows subRows=subRows
pagingLabel=pagingLabel pagingLabel=pagingLabel
fullRows=true
headers=headers as |sortable kind inst dt|}} headers=headers as |sortable kind inst dt|}}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}
{{pod-row model=inst dt=dt bulkActions=bulkActions showNode=showNode showActions=true showPrimaryActions=false fullColspan=sortable.fullColspan subRow=subRow}} {{pod-row model=inst dt=dt bulkActions=bulkActions showNode=showNode showActions=true showPrimaryActions=false fullColspan=sortable.fullColspan subRow=subRow}}

View File

@ -47,7 +47,6 @@
classNames="grid sortable-table" classNames="grid sortable-table"
body=linksArray body=linksArray
bulkActions=false bulkActions=false
fullRows=true
pagingLabel="pagination.link" pagingLabel="pagination.link"
headers=headers as |sortable kind row dt|}} headers=headers as |sortable kind row dt|}}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -38,15 +38,15 @@
{{#if showGroup}} {{#if showGroup}}
<div class="btn-group p-0 mr-10"> <div class="btn-group p-0 mr-10">
{{#tooltip-element type="tooltip-basic" model=(t 'nav.containers.groupNone') tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="tooltipLink"}} {{#tooltip-element type="tooltip-basic" model=(t 'nav.group.none') tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="tooltipLink"}}
{{#link-to (query-params group="none") classNames="btn btn-sm bg-default"}}<i class="icon icon-container"></i>{{/link-to}} {{#link-to (query-params group="none") classNames="btn btn-sm bg-default"}}<i class="icon icon-container"></i>{{/link-to}}
{{/tooltip-element}} {{/tooltip-element}}
{{#tooltip-element type="tooltip-basic" model=(t 'nav.containers.groupService') tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="tooltipLink"}} {{#tooltip-element type="tooltip-basic" model=(t 'nav.group.workload') tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="tooltipLink"}}
{{#link-to (query-params group="workload") classNames="btn btn-sm bg-default"}}<i class="icon icon-service"></i>{{/link-to}} {{#link-to (query-params group="workload") classNames="btn btn-sm bg-default"}}<i class="icon icon-service"></i>{{/link-to}}
{{/tooltip-element}} {{/tooltip-element}}
{{#tooltip-element type="tooltip-basic" model=(t 'nav.containers.groupStack') tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="tooltipLink"}} {{#tooltip-element type="tooltip-basic" model=(t 'nav.group.namespaceWorkload') tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="tooltipLink"}}
{{#link-to (query-params group="namespace") classNames="btn btn-sm bg-default"}}<i class="icon icon-list-nested"></i>{{/link-to}} {{#link-to (query-params group="namespace") classNames="btn btn-sm bg-default"}}<i class="icon icon-list-nested"></i>{{/link-to}}
{{/tooltip-element}} {{/tooltip-element}}
</div> </div>

View File

@ -74,6 +74,8 @@ export default Component.extend({
allowEmptyValue: false, allowEmptyValue: false,
addInitialEmptyRow: false, addInitialEmptyRow: false,
allowMultilineValue: true, allowMultilineValue: true,
base64Value: false,
concealValue: false,
editing: true, editing: true,
ary: null, ary: null,
@ -94,7 +96,10 @@ export default Component.extend({
return; return;
} }
this.$('INPUT.key').last()[0].focus(); let elem = this.$('INPUT.key').last()[0];
if ( elem ) {
elem.focus();
}
}); });
}, },
@ -147,6 +152,12 @@ export default Component.extend({
} }
if ( this.get('base64Value') ) {
ary.forEach((entry) => {
entry.value = AWS.util.base64.decode(entry.value).toString();
});
}
this.set('ary', ary); this.set('ary', ary);
if ( !ary.length && this.get('addInitialEmptyRow') ) if ( !ary.length && this.get('addInitialEmptyRow') )
{ {
@ -170,6 +181,10 @@ export default Component.extend({
var k = row.get('key').trim(); var k = row.get('key').trim();
var v = row.get('value').trim(); var v = row.get('value').trim();
if ( this.get('base64Value') ) {
v = AWS.util.base64.encode(v);
}
if ( k && (v || this.get('allowEmptyValue')) ) if ( k && (v || this.get('allowEmptyValue')) )
{ {
map[k] = v; map[k] = v;

View File

@ -35,9 +35,9 @@
<td data-title="{{t valueLabel}}:"> <td data-title="{{t valueLabel}}:">
{{#if editing}} {{#if editing}}
{{#if allowMultilineValue}} {{#if allowMultilineValue}}
{{textarea-autogrow class="form-control input-sm value" value=row.value placeholder=valuePlaceholder disabled=(eq row.editable false)}} {{textarea-autogrow class=(concat "form-control input-sm value" (if concealValue " conceal")) spellcheck="false" required=true value=row.value placeholder=valuePlaceholder disabled=(eq row.editable false)}}
{{else}} {{else}}
{{input class="form-control input-sm value" type="text" value=row.value placeholder=valuePlaceholder disabled=(eq row.editable false)}} {{input class=(concat "form-control input-sm value" (if concealValue " conceal")) spellcheck="false" type="text" value=row.value placeholder=valuePlaceholder disabled=(eq row.editable false)}}
{{/if}} {{/if}}
{{else}} {{else}}
{{row.value}} {{row.value}}

View File

@ -1,21 +1,64 @@
import { observer } from '@ember/object'; import { get, set } from '@ember/object';
import { resolve, reject } from 'rsvp';
import Component from '@ember/component'; import Component from '@ember/component';
import NewOrEdit from 'shared/mixins/new-or-edit'; import ViewNewEdit from 'shared/mixins/view-new-edit';
import layout from './template'; import layout from './template';
export default Component.extend(NewOrEdit, { export default Component.extend(ViewNewEdit, {
layout, layout,
model: null, model: null,
userValue: '', titleKey: 'newSecret.title',
userValueChanged: observer('userValue', function() {
this.set('primaryResource.value', AWS.util.base64.encode(this.get('userValue'))); scope: 'project',
}), namespace: null,
actions: { actions: {
updateData(map) {
set(this, 'primaryResource.data', map);
},
cancel() { cancel() {
this.sendAction('cancel'); this.sendAction('cancel');
},
},
doSave() {
let mode = get(this, 'mode');
let scope = get(this, 'scope');
let pr = get(this, 'primaryResource');
let ns = get(this, 'namespace');
if ( mode === 'edit' || scope === 'project' ) {
return this._super(...arguments);
} }
let promise = resolve();
// Convert to a namespacedSecret and create the NS as needed
if ( ns ) {
let obj = pr.serialize();
obj.type = 'namespacedSecret';
pr = get(this,'store').createRecord(obj);
set(this,'primaryResource',pr);
if ( get(ns, 'id') ) {
set(pr, 'namespaceId', get(ns, 'id'));
} else if ( ns ) {
promise = ns.save().then((newNs) => {
set(pr, 'namespaceId', get(newNs, 'id'));
return newNs.waitForState('active');
});
} else {
return reject('No namespace specified');
}
}
let self = this;
let sup = self._super;
return promise.then(() => {
return sup.apply(self,arguments);
});
}, },
doneSaving() { doneSaving() {

View File

@ -1,24 +1,72 @@
<section class="header clearfix"> <section class="header clearfix">
<h1>{{t (if editing 'newSecret.title.edit' 'newSecret.title.add')}}</h1> {{#if isView}}
<div class="right-buttons pull-right">
{{badge-state model=model}}
{{action-menu model=model showPrimary=false classNames="ml-10 inline-block" size="sm"}}
</div>
{{/if}}
<h1>{{title}}</h1>
</section> </section>
<section class="horizontal-form container-fluid"> {{#if isView}}
<div class="row"> {{#if model.description}}
{{banner-message color='bg-secondary mb-0 mt-10' message=(linkify model.container.description)}}
{{/if}}
{{else}}
{{form-name-description {{form-name-description
model=primaryResource model=primaryResource
nameRequired=true nameRequired=true
namePlaceholder="newSecret.name.placeholder" namePlaceholder="newSecret.name.placeholder"
descriptionPlaceholder="newSecret.description.placeholder" descriptionPlaceholder="newSecret.description.placeholder"
}} }}
{{/if}}
{{#unless editing}} <div class="row">
<div class="col span-6"> <div class="col span-6" style="min-height: 106px;">
<label class="acc-label pb-5">{{t 'newSecret.value.label'}}{{field-required}}</label> <label class="acc-label">{{t 'newSecret.scope.label'}}</label>
{{textarea-autogrow class="form-control" value=userValue placeholder="newSecret.value.placeholder"}} {{#if isNew}}
<div class="radio">
<label>{{radio-button selection=scope value="project"}}&nbsp;{{t 'newSecret.scope.project'}}</label>
</div> </div>
{{/unless}} <div class="radio">
<label>{{radio-button selection=scope value="namespace"}}&nbsp;{{t 'newSecret.scope.namespace'}}{{if (eq scope "namespace") ':'}}</label>
</div>
{{else}}
<div>
{{#if model.namespace}}
{{t 'newSecret.scope.namespace'}}: {{model.namespace.displayName}}
{{else}}
{{t 'newSecret.scope.project'}}
{{/if}}
</div>
{{/if}}
</div> </div>
</section>
{{#if (and isNew (eq scope "namespace"))}}
<div class="col span-6 box">
{{form-namespace
namespace=namespace
errors=namespaceErrors
}}
</div>
{{/if}}
</div>
<div class="box mt-10">
<label class="acc-label">{{t 'newSecret.values.label'}}</label>
{{form-key-value
initialMap=primaryResource.data
addActionLabel="newSecret.addActionLabel"
addInitialEmptyRow=true
base64Value=true
concealValue=true
editing=notIsView
changed=(action "updateData")
}}
</div>
{{#unless isView}}
{{top-errors errors=errors}} {{top-errors errors=errors}}
{{save-cancel editing=true save="save" cancel="cancel"}} {{save-cancel editing=true save="save" cancel="viewEditCancel"}}
{{/unless}}

View File

@ -1,16 +1,10 @@
import { or, equal, not, alias } from '@ember/object/computed'; import { or } from '@ember/object/computed';
import { get, computed } from '@ember/object';
import Component from '@ember/component'; import Component from '@ember/component';
import layout from './template'; import layout from './template';
import { inject as service } from '@ember/service' import { inject as service } from '@ember/service'
export const headersAll = [ export const headersAll = [
{
name: 'expand',
sort: false,
searchField: null,
width: 30,
views: ['project'],
},
{ {
name: 'state', name: 'state',
sort: ['sortState','displayName'], sort: ['sortState','displayName'],
@ -24,6 +18,13 @@ export const headersAll = [
searchField: 'displayName', searchField: 'displayName',
translationKey: 'generic.name', translationKey: 'generic.name',
}, },
{
name: 'cluster',
sort: ['cluster.displayName','name','id'],
searchField: 'cluster.displayName',
translationKey: 'nodesPage.table.clusterName',
views: ['global'],
},
{ {
name: 'ip', name: 'ip',
sort: ['displayIp','displayName'], sort: ['displayIp','displayName'],
@ -54,21 +55,16 @@ export const headersAll = [
translationKey: 'nodesPage.table.pod', translationKey: 'nodesPage.table.pod',
views: ['cluster','global'], views: ['cluster','global'],
}, },
{
name: 'instanceState',
sort: ['instanceCountSort:desc','displayName'],
searchField: null,
width: 140,
icon: 'icon icon-lg icon-container',
dtTranslationKey: 'nodesPage.table.instanceState',
translationKey: 'nodesPage.table.instanceStateWithIcon',
views: ['project'],
},
]; ];
export const headersProject = headersAll.filter((x) => !x.views || x.views.includes('project')); const headersMap = {
export const headersCluster = headersAll.filter((x) => !x.views || x.views.includes('cluster')); all: headersAll,
export const headersGlobal = headersAll.filter((x) => !x.views || x.views.includes('global' )); global: headersAll.filter((x) => !x.views || x.views.includes('global' )),
cluster: headersAll.filter((x) => !x.views || x.views.includes('cluster')),
};
export const headersCluster = headersMap.cluster;
export const headersGlobal = headersMap.global;
export default Component.extend({ export default Component.extend({
layout, layout,
@ -83,15 +79,9 @@ export default Component.extend({
showLabelRow: or('model.displayUserLabelStrings.length','model.requireAnyLabelStrings.length'), showLabelRow: or('model.displayUserLabelStrings.length','model.requireAnyLabelStrings.length'),
isGlobal: equal('view', 'global'), showCluster: computed('view', function() {
isCluster: equal('view','cluster'), return !!headersMap[get(this,'view')].findBy('name','cluster');
isProject: equal('view','project'), }),
showExpand: alias('isProject'),
linkName: alias('isProject'),
showInstanceStates: alias('isProject'),
showCpu: not('isProject'),
showPod: not('isProject'),
actions: { actions: {
toggle() { toggle() {

View File

@ -3,12 +3,6 @@
{{check-box nodeId=model.id}} {{check-box nodeId=model.id}}
</td> </td>
{{#if showExpand}}
<td>
<i role="button" {{action "toggle"}} class="icon icon-play eased text-small text-muted {{if expanded 'icon-rotate-90'}}"><span class="visually-hidden">Open accordion</span></i>
</td>
{{/if}}
<td data-title="{{dt.state}}" class="state"> <td data-title="{{dt.state}}" class="state">
{{badge-state model=model}} {{badge-state model=model}}
</td> </td>
@ -27,56 +21,33 @@
{{/each}} {{/each}}
</td> </td>
{{#if showCluster}}
<td data-title="{{dt.cluster}}">
{{#if model.cluster}}
{{model.cluster.displayName}}
{{else}}
<b>{{t 'generic.none'}}</b>
{{/if}}
</td>
{{/if}}
<td data-title="{{dt.ip}}"> <td data-title="{{dt.ip}}">
{{#copy-inline clipboardText=model.displayIp size="small"}} {{#copy-inline clipboardText=model.displayIp size="small"}}
{{format-ip model.displayIp}} {{format-ip model.displayIp}}
{{/copy-inline}} {{/copy-inline}}
</td> </td>
{{#if showCpu}}
<td data-title="{{dt.cpu}}"> <td data-title="{{dt.cpu}}">
{{model.cpuUsage}} {{model.cpuUsage}}
</td> </td>
{{/if}}
<td data-title="{{dt.memory}}"> <td data-title="{{dt.memory}}">
{{model.memoryUsage}} {{model.memoryUsage}}
</td> </td>
{{#if showPod}}
<td data-title="{{dt.pod}}"> <td data-title="{{dt.pod}}">
{{model.podUsage}} {{model.podUsage}}
</td> </td>
{{/if}}
{{#if showInstanceStates}}
<td data-title="{{dt.instanceState}}">
<div style="margin-top: 5px;">
{{progress-bar-multi
labelKey="state"
valueKey="count"
values=model.instanceStates.byColor
tooltipValues=model.instanceStates.byName
}}
<p class="text-muted m-0">
<small>
{{#if subMatches}}
{{#if (eq (get subMatches model.id) 0)}}
{{t 'pagination.containerNoSubset' count=model.arrangedInstances.length htmlSafe=true}}
{{else if (lt (get subMatches model.id) model.arrangedInstances.length)}}
{{t 'pagination.containerHighlightSubset' subset=(get subMatches model.id) count=model.arrangedInstances.length htmlSafe=true}}
{{else}}
<b>{{t 'pagination.container' pages=1 count=model.arrangedInstances.length}}</b>
{{/if}}
{{else}}
{{t 'pagination.container' pages=1 count=(concat model.arrangedInstances.length "")}}
{{/if}}
</small>
</p>
</div>
</td>
{{/if}}
<td data-title="{{dt.actions}}" class="actions"> <td data-title="{{dt.actions}}" class="actions">
{{action-menu model=model showPrimary=false}} {{action-menu model=model showPrimary=false}}

View File

@ -34,12 +34,12 @@
{{#if (and showNode model.node)}} {{#if (and showNode model.node)}}
<a href="{{href-to "host" model.node.id}}">{{model.node.displayName}}</a> / <a href="{{href-to "host" model.node.id}}">{{model.node.displayName}}</a> /
{{/if}} {{/if}}
{{t 'generic.createdDate' date=(date-from-now model.created)}} {{t 'generic.createdDate' date=(date-from-now model.created) htmlSafe=true}}
</p> </p>
</td> </td>
{{#if scalePlaceholder}} {{#if scalePlaceholder}}
<td class="text-muted text-center"> <td class="text-muted text-center">
<small>{{t 'stackRow.standalone'}}</small> <small>{{t 'namespaceGroup.none'}}</small>
</td> </td>
{{/if}} {{/if}}
{{#if showActions}} {{#if showActions}}

View File

@ -5,7 +5,6 @@
headers=headers headers=headers
body=model body=model
sortBy=sortBy sortBy=sortBy
fullRows=true
as |sortable kind p dt| as |sortable kind p dt|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -14,7 +14,6 @@
descending=descending descending=descending
headers=headers headers=headers
body=model body=model
fullRows=true
as |sortable kind row| as |sortable kind row|
}} }}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -4,7 +4,6 @@
searchText=searchText searchText=searchText
sortBy=sortBy sortBy=sortBy
bulkActions=false bulkActions=false
fullRows=true
pagingLabel="pagination.port" pagingLabel="pagination.port"
headers=headers as |sortable kind row dt|}} headers=headers as |sortable kind row dt|}}
{{#if (eq kind "row")}} {{#if (eq kind "row")}}

View File

@ -11,8 +11,18 @@
<td data-title="{{dt.description}}"> <td data-title="{{dt.description}}">
{{model.description}} {{model.description}}
</td> </td>
<td data-title="{{dt.namespace}}">
{{#if model.namespace}}
{{model.namespace.displayName}}
{{else}}
<span class="text-muted">{{t 'generic.all'}}</span>
{{/if}}
</td>
<td data-title="{{dt.keys}}">
{{join-array model.keys}}
</td>
<td data-title="{{dt.created}}"> <td data-title="{{dt.created}}">
{{date-from-now row.created}} {{date-from-now model.created}}
</td> </td>
<td data-title="{{dt.actions}} "class="actions"> <td data-title="{{dt.actions}} "class="actions">
{{action-menu model=model}} {{action-menu model=model}}

View File

@ -4,7 +4,6 @@
body=logs body=logs
bulkActions=false bulkActions=false
search=true search=true
fullRows=true
sortBy=sortBy sortBy=sortBy
pagingLabel="pagination.event" pagingLabel="pagination.event"
headers=headers as |sortable kind row dt|}} headers=headers as |sortable kind row dt|}}

View File

@ -80,7 +80,6 @@
{{/if}} {{/if}}
{{#if groupByKey}} {{#if groupByKey}}
{{! Note: Grouping requires fullRows}}
{{#if extraGroups.length}} {{#if extraGroups.length}}
{{#each extraGroups as |group|}} {{#each extraGroups as |group|}}
<tbody class="group"> <tbody class="group">
@ -99,7 +98,7 @@
{{else}} {{else}}
{{yield this (if arranged.length 'nomatch' 'norows')}} {{yield this (if arranged.length 'nomatch' 'norows')}}
{{/each}} {{/each}}
{{else if fullRows}} {{else}}
<tbody> <tbody>
{{#each pagedContent as |row|}} {{#each pagedContent as |row|}}
{{yield this 'row' row dt (array-includes childFilterNodes row.id)}} {{yield this 'row' row dt (array-includes childFilterNodes row.id)}}
@ -107,32 +106,6 @@
{{yield this (if arranged.length 'nomatch' 'norows')}} {{yield this (if arranged.length 'nomatch' 'norows')}}
{{/each}} {{/each}}
</tbody> </tbody>
{{else}}
<tbody>
{{#each pagedContent as |row|}}
<tr class="main-row">
{{#if bulkActions}}
<td data-title="{{generic.actions}}: " class="row-check">
{{check-box nodeId=row.id}}
</td>
{{/if}}
{{#if hasBlock}}
{{yield this 'row' row dt}}
{{else}}
{{#each headers as |header|}}
<td data-title={{header.displayName}} data-id={{row.id}}>{{select-property row header.name}}</td>
{{/each}}
{{/if}}
</tr>
{{#if hasBlock}}
{{yield this 'sub-row' row dt}}
{{/if}}
{{else}}
{{#if hasBlock}}
{{yield this (if arranged.length 'nomatch' 'norows')}}
{{/if}}
{{/each}}
</tbody>
{{/if}} {{/if}}
{{#if suffix}} {{#if suffix}}

View File

@ -14,6 +14,7 @@ export default TextArea.extend(IntlPlaceholder, {
tagName: 'textarea', tagName: 'textarea',
classNames: ['no-resize','no-ease'], classNames: ['no-resize','no-ease'],
attributeBindings: ['spellcheck'],
didInsertElement() { didInsertElement() {
run.scheduleOnce('afterRender', this, 'initHeights'); run.scheduleOnce('afterRender', this, 'initHeights');

View File

@ -49,7 +49,6 @@
classNames="grid fixed mb-0 sortable-table" classNames="grid fixed mb-0 sortable-table"
bulkActions=false bulkActions=false
pagingLabel="pagination.volumes" pagingLabel="pagination.volumes"
fullRows=true
rowActions=false rowActions=false
search=false search=false
stickyHeader=false stickyHeader=false

View File

@ -9,7 +9,7 @@
{{badge-state model=model}} {{badge-state model=model}}
</td> </td>
<td data-title="{{dt.name}}" class="clip"> <td data-title="{{dt.name}}" class="clip">
<a href="{{href-to "workload" model.id}}">{{model.displayName}} <i class="icon icon-service"></i></a> <a href="{{href-to "service" model.id}}">{{model.displayName}} <i class="icon icon-service"></i></a>
{{#if model.showTransitioningMessage}} {{#if model.showTransitioningMessage}}
<div class="clip text-small {{model.stateColor}}">{{model.transitioningMessage}}</div> <div class="clip text-small {{model.stateColor}}">{{model.transitioningMessage}}</div>
{{else if model.displayEndpoints}} {{else if model.displayEndpoints}}
@ -33,7 +33,7 @@
{{else}} {{else}}
{{t 'pagination.pod' pages=1 count=(concat model.pods.length "")}} {{t 'pagination.pod' pages=1 count=(concat model.pods.length "")}}
{{/if}} / {{/if}} /
{{t 'generic.createdDate' date=(date-from-now model.created)}} {{t 'generic.createdDate' date=(date-from-now model.created) htmlSafe=true}}
</p> </p>
</td> </td>
{{/if}} {{/if}}

View File

@ -1,7 +1,10 @@
import { helper } from '@ember/component/helper'; import { helper } from '@ember/component/helper';
import { htmlSafe} from '@ember/string';
export function dateFromNow(params) { export function dateFromNow(params) {
return moment(params[0]).fromNow(); let d = moment(params[0]);
let str = '<span title="' + d.format('llll') + '">' + d.fromNow() + '</span>';
return htmlSafe(str);
} }
export default helper(dateFromNow); export default helper(dateFromNow);

View File

@ -116,7 +116,7 @@ export default Mixin.create({
type = get(event.data, 'type'); type = get(event.data, 'type');
forceRemove = (event.name === 'resource.remove'); forceRemove = (event.name === 'resource.remove');
console.log(this.label, (forceRemove ? 'Remove' : 'Change'), type +':'+ event.data.id, clusterId, projectId); //console.log(this.label, (forceRemove ? 'Remove' : 'Change'), type +':'+ event.data.id, clusterId, projectId);
if ( get(this, 'updateProjectStore') && projectId && projectStore.hasType(type) ) { if ( get(this, 'updateProjectStore') && projectId && projectStore.hasType(type) ) {
//console.log(' Update project store', type, event.data.id, projectId); //console.log(' Update project store', type, event.data.id, projectId);

View File

@ -0,0 +1,49 @@
import Mixin from '@ember/object/mixin'
import NewOrEdit from './new-or-edit';
import { computed, get, set } from '@ember/object'
import { equal, or } from '@ember/object/computed'
import { inject as service } from '@ember/service';
export const VIEW = 'view';
export const NEW = 'new';
export const EDIT = 'edit';
export default Mixin.create(NewOrEdit, {
intl: service(),
titleKey: null,
inlineEdit: false,
isView: equal('mode', VIEW),
isNew: equal('mode', NEW),
isEdit: equal('mode', EDIT),
notView: or('isNew','isEdit'),
actions: {
inlineEdit() {
set(this, 'mode', EDIT);
set(this, 'inlineEdit', true);
},
viewEditCancel() {
if ( get(this, 'inlineEdit') ) {
set(this, 'inlineEdit', false);
set(this, 'mode', VIEW);
} else {
this.sendAction('cancel');
}
},
},
title: computed('mode', 'primaryResource.displayName', 'titleKey', function() {
const prefix = get(this, 'titleKey');
const mode = get(this, 'mode');
const intl = get(this, 'intl');
let name = get(this, 'originalModel.displayName')
|| get(this, 'primaryResource.displayName')
|| '';
return intl.t(prefix+'.'+mode, { name });
}),
});

View File

@ -9,6 +9,7 @@ export default Service.extend({
tooltipActions : null, tooltipActions : null,
actionToggle : null, actionToggle : null,
actionMenu : null, actionMenu : null,
actionContext : null,
app: service(), app: service(),
// offset is a parameter that we need to open in our api, it allows us to pass a // offset is a parameter that we need to open in our api, it allows us to pass a
@ -20,7 +21,7 @@ export default Service.extend({
// mirror: true // mirror: true
// }, // },
show: function(model,trigger,toggle, offset) { show: function(model, trigger, toggle, offset, context) {
if (this.get('open') && this.get('actionMenu')) { if (this.get('open') && this.get('actionMenu')) {
this.hide(); this.hide();
} }
@ -28,14 +29,12 @@ export default Service.extend({
let $menu = this.set('actionMenu', $('#resource-actions')); let $menu = this.set('actionMenu', $('#resource-actions'));
let $toggle = this.set('actionToggle', $(toggle||trigger)); let $toggle = this.set('actionToggle', $(toggle||trigger));
if ( model === this.get('model') && this.get('open') ) if ( model === this.get('model') && this.get('open') ) {
{
// @@TODO@@ - 10-27-17 - need to figure out where event went
// event.preventDefault();
return; return;
} }
this.set('model', model); this.set('model', model);
this.set('context', context);
$('BODY').one('click', () => { $('BODY').one('click', () => {
// check to see if we've opened the menu // check to see if we've opened the menu
@ -85,7 +84,7 @@ export default Service.extend({
}, },
triggerAction: function(actionName) { triggerAction: function(actionName) {
this.get('model').send(actionName); this.get('model').send(actionName, this.get('context'));
}, },
activeActions: function() { activeActions: function() {

View File

@ -924,6 +924,7 @@ nodesPage:
header: Nodes header: Nodes
addNode: Add Node addNode: Add Node
table: table:
clusterName: Cluster
cpu: CPU cpu: CPU
memory: RAM memory: RAM
disk: Disk disk: Disk
@ -1091,6 +1092,8 @@ secretsPage:
linkTo: Add Secret linkTo: Add Secret
noData: You do not have any Secrets yet noData: You do not have any Secrets yet
noMatch: No Secrets match the current search noMatch: No Secrets match the current search
table:
keys: Keys
servicePage: servicePage:
header: '{type}: {name}' header: '{type}: {name}'
@ -3649,15 +3652,20 @@ newReceiver:
newSecret: newSecret:
title: title:
edit: Edit Secret
add: Add Secret add: Add Secret
edit: 'Edit Secret: {name}'
view: 'Secret: {name}'
name: name:
placeholder: e.g. api-token placeholder: e.g. api-key
scope:
label: Scope
project: Available to all namespaces in this project
namespace: Available to a single namespace
description: description:
placeholder: e.g. Secret token for the API placeholder: e.g. S3 key pair
value: values:
label: Secret Value label: Secrets Values
placeholder: The secret value addActionLabel: Add Secret Value
orchestrationWelcome: orchestrationWelcome:
simple: simple:
@ -3904,7 +3912,7 @@ siteAccess:
namespaceGroup: namespaceGroup:
label: "Namespace: {name}" label: "Namespace: {name}"
none: Standalone none: Standalone
project: Project-Level project: Any Namespace in Project
svgServiceContainer: svgServiceContainer:
sidekicks: Sidekicks sidekicks: Sidekicks
@ -4087,10 +4095,12 @@ nav:
addBalancer: Add Balancer addBalancer: Add Balancer
addDns: Add Record addDns: Add Record
addVolume: Add Volume addVolume: Add Volume
groupNone: Flat Pod List
groupService: Group by Workload
groupStack: Group by Namespace/Workload
importCompose: Import from YAML importCompose: Import from YAML
group:
none: Flat List
workload: Group by Workload
namespace: Group by Namespace
namespaceWorkload: Group by Namespace/Workload
hosts: hosts:
tab: Hosts tab: Hosts
addHost: Add Host addHost: Add Host

95
vendor/dotsfont/OFL.txt vendored Normal file
View File

@ -0,0 +1,95 @@
https://github.com/kylewelsby/dotsfont
Copyright (c) 2016, Kyle Welsby (kyle@mekyle.com)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

BIN
vendor/dotsfont/dotsfont.woff vendored Normal file

Binary file not shown.

36
vendor/dotsfont/readme.md vendored Normal file
View File

@ -0,0 +1,36 @@
DotsFont: A font made of only dots
===
This font is to enable a work-around for `-webkit-text-security` property.
![Preview](./dotsfont.png)
Usage
---
Download the font
```css
@font-face {
font-family: 'dotsfont';
src: url('dotsfont.eot');
src: url('dotsfont.eot?#iefix') format('embedded-opentype'),
url('dotsfont.woff') format('woff'),
url('dotsfont.ttf') format('truetype'),
url('dotsfont.svg#dotsfontregular') format('svg');
}
[conceal]:not(:active):not(:focus) {
font-family: 'dotsfont';
}
```
```html
<span conceal>hide me</span>
```
License
---
Copyright (c) 2016, Kyle Welsby (kyle@mekyle.com)
This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is included in this repository (OFL.txt), and is also available with a FAQ at: http://scripts.sil.org/OFL