C:/GoDev/src/TCSTK-Angular/projects/tibco-tcstk/tc-liveapps-lib/src/lib/components/live-apps-form-preview/live-apps-form-preview.component.ts
selector | tcla-live-apps-form-preview |
styleUrls | ./live-apps-form-preview.component.css |
templateUrl | ./live-apps-form-preview.component.html |
constructor(processService: TcCaseProcessesService)
|
||||||
Parameters :
|
appIds | |
Type : string[]
|
|
formConfig | |
Type : FormConfig
|
|
formsFramework | |
options | |
Type : any[]
|
|
sandbox | |
Type : string
|
|
schema | |
Type : any
|
|
Default value : {}
|
|
formConfigUpdate | |
Type : EventEmitter<FormConfig>
|
|
~event saveFormConfiguration : save form config ~payload any : forms config object |
ngOnChanges | ||||||
ngOnChanges(changes: SimpleChanges)
|
||||||
Parameters :
Returns :
void
|
aceEditorOptions |
Type : any
|
Default value : {
maxLines: 1000,
printMargin: false,
showGutter: true,
autoScrollEditorIntoView: true
}
|
autoLayout |
Type : any[]
|
createDefaultSchema |
Default value : () => {...}
|
data |
Type : any
|
dataPanel |
Type : MatExpansionPanel
|
Decorators :
@ViewChild('dataPanel', {static: false})
|
dropData |
Default value : () => {...}
|
dropLayout |
Default value : () => {...}
|
formDataJSON |
Type : string
|
formSchemaJSON |
Type : string
|
Public formsFramework |
Type : string
|
Default value : 'material-design'
|
getProcessFormConfig |
Default value : () => {...}
|
handleAppSelection |
Default value : () => {...}
|
handleProcessSelection |
Default value : () => {...}
|
handleRenderedLayout |
Default value : () => {...}
|
handleSaveFormConfig |
Default value : () => {...}
|
initialLayout |
Type : any[]
|
layout |
Type : any[]
|
layoutChangeString |
Type : string
|
layoutString |
Type : string
|
openLayoutDocsTab |
Default value : () => {...}
|
parseLayoutString |
Default value : () => {...}
|
renderedFormComponent |
Type : RenderedFormComponent
|
Decorators :
@ViewChild(RenderedFormComponent, {static: false})
|
saveSampleData |
Default value : () => {...}
|
selectedApp |
Type : CaseType
|
selectedProcess |
Type : Process
|
selectedProcessFormConfig |
Type : ProcessFormConfig
|
setProcessFormConfig |
Default value : () => {...}
|
updateDataJSON |
Default value : () => {...}
|
updateLayout |
Default value : () => {...}
|
useAutoLayout |
Default value : () => {...}
|
useBasicLayout |
Default value : () => {...}
|
useExampleLayout |
Default value : () => {...}
|
useNewLayout |
Default value : () => {...}
|
FormsFramework | ||||
setFormsFramework(formsFramework)
|
||||
Parameters :
Returns :
void
|
import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild} from '@angular/core';
import {CaseType, JsonSchema, Process} from '../../models/liveappsdata';
import {TcCaseProcessesService} from '../../services/tc-case-processes.service';
import {MatExpansionPanel} from '@angular/material/expansion';
import {FormConfig, ProcessFormConfig} from '../../models/tc-liveapps-config';
import {TcCoreCommonFunctions} from '@tibco-tcstk/tc-core-lib';
import {RenderedFormComponent} from '@tibco-tcstk/tc-forms-lib';
import {TcFormConfigService} from '../../services/tc-form-config.service';
import {parse} from 'ts-node';
@Component({
selector: 'tcla-live-apps-form-preview',
templateUrl: './live-apps-form-preview.component.html',
styleUrls: ['./live-apps-form-preview.component.css']
})
export class LiveAppsFormPreviewComponent implements OnChanges {
@Input() schema: any = {};
@Input() options: any[];
@Input() appIds: string[];
@Input() sandbox: string;
@Input() formConfig: FormConfig;
public formsFramework = 'material-design';
@Input('formsFramework') set FormsFramework(formsFramework) {
if (formsFramework){
this.formsFramework = formsFramework;
}
}
/**
* ~event saveFormConfiguration : save form config
* ~payload any : forms config object
*/
@Output() formConfigUpdate: EventEmitter<FormConfig> = new EventEmitter<FormConfig>();
@ViewChild('dataPanel', {static: false}) dataPanel: MatExpansionPanel;
@ViewChild(RenderedFormComponent, {static: false}) renderedFormComponent: RenderedFormComponent;
layout: any[];
formSchemaJSON: string;
formDataJSON: string;
autoLayout: any[];
initialLayout: any[];
layoutString: string;
layoutChangeString: string;
data: any;
aceEditorOptions: any = {
maxLines: 1000,
printMargin: false,
showGutter: true,
autoScrollEditorIntoView: true
};
selectedProcessFormConfig: ProcessFormConfig;
selectedApp: CaseType;
selectedProcess: Process;
constructor(private processService: TcCaseProcessesService) { }
getProcessFormConfig = (formTag: string): ProcessFormConfig => {
let pfc;
if (this.formConfig && this.formConfig.processFormConfigs) {
pfc = this.formConfig.processFormConfigs.filter(fc => {
return fc.formTag === formTag;
});
}
return (pfc && pfc.length > 0) ? pfc[0] : undefined;
}
setProcessFormConfig = (formTag: string, layout?: any, data?: string) => {
if (!this.formConfig) {
this.formConfig = new FormConfig();
}
if (!this.formConfig.processFormConfigs) {
this.formConfig.processFormConfigs = [];
}
let updatedConfig = false;
this.formConfig.processFormConfigs.forEach(fc => {
if (fc.formTag === formTag) {
if (layout === 'RESET') {
fc.layout = undefined;
} else if (layout) {
fc.layout = layout;
}
if (data === 'RESET') {
fc.data = undefined;
} else if (data) {
fc.data = data;
}
if (!fc.data && !fc.layout) {
// no point keeping the config if there is no value
this.formConfig.processFormConfigs = this.formConfig.processFormConfigs.filter(fck => fck.formTag !== fc.formTag);
}
updatedConfig = true;
}
});
if (!updatedConfig) {
if (data || layout) {
const newConfig = new ProcessFormConfig().deserialize(
{
formTag,
processId: this.selectedProcess.id,
processType: this.selectedProcess.processType,
layout: (layout === 'RESET' ? undefined : layout),
data: (data === 'RESET' ? undefined : data),
}
);
this.formConfig.processFormConfigs.push(newConfig);
}
}
}
parseLayoutString = (layoutString: string): any => {
let newFormObject: any = null;
// tslint:disable-next-line:no-eval
eval('newFormObject = ' + layoutString);
return newFormObject;
}
updateLayout = (newLayout: string) => {
// if (this.layout !== newLayout) {
this.layout = this.parseLayoutString(newLayout);
this.layoutChangeString = newLayout;
this.renderedFormComponent.updateLayout(newLayout);
this.setProcessFormConfig(this.selectedProcess.formTag, this.layoutChangeString);
// }
}
updateDataJSON = (newDataJSON) => {
this.data = JSON.parse(newDataJSON);
this.setProcessFormConfig(this.selectedProcess.formTag, undefined, newDataJSON);
}
handleAppSelection = (app: CaseType) => {
this.selectedProcess = undefined;
this.selectedApp = app;
this.layout = undefined;
this.data = undefined;
this.formDataJSON = undefined;
this.schema = undefined;
}
handleProcessSelection = (process: Process) => {
this.selectedProcessFormConfig = undefined;
this.selectedProcess = undefined;
this.layout = undefined;
this.layoutString = undefined;
this.data = undefined;
this.formDataJSON = undefined;
this.schema = undefined;
const processFormConfig = this.getProcessFormConfig(process.formTag);
this.selectedProcessFormConfig = processFormConfig;
if (processFormConfig && processFormConfig.layout) {
this.layout = this.parseLayoutString(processFormConfig.layout);
this.layoutChangeString = processFormConfig.layout;
this.layoutString = processFormConfig.layout;
// this.renderedFormComponent.updateLayout(processFormConfig.layout);
this.initialLayout = this.layout;
} else {
this.layout = undefined;
}
if (processFormConfig && processFormConfig.data) {
this.data = JSON.parse(processFormConfig.data);
} else {
this.data = undefined;
}
this.formDataJSON = JSON.stringify(this.data, null, 2);
const tmpSchema = process.jsonSchema ? process.jsonSchema : this.createDefaultSchema(this.selectedApp);
if (tmpSchema && tmpSchema.$schema) {
delete tmpSchema.$schema;
}
this.schema = tmpSchema;
this.formSchemaJSON = JSON.stringify(tmpSchema, null, 2);
this.selectedProcess = process;
if (this.layoutString && this.renderedFormComponent) {
this.renderedFormComponent.updateLayout(this.layoutString);
}
}
createDefaultSchema = (app: CaseType): JsonSchema => {
const newSchema = new JsonSchema().deserialize({ type: 'object', 'properties': [ ] });
const topLevelType = {};
topLevelType[app.name] = {};
newSchema.properties.push(topLevelType);
return newSchema;
}
handleRenderedLayout = (layout: any) => {
if (!this.autoLayout) {
this.autoLayout = layout;
}
}
useAutoLayout = () => {
this.layout = this.autoLayout;
this.layoutString = TcCoreCommonFunctions.formLayoutToJson(this.autoLayout);
this.updateLayout(this.layoutString);
}
useBasicLayout = () => {
this.layout = [ { type: 'help',
helpvalue: '<span>Please fill in this form!</span>' }, '*' ];
this.layoutString = TcCoreCommonFunctions.formLayoutToJson(this.layout);
this.updateLayout(this.layoutString);
}
useNewLayout = () => {
this.layout = [ { type: 'help',
helpvalue: '<span>Please fill in this form!</span>' } ];
this.layoutString = TcCoreCommonFunctions.formLayoutToJson(this.layout);
this.updateLayout(this.layoutString);
}
useExampleLayout = () => {
this.layout = JSON.parse('[\n' +
' {\n' +
' "type": "help",\n' +
' "helpvalue": "<span>Please fill in this form!</span>"\n' +
' },\n' +
' {\n' +
' "key": "Expenses.ClaimantName",\n' +
' "type": "select",\n' +
' "titleMap": [\n' +
' { "value": "John Smith", "name": "John Smith" },\n' +
' { "value": "Justine Rogers", "name": "Justin Rogers" },\n' +
' { "value": "James West", "name": "James West"}\n' +
' ]\n' +
' },\n' +
' {\n' +
' "type": "conditional",\n' +
' "condition": "model.Expenses.ClaimantName",\n' +
' "items": [\n' +
' {\n' +
' "key": "Expenses.DepartmentCode",\n' +
' "type": "text"\n' +
' }\n' +
' ]\n' +
' }\n' +
']');
this.layoutString = TcCoreCommonFunctions.formLayoutToJson(this.layout);
this.updateLayout(this.layoutString);
}
dropLayout = () => {
this.layout = undefined;
this.layoutString = undefined;
this.setProcessFormConfig(this.selectedProcess.formTag, 'RESET');
}
dropData = () => {
this.formDataJSON = undefined;
this.data = undefined;
this.setProcessFormConfig(this.selectedProcess.formTag, undefined, 'RESET');
}
saveSampleData = (sampleData: any) => {
if (sampleData !== undefined && JSON.stringify(sampleData) !== '{}') {
this.formDataJSON = JSON.stringify(sampleData, null, 2);
this.data = sampleData;
this.dataPanel.open();
this.setProcessFormConfig(this.selectedProcess.formTag, undefined, this.formDataJSON);
}
}
handleSaveFormConfig = () => {
this.formConfigUpdate.emit(this.formConfig);
}
openLayoutDocsTab = () => {
window.open('https://github.com/json-schema-form/angular-schema-form/blob/master/docs/index.md#form-definitions');
}
ngOnChanges(changes: SimpleChanges): void {
if (!this.formsFramework) {
this.formsFramework = 'material-design';
}
if (this.schema) {
this.formSchemaJSON = JSON.stringify(this.schema, null, 2);
}
}
}
<div fxFill fxLayout="row" *ngIf="formConfig">
<div fxFlex class="tcs-form-config-pane">
<div class="tcs-form-config-header" fxLayout="row" fxLayoutAlign="space-between center">
<div fxLayoutAlign="start center">
<!--mat-icon svgIcon="tcs-config-icon"></mat-icon-->
<div class="tcs-form-config-header-text">Form Preview</div>
</div>
</div>
<div class="tcs-form-config-content" *ngIf="!selectedProcessFormConfig || !selectedProcessFormConfig?.externalForm; else customFormWarning">
<tcfrm-rendered-form *ngIf="selectedProcess" [schema]="schema" [layout]="initialLayout" [data]="data" [options]="options"
[formsFramework]="formsFramework" (formSubmit)="saveSampleData($event)"
(renderedLayout)="handleRenderedLayout($event)"></tcfrm-rendered-form>
</div>
<ng-template #customFormWarning>
<div class="tcs-form-config-content">This form is configured as a custom form in the custom form registry</div>
</ng-template>
</div>
<div fxFlex fxLayout="column">
<div fxFlex class="tcs-form-config-pane" fxLayout="column">
<div class="tcs-form-config-header" fxLayout="row" fxLayoutAlign="space-between center">
<div fxLayoutAlign="start center">
<!--mat-icon svgIcon="tcs-config-icon"></mat-icon-->
<div class="tcs-form-config-header-text">Form Configuration</div>
</div>
</div>
<div class="tcs-form-config-content">
<div fxLayout="row">
<tcla-live-apps-applications fxFlex [formFieldRendering]="true" [sandboxId]="sandbox" [appIds]="appIds"
(selection)="handleAppSelection($event)"></tcla-live-apps-applications>
<tcla-live-apps-processes fxFlex [sandboxId]="sandbox" [appId]="selectedApp?.applicationId"
[typeId]="selectedApp?.id" [includeCaseDataPage]="true"
(processClicked)="handleProcessSelection($event)"></tcla-live-apps-processes>
</div>
<mat-accordion>
<mat-expansion-panel [disabled]="!selectedProcess || selectedProcessFormConfig?.externalForm">
<mat-expansion-panel-header>
<mat-panel-title>Schema</mat-panel-title>
</mat-expansion-panel-header>
<div>This is the input schema (form) generated by Live Apps for the selected process. A form is auto
generated based on this schema. You cannot edit this schema directly but changing the form in Live Apps
Designer will change this schema.
</div>
<div *ngIf="formSchemaJSON"
ace-editor
[text]="formSchemaJSON"
[options]="aceEditorOptions"
[readOnly]="true"
[autoUpdateContent]="true"
style="width:100%; overflow: auto; border: 1px solid black;">
(loading form schema...)
</div>
</mat-expansion-panel>
<mat-expansion-panel [disabled]="!selectedProcess || selectedProcessFormConfig?.externalForm">
<mat-expansion-panel-header>
<mat-panel-title>Layout</mat-panel-title>
</mat-expansion-panel-header>
<div *ngIf="!layoutString">
<span>You can </span>
<span class="tcs-clickable" (click)="useAutoLayout()">edit</span>
<span> the generated layout or </span>
<span class="tcs-clickable" (click)="useBasicLayout()">append</span>
<span> the automatic layout </span>
<span> or create a </span>
<span class="tcs-clickable" (click)="useNewLayout()">new</span>
<span> custom layout or start with an </span>
<span class="tcs-clickable" (click)="useExampleLayout()">example</span>
<span> layout</span>
</div>
<div *ngIf="layoutString">
<span>Layout uses JSON schema form layout options - refer to 'Form Definitions' </span><span
class="tcs-clickable" (click)="openLayoutDocsTab()">here</span><span> for layout options</span>
<div *ngIf="selectedProcess && selectedProcess.processType === 'casedata'"><br><span>Note: Case Data forms are rendered read-only and buttons will not be displayed</span>
</div>
</div>
<div *ngIf="layoutString" fxLayoutAlign="row">
<div
ace-editor
[text]="layoutString"
[options]="aceEditorOptions"
[readOnly]="false"
[autoUpdateContent]="true"
(textChanged)="updateLayout($event)"
style="width:100%; overflow: auto; border: 1px solid black;">
(loading form layout...)
</div>
<mat-icon svgIcon="tcs-close-icon" (click)="dropLayout()" matTooltip="Clear layout"
matTooltipShowDelay="1000" matTooltipPosition="below"></mat-icon>
</div>
</mat-expansion-panel>
<mat-expansion-panel #dataPanel [disabled]="!selectedProcess || selectedProcessFormConfig?.externalForm">
<mat-expansion-panel-header>
<mat-panel-title>Data</mat-panel-title>
</mat-expansion-panel-header>
<div *ngIf="!formDataJSON">You can create a sample data set by using the preview form and clicking submit
</div>
<div *ngIf="formDataJSON">Edits to this data will be displayed in the preview</div>
<div *ngIf="formDataJSON" fxLayoutAlign="row">
<div
ace-editor
[text]="formDataJSON"
[options]="aceEditorOptions"
[readOnly]="false"
[autoUpdateContent]="true"
(textChanged)="updateDataJSON($event)"
style="width:100%; overflow: auto; border: 1px solid black;">
</div>
<mat-icon svgIcon="tcs-close-icon" (click)="dropData()" matTooltip="Clear data" matTooltipShowDelay="1000"
matTooltipPosition="below"></mat-icon>
</div>
</mat-expansion-panel>
</mat-accordion>
</div>
</div>
<div class="tcs-form-config-pane" fxLayout="column" *ngIf="formConfig && formConfig.processFormConfigs">
<div class="tcs-form-config-content" fxLayout="row">
<span>Custom Form Config for {{formConfig.processFormConfigs.length}} {{formConfig.processFormConfigs.length === 1 ? 'process' : 'processes'}}</span>
<div fxFlex fxLayout="column" fxLayoutAlign="end end" style="margin-right: 20px;">
<button mat-raised-button color="primary" (click)="handleSaveFormConfig()"
matTooltip="Save form configuration {{formConfig.processFormConfigs | json}}" matTooltipShowDelay="1000" matTooltipPosition="below">Save Form
Configuration
</button>
</div>
</div>
</div>
</div>
</div>
./live-apps-form-preview.component.css
.tcs-form-config-pane {
border-radius: 3px;
box-shadow: 0 2px 8px 0 #dedede;
background-color: #ffffff;
margin: 5px;
overflow: auto;
}
.tcs-form-config-content {
padding: 10px;
}
.tcs-form-config-header {
min-height: 40px;
border-radius: 3px 3px 0px 0px;
box-shadow: 0 1px 2px 0 #dedede;
padding-left: 20px;
padding-right: 20px;
}
.tcs-form-config-header-text {
font-family: Source Sans Pro;
font-size: 18px;
font-weight: 600;
font-style: normal;
font-stretch: normal;
line-height: 1.5;
letter-spacing: 0.3px;
text-align: left;
color: black;
margin-left: 10px;
}
.tcs-clickable {
cursor: pointer;
color: blue;
font-weight: bold;
}