comindware.core.ui
Version:
Comindware Core UI provides the basic components like editors, lists, dropdowns, popups that we so desperately need while creating Marionette-based single-page applications.
334 lines (299 loc) • 11.9 kB
JavaScript
const requireCode = require.context('babel-loader!../cases', true);
const requireText = require.context('raw-loader!../cases', true);
import template from 'text-loader!../templates/content.html';
import { valueEditorTypes } from '../meta';
export default Marionette.View.extend({
initialize() {
this.configCollection = new Backbone.Collection();
},
className: 'demo-content_wrapper',
template: Handlebars.compile(template),
templateContext() {
return {
description: this.model.get('description') || ''
};
},
regions: {
caseRepresentationRegion: {
el: '.js-case-representation-region',
replaceElement: true
},
attributesConfigurationRegion: '.js-attributes-configuration-region',
toolbarRegion: '.js-toolbar-region',
codeRegion: '.js-code'
},
ui: {
code: '.js-code'
},
onRender() {
let path;
if (this.model.id) {
path = `${this.model.get('sectionId')}/${this.model.get('groupId')}/${this.model.id}`;
} else {
path = `${this.model.get('sectionId')}/${this.model.get('groupId')}`;
}
const code = requireCode(`./${path}`).default;
this.representationView = code;
const representationView = code();
this.showChildView('caseRepresentationRegion', representationView);
const devTemporaryExcludeModules = ['MultiEditorEditor', 'DropdownEditor', 'DropdownMultiEditor', 'DatalistEditor', 'DatalistSingleEditor'];
this.devIsInteractive = this.model.get('sectionId') === 'editors' && !devTemporaryExcludeModules.includes(this.model.get('groupId'));
if (this.devIsInteractive) {
const defaults = Object.entries(_.omit(representationView.view.options, 'model', 'key')).map(item => ({
attribute: item[0],
default: item[1],
description: 'No description yet'
}));
const attributesConfig = this.model.get('attributesConfig');
attributesConfig.forEach(config => {
const finded = defaults.findIndex(z => z.attribute === config.attribute);
if (finded !== -1) {
Object.assign(defaults[finded], config);
} else {
defaults.push(config);
}
if (config.valueEditorType === valueEditorTypes.OBJECT_TREE) {
const element = defaults[defaults.findIndex(x => x.valueEditorType === valueEditorTypes.OBJECT_TREE)];
element.children = element.nestedattributesConfigs; //TO DO: bind this data to model (i.e. make autocommit working with nested properties too)
}
});
this.configCollection.reset(
defaults.map(config => {
const defaultValue = config.default || defaults[config.attribute];
const selectedValue = config.selectedValue ? config.selectedValue.id || config.selectedValue : defaultValue;
return Object.assign(config, {
selectedValue: config.valueEditorType === 'Datalist' ? { id: selectedValue } : selectedValue,
default: defaultValue
});
})
);
this.showChildView('attributesConfigurationRegion', this.__createAttributesConfigurationView());
}
const toolbarItems = new Backbone.Collection([
{
iconClass: 'plus',
id: 'component',
name: 'Component',
type: 'Checkbox',
severity: 'Low',
resultType: 'CustomClientAction',
context: 'Void',
isChecked: this.__getIsChecked('component')
},
{
iconType: 'Undefined',
id: 'attributes',
name: 'Attributes',
severity: 'None',
defaultTheme: true,
type: 'Checkbox',
isChecked: this.__getIsChecked('attributes')
},
{
iconType: 'Undefined',
id: 'code',
name: 'Code',
severity: 'None',
defaultTheme: true,
type: 'Checkbox',
isChecked: this.__getIsChecked('code', !Core.services.MobileService.isMobile)
}
]);
this.toolbarItems = toolbarItems;
const toolbar = new Core.components.Toolbar({
toolbarItems
});
this.listenTo(toolbar, 'command:execute', model => this.__handleToolbarClick(model));
this.showChildView('toolbarRegion', toolbar);
},
__getIsChecked(id, defaultValue = true) {
const isChecked = sessionStorage.getItem(`demoToolbar:${id}`);
return isChecked == null ? defaultValue : isChecked === 'true';
},
__saveIsChecked(id, value) {
sessionStorage.setItem(`demoToolbar:${id}`, value);
},
onAttach() {
let path;
if (this.model.id) {
path = `${this.model.get('sectionId')}/${this.model.get('groupId')}/${this.model.id}`;
} else {
path = `${this.model.get('sectionId')}/${this.model.get('groupId')}`;
}
const text = requireText(`./${path}`).default;
const textView = new Core.form.editors.CodeEditor({
model: new Backbone.Model({
code: text
}),
schema: {
type: 'Code',
autocommit: true,
mode: 'script',
readonly: true,
lineSeparator: '\n',
showDebug: false
},
key: 'code'
});
this.showChildView('codeRegion', textView);
textView.setReadonly(true);
this.__reloadEditor();
this.toolbarItems.forEach(model => this.__handleToolbarClick(model));
},
__createAttributesConfigurationView() {
const columns = [
{
key: 'attribute',
type: 'Text',
title: 'Attribute',
sorting: 'asc',
width: '0.2'
},
{
key: 'selectedValue',
schemaExtension: model => this.__getSchemaExtension(model),
editable: true,
readonly: false,
autocommit: true,
title: 'Current value',
sortAsc: (a, b) => (a.get('selectedValue') > b.get('selectedValue') ? 1 : -1),
sortDesc: (a, b) => (a.get('selectedValue') < b.get('selectedValue') ? 1 : -1),
width: '0.2'
},
{
key: 'default',
type: 'Text',
title: 'Default value',
width: '0.2'
},
{
key: 'description',
type: 'Text',
title: 'Description',
width: '0.4'
}
];
const gridController = new Core.list.GridView({
columns,
isTree: this.configCollection.some(x => !!x.get('children')),
childrenAttribute: 'children',
collection: this.configCollection
});
return gridController;
},
__getSchemaExtension(model) {
this.listenTo(model, 'change:selectedValue', () => this.__reloadEditor());
switch (model.get('valueEditorType')) {
case 'Datalist': {
const valuesArray = model
.get('values')
.split(',')
.map(ch => ({ id: ch.trim() }));
if (!model.get('selectedValue')) {
model.set('selectedValue', { id: model.get('default') });
}
return {
type: 'Datalist',
collection: new Backbone.Collection(valuesArray),
allowEmptyValue: false,
displayAttribute: 'id'
};
}
case 'Number': {
return {
type: 'Number'
};
}
case valueEditorTypes.ARRAY: {
return {
type: 'Text'
};
}
default:
if (!model.get('selectedValue')) {
model.set('selectedValue', model.get('default'));
}
return {
type: 'Text'
};
}
},
__reloadEditor() {
if (this.devIsInteractive) {
const __mapSelectedValue = (model, options) => {
if (options && options.isArray) {
const string = model.selectedValue;
return string
? string
.trim()
.slice(1, string.length - 1)
.split(',')
.map(x => x.trim())
.map(x => x.split("'")[1] || new RegExp(x.split('/')[1]))
: '';
}
if (model.selectedValue) {
return model.valueEditorType === 'Datalist' ? (Array.isArray(model.selectedValue) ? model.selectedValue[0].id : model.selectedValue.id) : model.selectedValue;
}
};
const caseView = this.getChildView('caseRepresentationRegion').view;
const attributes = caseView.model ? caseView.model.attributes : caseView.options.attributes;
const schema = {};
this.configCollection.toJSON().map(configModel => {
let attribute;
switch (configModel.valueEditorType) {
case valueEditorTypes.ARRAY:
attribute = __mapSelectedValue(configModel, { isArray: true });
break;
// TO DO: case valueEditorTypes.OBJECT_TREE:
// attribute = __mapSomeHow(configModel.children);
// break;
default:
attribute = this.__tryParse(__mapSelectedValue(configModel));
break;
}
return Object.assign(schema, { [configModel.attribute]: attribute });
});
this.detachChildView('caseRepresentationRegion');
this.showChildView(
'caseRepresentationRegion',
this.representationView({
attributes,
schema
})
);
}
},
__tryParse(string) {
switch (string) {
case 'undefined':
return undefined;
case 'null':
return null;
default:
try {
const res = JSON.parse(string);
return res;
} catch (e) {
return string;
}
}
},
__handleToolbarClick(model) {
const modelIsChecked = model.get('isChecked');
this.__saveIsChecked(model.id, modelIsChecked);
switch (model.id) {
case 'component':
this.$('.js-case-representation-region').toggle(model.get('isChecked'));
break;
case 'attributes':
this.$('.js-attributes-configuration-region').toggle(model.get('isChecked'));
break;
case 'code':
this.$('.demo-content__code').toggle(model.get('isChecked'));
break;
default:
break;
}
}
});