More bugs & i18n (#654)

* i18n, root disk size

* bugs, i18n

* Move VM support to per-environment
This commit is contained in:
Vincent Fiduccia 2016-05-12 16:00:43 -07:00
parent 9532ae9710
commit bbd78f8f8b
40 changed files with 253 additions and 176 deletions

View File

@ -215,11 +215,11 @@ rancher/server:${version}`;
hostRegistrationHelpText: Ember.computed('model.createScript.clusterSize', function() {
const intl = this.get('intl');
let out = intl.findTranslationByKey('haPage.haDisabled.haConfigScript.form.hostRegistrationHelpText.multiCluster');
let out = intl.findTranslationByKey('haPage.haDisabled.haConfigScript.form.hostRegistration.helpText.multiCluster');
out = intl.formatHtmlMessage(out, {clusterSize: this.get('model.createScript.clusterSize')});
if (this.get('model.createScript.clusterSize') === 1) {
out = intl.findTranslationByKey('haPage.haDisabled.haConfigScript.form.hostRegistrationHelpText.singleCluster');
out = intl.findTranslationByKey('haPage.haDisabled.haConfigScript.form.hostRegistration.helpText.singleCluster');
out = intl.formatHtmlMessage(out);
}
return out;

View File

@ -130,25 +130,25 @@
<input type="hidden" name="CSRF" value="{{csrf}}"/>
<div class="row form-group">
<div class="col-sm-6 col-md-2 form-control-static">
<label>{{t 'haPage.haDisabled.haConfigScript.form.clusterSize'}}</label>
<label>{{t 'haPage.haDisabled.haConfigScript.form.clusterSize.labelText'}}</label>
</div>
<div class="col-sm-6 col-md-10">
<div class="radio">
<label>
{{radio-button selection=model.createScript.clusterSize value=1}}
{{format-html-message 'haPage.haDisabled.haConfigScript.form.radio1'}}
{{format-html-message 'haPage.haDisabled.haConfigScript.form.clusterSize.radio1'}}
</label>
</div>
<div class="radio">
<label>
{{radio-button selection=model.createScript.clusterSize value=3}}
{{format-html-message 'haPage.haDisabled.haConfigScript.form.radio2'}}
{{format-html-message 'haPage.haDisabled.haConfigScript.form.clusterSize.radio2'}}
</label>
</div>
<div class="radio">
<label>
{{radio-button selection=model.createScript.clusterSize value=5}}
{{format-html-message 'haPage.haDisabled.haConfigScript.form.radio3'}}
{{format-html-message 'haPage.haDisabled.haConfigScript.form.clusterSize.radio3'}}
</label>
</div>
</div>

View File

@ -8,7 +8,6 @@ export default Ember.Route.extend({
return this.get('settings').load([
C.SETTING.API_HOST,
C.SETTING.CATALOG_URL,
C.SETTING.VM_ENABLED,
]);
},
@ -19,7 +18,6 @@ export default Ember.Route.extend({
return Ember.Object.create({
host : settings.get(C.SETTING.API_HOST),
catalog : settings.get(C.SETTING.CATALOG_URL),
vm : settings.get(C.SETTING.VM_ENABLED) || false,
machineDrivers : drivers,
});
});

View File

@ -10,11 +10,6 @@
{{catalog-settings catalog=model.catalog}}
</section>
<section class="well">
{{virtual-machine-settings virtualMachine=model.vm}}
</section>
<section class="well">
{{dynamic-driver-settings drivers=model.machineDrivers}}
</section>

View File

@ -75,7 +75,6 @@ export default Ember.Route.extend({
error(err) {
this.controllerFor('application').set('error',err);
this.set('app.showArticles',false);
this.transitionTo('failWhale');
console.log('Application Error', (err ? err.stack : undefined));
},

View File

@ -38,13 +38,13 @@
{{#advanced-section}}
<section class="header">
<h1>{{t 'apiPage.advanced.header'}}</h1>
<h1>{{t 'apiPage.account.header'}}</h1>
<button class="btn btn-sm btn-primary" {{action "newApikey" "account"}}>{{t 'apiPage.advanced.buttonText'}}</button>
<button class="btn btn-sm btn-primary" {{action "newApikey" "account"}}>{{t 'apiPage.account.buttonText'}}</button>
</section>
<section class="well">
<p>{{t 'apiPage.advanced.content.paragraph1'}} {{#if access.identity.name}}(<code>{{access.identity.displayName}}</code>){{/if}} {{t 'apiPage.advanced.content.paragraph2'}}</p>
<p>{{t 'apiPage.account.content.paragraph1'}} {{#if access.identity.name}}(<code>{{access.identity.displayName}}</code>){{/if}} {{t 'apiPage.account.content.paragraph2'}}</p>
<label>{{t 'apiPage.labelText'}}</label>
<code><a href="{{endpointWithAuth}}" target="_blank">{{displayEndpoint}}</a></code>
{{copy-to-clipboard clipboardText=endpointWithAuth size="sm"}}
@ -63,7 +63,7 @@
{{#each accountArranged as |key|}}
{{apikey-row model=key}}
{{else}}
<tr><td colspan="6" class="text-center text-muted">{{t 'apiPage.advanced.table.noData'}}</td></tr>
<tr><td colspan="6" class="text-center text-muted">{{t 'apiPage.account.table.noData'}}</td></tr>
{{/each}}
</tbody>
</table>

View File

@ -2,7 +2,8 @@ import Ember from 'ember';
export default Ember.Component.extend({
settings: Ember.inject.service(),
hasVm: Ember.computed.alias('settings.hasVm'),
projects: Ember.inject.service(),
hasVm: Ember.computed.alias('projects.current.virtualMachine'),
actions: {
changeStack(stack) {

View File

@ -76,7 +76,7 @@ export default Ember.Component.extend(ManageLabels, {
var sslPorts = this.get('listenersArray')
.filterBy('ssl',true)
.map((listener) => { return parseIpPort(listener.get('host'),'http'); })
.filterBy('port')
.filter((obj) => { return obj && obj.port; })
.map((obj) => { return obj.port; })
.sort().uniq();

View File

@ -66,7 +66,7 @@
{{input type="text" classNames="form-control lb-listener-target-port input-sm" min="1" max="65535" step="1" value=listener.container placeholder=(t 'formBalancerListeners.container.placeholder')}}
</td>
<td>&nbsp;</td>
<td data-title="{{t 'formBalancerListeners.table.listen'}}:">
<td data-title="{{t 'formBalancerListeners.table.listener'}}:">
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown" aria-expanded="false">{{t (if listener.isPublic 'formBalancerListeners.listen.public' 'formBalancerListeners.listen.internal')}} <i class="icon icon-chevron-down"></i></button>
<ul class="dropdown-menu" role="menu">

View File

@ -50,7 +50,7 @@
<div class="hidden-xs hidden-sm col-md-2 form-label">&nbsp;</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="radio small">
<label>{{radio-button selection=terminal value="terminal"}} {{format-html-message 'formCommand.console.terminal'}}></label>
<label>{{radio-button selection=terminal value="terminal"}} {{format-html-message 'formCommand.console.terminal'}}</label>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">

View File

@ -63,7 +63,6 @@ export default Ember.Component.extend({
this.get('instance.disks').unshiftObject({
name: 'root',
root: true,
size: 80,
driver: this.get('availableDrivers').objectAt(0)
});
},

View File

@ -1,16 +1,16 @@
<div class="row form-group">
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">Health Check</label>
<label class="form-control-static">{{t 'formHealthCheck.label'}}</label>
</div>
<div class="col-sm-12 col-md-9">
<div class="radio input pull-left r-mr20">
<label class="form-control-static">{{radio-button selection=checkType value="none"}} None</label>
<label class="form-control-static">{{radio-button selection=checkType value="none"}} {{t 'formHealthCheck.checkType.none'}}</label>
</div>
<div class="radio input pull-left r-mr20">
<label class="form-control-static">{{radio-button selection=checkType value="tcp"}} TCP Connection Opens</label>
<label class="form-control-static">{{radio-button selection=checkType value="tcp"}} {{t 'formHealthCheck.checkType.tcp'}}</label>
</div>
<div class="radio input pull-left">
<label class="form-control-static">{{radio-button selection=checkType value="http"}} HTTP Responds 2xx/3xx</label>
<label class="form-control-static">{{radio-button selection=checkType value="http"}} {{t 'formHealthCheck.checkType.http'}}</label>
</div>
</div>
</div>
@ -19,7 +19,7 @@
{{#if (eq checkType "http")}}
<div class="row form-group">
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">HTTP Request*</label>
<label class="form-control-static">{{t 'formHealthCheck.request.label'}}*</label>
</div>
<div class="col-sm-12 col-md-8">
<div class="input-group">
@ -27,7 +27,7 @@
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">{{uriMethod}} <i class="icon icon-chevron-down"></i></button>
<ul class="dropdown-menu" role="menu">
<li role="presentation" class="dropdown-header">
Select A HTTP Method:
{{t 'formHealthCheck.method.prompt'}}
</li>
{{#each uriMethodChoices as |choice|}}
<li {{action "chooseUriMethod" choice}}>
@ -37,13 +37,13 @@
</ul>
</div>
{{input type="text" classNames="form-control" placeholder="Request Path e.g. /healthcheck" value=uriPath}}
{{input type="text" classNames="form-control" placeholder=(t 'formHealthCheck.path.placeholder') value=uriPath}}
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">{{uriVersion}} <i class="icon icon-chevron-down"></i></button>
<ul class="dropdown-menu" role="menu">
<li role="presentation" class="dropdown-header">
Select A HTTP Version:
{{t 'formHealthCheck.version.prompt'}}
</li>
{{#each uriVersionChoices as |choice|}}
<li {{action "chooseUriVersion" choice}}>
@ -58,10 +58,10 @@
{{#if showUriHost}}
<div class="row form-group">
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">Host Header</label>
<label class="form-control-static">{{t 'formHealthCheck.host.label'}}</label>
</div>
<div class="col-sm-12 col-md-8">
{{input type="text" classNames="form-control" placeholder="e.g. www.example.com" value=uriHost}}
{{input type="text" classNames="form-control" placeholder=(t 'formHealthCheck.host.placeholder') value=uriHost}}
</div>
</div>
{{/if}}
@ -69,18 +69,18 @@
<div class="row form-group">
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">Port*</label>
<label class="form-control-static">{{t 'formHealthCheck.port.label'}}*</label>
</div>
<div class="col-sm-12 col-md-3">
{{input type="number" min="1" max="65535" classNames="form-control" placeholder="e.g. 80" value=healthCheck.port}}
{{input type="number" min="1" max="65535" classNames="form-control" placeholder=(t 'formHealthCheck.port.placeholder') value=healthCheck.port}}
</div>
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">Initializing Timeout</label>
<label class="form-control-static">{{t 'formHealthCheck.initializingTimeout.label'}}</label>
</div>
<div class="col-sm-12 col-md-3">
<div class="input-group">
{{input type="number" step=100 classNames="form-control" value=healthCheck.initializingTimeout}}
<span class="input-group-addon">ms</span>
<span class="input-group-addon">{{t 'formHealthCheck.initializingTimeout.unit'}}</span>
</div>
</div>
</div>
@ -88,42 +88,42 @@
<div class="row form-group">
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">Check Interval</label>
<label class="form-control-static">{{t 'formHealthCheck.interval.label'}}</label>
</div>
<div class="col-sm-12 col-md-3">
<div class="input-group">
{{input type="number" min=1 step=1000 classNames="form-control" value=healthCheck.interval}}
<span class="input-group-addon">ms</span>
<span class="input-group-addon">{{t 'formHealthCheck.interval.unit'}}</span>
</div>
</div>
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">Check Timeout</label>
<label class="form-control-static">{{t 'formHealthCheck.timeout.label'}}</label>
</div>
<div class="col-sm-12 col-md-3">
<div class="input-group">
{{input type="number" min=1 step=100 classNames="form-control" value=healthCheck.responseTimeout}}
<span class="input-group-addon">ms</span>
<span class="input-group-addon">{{t 'formHealthCheck.timeout.unit'}}</span>
</div>
</div>
</div>
<div class="row form-group">
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">Healthy Threshold</label>
<label class="form-control-static">{{t 'formHealthCheck.healthyThreshold.label'}}</label>
</div>
<div class="col-sm-12 col-md-3">
<div class="input-group">
{{input type="number" min=1 step=1 classNames="form-control" value=healthCheck.healthyThreshold}}
<span class="input-group-addon">successes</span>
<span class="input-group-addon">{{t 'formHealthCheck.healthyThreshold.unit'}}</span>
</div>
</div>
<div class="col-sm-12 col-md-2 form-label">
<label class="form-control-static">Unhealthy Threshold</label>
<label class="form-control-static">{{t 'formHealthCheck.unhealthyThreshold.label'}}</label>
</div>
<div class="col-sm-12 col-md-3">
<div class="input-group">
{{input type="number" min=1 step=1 classNames="form-control" value=healthCheck.unhealthyThreshold}}
<span class="input-group-addon">failures</span>
<span class="input-group-addon">{{t 'formHealthCheck.unhealthyThreshold.unit'}}</span>
</div>
</div>
</div>
@ -131,17 +131,24 @@
{{#if (and isService showStrategy)}}
<div class="row form-group">
<div class="col-sm-12 col-md-2 form-label">
<label>When Unhealthy</label>
<label>{{t 'formHealthCheck.strategy.label'}}</label>
</div>
<div class="col-sm-12 col-md-8">
<div class="radio input">
<label>{{radio-button selection=strategy value="none"}} Take no action</label>
<label>{{radio-button selection=strategy value="none"}} {{t 'formHealthCheck.strategy.none'}}</label>
</div>
<div class="radio input">
<label>{{radio-button selection=strategy value="recreate"}} Re-create</label>
<label>{{radio-button selection=strategy value="recreate"}} {{t 'formHealthCheck.strategy.recreate'}}</label>
</div>
<div class="radio input">
<label>{{radio-button selection=strategy value="recreateOnQuorum"}}<span class="with-input">Re-create, only when at least {{input type="number" min=1 safeStyle="width: 60px; display: inline-block;" class="form-control input-sm" value=quorum}} container{{if (eq quorum "1") ' is' 's are'}} healthy</span></label>
<label>
{{radio-button selection=strategy value="recreateOnQuorum"}}
<span class="with-input">
{{t 'formHealthCheck.strategy.recreateOnQuorumPrefix' quorum=quorum}}
{{input type="number" min=1 safeStyle="width: 60px; display: inline-block;" class="form-control input-sm" value=quorum}}
{{t 'formHealthCheck.strategy.recreateOnQuorumSuffix' quorum=quorum}}
</span>
</label>
</div>
</div>
</div>

View File

@ -1,12 +1,12 @@
<div class="form-label"><label class="form-control-static">Select Image</label></div>
<div class="form-label"><label class="form-control-static">{{t 'formImage.label'}}</label></div>
{{#if isVm}}
<div class="input-group">
{{input type="text" value=userInput placeholder="e.g. rancher/vm-ubuntu" class="form-control"}}
{{input type="text" value=userInput placeholder=(t 'formImage.vm.placeholder') class="form-control"}}
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><i class="icon icon-chevron-down"></i></button>
<ul class="dropdown-menu dropdown-menu-right" role="menu" style="min-width: 250px; max-height: 300px; overflow-y: auto;">
<li role="presentation" class="dropdown-header">{{settings.appName}} Images</li>
<li role="presentation" class="dropdown-header">{{t 'formImage.vm.dropdownLabel' appName=settings.appName}}</li>
<li><a href="#" {{action "setInput" "rancher/vm-ubuntu"}}>rancher/vm-ubuntu</a></li>
<li><a href="#" {{action "setInput" "rancher/vm-centos"}}>rancher/vm-centos</a></li>
<li><a href="#" {{action "setInput" "rancher/vm-rancheros"}}>rancher/vm-rancheros</a></li>
@ -14,11 +14,11 @@
</div>
</div>
{{else}}
{{input type="text" class="form-control" value=userInput placeholder="e.g. ubuntu:trusty"}}
{{input type="text" class="form-control" value=userInput placeholder=(t 'formImage.container.placeholder')}}
{{/if}}
<div class="row form-group">
<div class="r-pt10">
<label>{{input type="checkbox" checked=pullImage}} Always pull image before creating</label>
<label>{{input type="checkbox" checked=pullImage}} {{t 'formImage.pullImage.label'}}</label>
</div>
</div>

View File

@ -1,13 +1,12 @@
import Ember from 'ember';
export default Ember.Component.extend({
settings: Ember.inject.service(),
hasVm: Ember.computed.alias('settings.hasVm'),
projects: Ember.inject.service(),
hasVm: Ember.computed.alias('projects.current.virtualMachine'),
index: null,
choices: null,
showAdd: true,
addLabel: 'Sidekick Container',
initialIndex: -1,
actions: {

View File

@ -7,15 +7,13 @@
<li class="{{if (eq index choice.index) 'active'}}"><a href="#" {{action "switch" choice.index}}>{{choice.name}}</a></li>
{{/each}}
{{#if showAdd}}
<li class="hand"><a {{action "add"}}><i class="icon icon-plus"/> Add {{addLabel}}</a></li>
<li class="hand"><a {{action "add"}}><i class="icon icon-plus"/> {{t 'newContainer.addSidekickContainer'}}</a></li>
{{#if hasVm}}
<li class="hand"><a {{action "add" true}}><i class="icon icon-plus"/> Add Sidekick VM</a></li>
<li class="hand"><a {{action "add" true}}><i class="icon icon-plus"/> {{t 'newContainer.addSidekickVM'}}</a></li>
{{/if}}
{{/if}}
</ul>
</nav>
</span>
</div>
{{else}}
{{/if}}

View File

@ -15,7 +15,7 @@
{{#if isAdvanced}}
<th>{{t 'formTargets.hostname.label'}}</th>
<th width="90">{{t 'formTargets.srcPort.label'}}</th>
<th>{{t 'formTargets.srcPort.path'}}</th>
<th>{{t 'formTargets.srcPort.label'}}</th>
<th width="30">&nbsp;</th>
{{/if}}
{{#if isBalancer}}

View File

@ -1,5 +1,4 @@
import Ember from 'ember';
import C from 'ui/utils/constants';
export default Ember.Component.extend({
settings: Ember.inject.service(),
@ -14,7 +13,7 @@ export default Ember.Component.extend({
classNameBindings: ['settings.isRancher::hide'],
href: function() {
return C.EXT_REFERENCES.DOCS + this.get('link');
return this.get('settings.docsBase') + this.get('link');
}.property('link')
});

View File

@ -1,35 +1,35 @@
<div class="col-md-4 form-group">
<div class="clearfix r-mb10 r-mt15">
<label class="r-pt5">Private Key*</label>
<label class="r-pt5">{{t 'inputCertificate.key.label'}}*</label>
</div>
{{input-text-file
value=model.key
accept="text/*, .pem, .pkey, .key"
minHeight=60
placeholder="Paste in the private key, starting with -----BEGIN RSA PRIVATE KEY-----"
placeholder="inputCertificate.key.placeholder"
}}
</div>
<div class="col-md-4 form-group">
<div class="clearfix r-mb10 r-mt15">
<label class="r-pt5">Certificate*</label>
<label class="r-pt5">{{t 'inputCertificate.cert.label'}}*</label>
</div>
{{input-text-file
value=model.cert
accept="text/*, .pem, .crt"
minHeight=60
placeholder="Paste in the primary certificate, starting with -----BEGIN CERTIFICATE-----"
placeholder="inputCertificate.cert.placeholder"
}}
</div>
<div class="col-md-4 form-group">
<div class="clearfix r-mb10 r-mt15">
<label class="r-pt5">Chain Certs</label>
<label class="r-pt5">{{t 'inputCertificate.certChain.label'}} Certs</label>
</div>
{{input-text-file
value=model.certChain
accept="text/*, .pem, .crt"
minHeight=60
placeholder="Optional; Paste in the additional chained certificates, starting with -----BEGIN CERTIFICATE-----"
placeholder="inputCertificate.certChain.placeholder"
}}
</div>

View File

@ -23,7 +23,7 @@ export default Ember.Component.extend(Driver, {
projectId : '',
os : 'ubuntu_14_04',
facilityCode : 'ewr1',
plan : 'baremetal_1',
plan : 'baremetal_0',
billingCycle : 'hourly',
});

View File

@ -1,8 +1,8 @@
<section class="header">
<h1>Add Service Alias {{help-btn link="/rancher-ui/applications/stacks/adding-service-alias/"}}</h1>
</section>
<section class="horizontal-form container-fluid">
<h2>Add Service Alias {{help-btn link="/rancher-ui/applications/stacks/adding-service-alias/"}}</h2>
{{top-errors errors=errors}}
{{form-name-description
model=service
namePlaceholder="servicePage.newAlias.form.name.placeholder"
@ -17,4 +17,5 @@
}}
</section>
{{top-errors errors=errors}}
{{save-cancel save="save" cancel="cancel"}}

View File

@ -155,6 +155,8 @@ export default Ember.Component.extend(NewOrEdit, SelectTab, {
return this.get('targetsArray').filterBy('value').get('length') >= 2;
}.property('targetsArray.@each.value'),
showAdvancedMatchingWarning: Ember.computed.and('hasAdvancedSourcePorts','hasMultipleListeners','hasMultipleTargets'),
// ----------------------------------
// Labels
// ----------------------------------

View File

@ -1,7 +1,8 @@
<section class="horizontal-form container-fluid">
<h2>Add Load Balancer {{help-btn link="/rancher-ui/applications/stacks/adding-balancers/"}}</h2>
{{top-errors errors=errors}}
<section class="header">
<h1>Add Load Balancer {{help-btn link="/rancher-ui/applications/stacks/adding-balancers/"}}</h1>
</section>
<section class="horizontal-form container-fluid">
{{form-scale
initialLabels=launchConfig.labels
initialScale=service.scale
@ -26,7 +27,7 @@
setLabels=(action 'setLabels' 'ssl')
}}
{{#if (and hasAdvancedSourcePorts hasMultipleListeners hasMultipleTargets)}}
{{#if showAdvancedMatchingWarning}}
<div class="row">
<div class="col-sm-12 col-md-8 col-md-offset-2">
<div class="alert alert-info">
@ -121,4 +122,5 @@
</div>
</section>
{{top-errors errors=errors}}
{{save-cancel save="save" cancel="cancel"}}

View File

@ -6,6 +6,8 @@ import C from 'ui/utils/constants';
import Util from 'ui/utils/util';
export default Ember.Component.extend(NewOrEdit, SelectTab, {
intl: Ember.inject.service(),
isStandalone: true,
isService: false,
isSidekick: false,
@ -154,18 +156,27 @@ export default Ember.Component.extend(NewOrEdit, SelectTab, {
launchConfigChoices: function() {
var isUpgrade = this.get('isUpgrade');
let intl = this.get('intl');
// Enabled is only for upgrade, and isn't maintained if the names change, but they can't on upgrade.
var out = [
{index: -1, name: this.get('service.name') || '(Primary Service)', enabled: true}
{
index: -1,
name: this.get('service.name') || intl.t('newContainer.emptyPrimaryService'),
enabled: true
}
];
(this.get('service.secondaryLaunchConfigs')||[]).forEach((item, index) => {
out.push({index: index, name: item.get('name') || `(Sidekick #${index+1})`, enabled: !isUpgrade });
out.push({
index: index,
name: item.get('name') || intl.t('newContainer.emptySidekick', {num: index+1}),
enabled: !isUpgrade
});
});
return out;
}.property('service.name','service.secondaryLaunchConfigs.@each.name'),
}.property('service.name','service.secondaryLaunchConfigs.@each.name','intl._locale'),
noLaunchConfigsEnabled: function() {
return this.get('launchConfigChoices').filterBy('enabled',true).get('length') === 0;

View File

@ -15,7 +15,7 @@
{{/each}}
{{#each groupedContent as |group|}}
<optgroup label="{{if localizedLabel (t group.group) group.group}}">
<optgroup label="{{group.group}}">
{{#each group.options as |item|}}
<option value="{{get item optionValuePath}}" selected={{eq value (get item optionValuePath)}} disabled={{get item optionDisabledPath}}>
{{#if localizedLabel}}

View File

@ -28,6 +28,7 @@ export default Ember.Component.extend({
namespaceId : Ember.computed.alias('k8s.namespace.id'),
settings : Ember.inject.service(),
access : Ember.inject.service(),
prefs : Ember.inject.service(),
isAdmin : Ember.computed.alias('access.admin'),
// Component options
@ -61,6 +62,7 @@ export default Ember.Component.extend({
}
}
item.localizedLabel = fnOrValue(item.localizedLabel, this);
item.label = fnOrValue(item.label, this);
item.route = fnOrValue(item.route, this);
item.ctx = (item.ctx||[]).map((prop) => {
@ -68,11 +70,17 @@ export default Ember.Component.extend({
});
item.submenu = fnOrValue(item.submenu, this);
item.showAlert = false;
if ( typeof item.alertCondition === 'function' && item.alertCondition.call(this) === true ) {
item.showAlert = true;
}
item.submenu = (item.submenu||[]).filter((subitem) => {
if ( typeof subitem.condition === 'function' && !subitem.condition.call(this) ) {
return false;
}
subitem.localizedLabel = fnOrValue(subitem.localizedLabel, this);
subitem.label = fnOrValue(subitem.label, this);
subitem.route = fnOrValue(subitem.route, this);
subitem.ctx = (subitem.ctx||[]).map((prop) => {
@ -90,18 +98,23 @@ export default Ember.Component.extend({
shouldUpdateNavTree: function() {
Ember.run.once(this, 'updateNavTree');
}.observes('currentPath','project.orchestrationState','projectId','namespaceId',`settings.${C.SETTING.CATALOG_URL}`,'settings.hasVm','isAdmin'),
}.observes(
'projectId',
'namespaceId',
'project.{virtualMachine,orchestrationState}',
`settings.${C.SETTING.CATALOG_URL}`,
`prefs.${C.PREFS.ACCESS_WARNING}`,
'access.enabled',
'isAdmin'
),
// Utilities you can use in the condition() function to decide if an item is shown or hidden,
// beyond things listed in "Inputs"
pathIs(prefix) {
return this.get('currentPath').indexOf(prefix) === 0;
},
hasProject: function() {
return !!this.get('project');
}.property('project'),
hasVm: Ember.computed.alias('project.virtualMachine'),
hasSwarm: Ember.computed.alias('project.orchestrationState.hasSwarm'),
hasKubernetes: Ember.computed.alias('project.orchestrationState.hasKubernetes'),
hasMesos: Ember.computed.alias('project.orchestrationState.hasMesos'),

View File

@ -64,6 +64,11 @@
{{/if}}
{{/each}}
</ul>
{{#if item.showAlert}}
{{#tooltip-element class="tooltip-warning" type='tooltip-warning'}}
{{#link-to item.alertRoute data-toggle="tooltip" data-placement="bottom"}}!{{/link-to}}
{{/tooltip-element}}
{{/if}}
</li>
{{else}}
{{! No submenu }}

View File

@ -5,8 +5,8 @@ import FilterState from 'ui/mixins/filter-state';
export default Ember.Component.extend(FilterState, {
prefs: Ember.inject.service(),
settings: Ember.inject.service(),
hasVm: Ember.computed.alias('settings.hasVm'),
projects: Ember.inject.service(),
hasVm: Ember.computed.alias('projects.current.virtualMachine'),
model: null,
single: false,

View File

@ -119,7 +119,7 @@
</table>
{{else}}
<p class="help-block text-center">
{{t 'viewEditProject.helpBlock'}}
{{format-html-message 'viewEditProject.helpBlock'}}
</p>
{{/if}}
</div>
@ -128,6 +128,26 @@
</section>
{{#if showEdit}}
<section class="r-pt0">
<div class="row form-group">
<div class="col-md-2 form-label">
{{t 'viewEditProject.virtualMachine.label'}}
</div>
<div class="col-md-10">
<div>
<label class="r-mr20 hand">
{{radio-button selection=project.virtualMachine value=true}} {{t 'generic.enabled'}}
</label>
<label class="hand">
{{radio-button selection=project.virtualMachine value=false}} {{t 'generic.disabled'}}
</label>
</div>
<p class="help-block">{{format-html-message 'viewEditProject.virtualMachine.subtext'}}</p>
</div>
</div>
</section>
{{top-errors errors=errors}}
{{save-cancel editing=editing save="save" cancel="cancel"}}
{{/if}}

View File

@ -1,17 +0,0 @@
import Ember from 'ember';
import C from 'ui/utils/constants';
export default Ember.Component.extend({
settings : Ember.inject.service(),
virtualMachine : null,
actions: {
save: function(btnCb) {
this.get('settings').set(C.SETTING.VM_ENABLED, this.get('virtualMachine'));
this.get('settings').one('settingsPromisesResolved', () => {
btnCb(true);
this.sendAction('saved');
});
},
}
});

View File

@ -1,14 +0,0 @@
<h4>{{t 'virtualMachineSettings.header'}}</h4>
<hr>
<h5>{{format-html-message 'virtualMachineSettings.subtext'}}</h5>
<div class="r-pt10">
<label class="r-mr20 hand">
{{radio-button selection=virtualMachine value=true}} {{t 'generic.enabled'}}
</label>
<label class="hand">
{{radio-button selection=virtualMachine value=false}} {{t 'generic.disabled'}}
</label>
</div>
{{save-cancel cancelDisabled=true editing=true save="save"}}

View File

@ -15,11 +15,6 @@ var Project = Resource.extend(PolledResource, {
name: null,
description: null,
init() {
this._super(...arguments);
console.log('INIT PROJECT');
},
actions: {
edit: function() {
this.get('router').transitionTo('settings.projects.detail', this.get('id'), {queryParams: {editing: true}});
@ -85,6 +80,7 @@ var Project = Resource.extend(PolledResource, {
{ label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: this.get('canRemove'), altAction: 'delete' },
{ label: 'action.restore', icon: '', action: 'restore', enabled: !!a.restore },
{ label: 'action.purge', icon: '', action: 'purge', enabled: !!a.purge },
{ label: 'action.viewInApi', icon: 'icon icon-external-link',action: 'goToApi', enabled: true },
];

View File

@ -154,8 +154,6 @@ export default Ember.Service.extend(Ember.Evented, {
dockerMachineVersion: Ember.computed.alias(`asMap.${C.SETTING.VERSION_MACHINE}.value`),
goMachineVersion: Ember.computed.alias(`asMap.${C.SETTING.VERSION_GMS}.value`),
hasVm: Ember.computed.equal(`asMap.${C.SETTING.VM_ENABLED}.value`, 'true'),
_plValue: function() {
return this.get(`cookies.${C.COOKIE.PL}`) || '';
}.property(`cookies.${C.COOKIE.PL}`),

View File

@ -45,12 +45,13 @@ export default Ember.Service.extend({
},
sideLoadLanguage(language) {
let application = this.get('app');
let loadedLocales = this.get('loadedLocales');
if (loadedLocales.contains(language)) {
this.get('intl').setLocale(language);
return Ember.RSVP.resolve();
} else {
return ajaxPromise({url: `${this.get('app.baseAssets')}translations/${language}.json`,
return ajaxPromise({url: `${this.get('app.baseAssets')}translations/${language}.json?${application.version}`,
method: 'GET',
dataType: 'json',
}).then((resp) => {

View File

@ -186,8 +186,8 @@ div.tooltip-warning {
width : 15px;
border-radius : 50%;
position : absolute;
right : 6px;
top : 10px;
right : 3px;
top : 13px;
padding : 0;
line-height : 15px;
text-align : center;

View File

@ -937,11 +937,6 @@ SECTION.header {
}
HEADER {
div.tooltip-warning {
right: 0;
left: 62px;
}
.gh-avatar {
height: 30px;
width: 30px;

View File

@ -594,7 +594,7 @@ HR {
}
.divider {
margin: 6px 5px;
margin: 0;
}
.dropdown-header {

View File

@ -196,7 +196,6 @@ var C = {
},
API_HOST: 'api$host',
CATALOG_URL: 'catalog$url',
VM_ENABLED: 'vm$enabled',
SWARM_PORT: 'swarm$tls$port',
ENGINE_URL: 'engine$install$url',
MIN_DOCKER: 'ui$min$docker$version',

View File

@ -12,11 +12,18 @@ export const mesosReady = function() { return this.get('mesosReady'); };
/* Tree item options
{
id: 'str' (identifier to allow removal... should be unique)
label: 'Displayed label', (or function that returns string)
icon: 'icon icon-somethign',
condition: function() { return true if this item should be displayed },
// condition can depend on anything page-header/component.js shouldUpdateNavTree() depends on:
// 'currentPath','project.orchestrationState','projectId','namespaceId',`settings.${C.SETTING.CATALOG_URL}`,'settings.hasVm','isAdmin',
localizedLabel: 'i18n key', (or function that returns one)
label: 'Displayed unlocalized label', (or function that returns string)
icon: 'icon icon-something',
condition: function() {
// return true if this item should be displayed
// condition can depend on anything page-header/component.js shouldUpdateNavTree() depends on
}
alertRoute: 'target.route.path', // as in link-to
alertCondition: function() {
// return true if the alert (!) icon should be displayed
// can depend on anything page-header/component.js shouldUpdateNavTree() depends on
}
url: 'http://any/url', (url or route required)
target: '_blank', (for url only)
route: 'target.route.path', // as in link-to
@ -238,7 +245,7 @@ const navTree = [
icon: 'icon icon-vm',
route: 'virtualmachines',
ctx: [getProjectId],
condition: function() { return this.get('settings.hasVm'); },
condition: function() { return this.get('hasVm'); },
},
{
id: 'infra-storagepools',
@ -270,6 +277,10 @@ const navTree = [
localizedLabel: 'nav.admin.tab',
route: 'admin-tab',
condition: function() { return this.get('isAdmin'); },
alertRoute: 'admin-tab.auth',
alertCondition: function() {
return !this.get('access.enabled') && this.get('prefs.'+C.PREFS.ACCESS_WARNING) !== false;
},
submenu: [
{
id: 'admin-audit',

View File

@ -1,6 +1,6 @@
{
"name": "ui",
"version": "1.0.8",
"version": "1.0.9",
"private": true,
"directories": {
"doc": "doc",

View File

@ -6,25 +6,25 @@ languageName: "English (US)"
generic:
actions: Actions
closeModal: Close
default: Default
description: Description
disabled: Disabled
enabled: Enabled
emptyString: ""
enabled: Enabled
id: ID
image: Image
ipAddress: IP Address
loading: "Loading..."
missing: "*%MISSING%*"
moreActions: More Actions
na: 'N/A'
name: Name
none: None
remove: Remove
state: State
unknown: Unknown
description: Description
default: Default
type: Type
role: Role
na: 'N/A'
ipAddress: IP Address
image: Image
state: State
type: Type
unknown: Unknown
##############################
# Routes
@ -76,12 +76,13 @@ apiPage:
noName: None
noDescription: None
noPublicValue: No public value
advanced:
account:
header: Account API Keys
buttonText: Add Account API Key
content:
paragraph1: Account API Keys are tied to your specific account
paragraph2: "and can create, delete, and manipulate all Environments which you have access to."
table:
noData: "You don't have any Account API keys yet."
auditLogsPage:
@ -226,7 +227,6 @@ authPage:
pre: Enable Local Auth
post: 'Enabling...'
catalogPage:
index:
header: 'Catalog:'
@ -237,12 +237,10 @@ catalogPage:
singular: There are no compatible templates.
plural: There are no compatible templates in this catalog.
consolePage:
header: 'Shell:'
closeButton: Close
certificatesPage:
table:
cn: Domain Name
@ -374,7 +372,6 @@ failWhalePage:
<a href="#" onclick="window.location.href = window.location.href; return false;">Reload</a> to try again or
logoutButton: log out
haPage:
header:
enabled: 'High Availability is <b class="text-success">enabled</b>'
@ -613,7 +610,6 @@ hostsPage:
body:
noData: This host does not have any volumes.
k8sTab:
kubectl:
header: kubectl
@ -742,7 +738,6 @@ registriesPage:
labelText: Password
placeholder: e.g. password
servicePage:
header: 'Service:'
multistat:
@ -801,7 +796,6 @@ servicePage:
noData: This Service has no ports.
notActive: Ports are only available while the service is Active.
settingsPage:
index:
header: Environments
@ -817,7 +811,6 @@ settingsPage:
body:
noData: You don't have any environments yet.
stacksPage:
header:
all: All Stacks
@ -936,8 +929,6 @@ virtualMachinePage:
navTabs:
labels: Labels
virtualMachinesPage:
header: Virtual Machines
linkTo: Add Virtual Machine
@ -973,7 +964,6 @@ externalServicePartial:
hostname: 'Host Name:'
description: 'Description:'
hostPartial:
host:
addCommon:
@ -985,7 +975,6 @@ hostPartial:
addOptions:
labels: Labels
openLdap:
configuredIndication:
header:
@ -1135,7 +1124,6 @@ catalogSettings:
valueLabel: URL
valuePlaceholder: 'e.g. https://github.com/mycompany/mycatalog.git'
confirmDelete:
title: 'Are you sure you want to delete'
environmentNote: 'Note: All resources inside this Environment will be permanently removed, including any Hosts that were created through {appName}.'
@ -1237,6 +1225,7 @@ editApiKey:
saveWarning1: Save the keys above! This is the only time you'll be able to see the secret.
saveWarning2: If you lose it, you'll need to create a new API key.
noteOptional: Name and/or description are optional to help you remember what it's used for. You can just create a key by clicking Create.
#' fixes syntax highlighting so i dont go crazy
editBalancerService:
title: Edit Load Balancer
@ -1252,7 +1241,6 @@ editBalancerService:
label: '<code>defaults</code> section'
prompt: Custom defaults section lines
editCertificate:
title: Edit Certificate
name:
@ -1449,6 +1437,52 @@ formEngineOpts:
valueLabel: Mirror URL
valuePlaceholder: e.g. https://my-mirror.example.com:5000
formHealthCheck:
label: Health Check
checkType:
none: None
tcp: TCP Connection Opens
http: HTTP Responds 2xx/3xx
request:
label: HTTP Request
method:
prompt: "Select a HTTP Method:"
path:
placeholder: Request Path e.g. /healthcheck
version:
prompt: "Select a HTTP Version:"
host:
label: Host Header
placeholder: e.g. www.example.com
port:
label: Port
placeholder: e.g. 80
initializingTimeout:
label: Initializing Timeout
unit: ms
interval:
label: Check Interval
unit: ms
timeout:
label: Check Timeout
unit: ms
healthyThreshold:
label: Healthy Threshold
unit: successes
unhealthyThreshold:
label: Unhealthy Threshold
unit: failures
strategy:
label: When Unhealthy
none: Take no action
recreate: Re-create
recreateOnQuorumPrefix: Re-create, only when at least
recreateOnQuorumSuffix: |
{quorum, plural,
=1 {container is}
other {containers are}
} healthy
formKeyValue:
addAction: Add Pair
key:
@ -1460,6 +1494,16 @@ formKeyValue:
placeholder: Value
protip: 'ProTip: Paste one or more lines of key=value pairs into any key field for easy bulk entry.'
formImage:
label: Select Image
vm:
placeholder: e.g. rancher/vm-ubuntu
dropdownLabel: "{appName} Images"
container:
placeholder: "e.g. ubuntu:trusty"
pullImage:
label: Always pull image before creating
formNameDescription:
name:
label: Name
@ -1609,6 +1653,17 @@ machine:
publishSettingsFile:
placeholder: Your Publish Settings file
inputCertificate:
key:
label: Private Key
placeholder: "Paste in the private key, starting with -----BEGIN RSA PRIVATE KEY-----"
cert:
label: Certificate
placeholder: "Paste in the primary certificate, starting with -----BEGIN CERTIFICATE-----"
certChain:
label: Chain Certs
placeholder: "Optional; Paste in the additional chained certificates, starting with -----BEGIN CERTIFICATE-----"
inputPassword:
buttonText: Generate
@ -1648,6 +1703,10 @@ newContainer:
placeholder: e.g. myapp
description:
placeholder: e.g. My Application
emptyPrimaryService: "(Primary Service)"
emptySidekick: "(Sidekick #{num})"
addSidekickContainer: Add Sidekick Container
addSidekickVm: Add Sidekick VM
pageFooter:
notARelease: (Not a Release)
@ -1728,7 +1787,7 @@ stackSection:
loadBalancer: Add Load Balancer
serviceAlias: Add Service Alias
externalService: Add External Service
virtualMachine: Add Virtual
virtualMachine: Add Virtual Machine
storagePoolSection:
outputs: Outputs
@ -1775,7 +1834,7 @@ viewEditDescription:
placeholder: e.g. Environment for developer experimentation
viewEditProject:
showDdit:
showEdit:
edit: "Edit Environment:"
add: Add Environment
orchestration: Container Orchestration
@ -1785,11 +1844,11 @@ viewEditProject:
helpBlock: |
Access Control is not enabled.<br/>
Anybody with access to the API/UI acts as an admin and will be able to use any environment.
virtualMachine:
label: Virtual Machine Support
subtext: |
Requires hosts that have the <a href="https://en.wikipedia.org/wiki/Kernel-based_Virtual_Machine" target="_blank">KVM</a> kernel module loaded.
virtualMachineSettings:
header: Virtual Machine Support
subtext: |
Requires hosts that have the <a href="https://en.wikipedia.org/wiki/Kernel-based_Virtual_Machine" target="_blank">KVM</a> kernel module loaded.
vmConsole:
header: "console:"