diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts index b092874ad9..88d9278616 100644 --- a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts +++ b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts @@ -26,7 +26,7 @@ import { import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core'; import { FormService } from './../services/form.service'; -import { FormModel, FormOutcomeModel } from './widgets/widget.model'; +import { FormModel, FormOutcomeModel } from './widgets/core/index'; import { TabsWidget } from './widgets/tabs/tabs.widget'; import { ContainerWidget } from './widgets/container/container.widget'; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts index 2ee4b5da01..12e962b10e 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts @@ -16,7 +16,7 @@ */ import { Component, Input, AfterViewInit } from '@angular/core'; -import { ContainerModel } from './../widget.model'; +import { ContainerModel } from './../core/index'; import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core'; import { PRIMITIVE_WIDGET_DIRECTIVES } from './../index'; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts new file mode 100644 index 0000000000..94216ed655 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts @@ -0,0 +1,28 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormFieldModel } from './form-field.model'; + +export class ContainerColumnModel { + + size: number = 12; + fields: FormFieldModel[] = []; + + hasFields(): boolean { + return this.fields && this.fields.length > 0; + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts new file mode 100644 index 0000000000..3dc7cf78f6 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts @@ -0,0 +1,95 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormWidgetModel } from './form-widget.model'; +import { FormFieldMetadata } from './form-field-metadata'; +import { ContainerColumnModel } from './container-column.model'; +import { FormFieldTypes } from './form-field-types'; +import { FormModel } from './form.model'; +import { FormFieldModel } from './form-field.model'; + +// TODO: inherit FormFieldModel +export class ContainerModel extends FormWidgetModel { + + fieldType: string; + id: string; + name: string; + type: string; + tab: string; + numberOfColumns: number = 1; + params: FormFieldMetadata = {}; + + columns: ContainerColumnModel[] = []; + isExpanded: boolean = true; + + isGroup(): boolean { + return this.type === FormFieldTypes.GROUP; + } + + isCollapsible(): boolean { + let allowCollapse = false; + + if (this.isGroup() && this.params['allowCollapse']) { + allowCollapse = this.params['allowCollapse']; + } + + return allowCollapse; + } + + isCollapsedByDefault(): boolean { + let collapseByDefault = false; + + if (this.isCollapsible() && this.params['collapseByDefault']) { + collapseByDefault = this.params['collapseByDefault']; + } + + return collapseByDefault; + } + + constructor(form: FormModel, json?: any) { + super(form, json); + + if (json) { + this.fieldType = json.fieldType; + this.id = json.id; + this.name = json.name; + this.type = json.type; + this.tab = json.tab; + this.numberOfColumns = json.numberOfColumns; + this.params = json.params || {}; + + let columnSize: number = 12; + if (this.numberOfColumns > 1) { + columnSize = 12 / this.numberOfColumns; + } + + for (let i = 0; i < this.numberOfColumns; i++) { + let col = new ContainerColumnModel(); + col.size = columnSize; + this.columns.push(col); + } + + Object.keys(json.fields).map(key => { + let fields = (json.fields[key] || []).map(f => new FormFieldModel(form, f)); + let col = this.columns[parseInt(key, 10) - 1]; + col.fields = fields; + }); + + this.isExpanded = !this.isCollapsedByDefault(); + } + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-metadata.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-metadata.ts new file mode 100644 index 0000000000..02378e3b41 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-metadata.ts @@ -0,0 +1,20 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface FormFieldMetadata { + [key: string]: any; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-option.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-option.ts new file mode 100644 index 0000000000..81b39fc6c1 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-option.ts @@ -0,0 +1,21 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface FormFieldOption { + id: string; + name: string; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts new file mode 100644 index 0000000000..2b992d33f6 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts @@ -0,0 +1,32 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class FormFieldTypes { + static CONTAINER: string = 'container'; + static GROUP: string = 'group'; + static DROPDOWN: string = 'dropdown'; + static HYPERLINK: string = 'hyperlink'; + static RADIO_BUTTONS: string = 'radio-buttons'; + static DISPLAY_VALUE: string = 'readonly'; + static READONLY_TEXT: string = 'readonly-text'; + + static READONLY_TYPES: string[] = [ + FormFieldTypes.HYPERLINK, + FormFieldTypes.DISPLAY_VALUE, + FormFieldTypes.READONLY_TEXT + ]; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts new file mode 100644 index 0000000000..4a583cf050 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts @@ -0,0 +1,162 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormWidgetModel } from './form-widget.model'; +import { FormFieldOption } from './form-field-option'; +import { FormFieldTypes } from './form-field-types'; +import { FormFieldMetadata } from './form-field-metadata'; +import { FormModel } from './form.model'; + +export class FormFieldModel extends FormWidgetModel { + + private _value: string; + private _readOnly: boolean = false; + + fieldType: string; + id: string; + name: string; + type: string; + required: boolean; + overrideId: boolean; + tab: string; + colspan: number = 1; + options: FormFieldOption[] = []; + restUrl: string; + restResponsePath: string; + restIdProperty: string; + restLabelProperty: string; + hasEmptyValue: boolean; + className: string; + optionType: string; + params: FormFieldMetadata = {}; + hyperlinkUrl: string; + displayText: string; + + get value(): any { + return this._value; + } + + set value(v: any) { + this._value = v; + this.updateForm(); + } + + get readOnly(): boolean { + if (this.form && this.form.readOnly) { + return true; + } + return this._readOnly; + } + + constructor(form: FormModel, json?: any) { + super(form, json); + + if (json) { + this.fieldType = json.fieldType; + this.id = json.id; + this.name = json.name; + this.type = json.type; + this.required = json.required; + this._readOnly = json.readOnly; + this.overrideId = json.overrideId; + this.tab = json.tab; + this.restUrl = json.restUrl; + this.restResponsePath = json.restResponsePath; + this.restIdProperty = json.restIdProperty; + this.restLabelProperty = json.restLabelProperty; + this.colspan = json.colspan; + this.options = json.options || []; + this.hasEmptyValue = json.hasEmptyValue; + this.className = json.className; + this.optionType = json.optionType; + this.params = json.params || {}; + this.hyperlinkUrl = json.hyperlinkUrl; + this.displayText = json.displayText; + + this._value = this.parseValue(json); + this.updateForm(); + } + } + + static isReadOnlyType(type: string) { + return FormFieldTypes.READONLY_TYPES.indexOf(type) > -1; + } + + private parseValue(json: any): any { + let value = json.value; + + /* + This is needed due to Activiti issue related to reading dropdown values as value string + but saving back as object: { id: , name: } + */ + // TODO: needs review + if (json.type === FormFieldTypes.DROPDOWN) { + if (value === '') { + value = 'empty'; + } + } + + /* + This is needed due to Activiti issue related to reading radio button values as value string + but saving back as object: { id: , name: } + */ + if (json.type === FormFieldTypes.RADIO_BUTTONS) { + // Activiti has a bug with default radio button value, + // so try resolving current one with a fallback to first entry + let entry: FormFieldOption[] = this.options.filter(opt => opt.id === value); + if (entry.length > 0) { + value = entry[0].id; + } else if (this.options.length > 0) { + value = this.options[0].id; + } + } + + return value; + } + + updateForm() { + if (this.type === FormFieldTypes.DROPDOWN) { + /* + This is needed due to Activiti reading dropdown values as string + but saving back as object: { id: , name: } + */ + if (this.value === 'empty' || this.value === '') { + this.form.values[this.id] = {}; + } else { + let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value); + if (entry.length > 0) { + this.form.values[this.id] = entry[0]; + } + } + } else if (this.type === FormFieldTypes.RADIO_BUTTONS) { + /* + This is needed due to Activiti issue related to reading radio button values as value string + but saving back as object: { id: , name: } + */ + let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value); + if (entry.length > 0) { + this.form.values[this.id] = entry[0]; + } else if (this.options.length > 0) { + this.form.values[this.id] = this.options[0].id; + } + } else { + if (!FormFieldModel.isReadOnlyType(this.type)) { + this.form.values[this.id] = this.value; + } + } + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-outcome.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-outcome.model.ts new file mode 100644 index 0000000000..dbf37506b2 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-outcome.model.ts @@ -0,0 +1,44 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormWidgetModel } from './form-widget.model'; +import { FormModel } from './form.model'; + +export class FormOutcomeModel extends FormWidgetModel { + + private _id: string; + private _name: string; + + isSystem: boolean = false; + + get id() { + return this._id; + } + + get name() { + return this._name; + } + + constructor(form: FormModel, json?: any) { + super(form, json); + + if (json) { + this._id = json.id; + this._name = json.name; + } + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-values.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-values.ts new file mode 100644 index 0000000000..cfd32ee6a4 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-values.ts @@ -0,0 +1,21 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormFieldMetadata } from './form-field-metadata'; + +export interface FormValues extends FormFieldMetadata { +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-widget.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-widget.model.ts new file mode 100644 index 0000000000..39415c2547 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-widget.model.ts @@ -0,0 +1,41 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormModel } from './form.model'; + +export class FormWidgetModel { + + private _form: FormModel; + private _json: any; + + get form(): FormModel { + return this._form; + } + + get json(): any { + return this._json; + } + + constructor(form: FormModel, json: any) { + this._form = form; + this._json = json; + } +} + +export interface FormWidgetModelCache { + [key: string]: T; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts new file mode 100644 index 0000000000..71409438cd --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts @@ -0,0 +1,160 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormWidgetModelCache } from './form-widget.model'; +import { FormValues } from './form-values'; +import { ContainerModel } from './container.model'; +import { TabModel } from './tab.model'; +import { FormOutcomeModel } from './form-outcome.model'; + +export class FormModel { + + private UNSET_TASK_NAME: string = 'Nameless task'; + + private _id: string; + private _name: string; + private _taskId: string; + private _taskName: string = this.UNSET_TASK_NAME; + + get id(): string { + return this._id; + } + + get name(): string { + return this._name; + } + + get taskId(): string { + return this._taskId; + } + + get taskName(): string { + return this._taskName; + } + + readOnly: boolean = false; + tabs: TabModel[] = []; + fields: ContainerModel[] = []; + outcomes: FormOutcomeModel[] = []; + + values: FormValues = {}; + + private _json: any; + + get json() { + return this._json; + } + + hasTabs(): boolean { + return this.tabs && this.tabs.length > 0; + } + + hasFields(): boolean { + return this.fields && this.fields.length > 0; + } + + hasOutcomes(): boolean { + return this.outcomes && this.outcomes.length > 0; + } + + constructor(json?: any, data?: any, saveOption?: any, readOnly: boolean = false) { + this.readOnly = readOnly; + if (json) { + this._json = json; + + this._id = json.id; + this._name = json.name; + this._taskId = json.taskId; + this._taskName = json.taskName || json.name || this.UNSET_TASK_NAME; + + let tabCache: FormWidgetModelCache = {}; + + this.tabs = (json.tabs || []).map(t => { + let model = new TabModel(this, t); + tabCache[model.id] = model; + return model; + }); + + this.fields = (json.fields || json.formDefinition.fields || []).map(obj => new ContainerModel(this, obj)); + + if (data) { + this.loadData(data); + } + + for (let i = 0; i < this.fields.length; i++) { + let field = this.fields[i]; + if (field.tab) { + let tab = tabCache[field.tab]; + if (tab) { + tab.fields.push(new ContainerModel(this, field.json)); + } + } + } + if (this.isATaskForm()) { + let saveOutcome = new FormOutcomeModel(this, {id: '$save', name: 'Save'}); + saveOutcome.isSystem = true; + + let completeOutcome = new FormOutcomeModel(this, {id: '$complete', name: 'Complete'}); + completeOutcome.isSystem = true; + + let customOutcomes = (json.outcomes || []).map(obj => new FormOutcomeModel(this, obj)); + + this.outcomes = [saveOutcome].concat( + customOutcomes.length > 0 ? customOutcomes : [completeOutcome] + ); + } else { + if (saveOption && saveOption.observers.length > 0) { + let saveOutcome = new FormOutcomeModel(this, {id: '$custom', name: 'Save'}); + saveOutcome.isSystem = true; + + this.outcomes = [saveOutcome]; + } + } + } + } + + // Loads external data and overrides field values + // Typically used when form definition and form data coming from different sources + private loadData(data: any) { + for (let i = 0; i < this.fields.length; i++) { + let containerModel = this.fields[i]; + if (containerModel) { + for (let i = 0; i < containerModel.columns.length; i++) { + let containerModelColumn = containerModel.columns[i]; + if (containerModelColumn) { + for (let i = 0; i < containerModelColumn.fields.length; i++) { + let formField = containerModelColumn.fields[i]; + if (data[formField.id]) { + formField.value = data[formField.id]; + formField.json.value = data[formField.id]; + } + } + } + } + } + + } + } + + /** + * Check if the form is associated to a task or if is only the form definition + * @returns {boolean} + */ + private isATaskForm(): boolean { + return this._json.fields ? true : false; + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts new file mode 100644 index 0000000000..ce68bdba24 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts @@ -0,0 +1,28 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './form-field-metadata'; +export * from './form-values'; +export * from './form-field-types'; +export * from './form-field-option'; +export * from './form-widget.model'; +export * from './form-field.model'; +export * from './form.model'; +export * from './container-column.model'; +export * from './container.model'; +export * from './tab.model'; +export * from './form-outcome.model'; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/tab.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/tab.model.ts new file mode 100644 index 0000000000..e1932ba1f6 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/tab.model.ts @@ -0,0 +1,43 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormWidgetModel } from './form-widget.model'; +import { ContainerModel } from './container.model'; +import { FormModel } from './form.model'; + +export class TabModel extends FormWidgetModel { + + id: string; + title: string; + visibilityCondition: any; + + fields: ContainerModel[] = []; + + hasContent(): boolean { + return this.fields && this.fields.length > 0; + } + + constructor(form: FormModel, json?: any) { + super(form, json); + + if (json) { + this.id = json.id; + this.title = json.title; + this.visibilityCondition = json.visibilityCondition; + } + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/index.ts b/ng2-components/ng2-activiti-form/src/components/widgets/index.ts index f2c0a1e6f1..9e5d480583 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/index.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/index.ts @@ -30,9 +30,7 @@ import { DisplayTextWidget } from './display-text/display-text.widget'; // core export * from './widget.component'; - -// model -export * from './widget.model'; +export * from './core/index'; // containers export * from './tabs/tabs.widget'; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.ts index 75a891ee87..acd9536b84 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.ts @@ -17,7 +17,7 @@ import { Component, Input, AfterViewInit } from '@angular/core'; import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core'; -import { TabModel } from './../widget.model'; +import { TabModel } from './../core/index'; import { ContainerWidget } from './../container/container.widget'; declare let __moduleName: string; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts b/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts index b698afeb3a..7b4123954b 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts @@ -16,7 +16,7 @@ */ import { Input, AfterViewInit } from '@angular/core'; -import { FormFieldModel } from './widget.model'; +import { FormFieldModel } from './core/index'; declare let __moduleName: string; declare var componentHandler; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/widget.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/widget.model.ts deleted file mode 100644 index 180f96cfdb..0000000000 --- a/ng2-components/ng2-activiti-form/src/components/widgets/widget.model.ts +++ /dev/null @@ -1,475 +0,0 @@ -/*! - * @license - * Copyright 2016 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export interface FormFieldMetadata { - [key: string]: any; -} - -export interface FormValues extends FormFieldMetadata { -} - -export class FormFieldTypes { - static CONTAINER: string = 'container'; - static GROUP: string = 'group'; - static DROPDOWN: string = 'dropdown'; - static HYPERLINK: string = 'hyperlink'; - static RADIO_BUTTONS: string = 'radio-buttons'; - static DISPLAY_VALUE: string = 'readonly'; - static READONLY_TEXT: string = 'readonly-text'; - - static READONLY_TYPES: string[] = [ - FormFieldTypes.HYPERLINK, - FormFieldTypes.DISPLAY_VALUE, - FormFieldTypes.READONLY_TEXT - ]; -} - -export class FormWidgetModel { - - private _form: FormModel; - private _json: any; - - get form(): FormModel { - return this._form; - } - - get json(): any { - return this._json; - } - - constructor(form: FormModel, json: any) { - this._form = form; - this._json = json; - } -} - -export interface FormFieldOption { - id: string; - name: string; -} - -export class FormFieldModel extends FormWidgetModel { - - private _value: string; - private _readOnly: boolean = false; - - fieldType: string; - id: string; - name: string; - type: string; - required: boolean; - overrideId: boolean; - tab: string; - colspan: number = 1; - options: FormFieldOption[] = []; - restUrl: string; - restResponsePath: string; - restIdProperty: string; - restLabelProperty: string; - hasEmptyValue: boolean; - className: string; - optionType: string; - params: FormFieldMetadata = {}; - hyperlinkUrl: string; - displayText: string; - - get value(): any { - return this._value; - } - - set value(v: any) { - this._value = v; - this.updateForm(); - } - - get readOnly(): boolean { - if (this.form && this.form.readOnly) { - return true; - } - return this._readOnly; - } - - constructor(form: FormModel, json?: any) { - super(form, json); - - if (json) { - this.fieldType = json.fieldType; - this.id = json.id; - this.name = json.name; - this.type = json.type; - this.required = json.required; - this._readOnly = json.readOnly; - this.overrideId = json.overrideId; - this.tab = json.tab; - this.restUrl = json.restUrl; - this.restResponsePath = json.restResponsePath; - this.restIdProperty = json.restIdProperty; - this.restLabelProperty = json.restLabelProperty; - this.colspan = json.colspan; - this.options = json.options || []; - this.hasEmptyValue = json.hasEmptyValue; - this.className = json.className; - this.optionType = json.optionType; - this.params = json.params || {}; - this.hyperlinkUrl = json.hyperlinkUrl; - this.displayText = json.displayText; - - this._value = this.parseValue(json); - this.updateForm(); - } - } - - static isReadOnlyType(type: string) { - return FormFieldTypes.READONLY_TYPES.indexOf(type) > -1; - } - - private parseValue(json: any): any { - let value = json.value; - - /* - This is needed due to Activiti issue related to reading dropdown values as value string - but saving back as object: { id: , name: } - */ - // TODO: needs review - if (json.type === FormFieldTypes.DROPDOWN) { - if (value === '') { - value = 'empty'; - } - } - - /* - This is needed due to Activiti issue related to reading radio button values as value string - but saving back as object: { id: , name: } - */ - if (json.type === FormFieldTypes.RADIO_BUTTONS) { - // Activiti has a bug with default radio button value, - // so try resolving current one with a fallback to first entry - let entry: FormFieldOption[] = this.options.filter(opt => opt.id === value); - if (entry.length > 0) { - value = entry[0].id; - } else if (this.options.length > 0) { - value = this.options[0].id; - } - } - - return value; - } - - updateForm() { - if (this.type === FormFieldTypes.DROPDOWN) { - /* - This is needed due to Activiti reading dropdown values as string - but saving back as object: { id: , name: } - */ - if (this.value === 'empty' || this.value === '') { - this.form.values[this.id] = {}; - } else { - let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value); - if (entry.length > 0) { - this.form.values[this.id] = entry[0]; - } - } - } else if (this.type === FormFieldTypes.RADIO_BUTTONS) { - /* - This is needed due to Activiti issue related to reading radio button values as value string - but saving back as object: { id: , name: } - */ - let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value); - if (entry.length > 0) { - this.form.values[this.id] = entry[0]; - } else if (this.options.length > 0) { - this.form.values[this.id] = this.options[0].id; - } - } else { - if (!FormFieldModel.isReadOnlyType(this.type)) { - this.form.values[this.id] = this.value; - } - } - } -} - -export class ContainerColumnModel { - - size: number = 12; - fields: FormFieldModel[] = []; - - hasFields(): boolean { - return this.fields && this.fields.length > 0; - } -} - -// TODO: inherit FormFieldModel -export class ContainerModel extends FormWidgetModel { - - fieldType: string; - id: string; - name: string; - type: string; - tab: string; - numberOfColumns: number = 1; - params: FormFieldMetadata = {}; - - columns: ContainerColumnModel[] = []; - isExpanded: boolean = true; - - isGroup(): boolean { - return this.type === FormFieldTypes.GROUP; - } - - isCollapsible(): boolean { - let allowCollapse = false; - - if (this.isGroup() && this.params['allowCollapse']) { - allowCollapse = this.params['allowCollapse']; - } - - return allowCollapse; - } - - isCollapsedByDefault(): boolean { - let collapseByDefault = false; - - if (this.isCollapsible() && this.params['collapseByDefault']) { - collapseByDefault = this.params['collapseByDefault']; - } - - return collapseByDefault; - } - - constructor(form: FormModel, json?: any) { - super(form, json); - - if (json) { - this.fieldType = json.fieldType; - this.id = json.id; - this.name = json.name; - this.type = json.type; - this.tab = json.tab; - this.numberOfColumns = json.numberOfColumns; - this.params = json.params || {}; - - let columnSize: number = 12; - if (this.numberOfColumns > 1) { - columnSize = 12 / this.numberOfColumns; - } - - for (let i = 0; i < this.numberOfColumns; i++) { - let col = new ContainerColumnModel(); - col.size = columnSize; - this.columns.push(col); - } - - Object.keys(json.fields).map(key => { - let fields = (json.fields[key] || []).map(f => new FormFieldModel(form, f)); - let col = this.columns[parseInt(key, 10) - 1]; - col.fields = fields; - }); - - this.isExpanded = !this.isCollapsedByDefault(); - } - } -} - -export class TabModel extends FormWidgetModel { - - id: string; - title: string; - visibilityCondition: any; - - fields: ContainerModel[] = []; - - hasContent(): boolean { - return this.fields && this.fields.length > 0; - } - - constructor(form: FormModel, json?: any) { - super(form, json); - - if (json) { - this.id = json.id; - this.title = json.title; - this.visibilityCondition = json.visibilityCondition; - } - } -} - -export interface WidgetModelCache { - [key: string]: T; -} - -export class FormOutcomeModel extends FormWidgetModel { - - private _id: string; - private _name: string; - - isSystem: boolean = false; - - get id() { - return this._id; - } - - get name() { - return this._name; - } - - constructor(form: FormModel, json?: any) { - super(form, json); - - if (json) { - this._id = json.id; - this._name = json.name; - } - } -} - -export class FormModel { - - private UNSET_TASK_NAME: string = 'Nameless task'; - - private _id: string; - private _name: string; - private _taskId: string; - private _taskName: string = this.UNSET_TASK_NAME; - - get id(): string { - return this._id; - } - - get name(): string { - return this._name; - } - - get taskId(): string { - return this._taskId; - } - - get taskName(): string { - return this._taskName; - } - - readOnly: boolean = false; - tabs: TabModel[] = []; - fields: ContainerModel[] = []; - outcomes: FormOutcomeModel[] = []; - - values: FormValues = {}; - - private _json: any; - - get json() { - return this._json; - } - - hasTabs(): boolean { - return this.tabs && this.tabs.length > 0; - } - - hasFields(): boolean { - return this.fields && this.fields.length > 0; - } - - hasOutcomes(): boolean { - return this.outcomes && this.outcomes.length > 0; - } - - constructor(json?: any, data?: any, saveOption?: any, readOnly: boolean = false) { - this.readOnly = readOnly; - if (json) { - this._json = json; - - this._id = json.id; - this._name = json.name; - this._taskId = json.taskId; - this._taskName = json.taskName || json.name || this.UNSET_TASK_NAME; - - let tabCache: WidgetModelCache = {}; - - this.tabs = (json.tabs || []).map(t => { - let model = new TabModel(this, t); - tabCache[model.id] = model; - return model; - }); - - this.fields = (json.fields || json.formDefinition.fields || []).map(obj => new ContainerModel(this, obj)); - - if (data) { - this.loadData(data); - } - - for (let i = 0; i < this.fields.length; i++) { - let field = this.fields[i]; - if (field.tab) { - let tab = tabCache[field.tab]; - if (tab) { - tab.fields.push(new ContainerModel(this, field.json)); - } - } - } - if (this.isATaskForm()) { - let saveOutcome = new FormOutcomeModel(this, {id: '$save', name: 'Save'}); - saveOutcome.isSystem = true; - - let completeOutcome = new FormOutcomeModel(this, {id: '$complete', name: 'Complete'}); - completeOutcome.isSystem = true; - - let customOutcomes = (json.outcomes || []).map(obj => new FormOutcomeModel(this, obj)); - - this.outcomes = [saveOutcome].concat( - customOutcomes.length > 0 ? customOutcomes : [completeOutcome] - ); - } else { - if (saveOption && saveOption.observers.length > 0) { - let saveOutcome = new FormOutcomeModel(this, {id: '$custom', name: 'Save'}); - saveOutcome.isSystem = true; - - this.outcomes = [saveOutcome]; - } - } - } - } - - // Loads external data and overrides field values - // Typically used when form definition and form data coming from different sources - private loadData(data: any) { - for (let i = 0; i < this.fields.length; i++) { - let containerModel = this.fields[i]; - if (containerModel) { - for (let i = 0; i < containerModel.columns.length; i++) { - let containerModelColumn = containerModel.columns[i]; - if (containerModelColumn) { - for (let i = 0; i < containerModelColumn.fields.length; i++) { - let formField = containerModelColumn.fields[i]; - if (data[formField.id]) { - formField.value = data[formField.id]; - formField.json.value = data[formField.id]; - } - } - } - } - } - - } - } - - /** - * Check if the form is associated to a task or if is only the form definition - * @returns {boolean} - */ - private isATaskForm(): boolean { - return this._json.fields ? true : false; - } -} diff --git a/ng2-components/ng2-activiti-form/src/services/form.service.ts b/ng2-components/ng2-activiti-form/src/services/form.service.ts index 4eb6228416..f41a8ea394 100644 --- a/ng2-components/ng2-activiti-form/src/services/form.service.ts +++ b/ng2-components/ng2-activiti-form/src/services/form.service.ts @@ -19,7 +19,7 @@ import { Injectable } from '@angular/core'; import { Response, Http, Headers, RequestOptions } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import { AlfrescoAuthenticationService } from 'ng2-alfresco-core'; -import { FormValues } from './../components/widgets/widget.model'; +import { FormValues } from './../components/widgets/core/index'; import { AlfrescoSettingsService } from 'ng2-alfresco-core'; @Injectable()