mirror of https://github.com/rancher/ui.git
commit
049abae695
|
|
@ -21,6 +21,11 @@ export default Ember.Component.extend({
|
|||
click(e) {
|
||||
var tgt = Ember.$(e.target);
|
||||
var more = tgt.closest('.more-actions');
|
||||
var offsets = {
|
||||
y: -1,
|
||||
x: 2,
|
||||
mirror: true
|
||||
};
|
||||
if ( more && more.length ) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
@ -31,7 +36,7 @@ export default Ember.Component.extend({
|
|||
this.get('resourceActions').set('tooltipActions', false);
|
||||
}
|
||||
|
||||
this.get('resourceActions').show(this.get('model'), more, this.$());
|
||||
this.get('resourceActions').show(this.get('model'), more, this.$(), offsets);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import Ember from 'ember';
|
||||
import NewOrEdit from 'ui/mixins/new-or-edit';
|
||||
import C from 'ui/utils/constants';
|
||||
import StackState from 'ui/mixins/stack-memory';
|
||||
|
||||
export default Ember.Component.extend(NewOrEdit, {
|
||||
export default Ember.Component.extend(NewOrEdit, StackState, {
|
||||
intl : Ember.inject.service(),
|
||||
settings : Ember.inject.service(),
|
||||
prefs: Ember.inject.service(),
|
||||
|
||||
service : null,
|
||||
editing : null,
|
||||
|
|
@ -252,6 +254,7 @@ export default Ember.Component.extend(NewOrEdit, {
|
|||
},
|
||||
|
||||
doneSaving() {
|
||||
this._super(...arguments);
|
||||
this.send('done');
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Ember from 'ember';
|
||||
import NewOrEdit from 'ui/mixins/new-or-edit';
|
||||
import Errors from 'ui/utils/errors';
|
||||
import StackState from 'ui/mixins/stack-memory';
|
||||
|
||||
const HOSTNAME = 'externalhostname';
|
||||
const IP = 'externalip';
|
||||
|
|
@ -15,7 +16,7 @@ function modeToType(mode) {
|
|||
}
|
||||
}
|
||||
|
||||
export default Ember.Component.extend(NewOrEdit, {
|
||||
export default Ember.Component.extend(NewOrEdit, StackState, {
|
||||
intl: Ember.inject.service(),
|
||||
|
||||
record: null,
|
||||
|
|
@ -156,6 +157,7 @@ export default Ember.Component.extend(NewOrEdit, {
|
|||
},
|
||||
|
||||
doneSaving() {
|
||||
this.send('cancel');
|
||||
this._super(...arguments);
|
||||
this.send('done');
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,37 +1,31 @@
|
|||
{{~#if project~}}
|
||||
<li class="dropdown pull-right">
|
||||
<li class="dropdown pull-right ">
|
||||
{{#if (gt byCluster.length 1)}}
|
||||
<ul class="list-unstyled pr-40" style="padding: 4px;">
|
||||
<li>
|
||||
<a href="#" role="button" class="text-white dropdown-toggle clip" aria-haspopup="true" aria-expanded="false" aria-label="{{t 'nav.cluster.label'}}">
|
||||
<i class="icon icon-cluster icon-fw"></i>
|
||||
{{project.cluster.displayName}}
|
||||
<span class="sr-only">{{t 'nav.srToggleDropdown'}}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="pl-15 text-small text-muted">
|
||||
<a href="#" role="button" class="text-white dropdown-toggle clip" aria-haspopup="true" aria-expanded="false" aria-label="{{t 'nav.environment.label'}}">
|
||||
<i class="{{project.icon}} project-icon icon-fw"></i>
|
||||
{{project.displayName}}
|
||||
<span class="sr-only">{{t 'nav.srToggleDropdown'}}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<i class="icon icon-chevron-down project-chevron ml-10 text-white" style="position: absolute; right: 20px; top: 20px;"></i>
|
||||
</ul>
|
||||
{{else}}
|
||||
<span class="environment-dropdown">
|
||||
<i class="{{project.icon}} project-icon icon-fw"></i>
|
||||
<a href="#" role="button" class="dropdown-toggle clip" aria-haspopup="true" aria-expanded="false" aria-label="{{t 'nav.environment.label'}}">
|
||||
<div class="cluster-dropdown dropdown-toggle" aria-haspopup="true" aria-expanded="false" aria-label="{{t 'nav.cluster.label'}}" data-toggle="environment">
|
||||
<span class="text-white clip" >
|
||||
<i class="icon icon-cluster icon-fw"></i>
|
||||
{{project.cluster.displayName}}
|
||||
<span class="sr-only">{{t 'nav.srToggleDropdown'}}</span>
|
||||
</span>
|
||||
<span class="block pl-15 text-small text-muted">
|
||||
<i class="{{project.icon}} project-icon icon-fw"></i>
|
||||
{{project.displayName}}
|
||||
<span class="sr-only">{{t 'nav.srToggleDropdown'}}</span>
|
||||
</a>
|
||||
</span>
|
||||
<i class="icon icon-chevron-down project-chevron ml-10 text-white" style="position: absolute; right: 20px; top: 20px;"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<span class="environment-dropdown dropdown-toggle" aria-role="button" aria-haspopup="true" aria-expanded="false" aria-label="{{t 'nav.environment.label'}}" data-toggle="environment">
|
||||
<i class="{{project.icon}} project-icon icon-fw"></i>
|
||||
<span class="text-white clip" >
|
||||
{{project.displayName}}
|
||||
<span class="sr-only">{{t 'nav.srToggleDropdown'}}</span>
|
||||
</span>
|
||||
<i class="icon icon-chevron-down project-chevron"></i>
|
||||
</span>
|
||||
{{/if}}
|
||||
|
||||
<ul class="dropdown-menu project-menu" role="menu" data-dropdown-id="enviroment">
|
||||
<ul class="dropdown-menu dropdown-menu-right project-menu" role="menu" data-dropdown-id="environment">
|
||||
{{#if (gt byCluster.length 1)}}
|
||||
{{#each byCluster as |entry|}}
|
||||
<li class="{{if entry.system.active 'active selected'}}">
|
||||
|
|
|
|||
|
|
@ -48,6 +48,14 @@ export default Ember.Component.extend(HoverDropdown, {
|
|||
},
|
||||
},
|
||||
|
||||
willRender() {
|
||||
if (Ember.$('BODY').hasClass('touch') && Ember.$('header > nav').hasClass('nav-open')) {
|
||||
Ember.run.later(() => {
|
||||
Ember.$('header > nav').removeClass('nav-open');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.get('intl.locale');
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@
|
|||
|
||||
<ul class="nav-user dropdown">
|
||||
<li>
|
||||
<a class="btn dropdown-toggle" style="height: 51px; padding-top: 8px;" role="button" aria-haspopup="true" aria-expanded="false" aria-label={{t 'nav.user.label' username=session.user}}>
|
||||
<a class="btn dropdown-toggle" style="height: 51px; padding-top: 8px;" role="button" aria-haspopup="true" aria-expanded="false" aria-label="{{t 'nav.user.label' username=session.user}}" data-toggle="header-user-menu" >
|
||||
{{#if accessEnabled}}
|
||||
{{identity-avatar link=false identity=access.identity}}
|
||||
{{else}}
|
||||
|
|
|
|||
|
|
@ -452,7 +452,6 @@ export default Ember.Component.extend(Sortable, StickyHeader, {
|
|||
}
|
||||
|
||||
this.set('prevNode', node);
|
||||
e.stopPropagation();
|
||||
},
|
||||
|
||||
nodesBetween(a,b) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,13 @@ let timerObj = null;
|
|||
let dropdown = null;
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
willRender(){
|
||||
if (Ember.$('BODY').hasClass('touch')) {
|
||||
Ember.run.later(() => {
|
||||
this.clearHeaderMenus();
|
||||
}, DROPDOWNCLOSETIMER);
|
||||
}
|
||||
},
|
||||
didInsertElement: function() {
|
||||
let $body = Ember.$('BODY');
|
||||
|
||||
|
|
@ -24,7 +31,7 @@ export default Ember.Mixin.create({
|
|||
}
|
||||
});
|
||||
|
||||
this.$('#environment-dropdown').on('touchstart', (e) => {
|
||||
this.$('[data-toggle="header-user-menu"]').on('touchstart', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.touchHandler(e);
|
||||
|
|
@ -111,7 +118,20 @@ export default Ember.Mixin.create({
|
|||
},
|
||||
|
||||
enterHandler(e) {
|
||||
let anchor = Ember.$(e.currentTarget).find('a:first');
|
||||
let anchor = Ember.$(e.currentTarget).find('.dropdown-toggle');
|
||||
let dataTarget = anchor.data('toggle') ? anchor.data('toggle') : null;
|
||||
let findTarget = dataTarget ? `ul[data-dropdown-id ="${dataTarget}"]` : 'ul';
|
||||
let offset = null;
|
||||
|
||||
if (anchor.data('offset-x') || anchor.data('offset-y')) {
|
||||
offset = {};
|
||||
if (anchor.data('offset-x')) {
|
||||
offset.x = anchor.data('offset-x');
|
||||
}
|
||||
if (anchor.data('offset-y')) {
|
||||
offset.y = anchor.data('offset-y');
|
||||
}
|
||||
}
|
||||
|
||||
Ember.run.cancel(timerObj);
|
||||
|
||||
|
|
@ -126,15 +146,15 @@ export default Ember.Mixin.create({
|
|||
dropdown = Ember.$(e.currentTarget).find('ul');
|
||||
|
||||
if (dropdown) {
|
||||
this.showMenu(anchor, dropdown);
|
||||
this.showMenu(anchor, dropdown, offset);
|
||||
}
|
||||
}
|
||||
} else { // no dropdown open
|
||||
|
||||
dropdown = Ember.$(e.currentTarget).find('ul');
|
||||
dropdown = Ember.$(e.currentTarget).find(findTarget);
|
||||
|
||||
if (dropdown) {
|
||||
this.showMenu(anchor, dropdown);
|
||||
this.showMenu(anchor, dropdown, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -224,15 +244,10 @@ export default Ember.Mixin.create({
|
|||
}
|
||||
},
|
||||
|
||||
showMenu: function(el, drpd) {
|
||||
let body = Ember.$('BODY');
|
||||
if (body.hasClass('touch')) {
|
||||
Ember.$('BODY').addClass('nav-dropdown-open');
|
||||
}
|
||||
|
||||
showMenu: function(el, drpd, offset) {
|
||||
drpd.addClass('invisible');
|
||||
drpd.addClass('block');
|
||||
positionDropdown(drpd, el, drpd.hasClass('dropdown-menu-right'));
|
||||
positionDropdown(drpd, el, drpd.hasClass('dropdown-menu-right'), offset);
|
||||
drpd.removeClass('invisible');
|
||||
|
||||
if (el.attr('aria-expanded')) {
|
||||
|
|
@ -241,10 +256,6 @@ export default Ember.Mixin.create({
|
|||
},
|
||||
|
||||
clearHeaderMenus: function() {
|
||||
let body = Ember.$('BODY');
|
||||
if (body.hasClass('touch')) {
|
||||
Ember.$('BODY').removeClass('nav-dropdown-open');
|
||||
}
|
||||
const navbar = Ember.$(PARENT);
|
||||
|
||||
dropdown = null;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
prefs: Ember.inject.service(),
|
||||
stack: null,
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.setStack();
|
||||
},
|
||||
setStack() {
|
||||
let stackId = this.get(`prefs.${C.PREFS.LAST_STACK}`) || null;
|
||||
if (stackId) {
|
||||
this.set('stack', this.get('store').getById('stack', stackId));
|
||||
}
|
||||
},
|
||||
doneSaving() {
|
||||
if (this.get('stack')) {
|
||||
this.set(`prefs.${C.PREFS.LAST_STACK}`, this.get('stack.id'));
|
||||
}
|
||||
this.send('done');
|
||||
},
|
||||
});
|
||||
|
|
@ -2,6 +2,7 @@ import Ember from 'ember';
|
|||
|
||||
export default Ember.Controller.extend({
|
||||
application: Ember.inject.controller(),
|
||||
projects: Ember.inject.service(),
|
||||
|
||||
service: Ember.computed.alias('model.service'),
|
||||
rules: Ember.computed.alias('service.lbConfig.portRules'),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ export default Ember.Route.extend({
|
|||
if (model.get('service.initPorts')) {
|
||||
model.get('service').initPorts();
|
||||
}
|
||||
if (model.get('service.stackId')) {
|
||||
model.set('stack', this.get('store').getById('stack', model.get('service.stackId')));
|
||||
}
|
||||
},
|
||||
|
||||
getServiceLogs(serviceId) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,28 @@
|
|||
|
||||
<section>
|
||||
<div class="row banner bg-info basics">
|
||||
{{#if service.externalIpAddresses}}
|
||||
<div class="inline-block">
|
||||
<label class="text-muted ml-15">{{t 'servicePage.external.externalIp' count=service.externalIpAddresses.length}}</label>
|
||||
{{join-array service.externalIpAddresses}}
|
||||
</div>
|
||||
{{else if service.hostname}}
|
||||
<div class="inline-block">
|
||||
<label class="text-muted">{{t 'servicePage.external.externalHostname'}} </label> {{service.hostname}}
|
||||
</div>
|
||||
{{else if service.selector}}
|
||||
<div class="inline-block">
|
||||
<label class="text-muted">{{t 'servicePage.selector.label'}} </label> {{service.selector}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if service.hasImage}}
|
||||
<div class="inline-block">
|
||||
<label class="acc-label p-0">{{t 'servicePage.multistat.image'}}</label>
|
||||
{{fixedLaunchConfig.image}} {{copy-to-clipboard clipboardText=fixedLaunchConfig.image size="small"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if fixedLaunchConfig.memoryReservation}}
|
||||
<div class="inline-block">
|
||||
<label class="acc-label p-0">{{t 'containersPage.containerPage.infoMultiStats.memoryReservation.labelText'}}</label>
|
||||
|
|
@ -57,27 +79,14 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if service.hasImage}}
|
||||
|
||||
{{#if model.stack}}
|
||||
<div class="inline-block">
|
||||
<label class="acc-label p-0">{{t 'servicePage.multistat.image'}}</label>
|
||||
{{fixedLaunchConfig.image}} {{copy-to-clipboard clipboardText=fixedLaunchConfig.image size="small"}}
|
||||
<label class="acc-label p-0">{{t 'generic.stack'}}:</label>
|
||||
{{#link-to "stack" projects.current.id model.stack.id}}{{model.stack.displayName}}{{/link-to}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if service.externalIpAddresses}}
|
||||
<div class="inline-block">
|
||||
<label class="text-muted ml-15">{{t 'servicePage.external.externalIp' count=service.externalIpAddresses.length}}</label>
|
||||
{{join-array service.externalIpAddresses}}
|
||||
</div>
|
||||
{{else if service.hostname}}
|
||||
<div class="inline-block">
|
||||
<label class="text-muted">{{t 'servicePage.external.externalHostname'}} </label> {{service.hostname}}
|
||||
</div>
|
||||
{{else if service.selector}}
|
||||
<div class="inline-block">
|
||||
<label class="text-muted">{{t 'servicePage.selector.label'}} </label> {{service.selector}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,16 @@ export default Ember.Service.extend({
|
|||
actionToggle : null,
|
||||
actionMenu : null,
|
||||
|
||||
show: function(model,trigger,toggle) {
|
||||
// offset is a parameter that we need to open in our api, it allows us to pass a
|
||||
// positial x/y offset to the position-calculator library
|
||||
// http://tlindig.github.io/position-calculator/
|
||||
// itemOffset: {
|
||||
// y: -1,
|
||||
// x: 2,
|
||||
// mirror: true
|
||||
// },
|
||||
|
||||
show: function(model,trigger,toggle, offset) {
|
||||
if (this.get('open') && this.get('actionMenu')) {
|
||||
this.hide();
|
||||
}
|
||||
|
|
@ -52,7 +61,7 @@ export default Ember.Service.extend({
|
|||
this.set('open',true);
|
||||
// Delay ensure it works in firefox
|
||||
Ember.run.next(() => {
|
||||
positionDropdown($menu, trigger, true);
|
||||
positionDropdown($menu, trigger, true, offset);
|
||||
$('#resource-actions-first')[0].focus();
|
||||
$menu.css('visibility','visible');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import Ember from 'ember';
|
||||
import { headersWithHost as containerHeaders } from 'ui/components/container-table/component';
|
||||
import { searchFields as containerSearchFields } from 'ui/components/container-dots/component';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
prefs: Ember.inject.service(),
|
||||
|
|
@ -99,11 +100,68 @@ export default Ember.Controller.extend({
|
|||
name: 'scale',
|
||||
sort: ['scale:desc','isGlobalScale:desc','displayName'],
|
||||
searchField: null,
|
||||
width: 100,
|
||||
translationKey: 'stacksPage.table.scale',
|
||||
classNames: 'text-center',
|
||||
width: 100
|
||||
},
|
||||
],
|
||||
storageSortBy: 'state',
|
||||
storageHeaders: [
|
||||
{
|
||||
name: 'expand',
|
||||
sort: false,
|
||||
searchField: null,
|
||||
width: 30
|
||||
},
|
||||
{
|
||||
name: 'state',
|
||||
sort: ['stateSort','displayName'],
|
||||
searchField: 'displayState',
|
||||
translationKey: 'generic.state',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
sort: ['displayName','id'],
|
||||
searchField: 'displayName',
|
||||
translationKey: 'generic.name',
|
||||
},
|
||||
{
|
||||
name: 'mounts',
|
||||
sort: ['mounts.length','displayName','id'],
|
||||
translationKey: 'volumesPage.mounts.label',
|
||||
searchField: null,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
name: 'scope',
|
||||
sort: ['scope'],
|
||||
translationKey: 'volumesPage.scope.label',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
name: 'driver',
|
||||
sort: ['driver','displayName','id'],
|
||||
searchField: 'displayType',
|
||||
translationKey: 'volumesPage.driver.label',
|
||||
width: 150
|
||||
},
|
||||
],
|
||||
|
||||
extraSearchFields: ['id:prefix','displayIp:ip'],
|
||||
extraSearchSubFields: containerSearchFields,
|
||||
rows: Ember.computed('instances.[]', 'scalingGroups.[]', function() {
|
||||
let out = [];
|
||||
let containers = this.get('instances');
|
||||
let scalinggroups = this.get('scalingGroups');
|
||||
return out.concat(containers, scalinggroups);
|
||||
}),
|
||||
|
||||
containerStats: Ember.computed('instances.[]', 'scalingGroups.[]', function() {
|
||||
let containerLength = this.get('instances.length') || 0;
|
||||
let scalingGroupsLength = this.get('scalingGroups.length') || 0;
|
||||
return containerLength += scalingGroupsLength;
|
||||
}),
|
||||
|
||||
getType(ownType, real=true) {
|
||||
return this.get('model.services').filter((service) => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,27 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
parentRoute: 'stack',
|
||||
|
||||
resetController: function (controller, isExisting/*, transition*/) {
|
||||
if (isExisting)
|
||||
{
|
||||
controller.set('showAddtlInfo', false);
|
||||
}
|
||||
},
|
||||
|
||||
model(/* params, transition */) {
|
||||
let model = this.modelFor(this.get('parentRoute'));
|
||||
|
||||
return this.get('store').findAll('volume').then((volumes) => {
|
||||
return this.get('store').findAll('volumetemplate').then((volumeTemplates) => {
|
||||
|
||||
let volOut = [];
|
||||
|
||||
model.volumes = volOut.concat(volumes.filterBy('stackId', model.get('stack.id')), volumeTemplates.filterBy('stackId', model.get('stack.id')));
|
||||
|
||||
return model;
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,67 +1,63 @@
|
|||
{{stack-header model=model.stack all=model.all.stacks}}
|
||||
|
||||
{{#if model.stack.description}}
|
||||
{{banner-message color='bg-secondary mb-0 mt-10' message=model.stack.description}}
|
||||
{{/if}}
|
||||
|
||||
<section>
|
||||
{{#accordion-list as |al expandFn| }}
|
||||
{{#accordion-list-item
|
||||
title=(t 'stackPage.containers.header')
|
||||
detail=(t 'stackPage.containers.detail')
|
||||
status=(t 'stackPage.containers.status' count=instances.length)
|
||||
statusClass=(if instances.length 'bg-success' 'text-muted')
|
||||
statusClass=(if containerStats 'bg-success' 'text-muted')
|
||||
expandOnInit=true
|
||||
expandAll=al.expandAll
|
||||
expand=(action expandFn)
|
||||
componentName='container-table'
|
||||
as | parent |
|
||||
}}
|
||||
{{component parent.intent
|
||||
body=instances
|
||||
search=true
|
||||
sortBy=sortBy
|
||||
stickyHeader=false
|
||||
bulkActions=true
|
||||
showHost=false
|
||||
}}
|
||||
{{/accordion-list-item}}
|
||||
|
||||
{{#accordion-list-item
|
||||
title=(t 'stackPage.scalingGroups.header')
|
||||
detail=(t 'stackPage.scalingGroups.detail')
|
||||
status=(t 'stackPage.scalingGroups.status' count=scalingGroups.length)
|
||||
statusClass=(if scalingGroups.length 'bg-success' 'text-muted')
|
||||
expandAll=al.expandAll
|
||||
expand=(action expandFn)
|
||||
componentName='sortable-table'
|
||||
as | parent |
|
||||
}}
|
||||
{{#component parent.intent
|
||||
body=scalingGroups
|
||||
bulkActions=true
|
||||
{{#sortable-table
|
||||
tableClassNames="double-rows"
|
||||
classNames="grid sortable-table"
|
||||
fullRows=true
|
||||
headers=sgHeaders
|
||||
pagingLabel="pagination.service"
|
||||
body=rows
|
||||
searchText=searchText
|
||||
sortBy=sortBy
|
||||
stickyHeader=false
|
||||
subHeaders=containerHeaders
|
||||
bulkActions=true
|
||||
subRows=true
|
||||
fullRows=true
|
||||
pagingLabel="pagination.containerService"
|
||||
subSearchField="instances"
|
||||
as |sortable kind serv dt|}}
|
||||
extraSearchFields=extraSearchFields
|
||||
extraSearchSubFields=extraSearchSubFields
|
||||
headers=sgHeaders as |sortable kind inst dt|}}
|
||||
{{#if (eq kind "row")}}
|
||||
{{service-row
|
||||
canExpand=true
|
||||
expanded=(array-includes expandedInstances serv.id)
|
||||
fullColspan=sortable.fullColspan
|
||||
model=serv
|
||||
searchText=searchText
|
||||
showInstanceCount=false
|
||||
subMatches=sortable.subMatches
|
||||
toggle=(action "toggleExpand" serv.id)
|
||||
dt=dt
|
||||
}}
|
||||
{{#if (eq inst.baseType "instance")}}
|
||||
{{container-row
|
||||
model=inst
|
||||
dt=dt
|
||||
showHost=true
|
||||
expandPlaceholder=true
|
||||
scalePlaceholder=true
|
||||
fullColspan=sortable.fullColspan
|
||||
}}
|
||||
{{else}}
|
||||
{{service-row
|
||||
model=inst
|
||||
toggle=(action "toggleExpand" inst.id)
|
||||
expanded=(array-includes expandedInstances inst.id)
|
||||
searchText=searchText
|
||||
subMatches=sortable.subMatches
|
||||
fullColspan=sortable.fullColspan
|
||||
dt=dt
|
||||
}}
|
||||
{{/if}}
|
||||
{{else if (eq kind "nomatch")}}
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'containersPage.table.noMatch'}}</td></tr>
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'containersPage.table.noMatch'}}</td></tr>
|
||||
{{else if (eq kind "norows")}}
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'containersPage.table.noData'}}</td></tr>
|
||||
{{/if}}
|
||||
{{/component}}
|
||||
{{/sortable-table}}
|
||||
{{/accordion-list-item}}
|
||||
|
||||
{{#accordion-list-item
|
||||
|
|
@ -144,5 +140,48 @@
|
|||
{{/if}}
|
||||
{{/component}}
|
||||
{{/accordion-list-item}}
|
||||
|
||||
{{#accordion-list-item
|
||||
title=(t 'stackPage.volumesTab.header')
|
||||
detail=(t 'stackPage.volumesTab.detail')
|
||||
status=(t 'pagination.volume' pages=1 count=(or model.volumes.length 0))
|
||||
statusClass=(if model.volumes.length 'bg-success' 'text-muted')
|
||||
expandAll=al.expandAll
|
||||
expand=(action expandFn)
|
||||
componentName='sortable-table'
|
||||
as | parent |
|
||||
}}
|
||||
{{#component parent.intent
|
||||
body=model.volumes
|
||||
bulkActions=true
|
||||
classNames="grid sortable-table"
|
||||
fullRows=true
|
||||
isVisible=parent.expanded
|
||||
pagingLabel="pagination.volume"
|
||||
searchText=searchText
|
||||
sortBy=sortBy
|
||||
stickyHeader=false
|
||||
subHeaders=containerHeaders
|
||||
subRows=true
|
||||
subSearchField="instances"
|
||||
headers=storageHeaders as |sortable kind mount dt|
|
||||
}}
|
||||
{{#if (eq kind "row")}}
|
||||
{{volume-row
|
||||
model=mount
|
||||
toggle=(action "toggleExpand" mount.id)
|
||||
expanded=(array-includes expandedInstances mount.id)
|
||||
searchText=searchText
|
||||
subMatches=sortable.subMatches
|
||||
fullColspan=sortable.fullColspan
|
||||
dt=dt
|
||||
}}
|
||||
{{else if (eq kind "nomatch")}}
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'stackPage.volumesTab.table.noMatch'}}</td></tr>
|
||||
{{else if (eq kind "norows")}}
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'stackPage.volumesTab.table.noData'}}</td></tr>
|
||||
{{/if}}
|
||||
{{/component}}
|
||||
{{/accordion-list-item}}
|
||||
{{/accordion-list}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -42,8 +42,15 @@ $user-btn : darken($header, 10%) !default;
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
.cluster-dropdown {
|
||||
padding: 4px 40px 4px 4px;
|
||||
@extend .clip;
|
||||
@extend .hand;
|
||||
}
|
||||
.environment-dropdown {
|
||||
padding: 0 10px;
|
||||
@extend .clip;
|
||||
@extend .hand;
|
||||
|
||||
a {
|
||||
color: white;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,6 @@
|
|||
//nav
|
||||
.responsive-nav {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background-color: $header;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +201,9 @@
|
|||
}
|
||||
/* Class added via JS when toggled open */
|
||||
.nav-open {
|
||||
overflow: visible;
|
||||
.nav-list {
|
||||
max-height: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
/* NAV LIST*/
|
||||
|
|
@ -213,6 +214,13 @@
|
|||
border-bottom-right-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
width: 100%;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
-webkit-transition: max-height .5s;
|
||||
-moz-transition: max-height .5s;
|
||||
-ms-transition: max-height .5s;
|
||||
-o-transition: max-height .5s;
|
||||
transition: max-height .5s;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -284,7 +292,7 @@
|
|||
background-size: 75%;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.page-header NAV .dropdown-menu {
|
||||
.page-header NAV .nav-list .dropdown-menu {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
max-width: 100%;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
.dot {
|
||||
float: left;
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export function resizeDropdown(event) {
|
|||
return positionDropdown($item, target, right);
|
||||
}
|
||||
|
||||
export function positionDropdown(menu, trigger, right) {
|
||||
export function positionDropdown(menu, trigger, right, offset) {
|
||||
// https://github.com/twbs/bootstrap/issues/10756#issuecomment-41041800
|
||||
var direction = (right === true ? 'right' : 'left');
|
||||
var $menu = $(menu);
|
||||
|
|
@ -17,19 +17,20 @@ export function positionDropdown(menu, trigger, right) {
|
|||
left: 0
|
||||
});
|
||||
|
||||
// calculate new position
|
||||
var calculator = new $.PositionCalculator({
|
||||
let pco = {
|
||||
item: $menu,
|
||||
target: trigger,
|
||||
itemAt: 'top ' + direction,
|
||||
itemOffset: {
|
||||
y: 3,
|
||||
x: 0,
|
||||
mirror: true
|
||||
},
|
||||
targetAt: 'bottom ' + direction,
|
||||
flip: 'both'
|
||||
});
|
||||
};
|
||||
|
||||
if (offset) {
|
||||
pco.itemOffset = offset;
|
||||
}
|
||||
|
||||
// calculate new position
|
||||
var calculator = new $.PositionCalculator(pco);
|
||||
var posResult = calculator.calculate();
|
||||
|
||||
// set new position
|
||||
|
|
|
|||
|
|
@ -7,17 +7,19 @@ export default Ember.Route.extend({
|
|||
},
|
||||
},
|
||||
model: function(params) {
|
||||
|
||||
let out = Ember.Object.create({
|
||||
volume: this.get('store').getById(params.type, params.volume_id)
|
||||
});
|
||||
|
||||
if (out.volume.stackId) {
|
||||
out.stack = this.controllerFor('volume').set('stack', this.get('store').getById('stack', out.volume.stackId));
|
||||
out.stack = this.get('store').getById('stack', out.volume.stackId);
|
||||
}
|
||||
|
||||
if (out.volume.hostId) {
|
||||
out.host = this.controllerFor('volume').set('host', this.get('store').getById('host', out.volume.hostId));
|
||||
out.host = this.get('store').getById('host', out.volume.hostId);
|
||||
}
|
||||
|
||||
return out;
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -922,7 +922,7 @@ stackPage:
|
|||
backLink: Back to all stacks
|
||||
containers:
|
||||
header: Containers
|
||||
detail: Standalone Containers that are not part of a Service or Load Balancer
|
||||
detail: Standalone Containers and Services contained in this stack
|
||||
status: |
|
||||
{count, plural,
|
||||
=0 {No containers}
|
||||
|
|
@ -956,6 +956,15 @@ stackPage:
|
|||
=1 {# container}
|
||||
other {# containers}
|
||||
}
|
||||
volumesTab:
|
||||
header: Volumes
|
||||
detail: 'These properties show the volumes attached to your container.'
|
||||
table:
|
||||
path: Mount Point
|
||||
shared: Shared With
|
||||
writable: Writable
|
||||
noData: This stack has no volumes mounted
|
||||
noMatch: No volumes match the current search
|
||||
|
||||
newStack:
|
||||
header: Import Compose.yml
|
||||
|
|
|
|||
Loading…
Reference in New Issue