#572 split widget model into separate files

This commit is contained in:
Denys Vuika
2016-08-15 13:46:36 +01:00
parent 9f9187c3da
commit 070323585d
19 changed files with 701 additions and 483 deletions

View File

@@ -26,7 +26,7 @@ import {
import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core'; import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core';
import { FormService } from './../services/form.service'; 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 { TabsWidget } from './widgets/tabs/tabs.widget';
import { ContainerWidget } from './widgets/container/container.widget'; import { ContainerWidget } from './widgets/container/container.widget';

View File

@@ -16,7 +16,7 @@
*/ */
import { Component, Input, AfterViewInit } from '@angular/core'; 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 { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core';
import { PRIMITIVE_WIDGET_DIRECTIVES } from './../index'; import { PRIMITIVE_WIDGET_DIRECTIVES } from './../index';

View File

@@ -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;
}
}

View File

@@ -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 = <boolean> this.params['allowCollapse'];
}
return allowCollapse;
}
isCollapsedByDefault(): boolean {
let collapseByDefault = false;
if (this.isCollapsible() && this.params['collapseByDefault']) {
collapseByDefault = <boolean> 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 = <number> json.numberOfColumns;
this.params = <FormFieldMetadata> 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();
}
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
];
}

View File

@@ -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 = <boolean> json.required;
this._readOnly = <boolean> json.readOnly;
this.overrideId = <boolean> json.overrideId;
this.tab = json.tab;
this.restUrl = json.restUrl;
this.restResponsePath = json.restResponsePath;
this.restIdProperty = json.restIdProperty;
this.restLabelProperty = json.restLabelProperty;
this.colspan = <number> json.colspan;
this.options = <FormFieldOption[]> json.options || [];
this.hasEmptyValue = <boolean> json.hasEmptyValue;
this.className = json.className;
this.optionType = json.optionType;
this.params = <FormFieldMetadata> 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: <id>, name: <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: <id>, name: <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: <id>, name: <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: <id>, name: <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;
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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 {
}

View File

@@ -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<T extends FormWidgetModel> {
[key: string]: T;
}

View File

@@ -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<TabModel> = {};
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;
}
}

View File

@@ -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';

View File

@@ -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;
}
}
}

View File

@@ -30,9 +30,7 @@ import { DisplayTextWidget } from './display-text/display-text.widget';
// core // core
export * from './widget.component'; export * from './widget.component';
export * from './core/index';
// model
export * from './widget.model';
// containers // containers
export * from './tabs/tabs.widget'; export * from './tabs/tabs.widget';

View File

@@ -17,7 +17,7 @@
import { Component, Input, AfterViewInit } from '@angular/core'; import { Component, Input, AfterViewInit } from '@angular/core';
import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-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'; import { ContainerWidget } from './../container/container.widget';
declare let __moduleName: string; declare let __moduleName: string;

View File

@@ -16,7 +16,7 @@
*/ */
import { Input, AfterViewInit } from '@angular/core'; import { Input, AfterViewInit } from '@angular/core';
import { FormFieldModel } from './widget.model'; import { FormFieldModel } from './core/index';
declare let __moduleName: string; declare let __moduleName: string;
declare var componentHandler; declare var componentHandler;

View File

@@ -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 = <boolean> json.required;
this._readOnly = <boolean> json.readOnly;
this.overrideId = <boolean> json.overrideId;
this.tab = json.tab;
this.restUrl = json.restUrl;
this.restResponsePath = json.restResponsePath;
this.restIdProperty = json.restIdProperty;
this.restLabelProperty = json.restLabelProperty;
this.colspan = <number> json.colspan;
this.options = <FormFieldOption[]> json.options || [];
this.hasEmptyValue = <boolean> json.hasEmptyValue;
this.className = json.className;
this.optionType = json.optionType;
this.params = <FormFieldMetadata> 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: <id>, name: <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: <id>, name: <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: <id>, name: <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: <id>, name: <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 = <boolean> this.params['allowCollapse'];
}
return allowCollapse;
}
isCollapsedByDefault(): boolean {
let collapseByDefault = false;
if (this.isCollapsible() && this.params['collapseByDefault']) {
collapseByDefault = <boolean> 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 = <number> json.numberOfColumns;
this.params = <FormFieldMetadata> 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<T extends FormWidgetModel> {
[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<TabModel> = {};
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;
}
}

View File

@@ -19,7 +19,7 @@ import { Injectable } from '@angular/core';
import { Response, Http, Headers, RequestOptions } from '@angular/http'; import { Response, Http, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx'; import { Observable } from 'rxjs/Rx';
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core'; 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'; import { AlfrescoSettingsService } from 'ng2-alfresco-core';
@Injectable() @Injectable()