File

C:/GoDev/src/TCSTK-Angular/projects/tibco-tcstk/tc-liveapps-lib/src/lib/components/live-apps-form-preview/live-apps-form-preview.component.ts

Implements

OnChanges

Metadata

selector tcla-live-apps-form-preview
styleUrls ./live-apps-form-preview.component.css
templateUrl ./live-apps-form-preview.component.html

Index

Properties
Methods
Inputs
Outputs
Accessors

Constructor

constructor(processService: TcCaseProcessesService)
Parameters :
Name Type Optional
processService TcCaseProcessesService No

Inputs

appIds
Type : string[]
formConfig
Type : FormConfig
formsFramework
options
Type : any[]
sandbox
Type : string
schema
Type : any
Default value : {}

Outputs

formConfigUpdate
Type : EventEmitter<FormConfig>

~event saveFormConfiguration : save form config ~payload any : forms config object

Methods

ngOnChanges
ngOnChanges(changes: SimpleChanges)
Parameters :
Name Type Optional
changes SimpleChanges No
Returns : void

Properties

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 : () => {...}

Accessors

FormsFramework
setFormsFramework(formsFramework)
Parameters :
Name Optional
formsFramework No
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&nbsp;</span>
              <span class="tcs-clickable" (click)="useAutoLayout()">edit</span>
              <span>&nbsp;the generated layout or&nbsp;</span>
              <span class="tcs-clickable" (click)="useBasicLayout()">append</span>
              <span>&nbsp;the automatic layout&nbsp;</span>
              <span>&nbsp;or create a &nbsp;</span>
              <span class="tcs-clickable" (click)="useNewLayout()">new</span>
              <span>&nbsp;custom layout or start with an&nbsp;</span>
              <span class="tcs-clickable" (click)="useExampleLayout()">example</span>
              <span>&nbsp;layout</span>
            </div>
            <div *ngIf="layoutString">
              <span>Layout uses JSON schema form layout options - refer to 'Form Definitions'&nbsp;</span><span
              class="tcs-clickable" (click)="openLayoutDocsTab()">here</span><span>&nbsp;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;
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""