Keyboard shortcuts

This commit is contained in:
Vincent Fiduccia 2017-04-21 11:10:58 -07:00
parent 04cce2a66b
commit df41052370
No known key found for this signature in database
GPG Key ID: 2B29AD6BB2BB2582
31 changed files with 196 additions and 113 deletions

View File

@ -7,6 +7,7 @@ export default Ember.Route.extend({
github : Ember.inject.service(),
language : Ember.inject.service('user-language'),
modal : Ember.inject.service(),
prefs : Ember.inject.service(),
settings : Ember.inject.service(),
previousParams : null,
@ -122,11 +123,16 @@ export default Ember.Route.extend({
this.set('previousLang', cur);
svc.sideLoadLanguage('none');
}
},
systemToggle() {
this.get('prefs').toggleProperty('showSystemResources');
}
},
shortcuts: {
'shift+l': 'langToggle',
'shift+s': 'systemToggle',
},
finishLogin() {

View File

@ -47,8 +47,13 @@ export default Ember.Controller.extend({
return this.get('projects.isReady') && this.get('hasHosts');
}.property('projects.isReady','hasHosts'),
forceUpgrade: function() {
return this.get('currentPath').indexOf('authenticated.settings.projects') !== 0 &&
this.get('currentPath').indexOf('authenticated.admin-tab.') !== 0;
}.property('currentPath'),
forceUpgrade: false,
checkForUpgrade: function() {
let path = this.get('currentPath');
Ember.run.next(() => {
let force = path.indexOf('authenticated.settings.projects') !== 0 &&
path.indexOf('authenticated.admin-tab.') !== 0;
this.set('forceUpgrade', force);
});
}.observes('currentPath'),
});

View File

@ -265,5 +265,28 @@ export default Ember.Route.extend(Subscribe, PromiseToCb, {
this.refresh();
console.log('Switch finished');
},
gotoA() { this.transitionTo('apps-tab.index', this.get('projects.current.id')); },
gotoC() { this.transitionTo('containers.index', this.get('projects.current.id')); },
gotoD() { this.transitionTo('dns.index', this.get('projects.current.id')); },
gotoE() { this.transitionTo('settings.projects.index' ); },
gotoH() { this.transitionTo('hosts.index', this.get('projects.current.id')); },
gotoK() { this.transitionTo('authenticated.project.api.keys', this.get('projects.current.id')); },
gotoL() { this.transitionTo('balancers.index', this.get('projects.current.id')); },
gotoS() { this.transitionTo('scaling-groups.index', this.get('projects.current.id')); },
help() { this.get('modalService').toggleModal('modal-shortcuts'); },
},
shortcuts: {
'a': 'gotoA',
'c': 'gotoC',
'd': 'gotoD',
'e': 'gotoE',
'h': 'gotoH',
'k': 'gotoK',
'l': 'gotoL',
's': 'gotoS',
'shift+/': 'help',
},
});

View File

