mirror of https://github.com/rancher/ui.git
213 lines
5.8 KiB
JavaScript
213 lines
5.8 KiB
JavaScript
import Component from '@ember/component';
|
|
import ModalBase from 'shared/mixins/modal-base';
|
|
import layout from './template';
|
|
import { get, set, computed, setProperties } from '@ember/object';
|
|
import { inject as service } from '@ember/service';
|
|
import {
|
|
loadScript,
|
|
loadStylesheet,
|
|
proxifyUrl
|
|
} from 'shared/utils/load-script';
|
|
import { empty } from '@ember/object/computed';
|
|
import { allSettled, resolve } from 'rsvp';
|
|
import Preload from 'ui/mixins/preload';
|
|
import C from 'ui/utils/constants';
|
|
|
|
export default Component.extend(ModalBase, Preload, {
|
|
growl: service(),
|
|
modalService: service('modal'),
|
|
globalStore: service(),
|
|
intl: service(),
|
|
|
|
layout,
|
|
model: null,
|
|
driver: null,
|
|
onAdd: null,
|
|
|
|
loading: true,
|
|
editing: false,
|
|
cloning: false,
|
|
allNodeDrivers: null,
|
|
|
|
needReloadSchema: false,
|
|
reloadingSchema: false,
|
|
schemaReloaded: false,
|
|
customDrivers: null,
|
|
rejectedDriverIds: null,
|
|
|
|
showPicker: empty('model.id'),
|
|
|
|
didReceiveAttrs() {
|
|
const opts = get(this, 'modalService.modalOpts') || {};
|
|
const originalModel = get(opts, 'nodeTemplate');
|
|
let { driver } = this;
|
|
let override = get(opts, 'driver');
|
|
let newModel = null;
|
|
let editing = false;
|
|
let cloning = false;
|
|
|
|
if (get(opts, 'edit')) {
|
|
newModel = originalModel.clone();
|
|
editing = true;
|
|
} else if (get(opts, 'clone')) {
|
|
newModel = originalModel.cloneForNew();
|
|
editing = true;
|
|
cloning = true;
|
|
}
|
|
|
|
|
|
if ( originalModel ) {
|
|
setProperties(this, {
|
|
model: newModel,
|
|
originalModel,
|
|
editing,
|
|
cloning,
|
|
})
|
|
} else {
|
|
set(this, 'model', get(this, 'globalStore').createRecord({ type: 'nodeTemplate', }));
|
|
}
|
|
|
|
if ( override ) {
|
|
driver = override;
|
|
|
|
set(this, 'showPicker', false);
|
|
}
|
|
|
|
set(this, 'onAdd', get(opts, 'onAdd'));
|
|
|
|
// need to reload the schemas to fetch any new custom node template schemas so they are available for the availableDrivers
|
|
return this.loadSchemas('globalStore').then(() => {
|
|
return get(this, 'globalStore').findAll('nodeDriver').then((allNodeDrivers) => {
|
|
set(this, 'allNodeDrivers', allNodeDrivers);
|
|
|
|
const active = get(this, 'availableDrivers');
|
|
|
|
if ( !driver || !active.findBy('name', driver) ) {
|
|
driver = get(active, 'firstObject.name');
|
|
}
|
|
|
|
set(this, 'driver', driver);
|
|
|
|
return this.loadCustomUi().then(() => {
|
|
set(this, 'loading', false);
|
|
})
|
|
});
|
|
});
|
|
},
|
|
|
|
actions: {
|
|
switchDriver(name) {
|
|
set(this, 'driver', name);
|
|
},
|
|
|
|
saved() {
|
|
const fn = get(this, 'onAdd');
|
|
const model = get(this, 'model');
|
|
|
|
if ( fn ) {
|
|
fn(model);
|
|
}
|
|
},
|
|
|
|
hidePicker() {
|
|
this.set('showPicker', false);
|
|
},
|
|
},
|
|
|
|
availableDrivers: computed('allNodeDrivers.@each.state', 'rejectedDriverIds.[]', function() {
|
|
const out = [];
|
|
const rejectedDriverIds = get(this, 'rejectedDriverIds') || [];
|
|
const drivers = get(this, 'allNodeDrivers').filter((driver) => {
|
|
if (get(driver, 'state') === 'active' && !rejectedDriverIds.includes(get(driver, 'id'))) {
|
|
return driver;
|
|
}
|
|
}).sortBy('name');
|
|
|
|
drivers.forEach((driver) => {
|
|
const configName = `${ get(driver, 'name') }Config`;
|
|
const driverSchema = get(this, 'globalStore').getById('schema', configName.toLowerCase());
|
|
|
|
if ( driverSchema ) {
|
|
out.push(driver);
|
|
}
|
|
});
|
|
|
|
return out;
|
|
}),
|
|
|
|
availableDriversGroups: computed('availableDrivers.@each.state', function() {
|
|
const { availableDrivers } = this;
|
|
const group = [];
|
|
let groupIndex = 0;
|
|
|
|
availableDrivers.forEach((item, index) => {
|
|
if (index % 5 === 0) {
|
|
group.push([item]);
|
|
groupIndex++;
|
|
} else {
|
|
group[groupIndex - 1].push(item);
|
|
}
|
|
});
|
|
|
|
return group;
|
|
}),
|
|
|
|
driverObj: computed('availableDrivers', 'driver', function() {
|
|
return get(this, 'availableDrivers').filterBy('name', get(this, 'driver'))[0];
|
|
}),
|
|
|
|
uiFieldHints: computed('driverObj.annotations.[]', function() {
|
|
const uiFieldHints = get(this, 'driverObj.annotations')[C.LABEL.UI_HINTS] || null;
|
|
|
|
if (uiFieldHints) {
|
|
return JSON.parse(uiFieldHints);
|
|
} else {
|
|
return {};
|
|
}
|
|
}),
|
|
|
|
// Loads the custom UI CSS/JS for drivers that have a uiUrl,
|
|
loadCustomUi() {
|
|
const promises = [];
|
|
|
|
let customDrivers = (get(this, 'customDrivers') || []);
|
|
|
|
get(this, 'availableDrivers').forEach((driver) => {
|
|
const name = get(driver, 'name');
|
|
const uiUrl = get(driver, 'uiUrl');
|
|
|
|
if ( uiUrl ) {
|
|
if (!customDrivers.includes(name)) {
|
|
customDrivers.pushObject(name);
|
|
}
|
|
const jsUrl = proxifyUrl(driver.uiUrl, this.get('app.proxyEndpoint'));
|
|
const cssUrl = proxifyUrl(driver.uiUrl.replace(/\.js$/, '.css'), this.get('app.proxyEndpoint'));
|
|
|
|
promises.push(loadScript(jsUrl, `driver-ui-js-${ name }`));
|
|
promises.push(loadStylesheet(cssUrl, `driver-ui-css-${ name }`));
|
|
}
|
|
});
|
|
|
|
set(this, 'customDrivers', customDrivers);
|
|
|
|
return allSettled(promises).then((results) => {
|
|
let rejectedResutls = results.filterBy('state', 'rejected');
|
|
|
|
if (rejectedResutls.length >= 1) {
|
|
let rejectedIds = rejectedResutls.map((rej) => {
|
|
return ( get(rej, 'reason.srcElement.id') || '').split('-').get('lastObject')
|
|
}).compact().uniq();
|
|
|
|
set(this, 'rejectedDriverIds', rejectedIds);
|
|
|
|
rejectedIds.forEach((reject) => {
|
|
this.growl.fromError(this.intl.t('nodeDriver.externalError', { driverName: reject }));
|
|
});
|
|
}
|
|
|
|
resolve();
|
|
});
|
|
},
|
|
|
|
});
|