Merge branch 'master' of github.com:hubert-he/ui

This commit is contained in:
zhenhua he 2019-11-13 14:47:17 +08:00
commit 106de7be6b
23 changed files with 352 additions and 170 deletions

View File

@ -26,7 +26,8 @@ export default Route.extend({
let agent = window.navigator.userAgent.toLowerCase(); let agent = window.navigator.userAgent.toLowerCase();
if ( agent.indexOf('msie ') >= 0 || agent.indexOf('trident/') >= 0 ) { // Show the we don't support internet explorer or edge browsers (only edge html based browsers the mobile and chromium based browsers should be okay).
if ( agent.indexOf('msie ') >= 0 || agent.indexOf('trident/') >= 0 || agent.indexOf('edge/') >= 0) {
this.replaceWith('ie'); this.replaceWith('ie');
return; return;

View File

@ -61,7 +61,6 @@ export default Component.extend({
lastScrollTop = scrollTop; lastScrollTop = scrollTop;
}); });
this.exec();
var btn = $('.scroll-bottom')[0]; // eslint-disable-line var btn = $('.scroll-bottom')[0]; // eslint-disable-line
if ( btn ) { if ( btn ) {

View File

@ -2,5 +2,5 @@
<br><br> <br><br>
<div class="sad-ie"></div> <div class="sad-ie"></div>
<br><br> <br><br>
<h3s>Sorry, IE is not supported.</h3s> <h3s>Sorry, IE and Edge are not supported.</h3s>
</section> </section>

View File

@ -57,7 +57,7 @@ export default Resource.extend({
return out; return out;
}), }),
validationErrors() { validationErrors(answersMap) {
const { const {
intl, allQuestions, valuesYaml intl, allQuestions, valuesYaml
} = this; } = this;
@ -96,7 +96,7 @@ export default Resource.extend({
} else { } else {
if ( filteredQuestions ) { if ( filteredQuestions ) {
filteredQuestions.forEach((item) => { filteredQuestions.forEach((item) => {
if ( item.required && item.type !== 'boolean' && !item.answer ) { if ( item.required && item.type !== 'boolean' && isEmpty(answersMap[item.variable]) ) {
errors.push(intl.t('validation.required', { key: item.label })); errors.push(intl.t('validation.required', { key: item.label }));
} }

View File

@ -205,6 +205,11 @@
white-space: normal; white-space: normal;
} }
.list-small {
line-height: 14px;
padding: 0 0 0 22px;
margin: 0;
}
.list-unstyled { @include list-unstyled } .list-unstyled { @include list-unstyled }
.no-select { @include no-select } .no-select { @include no-select }
.no-resize { @include no-resize } .no-resize { @include no-resize }

View File

@ -112,7 +112,7 @@ select {
&:hover { &:hover {
border-color: $input-bg-hover; border-color: $input-bg-hover;
background: rgba($input-bg-hover, .2); background-color: rgba($input-bg-hover, .2);
&::placeholder { &::placeholder {
color: rgba($input-color-placeholder, .35); color: rgba($input-color-placeholder, .35);
} }
@ -126,7 +126,7 @@ select {
} }
} }
&:focus { &:focus {
background: rgba($input-border-focus, .2); background-color: rgba($input-border-focus, .2);
border-color: $input-border-focus; border-color: $input-border-focus;
transition: ease-in-out all .25s; transition: ease-in-out all .25s;
&::placeholder { &::placeholder {

View File

@ -13,7 +13,6 @@
white-space: -pre-wrap; white-space: -pre-wrap;
white-space: -o-pre-wrap; white-space: -o-pre-wrap;
word-wrap: break-word; word-wrap: break-word;
width: auto;
} }
} }

View File

@ -89,6 +89,7 @@ export default Component.extend(NewOrEdit, CatalogApp, {
selectedTemplateUrl: null, selectedTemplateUrl: null,
multiClusterApp: { targets: [], }, multiClusterApp: { targets: [], },
}, },
mcAppIsSaving: false,
overridesHeaders: OVERRIDE_HEADERS, overridesHeaders: OVERRIDE_HEADERS,
@ -277,6 +278,10 @@ export default Component.extend(NewOrEdit, CatalogApp, {
}, },
updateAnswerOverrides: observer('selectedTemplateModel', 'multiClusterApp.answers.@each.{values}', function() { updateAnswerOverrides: observer('selectedTemplateModel', 'multiClusterApp.answers.@each.{values}', function() {
if (this.mcAppSaving) {
return;
}
let { selectedTemplateModel = {} } = this; let { selectedTemplateModel = {} } = this;
const questions = get(selectedTemplateModel, 'questions') const questions = get(selectedTemplateModel, 'questions')
@ -363,7 +368,7 @@ export default Component.extend(NewOrEdit, CatalogApp, {
} }
}), }),
templateOrHelmChartQuestions: computed('selectedTemplateModel', function() { templateOrHelmChartQuestions: computed('selectedTemplateModel', 'selectedTemplateModel.allQuestions.@each.{answer,variable}', function() {
let { selectedTemplateModel, multiClusterApp } = this; let { selectedTemplateModel, multiClusterApp } = this;
let nueQuestions = []; let nueQuestions = [];
@ -587,7 +592,7 @@ export default Component.extend(NewOrEdit, CatalogApp, {
this._super(...arguments); this._super(...arguments);
const errors = get(this, 'errors') || []; const errors = get(this, 'errors') || [];
errors.pushObjects(get(this, 'selectedTemplateModel').validationErrors() || []); errors.pushObjects(get(this, 'selectedTemplateModel').validationErrors(this.answers) || []);
errors.pushObjects(this.validateTargetsProjectIds()); errors.pushObjects(this.validateTargetsProjectIds());
set(this, 'errors', errors.uniq()); set(this, 'errors', errors.uniq());

View File

@ -408,6 +408,7 @@
{{save-cancel {{save-cancel
createLabel=(if editing saveUpgrade saveNew) createLabel=(if editing saveUpgrade saveNew)
save=(action "save") save=(action "save")
saving=mcAppSaving
cancel=(action "cancel") cancel=(action "cancel")
}} }}
</div> </div>

View File

@ -135,6 +135,7 @@ export default Component.extend(NodeDriver, {
this.initCustomAttributes(); this.initCustomAttributes();
this.initTag(); this.initTag();
this.initNetwork(); this.initNetwork();
this.initUseDataStoreCluster();
}, },
actions: { actions: {
@ -166,6 +167,12 @@ export default Component.extend(NodeDriver, {
return keyContent.filter((keyContent) => { return keyContent.filter((keyContent) => {
return keyValuePairs.findIndex((kvp) => kvp.key === keyContent.value) === -1; return keyValuePairs.findIndex((kvp) => kvp.key === keyContent.value) === -1;
}); });
},
toggleUseDataStoreCluster(value) {
set(this, 'config.useDataStoreCluster', value);
const clearKey = value ? 'config.datastore' : 'config.datastoreCluster';
set(this, clearKey, '');
} }
}, },
@ -236,6 +243,16 @@ export default Component.extend(NodeDriver, {
return this.mapPathOptionsToContent(options); return this.mapPathOptionsToContent(options);
}), }),
dataStoreClusterContent: computed('config.datacenter', async function() {
const options = await this.requestOptions(
'data-store-clusters',
get(this, 'model.cloudCredentialId'),
get(this, 'config.datacenter')
);
return this.mapPathOptionsToContent(options);
}),
folderContent: computed('config.datacenter', async function() { folderContent: computed('config.datacenter', async function() {
const options = await this.requestOptions( const options = await this.requestOptions(
'folders', 'folders',
@ -324,6 +341,7 @@ export default Component.extend(NodeDriver, {
let config = get(this, 'globalStore').createRecord({ let config = get(this, 'globalStore').createRecord({
type: CONFIG, type: CONFIG,
useDataStoreCluster: false,
cpuCount: '2', cpuCount: '2',
memorySize: '2048', memorySize: '2048',
diskSize: '20000', diskSize: '20000',
@ -406,6 +424,17 @@ export default Component.extend(NodeDriver, {
} }
}, },
initUseDataStoreCluster() {
const useDataStoreCluster = !!get(this, 'config.datastoreCluster');
set(this, 'config.useDataStoreCluster', useDataStoreCluster);
// Only one should be set at a time
const clearKey = useDataStoreCluster ? 'config.datastore' : 'config.datastoreCluster';
set(this, clearKey, '');
},
updateVappOptions(opts) { updateVappOptions(opts) {
set(this, 'config.vappIpprotocol', opts.vappIpprotocol); set(this, 'config.vappIpprotocol', opts.vappIpprotocol);
set(this, 'config.vappIpallocationpolicy', opts.vappIpallocationpolicy); set(this, 'config.vappIpallocationpolicy', opts.vappIpallocationpolicy);
@ -418,6 +447,13 @@ export default Component.extend(NodeDriver, {
const configCustomAttribute = get(this, 'customAttribute').map((kvp) => `${ kvp.key }=${ kvp.value }`); const configCustomAttribute = get(this, 'customAttribute').map((kvp) => `${ kvp.key }=${ kvp.value }`);
set(this, 'config.customAttribute', configCustomAttribute); set(this, 'config.customAttribute', configCustomAttribute);
const clearKey = get(this, 'config.useDataStoreCluster')
? 'config.datastore'
: 'config.datastoreCluster';
set(this, clearKey, '');
const vappMode = get(this, 'vappMode') const vappMode = get(this, 'vappMode')
if (vappMode === VAPP_MODE_DISABLED) { if (vappMode === VAPP_MODE_DISABLED) {

View File

@ -49,6 +49,7 @@
<p class="help-block"> <p class="help-block">
{{t "nodeDriver.vmwarevsphere.dataCenter.help"}} {{t "nodeDriver.vmwarevsphere.dataCenter.help"}}
</p> </p>
<SelectValueCheck @values={{config.datacenter}} @options={{datacenterContent}} />
</div> </div>
<div class="col span-6"> <div class="col span-6">
@ -64,6 +65,7 @@
<p class="help-block"> <p class="help-block">
{{t "nodeDriver.vmwarevsphere.pool.help"}} {{t "nodeDriver.vmwarevsphere.pool.help"}}
</p> </p>
<SelectValueCheck @values={{config.pool}} @options={{resourcePoolContent}} />
</div> </div>
</div> </div>
@ -71,7 +73,30 @@
<div class="col span-6"> <div class="col span-6">
<label class="acc-label"> <label class="acc-label">
{{t "nodeDriver.vmwarevsphere.dataStore.label"}} {{t "nodeDriver.vmwarevsphere.dataStore.label"}}
<TooltipElement
@type="tooltip-basic"
@tooltipTemplate="tooltip-static"
@model={{t "nodeDriver.vmwarevsphere.dataStore.cluster.tooltip"}}
@inlineBlock={{true}}
>
<BtnToggle
@toggled={{action "toggleUseDataStoreCluster"}}
@checked={{mut config.useDataStoreCluster}}
/>
</TooltipElement>
</label> </label>
{{#if config.useDataStoreCluster}}
<NewSelect
@class="form-control"
@useContentForDefaultValue={{true}}
@content={{dataStoreClusterContent}}
@value={{config.datastoreCluster}}
/>
<p class="help-block">
{{t "nodeDriver.vmwarevsphere.dataStore.cluster.help"}}
</p>
<SelectValueCheck @values={{config.datastoreCluster}} @options={{dataStoreClusterContent}} />
{{else}}
<NewSelect <NewSelect
@class="form-control" @class="form-control"
@useContentForDefaultValue={{true}} @useContentForDefaultValue={{true}}
@ -81,6 +106,8 @@
<p class="help-block"> <p class="help-block">
{{t "nodeDriver.vmwarevsphere.dataStore.help"}} {{t "nodeDriver.vmwarevsphere.dataStore.help"}}
</p> </p>
<SelectValueCheck @values={{config.datastore}} @options={{dataStoreContent}} />
{{/if}}
</div> </div>
<div class="col span-6"> <div class="col span-6">
<label class="acc-label"> <label class="acc-label">
@ -95,6 +122,7 @@
<p class="help-block"> <p class="help-block">
{{t "nodeDriver.vmwarevsphere.folder.help"}} {{t "nodeDriver.vmwarevsphere.folder.help"}}
</p> </p>
<SelectValueCheck @values={{config.folder}} @options={{folderContent}} />
</div> </div>
</div> </div>
@ -112,6 +140,7 @@
<p class="help-block"> <p class="help-block">
{{t "nodeDriver.vmwarevsphere.host.help"}} {{t "nodeDriver.vmwarevsphere.host.help"}}
</p> </p>
<SelectValueCheck @values={{config.hostsystem}} @options={{hostContent}} />
</div> </div>
</div> </div>
{{/accordion-list-item}} {{/accordion-list-item}}
@ -274,6 +303,7 @@
@valueLabel="nodeDriver.vmwarevsphere.network.valueLabel" @valueLabel="nodeDriver.vmwarevsphere.network.valueLabel"
@valuePlaceholder="nodeDriver.vmwarevsphere.network.valuePlaceholder" @valuePlaceholder="nodeDriver.vmwarevsphere.network.valuePlaceholder"
/> />
<SelectValueCheck @values={{config.network}} @options={{networkContent}} />
</div> </div>
</div> </div>

View File

@ -1,6 +1,8 @@
{{#if applyClusterTemplate}} {{#if applyClusterTemplate}}
{{#if (has-override questions=questions paramName=paramName)}} {{#if (has-override questions=questions paramName=paramName)}}
{{yield}} {{yield (hash
hasOverride=true
)}}
{{else}} {{else}}
<div> <div>
{{#if value}} {{#if value}}

View File

@ -1,15 +1,15 @@
import Component from '@ember/component' import Component from '@ember/component'
import ClusterDriver from 'shared/mixins/cluster-driver'; import ClusterDriver from 'shared/mixins/cluster-driver';
import layout from './template'; import layout from './template';
import { import {
get, set, computed, observer, setProperties get, set, computed, observer, setProperties
} from '@ember/object'; } from '@ember/object';
import { sortableNumericSuffix } from 'shared/utils/util'; import { sortableNumericSuffix } from 'shared/utils/util';
import { reject, all } from 'rsvp'; import { reject, all } from 'rsvp';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import { equal } from '@ember/object/computed' import { equal } from '@ember/object/computed';
import $ from 'jquery'; import $ from 'jquery';
import { isEmpty } from '@ember/utils';
const times = [ const times = [
{ {
@ -224,6 +224,8 @@ export default Component.extend(ClusterDriver, {
diskType: 'pd-standard', diskType: 'pd-standard',
region: 'us-west2', region: 'us-west2',
taints: [], taints: [],
useIpAliases: true,
ipPolicyCreateSubnetwork: true,
}); });
setProperties(this, { setProperties(this, {
@ -448,8 +450,14 @@ export default Component.extend(ClusterDriver, {
const subNetworkContent = get(this, 'subNetworkContent') || [] const subNetworkContent = get(this, 'subNetworkContent') || []
if (subNetworkContent.length > 0) { if (subNetworkContent.length > 1) {
set(this, 'config.subNetwork', subNetworkContent[0] && subNetworkContent[0].value) const firstNonNullSubnetMatch = subNetworkContent.find((sn) => !isEmpty(sn.value));
setProperties(this, {
'config.subNetwork': firstNonNullSubnetMatch.value,
'config.ipPolicyCreateSubnetwork': false,
})
const secondaryIpRangeContent = get(this, 'secondaryIpRangeContent') || [] const secondaryIpRangeContent = get(this, 'secondaryIpRangeContent') || []
if (secondaryIpRangeContent.length > 0) { if (secondaryIpRangeContent.length > 0) {
@ -463,6 +471,20 @@ export default Component.extend(ClusterDriver, {
} }
}), }),
subnetworkChange: observer('config.subNetwork', function() {
if (this.saving) {
return;
}
const { config: { subNetwork } } = this;
if (isEmpty(subNetwork)) {
set(this, 'config.ipPolicyCreateSubnetwork', true);
} else {
set(this, 'config.ipPolicyCreateSubnetwork', false);
}
}),
secondaryIpRangeContentChange: observer('secondaryIpRangeContent.[]', 'config.useIpAliases', function() { secondaryIpRangeContentChange: observer('secondaryIpRangeContent.[]', 'config.useIpAliases', function() {
if (this.saving) { if (this.saving) {
return; return;
@ -480,8 +502,15 @@ export default Component.extend(ClusterDriver, {
return; return;
} }
if (!get(this, 'config.useIpAliases')) { if (get(this, 'config.useIpAliases')) {
set(this, 'config.enablePrivateNodes', false) if (!isEmpty(this.config.subNetwork)) {
set(this, 'config.ipPolicyCreateSubnetwork', false);
}
} else {
setProperties(this, {
'config.enablePrivateNodes': false,
'config.ipPolicyCreateSubnetwork': false,
});
} }
}), }),
@ -544,43 +573,62 @@ export default Component.extend(ClusterDriver, {
return zoneChoices.filter((z) => (z.name || '').startsWith(locationName) && z.name !== zone) return zoneChoices.filter((z) => (z.name || '').startsWith(locationName) && z.name !== zone)
}), }),
networkContent: computed('networks', function() { networkContent: computed('networks', 'config.zone', function() {
return get(this, 'networks') return get(this, 'networks')
}), }),
subNetworkContent: computed('subNetworks.[]', 'config.network', function() { subNetworkContent: computed('subNetworks.[]', 'config.network', 'config.zone', function() {
const subNetworks = get(this, 'subNetworks') || [] const {
const networkName = get(this, 'config.network') config: { network: networkName },
networkContent,
subNetworks = [],
} = this;
const out = subNetworks.filter((s) => { const filteredSubnets = (subNetworks || []).filter((s) => {
const { network = '' } = s const network = networkContent.findBy('selfLink', s.network);
const arr = network.split('/') || [] const networkDisplayName = network.name;
const networkDisplayName = arr[arr.length - 1]
if (networkDisplayName === networkName) { if (networkDisplayName === networkName) {
return true return true
} }
}) });
const mappedSubnets = filteredSubnets.map((o) => {
const network = networkContent.findBy('selfLink', o.network);
const networkDisplayName = network.name;
return out.map((o) => {
return { return {
label: `${ o.name }(${ o.ipCidrRange })`, label: `${ o.name }(${ o.ipCidrRange })`,
value: o.name, value: o.name,
secondaryIpRanges: o.secondaryIpRanges, secondaryIpRanges: o.secondaryIpRanges,
networkDisplayName
} }
}) });
const defaultSubnetAry = [{
label: this.intl.t('clusterNew.googlegke.ipPolicyCreateSubnetwork.autoLabel'),
value: '',
}];
return [...defaultSubnetAry, ...mappedSubnets];
}), }),
secondaryIpRangeContent: computed('subNetworkContent.[]', 'config.network', function() { secondaryIpRangeContent: computed('subNetworkContent.[]', 'config.network', function() {
const subNetworkContent = get(this, 'subNetworkContent') const { subNetworkContent = [], config: { network } } = this;
const { secondaryIpRanges = [] } = subNetworkContent const subNetwork = subNetworkContent.findBy('networkDisplayName', network);
if (subNetwork) {
const { secondaryIpRanges = [] } = subNetwork;
return secondaryIpRanges.map((s) => { return secondaryIpRanges.map((s) => {
return { return {
lable: `${ s.rangeName }(${ s.ipCidrRange })`, label: `${ s.rangeName }(${ s.ipCidrRange })`,
value: s.rangeName, value: s.rangeName,
} }
}) });
}
return [];
}), }),
serviceAccountContent: computed('serviceAccounts', function() { serviceAccountContent: computed('serviceAccounts', function() {
@ -593,6 +641,24 @@ export default Component.extend(ClusterDriver, {
return get(this, 'maintenanceWindowTimes').findBy('value', get(this, 'config.maintenanceWindow')) || { label: 'Any Time' }; return get(this, 'maintenanceWindowTimes').findBy('value', get(this, 'config.maintenanceWindow')) || { label: 'Any Time' };
}), }),
shouldAllowDisableCreateSubNetwork: computed('config.subNetwork', function() {
const {
config: { subNetwork },
secondaryIpRangeContent,
editing,
} = this;
if (isEmpty(subNetwork)) {
return true;
}
if (editing && isEmpty(secondaryIpRangeContent)) {
return true;
}
return false;
}),
fetchZones() { fetchZones() {
return get(this, 'globalStore').rawRequest({ return get(this, 'globalStore').rawRequest({
url: '/meta/gkeZones', url: '/meta/gkeZones',

View File

@ -315,14 +315,16 @@
selection=config.enableHorizontalPodAutoscaling selection=config.enableHorizontalPodAutoscaling
value=true value=true
disabled=editing disabled=editing
}} {{t "generic.enabled"}} }}
{{t "generic.enabled"}}
</label> </label>
<label class={{concat (if editing "text-muted") " hand"}}> <label class={{concat (if editing "text-muted") " hand"}}>
{{radio-button {{radio-button
selection=config.enableHorizontalPodAutoscaling selection=config.enableHorizontalPodAutoscaling
value=false value=false
disabled=editing disabled=editing
}} {{t "generic.disabled"}} }}
{{t "generic.disabled"}}
</label> </label>
</div> </div>
</div> </div>
@ -345,6 +347,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col span-6"> <div class="col span-6">
<label class="acc-label"> <label class="acc-label">
@ -385,9 +388,6 @@
{{/if}} {{/if}}
</div> </div>
{{#advanced-section advanced=clusterAdvanced}}
<h4 class="mt-20 mb-10">{{t "clusterNew.googlegke.header.iPAllocationPolicy"}}</h4>
<hr/>
<div class="row"> <div class="row">
<div class="col span-6"> <div class="col span-6">
<label class="acc-label"> <label class="acc-label">
@ -400,43 +400,18 @@
value=true value=true
disabled=editing disabled=editing
}} }}
{{t "generic.yes"}} {{t "generic.enabled"}}
</label> </label>
<label class={{concat (if editing "text-muted") " hand"}}> <label class={{concat (if editing "text-muted") " hand"}}>
{{radio-button {{radio-button
selection=config.useIpAliases selection=config.useIpAliases
value=false value=false
disabled=editing disabled=(or editing (not config.subNetwork))
}}
{{t "generic.no"}}
</label>
</div>
</div>
{{#if config.useIpAliases}}
<div class="col span-6">
<label class="acc-label">
{{t "clusterNew.googlegke.ipPolicyCreateSubnetwork.label"}}
</label>
<div class="form-control-static">
<label class={{concat (if editing "text-muted") " mr-20 hand"}}>
{{radio-button
selection=config.ipPolicyCreateSubnetwork
value=true
disabled=editing
}}
{{t "generic.enabled"}}
</label>
<label class={{concat (if editing "text-muted") " hand"}} class={{concat (if (eq secondaryIpRangeContent.length 0) "text-muted") " hand"}}>
{{radio-button
selection=config.ipPolicyCreateSubnetwork
value=false
disabled=(or editing (eq secondaryIpRangeContent.length 0))
}} }}
{{t "generic.disabled"}} {{t "generic.disabled"}}
</label> </label>
</div> </div>
</div> </div>
{{/if}}
</div> </div>
{{#if config.useIpAliases}} {{#if config.useIpAliases}}
{{#if (and config.ipPolicyCreateSubnetwork config.useIpAliases)}} {{#if (and config.ipPolicyCreateSubnetwork config.useIpAliases)}}
@ -490,6 +465,8 @@
{{/if}} {{/if}}
{{/if}} {{/if}}
{{#advanced-section advanced=clusterAdvanced}}
<h4 class="mt-20 mb-10"> <h4 class="mt-20 mb-10">
{{t "clusterNew.googlegke.header.privateCluster"}} {{t "clusterNew.googlegke.header.privateCluster"}}
</h4> </h4>

View File

@ -40,7 +40,7 @@
@computedState={{not (eq selectedCloudProvider "none")}} @computedState={{not (eq selectedCloudProvider "none")}}
> >
{{#input-or-display {{#input-or-display
editable=(not-eq mode "view") editable=(or (and (eq mode "new") (or (not applyClusterTemplate) (and (eq mode "new") selectedCloudProviderOverrideAvailable))) clusterTemplateCreate)
value=selectedCloudProvider value=selectedCloudProvider
}} }}
<div class="col span-6"> <div class="col span-6">
@ -134,7 +134,7 @@
</div> </div>
{{/input-or-display}} {{/input-or-display}}
</CheckComputedOverride> </CheckComputedOverride>
{{#unless (eq selectedCloudProvider "none")}} {{#if (and (not-eq selectedCloudProvider "none") (eq mode "new"))}}
<div class="col span-6"> <div class="col span-6">
<BannerMessage <BannerMessage
@color="bg-info mt-0 mb-0" @color="bg-info mt-0 mb-0"
@ -142,7 +142,7 @@
@message={{t "cloudProvider.warning"}} @message={{t "cloudProvider.warning"}}
/> />
</div> </div>
{{/unless}} {{/if}}
</div> </div>
{{#if (eq selectedCloudProvider "azure")}} {{#if (eq selectedCloudProvider "azure")}}

View File

@ -16,9 +16,10 @@
@paramName="rancherKubernetesEngineConfig.network.plugin" @paramName="rancherKubernetesEngineConfig.network.plugin"
@clusterTemplateRevision={{clusterTemplateRevision.clusterConfig}} @clusterTemplateRevision={{clusterTemplateRevision.clusterConfig}}
@applyClusterTemplate={{applyClusterTemplate}} @applyClusterTemplate={{applyClusterTemplate}}
as |override|
> >
{{#input-or-display {{#input-or-display
editable=(eq mode "new") editable=(or (and (eq mode "new") (or (not applyClusterTemplate) override.hasOverride)) clusterTemplateCreate)
value=config.network.plugin value=config.network.plugin
}} }}
{{new-select {{new-select

View File

@ -0,0 +1,34 @@
import Component from '@ember/component';
import layout from './template';
import { computed, get } from '@ember/object';
import StatefulPromise from 'shared/utils/stateful-promise';
export default Component.extend({
layout,
optionValues: computed.mapBy('asyncOptions.value', 'value'),
asyncOptions: computed('content', function() {
return StatefulPromise.wrap(get(this, 'options'), []);
}),
valueArray: computed('values', function() {
const values = get(this, 'values');
return Array.isArray(values)
? values
: [values];
}),
missingValues: computed('valueArray', 'optionValues', function() {
const optionValues = get(this, 'optionValues');
if (optionValues.length === 0) {
return [];
}
return get(this, 'valueArray').filter((value) => {
return optionValues.indexOf(value) === -1
});
}),
showMessaging: computed('values', 'missingValues.length', function() {
return get(this, 'values') && get(this, 'missingValues.length') > 0;
})
});

View File

@ -0,0 +1,10 @@
{{#if showMessaging}}
<div class="select-value-check text-small text-warning">
{{t "selectValueCheck.message" values=missingValues.length}}
<ul class="list-small">
{{#each missingValues as |missingValue|}}
<li>"{{missingValue}}"</li>
{{/each}}
</ul>
</div>
{{/if}}

View File

@ -1,4 +1,4 @@
import { schedule, cancel, later } from '@ember/runloop'; import { schedule, cancel, later, next } from '@ember/runloop';
import Mixin from '@ember/object/mixin'; import Mixin from '@ember/object/mixin';
import { get, set, setProperties } from '@ember/object'; import { get, set, setProperties } from '@ember/object';
import Ember from 'ember'; import Ember from 'ember';
@ -121,17 +121,17 @@ export default Mixin.create({
// console.log(this.label, (forceRemove ? 'Remove' : 'Change'), type +':'+ event.data.id, projectId); // console.log(this.label, (forceRemove ? 'Remove' : 'Change'), type +':'+ event.data.id, projectId);
if ( get(this, 'updateProjectStore') && projectId && projectStore.hasType(type) ) { if ( get(this, 'updateProjectStore') && projectId && checkStoreHasType(projectStore, type) ) {
// console.log(' Update project store', type, event.data.id, projectId); // console.log(' Update project store', type, event.data.id, projectId);
updateStore(projectStore, event.data, forceRemove); updateStore(projectStore, event.data, forceRemove);
} }
if ( get(this, 'updateClusterStore') && clusterStore.hasType(type) ) { if ( get(this, 'updateClusterStore') && checkStoreHasType(clusterStore, type) ) {
// console.log(' Update cluster store', type, event.data.id); // console.log(' Update cluster store', type, event.data.id);
updateStore(clusterStore, event.data, forceRemove); updateStore(clusterStore, event.data, forceRemove);
} }
if ( get(this, 'updateGlobalStore') && globalStore.hasType(type) ) { if ( get(this, 'updateGlobalStore') && checkStoreHasType(globalStore, type)) {
// console.log(' Update global store', type, event.data.id); // console.log(' Update global store', type, event.data.id);
updateStore(globalStore, event.data, forceRemove); updateStore(globalStore, event.data, forceRemove);
} }
@ -143,6 +143,10 @@ export default Mixin.create({
Ember.endPropertyChanges(); Ember.endPropertyChanges();
// console.log(`Processed ${count} ${this.label} change events`); // console.log(`Processed ${count} ${this.label} change events`);
function checkStoreHasType(store, type) {
return next(() => store.hasType(type));
}
function updateStore(store, data, forceRemove = false) { function updateStore(store, data, forceRemove = false) {
// Update the state to removed before we remove it from store // Update the state to removed before we remove it from store
if ( forceRemove ) { if ( forceRemove ) {

View File

@ -0,0 +1 @@
export { default } from 'shared/components/select-value-check/component';

View File

@ -26,7 +26,7 @@
"devDependencies": { "devDependencies": {
"@ember/jquery": "^0.6.0", "@ember/jquery": "^0.6.0",
"@ember/optional-features": "^0.7.0", "@ember/optional-features": "^0.7.0",
"@rancher/ember-api-store": "2.9.4", "@rancher/ember-api-store": "2.9.6",
"ansi_up": "^2.0.2", "ansi_up": "^2.0.2",
"async": "2.1.2", "async": "2.1.2",
"babel-eslint": "^9.0.0", "babel-eslint": "^9.0.0",
@ -65,6 +65,7 @@
"ember-drag-drop": "^0.4.7", "ember-drag-drop": "^0.4.7",
"ember-engines": "^0.8.2", "ember-engines": "^0.8.2",
"ember-export-application-global": "^2.0.0", "ember-export-application-global": "^2.0.0",
"ember-fetch": "^6.5.1",
"ember-flatpickr": "^2.7.0", "ember-flatpickr": "^2.7.0",
"ember-href-to": "^2.0.1", "ember-href-to": "^2.0.1",
"ember-intl": "^4.2.0", "ember-intl": "^4.2.0",

View File

@ -3620,12 +3620,13 @@ clusterNew:
label: Master IP range label: Master IP range
placeholder: e.g. 10.42.0.0/28 placeholder: e.g. 10.42.0.0/28
useIpAliases: useIpAliases:
label: Use Ip Aliases label: Ip Aliases
ipPolicySubnetworkName: ipPolicySubnetworkName:
label: Subnetwork Name label: Subnetwork Name
placeholder: Your Subnetwork Name placeholder: Your Subnetwork Name
ipPolicyCreateSubnetwork: ipPolicyCreateSubnetwork:
label: Create Subnetwork label: Create Subnetwork
autoLabel: Auto Create Subnetwork
ipPolicyClusterSecondaryRangeName: ipPolicyClusterSecondaryRangeName:
label: Cluster Secondary Range Name label: Cluster Secondary Range Name
placeholder: Your Cluster Secondary Range Name placeholder: Your Cluster Secondary Range Name
@ -8313,6 +8314,9 @@ nodeDriver:
valuePlaceholder: "e.g. VM Network" valuePlaceholder: "e.g. VM Network"
help: "Networks to attach VM to" help: "Networks to attach VM to"
dataStore: dataStore:
cluster:
tooltip: Use datastore cluster?
help: "Datastore cluster to create VM on"
label: Data Store label: Data Store
placeholder: "e.g. datastore_cluster_name/datastore_name" placeholder: "e.g. datastore_cluster_name/datastore_name"
help: "Datastore to create VM disk on" help: "Datastore to create VM disk on"
@ -9823,3 +9827,10 @@ pipelineNotification:
recipients: recipients:
required: Recipient is required required: Recipient is required
asMessage: Send a message to asMessage: Send a message to
selectValueCheck:
message: |
{values, plural,
=1 {Please select a new value. The following is no longer valid:}
other {Please select new values. The following are no longer valid:}
}

View File

@ -1121,17 +1121,16 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
"@rancher/ember-api-store@2.9.4": "@rancher/ember-api-store@2.9.6":
version "2.9.4" version "2.9.6"
resolved "https://registry.yarnpkg.com/@rancher/ember-api-store/-/ember-api-store-2.9.4.tgz#84920e719ce2c0306668db7fd031138c1fec8b72" resolved "https://registry.yarnpkg.com/@rancher/ember-api-store/-/ember-api-store-2.9.6.tgz#296195610a418c860dc98325e8aacaa53a159b62"
integrity sha512-Jef11/K9qGZyrSbufnlfDhY9WNfuo1th+azjRjDNwGv/7wrKiOxOquGmdKViWQXxjy8Hvm7RwsjKK5h2f85wpQ== integrity sha512-SkJsDQiBPRzjjggJLT3mLPMJJBTKRTQbSjNdUoS7wjMWGqOzp+/XYtF8raov3cfYRja2D9bPV1HJo8OW2cF7dA==
dependencies: dependencies:
babel-eslint "^10.0.1" babel-eslint "^10.0.1"
broccoli-file-creator "^2.1.1" broccoli-file-creator "^2.1.1"
ember-auto-import "^1.2.19" ember-auto-import "^1.2.19"
ember-cli-babel "^7.1.2" ember-cli-babel "^7.1.2"
ember-cookies "^0.4.0" ember-cookies "^0.4.0"
ember-fetch "^6.5.1"
eslint "^4.19.1" eslint "^4.19.1"
node-fetch "^2.3.0" node-fetch "^2.3.0"
set-cookie-parser "^2.2.1" set-cookie-parser "^2.2.1"