Readonly mode for completed forms (dynamic table)

This commit is contained in:
Denys Vuika 2016-10-26 13:41:16 +01:00 committed by Vito Albano
parent 0ad2c10930
commit 9c916f3797
8 changed files with 195 additions and 14 deletions

View File

@ -244,22 +244,25 @@ will also be executed after your custom code.**
## Supported form widgets
Form renderer provides support for all basic widgets:
- [x] Tabs
- [x] Text
- [x] Multiline Text
- [x] Number
- [x] Checkbox
- [ ] Date
- [x] Date
- Dropdown
* [x] Manual
* [x] REST service
* [ ] Data source
- [x] Typeahead
- [ ] Amount
- [x] Radio buttons
- [x] Amount
- Radio buttons
* [x] Manual
* [x] REST service
- [x] People
- [x] Group of People
- [ ] Dynamic Table
- [x] Dynamic Table
- [x] Hyperlink
- Header
* [x] Plain header

View File

@ -17,11 +17,14 @@
<div *ngFor="let field of form.fields">
<div [ngSwitch]="field.type">
<div *ngSwitchCase="'container'">
<container-widget [content]="field" (formValueChanged)="checkVisibility($event);"></container-widget>
<container-widget [content]="field" (formValueChanged)="checkVisibility($event)"></container-widget>
</div>
<div *ngSwitchCase="'dynamic-table'">
<dynamic-table-widget [content]="field"></dynamic-table-widget>
</div>
<div *ngSwitchCase="'readonly'">
<display-value-widget [field]="field.field" (fieldChanged)="checkVisibility($event)"></display-value-widget>
</div>
<div *ngSwitchDefault>
<span>UNKNOWN WIDGET TYPE: {{field.type}}</span>
</div>

View File

@ -174,6 +174,14 @@ export class FormModel {
result.push(new ContainerModel(this, field));
} else if (field.type === FormFieldTypes.DYNAMIC_TABLE) {
result.push(new DynamicTableModel(this, field));
} else if (field.type === FormFieldTypes.DISPLAY_VALUE) {
// workaround for dynamic table on a completed/readonly form
if (field.params) {
let originalField = field.params['field'];
if (originalField.type === FormFieldTypes.DYNAMIC_TABLE) {
result.push(new DynamicTableModel(this, field));
}
}
}
}

View File

@ -1,3 +1,11 @@
.display-value-widget {
width: 100%;
}
.display-value-widget__dynamic-table {
padding: 8px;
}
.display-value-widget__dynamic-table table {
width: 100%;
}

View File