@ -12,58 +12,7 @@
</td>
<td data-title="{{dt.image}}" class="clip top-half">
{{model.displayImage}}
{{#if (and (eq showCommand "inline") model.command)~}}
({{model.command}})
{{/if}}
</td>
{{#if showStats}}
<td data-title="{{dt.stats}}" class="spark-td">
{{#if (and statsAvailable model.cpuSpark)}}
{{#tooltip-element tagName="span" inlineBlock=false type="tooltip-basic" model=sparkCPUModel tooltipTemplate='tooltip-static' tooltipFor="sparkCPU"}}
{{spark-line
data=model.cpuSpark
width=60 height=25 max=cpuMax
prefix="containersPage.table.sparkPrefixCpu"
formatter="percent"
type="cpu"
tooltipModel=(mut sparkCPUModel)
}}
{{/tooltip-element}}
{{#tooltip-element tagName="span" inlineBlock=false type="tooltip-basic" model=sparkMemoryModel tooltipTemplate='tooltip-static' tooltipFor="sparkMemory"}}
{{spark-line
data=model.memorySpark
width=60 height=25 max=memoryMax
prefix="containersPage.table.sparkPrefixMemory"
formatter="mib"
type="memory"
tooltipModel=(mut sparkMemoryModel)
}}
{{/tooltip-element}}
{{#tooltip-element tagName="span" inlineBlock=false type="tooltip-basic" model=sparkNetworkModel tooltipTemplate='tooltip-static' tooltipFor="sparkNetwork"}}
{{spark-line
data=model.networkSpark
width=60 height=25 max=networkMax
prefix="containersPage.table.sparkPrefixNetwork"
formatter="kbps"
type="network"
tooltipModel=(mut sparkNetworkModel)
}}
{{/tooltip-element}}
{{#tooltip-element tagName="span" inlineBlock=false type="tooltip-basic" model=sparkStorageModel tooltipTemplate='tooltip-static' tooltipFor="sparkStorage"}}
{{spark-line
data=model.storageSpark
width=60 height=25 max=storageMax
prefix="containersPage.table.sparkPrefixStorage"
formatter="kbps"
type="storage"
tooltipModel=(mut sparkStorageModel)
}}
{{/tooltip-element}}
{{else}}
<span class="text-muted">{{t 'generic.na'}}</span>
{{/if}}
</td>
{{/if}}
{{#if showActions}}
<td rowspan="2" data-title="{{dt.actions}}" class="actions">
{{action-menu model=model showPrimary=showPrimaryActions}}
@ -82,3 +31,4 @@
{{t 'generic.createdDate' date=(date-from-now model.created)}}
</td>
</tr>
{{partial "error-sub-row"}}

View File

@ -17,7 +17,7 @@
groupByRef=groupByRef
headers=headers as |sortable kind inst dt|}}
{{#if (eq kind "row")}}
{{container-row model=inst dt=dt showCommand="column" bulkActions=bulkActions showHost=showHost showActions=true showPrimaryActions=false}}
{{container-row model=inst dt=dt showCommand="column" bulkActions=bulkActions showHost=showHost showActions=true showPrimaryActions=false fullColspan=sortable.fullColspan}}
{{else if (eq kind "group")}}
<tr class="group-row">
<td colspan={{sub sortable.fullColspan 2}}>

View File

@ -1,4 +1,4 @@
<tr class="main-row {{if expanded 'no-bottom'}}">
<tr class="main-row">
<td class="row-check" rowspan={{if showLabelRow 2 1}}>
{{check-box nodeId=model.id}}
</td>
@ -48,6 +48,8 @@
</tr>
{{/if}}
{{partial "error-sub-row"}}
{{#if canExpand}}
<tr class="sub-row hide">{{! make the alternating color match }}</tr>
<tr class="sub-row {{unless expanded 'hide'}}">

View File

@ -34,17 +34,18 @@ export default Ember.Component.extend({
// Find the default stack if none is passed in
if ( this.get('mode') === REUSE && !this.get('stack') ) {
let stack = all.findBy('name', this.get('defaultName'))
if ( stack ) {
if ( stack && stack.get('id') ) {
this.set('reuseStackId', stack.get('id'));
Ember.run.next(() => {
this.updateStack();
});
} else {
Ember.run.next(() => {
this.set('mode', CREATE);
this.set('showAdvanced', true);
});
}
Ember.run.next(() => {
this.updateStack();
});
}
},

View File

@ -1,4 +1,4 @@
<tr class="main-row {{if showLabelRow 'no-bottom'}}">
<tr class="main-row">
<td class="row-check" rowspan={{if showLabelRow 2 1}}>
{{check-box nodeId=model.id}}
</td>

View File

@ -0,0 +1,7 @@
import Ember from 'ember';
import ModalBase from 'ui/mixins/modal-base';
export default Ember.Component.extend(ModalBase, {
classNames: ['generic', 'medium-modal'],
settings: Ember.inject.service(),
});

View File

@ -0,0 +1,64 @@
<div class="row">
<div class="col span-6">
<table>
<tr>
<td colspan="2" class="text-bold">General Navigation</td>
</tr>
<tr>
<td width="30">A</td>
<td>"Apps" page</td>
</tr>
<tr>
<td width="30">C</td>
<td>"Containers" page</td>
</tr>
<tr>
<td width="30">D</td>
<td>"DNS" page</td>
</tr>
<tr>
<td width="30">E</td>
<td>"Manage Environments" page</td>
</tr>
<tr>
<td width="30">H</td>
<td>"Hosts" page</td>
</tr>
<tr>
<td width="30">K</td>
<td>"API Keys" page</td>
</tr>
<tr>
<td width="30">L</td>
<td>"Load Balancers" page</td>
</tr>
<tr>
<td width="30">S</td>
<td>"Scaling Groups" page</td>
</tr>
<tr>
<td width="30">?</td>
<td>You are here</td>
</tr>
</table>
</div>
<div class="col span-6">
<table>
<tr>
<td colspan="2" class="text-bold">Other Stuff</td>
</tr>
<tr>
<td width="30">G</td>
<td>Toggle View Grouping</td>
</tr>
<tr>
<td width="30">Shift+S</td>
<td>Toggle "Show System"</td>
</tr>
</table>
</div>
</div>
<div class="footer-actions">
<button {{action "cancel"}} class="btn bg-primary">{{t 'generic.closeModal'}}</button>
</div>

View File

@ -129,7 +129,7 @@
<li role="separator" class="divider"></li>
<li>{{#link-to "settings.projects"}}{{t 'nav.environment.manage'}}{{/link-to}}</li>
{{#if isCaas}}
<li>{{#link-to "user-settings"}}{{t 'nav.userSettings.link'}}{{/link-to}}</li>
<li>{{#link-to "user-preferences"}}{{t 'nav.userPreferences.link'}}{{/link-to}}</li>
{{/if}}
<li role="separator" class="divider"></li>
<li>{{#link-to "logout" class="user-logout"}}<i class="icon icon-logout"></i> {{t 'nav.user.logout'}}{{/link-to}}</li>

View File

@ -1,4 +1,4 @@
<tr class="main-row {{if (or expanded showLabelRow) 'no-bottom'}}">
<tr class="main-row">
<td class="row-check" rowspan={{if showLabelRow 2 1}}>
{{check-box nodeId=model.id}}
</td>
@ -63,12 +63,14 @@
</tr>
{{/if}}
{{partial "error-sub-row"}}
{{#if canExpand}}
<tr class="sub-row hide">{{! make the alternating color match }}</tr>
<tr class="sub-row {{unless expanded 'hide'}}">
<td colspan="2">{{! checkbox and expand}}</td>
<td colspan="{{sub fullColspan 3}}">
{{#liquid-if expanded}}
{{#if expanded}}
{{container-table
body=model.instances
stickyHeader=false
@ -78,7 +80,7 @@
subRow=true
showHost=true
}}
{{/liquid-if}}
{{/if}}
</td>
<td>{{! actions}}</td>
</tr>

View File

@ -1,22 +1,22 @@
<h2>{{t 'userSettingsPage.theme.header'}}</h2>
<h2>{{t 'userPreferencesPage.theme.header'}}</h2>
<div class="container-theme-toggle row">
<div class="col span-4 bg-default {{if (eq theme 'ui-light') 'active' ''}}" {{action 'changeTheme' 'ui-light'}}>
<i class="icon icon-sun icon-4x"></i>
<div>
{{t 'userSettingsPage.theme.light'}}
{{t 'userPreferencesPage.theme.light'}}
</div>
</div>
<div class="col span-4 bg-default {{if (eq theme 'ui-auto') 'active' ''}}" {{action 'changeTheme' 'ui-auto'}} >
<i class="icon icon-auto icon-4x"></i>
<div>
{{t 'userSettingsPage.theme.auto'}}
{{t 'userPreferencesPage.theme.auto'}}
</div>
</div>
<div class="col span-4 bg-default {{if (eq theme 'ui-dark') 'active' ''}}" {{action 'changeTheme' 'ui-dark'}} >
<i class="icon icon-moon icon-4x"></i>
<div>
{{t 'userSettingsPage.theme.dark'}}
{{t 'userPreferencesPage.theme.dark'}}
</div>
</div>
</div>
<p class="help-block text-center">{{t 'userSettingsPage.theme.autoDetail'}}</p>
<p class="help-block text-center">{{t 'userPreferencesPage.theme.autoDetail'}}</p>

View File

@ -1,18 +1,18 @@
<h2>{{t 'userSettingsPage.generalInfo.header'}}</h2>
<h2>{{t 'userPreferencesPage.generalInfo.header'}}</h2>
<div class="row">
<div class="col span-12">
<label>{{t 'userSettingsPage.generalInfo.name.label'}}</label>
<label>{{t 'userPreferencesPage.generalInfo.name.label'}}</label>
{{input-or-display editable=editing value=account.name}}
</div>
</div>
<div class="row">
<div class="col span-12">
<label>{{t (if app.isCaas 'userSettingsPage.generalInfo.email.label' 'userSettingsPage.generalInfo.username.label')}}</label>
<label>{{t (if app.isCaas 'userPreferencesPage.generalInfo.email.label' 'userPreferencesPage.generalInfo.username.label')}}</label>
{{input-or-display editable=editing value=account.login}}
</div>
</div>
<div class="row">
<div class="col span-12">
<button class="btn bg-primary" {{action 'editPassword'}}>{{t 'userSettingsPage.generalInfo.password.text'}}</button>
<button class="btn bg-primary" {{action 'editPassword'}}>{{t 'userPreferencesPage.generalInfo.password.text'}}</button>
</div>
</div>

View File

@ -1,5 +1,5 @@
<div>
{{form-command
{{container/form-command
instance=model
initialLabels=model.labels
editing=false

View File

@ -1,4 +1,4 @@
{{form-networking
{{container/form-networking
editing=false
instance=model.container
initialLabels=model.container.labels

View File

@ -1 +1,4 @@
{{form-security instance=model editing=false}}
{{container/form-security
instance=model
editing=false
}}

View File

@ -5,4 +5,15 @@ export default Ember.Route.extend({
setDefaultRoute: Ember.on('activate', function() {
this.set(`session.${C.SESSION.CONTAINER_ROUTE}`,'containers');
}),
actions: {
toggleGrouping() {
let cur = this.get('controller.mode');
this.set('controller.mode', (cur === 'list' ? 'grouped' : 'list'));
},
},
shortcuts: {
'g': 'toggleGrouping',
}
});

View File

@ -8,4 +8,17 @@ export default Ember.Route.extend({
};
});
},
actions: {
toggleGrouping() {
let choices = ['list','dot','grouped'];
let cur = this.get('controller.mode');
let neu = choices[((choices.indexOf(cur)+1) % choices.length)];
this.set('controller.mode', neu);
},
},
shortcuts: {
'g': 'toggleGrouping',
}
});

View File

@ -24,6 +24,7 @@ var queue = async.queue(getUpgradeInfo, 2);
function getUpgradeInfo(task, cb) {
var obj = task.obj;
console.log('Upgrade info', obj.model.id);
let deps = {
upgradeInfo: obj.get('catalog').fetchTemplate(task.id, true)
@ -102,10 +103,6 @@ function getUpgradeInfo(task, cb) {
obj.set('upgradeStatus', ERROR);
}
}).finally(() => {
if ( obj.isDestroyed || obj.isDestroying ) {
return;
}
cb();
});
}
@ -123,6 +120,7 @@ export default Ember.Mixin.create({
init() {
this._super(...arguments);
console.log('init', this.get('model.id'));
this.updateStatus();
},
@ -212,6 +210,9 @@ export default Ember.Mixin.create({
},
externalIdChanged: function() {
Ember.run.once(this, 'updateStatus');
Ember.run.once(() => {
console.log('externalIdChange', this.get('model.id'));
this.updateStatus();
});
}.observes('model.{externalId,state}'),
});

View File

@ -66,7 +66,6 @@ var Host = Resource.extend(StateCounts,{
var url = this.linkFor('config');
if ( url )
{
url = this.get('endpointSvc').addAuthParams(url);
Util.download(url);
}
}

View File

@ -263,6 +263,7 @@ var Service = Resource.extend(StateCounts, {
return [
'service',
'scalinggroup',
'networkdriverservice',
'storagedriverservice',
'loadbalancerservice',

View File

@ -90,8 +90,7 @@ var Stack = Resource.extend(StateCounts, {
},
exportConfig: function() {
var url = this.get('endpointSvc').addAuthParams(this.linkFor('composeConfig'));
download(url);
download(this.linkFor('composeConfig'));
},
viewCode: function() {

View File

@ -26,7 +26,7 @@ Router.map(function() {
this.route('style-guide', {path: '/style-guide'});
this.route('dummy-dev', {path: '/dev'});
this.route('user-settings', {path: '/user-settings', resetNamespace: true});
this.route('user-preferences', {path: '/user-preferences', resetNamespace: true});
// Settings
this.route('settings', {resetNamespace: true}, function() {

View File

@ -34,22 +34,6 @@ export default Ember.Service.extend({
return a.origin;
}.property('absolute'),
addAuthParams: function(url) {
var token = this.get('cookies').get(C.COOKIE.TOKEN);
if ( token )
{
url = Util.addQueryParam(url, 'token', token);
}
var projectId = this.get(`tab-session.${C.TABSESSION.PROJECT}`);
if ( projectId )
{
url = Util.addQueryParam(url, 'projectId', projectId);
}
return url;
},
swarm: function() {
var port = this.get(`settings.${C.SETTING.SWARM_PORT}`);
if ( !port ) {

View File

@ -28,15 +28,17 @@ $group-row-height : 40px;
}
> TR {
background-color: $table-bg;
border: $table-border-color solid 1px;
&:not(:last-of-type) {
border-bottom: 0;
}
> TD {
border: none;
// &:nth-child(2) {
// border-bottom: $table-border-color solid 1px;
// }
}
background-color: $table-bg;
border: $table-border-color solid 1px;
&.row-selected {
background-color: $table-bg-selected;
}

View File

@ -0,0 +1,10 @@
{{#if model.showTransitioningMessage}}
<tr class="sub-row hide">{{! make the alternating color match }}</tr>
<tr class="sub-row">
<td>{{! checkbox}}</td>
<td colspan="{{sub fullColspan 2}}" class="{{model.stateColor}} text-small">
{{model.transitioningMessage}}
</td>
<td>{{! actions}}</td>
</tr>
{{/if}}

View File

@ -1,5 +1,5 @@
<section class="header clearfix">
<h1>{{t 'userSettingsPage.header'}}</h1>
<h1>{{t 'userPreferencesPage.header'}}</h1>
</section>
<section class="row">
<div class="col span-11-of-23">

View File

@ -1150,7 +1150,7 @@ swarmPage:
body:
noData: You do not have any Services yet.
userSettingsPage:
userPreferencesPage:
header: Preferences
theme:
header: Theme
@ -3676,8 +3676,8 @@ nav:
themeLight: Light
themeAuto: Auto
themeDark: Dark
userSettings:
link: "User Settings"
userPreferences:
link: "Preferences"
##############################
# Resource Actions