@ -38,6 +38,29 @@
<a [href]="linkUrl" target="_blank" rel="nofollow">{{linkText}}</a>
</div>
</div>
<div *ngSwitchCase="'dynamic-table'">
<div class="display-value-widget__dynamic-table">
<div>{{field.name}}</div>
<table class="mdl-data-table mdl-js-data-table">
<thead>
<tr>
<th *ngFor="let column of visibleColumns"
class="mdl-data-table__cell--non-numeric">
{{column.name}}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of rows">
<td *ngFor="let column of visibleColumns"
class="mdl-data-table__cell--non-numeric">
{{ getCellValue(row, column) }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div *ngSwitchDefault
class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label text-widget">
<input class="mdl-textfield__input"

View File

@ -21,6 +21,8 @@ import { FormService } from '../../../services/form.service';
import { FormFieldModel } from './../core/form-field.model';
import { FormFieldTypes } from '../core/form-field-types';
import { FormModel } from '../core/form.model';
import { DynamicTableRow } from './../core/dynamic-table-row';
import { DynamicTableColumn } from './../core/dynamic-table-column';
describe('DisplayValueWidget', () => {
@ -539,4 +541,104 @@ describe('DisplayValueWidget', () => {
expect(widget.value).toBe(value);
});
it('should setup [DYNAMIC_TABLE] field', () => {
let columns = [{ id: '1', visible: false }, { id: '2', visible: true }];
let rows = [{}, {}];
widget.field = new FormFieldModel(null, {
type: FormFieldTypes.DISPLAY_VALUE,
params: {
field: {
type: FormFieldTypes.DYNAMIC_TABLE
}
},
columnDefinitions: columns,
value: rows
});
widget.ngOnInit();
expect(widget.columns.length).toBe(2);
expect(widget.columns[0].id).toBe(columns[0].id);
expect(widget.columns[1].id).toBe(columns[1].id);
expect(widget.visibleColumns.length).toBe(1);
expect(widget.visibleColumns[0].id).toBe(columns[1].id);
expect(widget.rows.length).toBe(2);
});
it('should setup [DYNAMIC_TABLE] field with empty schema', () => {
widget.field = new FormFieldModel(null, {
type: FormFieldTypes.DISPLAY_VALUE,
params: {
field: {
type: FormFieldTypes.DYNAMIC_TABLE
}
},
columnDefinitions: null,
value: null
});
widget.ngOnInit();
expect(widget.value).toBeNull();
expect(widget.columns).toEqual([]);
expect(widget.rows).toEqual([]);
});
it('should retrieve default cell value', () => {
const value = '<value>';
let row = <DynamicTableRow> { value: { key: value } };
let column = <DynamicTableColumn> { id: 'key' };
expect(widget.getCellValue(row, column)).toBe(value);
});
it('should retrieve dropdown cell value', () => {
const value = { id: '1', name: 'one' };
let row = <DynamicTableRow> { value: { key: value } };
let column = <DynamicTableColumn> { id: 'key', type: 'Dropdown' };
expect(widget.getCellValue(row, column)).toBe(value.name);
});
it('should fallback to empty cell value for dropdown', () => {
let row = <DynamicTableRow> { value: {} };
let column = <DynamicTableColumn> { id: 'key', type: 'Dropdown' };
expect(widget.getCellValue(row, column)).toBe('');
});
it('should retrieve boolean cell value', () => {
let row1 = <DynamicTableRow> { value: { key: true } };
let row2 = <DynamicTableRow> { value: { key: 'positive' } };
let row3 = <DynamicTableRow> { value: { key: null } };
let column = <DynamicTableColumn> { id: 'key', type: 'Boolean' };
expect(widget.getCellValue(row1, column)).toBe(true);
expect(widget.getCellValue(row2, column)).toBe(true);
expect(widget.getCellValue(row3, column)).toBe(false);
});
it('should retrieve date cell value', () => {
const value = '2016-10-04T00:00:00.000Z';
let row = <DynamicTableRow> { value: { key: value } };
let column = <DynamicTableColumn> { id: 'key', type: 'Date' };
expect(widget.getCellValue(row, column)).toBe('04-10-2016');
});
it('should fallback to empty cell value for date', () => {
let row = <DynamicTableRow> { value: {} };
let column = <DynamicTableColumn> { id: 'key', type: 'Date' };
expect(widget.getCellValue(row, column)).toBe('');
});
it('should retrieve empty text cell value', () => {
let row = <DynamicTableRow> { value: {} };
let column = <DynamicTableColumn> { id: 'key' };
expect(widget.getCellValue(row, column)).toBe('');
});
});

View File

@ -20,6 +20,8 @@ import { WidgetComponent } from './../widget.component';
import { FormFieldTypes } from '../core/form-field-types';
import { FormService } from '../../../services/form.service';
import { FormFieldOption } from './../core/form-field-option';
import { DynamicTableColumn } from './../core/dynamic-table-column';
import { DynamicTableRow } from './../core/dynamic-table-row';
@Component({
moduleId: module.id,
@ -31,9 +33,16 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
value: any;
fieldType: string;
// hyperlink
linkUrl: string;
linkText: string;
// dynamic table
rows: DynamicTableRow[] = [];
columns: DynamicTableColumn[] = [];
visibleColumns: DynamicTableColumn[] = [];
constructor(private formService: FormService) {
super();
}
@ -103,6 +112,16 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
this.linkUrl = this.getHyperlinkUrl(this.field);
this.linkText = this.getHyperlinkText(this.field);
break;
case FormFieldTypes.DYNAMIC_TABLE:
let json = this.field.json;
if (json.columnDefinitions) {
this.columns = json.columnDefinitions.map(obj => <DynamicTableColumn> obj);
this.visibleColumns = this.columns.filter(col => col.visible);
}
if (json.value) {
this.rows = json.value.map(obj => <DynamicTableRow> { selected: false, value: obj });
}
break;
default:
this.value = this.field.value;
break;
@ -141,4 +160,26 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
}
);
}
getCellValue(row: DynamicTableRow, column: DynamicTableColumn): any {
let result = row.value[column.id];
if (column.type === 'Dropdown') {
if (result) {
return result.name;
}
}
if (column.type === 'Boolean') {
return result ? true : false;
}
if (column.type === 'Date') {
if (result) {
return moment(result.split('T')[0], 'YYYY-MM-DD').format('DD-MM-YYYY');
}
}
return result || '';
}
}

View File

@ -16,14 +16,7 @@
*/
import { TextEditorComponent } from './text.editor';
import {
// DynamicTableModel,
DynamicTableRow,
DynamicTableColumn// ,
// DynamicTableColumnOption,
// FormFieldModel,
// FormModel
} from './../../../core/index';
import { DynamicTableRow, DynamicTableColumn } from './../../../core/index';
describe('TextEditorComponent', () => {