import { Data, Expression, Scope, XmlError, ObjectData, Block, parseXML, PrimitiveData, Variables, Jump, FunctionData, DictionaryDefinitions, Variable, AnyData, ObjectDataType, } from '@cyklang/core'; import { DeclareInstruction, Instruction, InstructionType, Tag, } from '@cyklang/core'; import loglevel from 'loglevel'; import { useCykStore } from './cykStore'; import { structure, ComponentModel, PushModalDialogFunction, ValidationFunction, PopModalDialogFunction } from './cykLang'; import { AlertException, ShowMessageFunction } from './cykRun'; import { DirtyManager, NotifyChangeInstructionType, VariableReact } from './cykReact'; import { OpenWindowTabInstructionType, SetPathInstructionType, OpenWindowLocationInstructionType, WindowTabManager, SetWindowNameInstructionType, ReloadWindowLocationInstructionType } from './WindowTabManager'; import { LocalStorageInstructionType } from './LocalStorage'; import { GeoLocationInstructionType } from './GeoLocation'; import { Ref } from 'vue'; import { UploadFileInstructionType } from './cykUpload'; import { BarcodeScanner } from '@capacitor-mlkit/barcode-scanning'; import { Capacitor } from '@capacitor/core'; const logger = loglevel.getLogger('WindowManager.ts'); logger.setLevel('debug'); export class WindowManager { scopeRun: Scope; dialogCount = 0 variableReact: VariableReact currentformComponent: ComponentModel | undefined setFormComponentValue: (formComponent: ComponentModel | undefined) => void; validateForm: ValidationFunction; browserHistoryPush: (url: string) => void; dialogStack: ComponentModel[] = [] pushModalDialogFunction: PushModalDialogFunction; popModalDialogFunction: PopModalDialogFunction; validateModalDialog: ValidationFunction; appendOutput: (line: string) => void; refreshModalDialog: () => void; resetModalDialogDirty: () => void; sendEventModalDialog: (componentName: string, event: string) => void; debugShowDialog: (scope: Scope, tag: Tag) => Promise; showMessageFunction: ShowMessageFunction; showLoading: (msg: string) => void; hidLoading: () => void; windowTabManager: WindowTabManager constructor( moduleName: string, setFormComponentValue: (formComponent: ComponentModel | undefined) => void, validateForm: ValidationFunction, browserHistoryPush: (url: string) => void, pushModalDialogFunction: PushModalDialogFunction, popModalDialogFunction: PopModalDialogFunction, validateModalDialog: ValidationFunction, appendOutput: (line: string) => void, refreshModalDialog: () => void, resetModalDialogDirty: () => void, sendEventModalDialog: (componentName: string, event: string) => void, debugShowDialog: (scope: Scope, tag: Tag) => Promise, showMessageFunction: ShowMessageFunction, showLoading: (msg: string) => void, hideLoading: () => void ) { this.scopeRun = new Scope(structure, structure.scope, undefined); this.windowTabManager = new WindowTabManager(moduleName) this.variableReact = new VariableReact() this.setFormComponentValue = setFormComponentValue this.validateForm = validateForm this.browserHistoryPush = browserHistoryPush this.pushModalDialogFunction = pushModalDialogFunction this.popModalDialogFunction = popModalDialogFunction this.validateModalDialog = validateModalDialog this.refreshModalDialog = refreshModalDialog this.resetModalDialogDirty = resetModalDialogDirty this.sendEventModalDialog = sendEventModalDialog this.debugShowDialog = debugShowDialog this.showMessageFunction = showMessageFunction this.showLoading = showLoading this.hidLoading = hideLoading this.scopeRun.structure.scope.addInstructionType(new ShowFormInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new CloseFormInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new PrintInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new AlertInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new ShowDialogInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new CloseDialogInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new BrowserHistoryPushInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new SetMenuInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new RefreshDialogInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new ResetDialogDirtyInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new SendEventInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new SetToolbarInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new DebugInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new OpenWindowTabInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new LocalStorageInstructionType()) this.scopeRun.structure.scope.addInstructionType(new GeoLocationInstructionType()) this.scopeRun.structure.scope.addInstructionType(new SetPathInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new SetWindowNameInstructionType(this)) this.scopeRun.structure.scope.addInstructionType(new OpenWindowLocationInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new ReloadWindowLocationInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new NotifyChangeInstructionType(this)); this.scopeRun.structure.scope.addInstructionType(new UploadFileInstructionType(this)); this.scopeRun.structure.scope.addFunction('scan_barcode', this.scanBarcodeFunction) this.scopeRun.structure.scope.addInstructionType(new UnsupportedInstructionType('attach_to_pdf')); this.scopeRun.structure.scope.addInstructionType(new UnsupportedInstructionType('combine_pdf_factur_x')); this.scopeRun.structure.scope.addInstructionType(new UnsupportedInstructionType('db.pdfmerge')); this.addDBResultSelectFunction() this.addConfirmFunction() this.scopeRun.addFunction('innerwidth', async (): Promise => { return new PrimitiveData(this.scopeRun.structure.numberDataType, window.innerWidth) }) this.scopeRun.addFunction('innerheight', async (): Promise => { return new PrimitiveData(this.scopeRun.structure.numberDataType, window.innerHeight) }) this.appendOutput = appendOutput } /** * scanBarcodeFunction * @returns */ scanBarcodeFunction = async (): Promise => { try { const result = new ObjectData(structure.objectDataType, new Tag(''), structure.scope) // 1. Demander et vérifier les permissions await BarcodeScanner.requestPermissions(); const permissionStatus = await BarcodeScanner.checkPermissions(); if (permissionStatus.camera !== 'granted') { throw new Error('Permission pour utiliser la caméra refusée.'); } // 2. Vérifier / installer le module Google sur Android const platform = Capacitor.getPlatform(); if (platform === 'android') { const { available } = await BarcodeScanner.isGoogleBarcodeScannerModuleAvailable(); if (!available) { // Tu peux informer l'utilisateur ici (via un dialogue par exemple) this.showLoading('Installation du module de scan Google') console.log('Installation du module de scan Google...'); await BarcodeScanner.installGoogleBarcodeScannerModule(); this.hidLoading() } } // 3. Lancer l'interface de scan const { barcodes } = await BarcodeScanner.scan(); for (let ind = 0; ind < barcodes.length; ind++) { const barcode = barcodes[ind] const variable = new Variable(structure.stringDataType, new PrimitiveData(structure.stringDataType, barcode.displayValue)) result.variables.push(undefined, variable) } return result; } catch (err) { throw err } } /** * * @param dialogData */ async pushModalDialog(dialogData: ObjectData): Promise { const dirtyManager = new DirtyManager(dialogData) const varDirtyManager = new Variable(structure.anyDataType, new AnyData(structure.anyDataType, dirtyManager)) dialogData.variables.setVariable('__dirtyManager__', varDirtyManager) const dialogComponent = new ComponentModel(dialogData, undefined, this.variableReact, dirtyManager) dialogComponent.validationFunctionSetter = (validationFunction) => { dialogComponent.validationFunction = validationFunction } dialogComponent.promise = new Promise((resolve) => dialogComponent.resolve = resolve) this.dialogStack.push(dialogComponent) this.dialogCount++ await this.pushModalDialogFunction(dialogComponent) } /** * * @param formData * @param toolbarData * @param scope * @returns */ async setFormComponent(formData: ObjectData, toolbarData: ObjectData | undefined, scope: Scope): Promise { // logger.debug("setFormComponent"); if (formData.type.name.toUpperCase() !== 'FORM') throw 'setForm() type=' + formData.type.name const dirtyManager = new DirtyManager(formData) const varDirtyManager = new Variable(structure.anyDataType, new AnyData(structure.anyDataType, dirtyManager)) formData.variables.setVariable('__dirtyManager__', varDirtyManager) const formComponent = new ComponentModel(formData, undefined, this.variableReact, dirtyManager) formComponent.validationFunctionSetter = (validationFunction) => { formComponent.validationFunction = validationFunction } formComponent.promise = new Promise((resolve) => formComponent.resolve = resolve) // store.variableReact = formData.variableReact; if (this.currentformComponent !== undefined) { logger.error("setFormComponent called before reset"); } this.currentformComponent = formComponent this.setFormComponentValue(formComponent); // keyFormComponent.value++; const express = new Expression(scope) const title = await express.substitute(formData.tag.attributes.TITLE || '') useCykStore().formTitle = structure.scope.xlate(title) document.title = useCykStore().formTitle useCykStore().toolbarData = toolbarData useCykStore().keyToolbarData++ return formComponent.promise; }; resetFormComponent() { // logger.debug('resetFormComponent') if (this.currentformComponent === undefined) { logger.error("resetFormComponent called before set"); } else if (this.currentformComponent.resolve === undefined) { logger.error("resetFormComponent and resolve is undefined"); } else { this.currentformComponent.resolve(); } this.setFormComponentValue(undefined); }; async closeForm() { if (this.dialogCount > 0) { await this.popModalDialogFunction() this.dialogCount-- } else { this.resetFormComponent() } } addDBResultSelectFunction() { this.scopeRun.addFunction('dbresultselect', async (params: Variables): Promise => { const pResult = params.at(0) if (!pResult) throw Error('dbresultset need at least an argument, the dbresult object') if (pResult === undefined || pResult.variable.data === undefined || pResult.variable.data === null) throw Error('dbresultset need at least an argument, the dbresult object') if (pResult.variable.data.type.isPrimitive()) throw Error('dbresultselect first argument must be an object') const dbResultObject = pResult.variable.data // scan dbResultObject const entities: string[] = [] let resultsetOk = false let metaOk = false dbResultObject.variables.forEach(({ name }) => { switch (name) { case 'resultset': resultsetOk = true; break; case 'meta': metaOk = true; break; default: if (name !== undefined) entities.push(name) } }) if (resultsetOk === false) throw Error('dbResult resultset is missing') if (metaOk === false) throw Error('dbresult meta is missing') if (entities.length === 0) throw 'dbresult no entity recordset' const pEntity = params.at(1) let selectEntity: string if (entities.length === 1) { selectEntity = entities[0] if (pEntity !== undefined && pEntity.variable.data !== undefined && pEntity.variable.data !== null) { const entity = String((pEntity.variable.data as PrimitiveData).getValue()) if (entity !== selectEntity) throw 'dbresult has only one entity ' + selectEntity + ' and you want ' + entity } } else { if (pEntity === undefined || pEntity.variable.data === undefined || pEntity.variable.data === null) { throw 'dbresult contains ' + entities.length + ' entities, choose one by giving a second argument to dbresultselect()' } const entity = String((pEntity.variable.data as PrimitiveData).getValue()) if (entities.includes(entity) === false) throw 'dbresult doe not containt ' + entity + ' entity' selectEntity = entity } const xmlResult = ` 'new' ` const result = await this.scopeRun.structure.objectDataType.parseData(parseXML('xmlResult', xmlResult), this.scopeRun) return result }) } async addDataTypes() { const xml = ` false false `; const tag = parseXML('script', xml) const block = new Block(tag, this.scopeRun); await block.parseInstructions(); await block.executeInScope(this.scopeRun); await this.addFormMethods() await this.addDialogMethods() //logger.trace('WindowManager types added') } /** * */ async addFormMethods() { const formDataType = (await this.scopeRun.getDataType('form')) as ObjectDataType if (!formDataType) throw 'form datatype not found' const methodShow = new FunctionData(this.scopeRun) methodShow.funct = async (params: Variables, callerScope: Scope) => { const varThis = params.getVariable('this') if (!varThis) throw 'method form.show() variable is missing' if (!varThis.data || !varThis.data.type.isObject()) throw 'variable is not an object' const objThis = (varThis.data as ObjectData) const varToolbar = params.getVariable('toolbar') let objToolbar: ObjectData | undefined if (varToolbar?.data && varToolbar.data.type.isObject()) { objToolbar = varToolbar.data as ObjectData } /*await */ this.setFormComponent(objThis, objToolbar, callerScope) } formDataType.methods.set("show", methodShow) } /** * */ async addDialogMethods() { const dialogDataType = (await this.scopeRun.getDataType('dialog')) as ObjectDataType if (!dialogDataType) throw 'dialog datatype not found' const methodShow = new FunctionData(this.scopeRun) methodShow.funct = async (params: Variables, callerScope: Scope) => { const varThis = params.getVariable('this') if (!varThis) throw 'method dialog.show() variable is missing' if (!varThis.data || !varThis.data.type.isObject()) throw 'variable is not an object' const objThis = (varThis.data as ObjectData) const varLocked = params.getVariable('locked') // logger.debug('dialog.methodShow varLocked=', varLocked) let locked: boolean | undefined if (varLocked && varLocked.data && varLocked.data !== null && varLocked.data.type.isPrimitive()) { locked = varLocked.getBoolean() } await this.pushModalDialog(objThis) } dialogDataType.methods.set("show", methodShow) const methodIsDirty = new FunctionData(this.scopeRun) methodIsDirty.funct = async (params: Variables, callerScope: Scope): Promise => { const varThis = params.getVariable('this') if (!varThis) throw 'method dialog.isDirty() variable is missing' if (!varThis.data || !varThis.data.type.isObject()) throw 'variable is not an object' const objThis = (varThis.data as ObjectData) let isDirty = false const dirtyManagerData = objThis.variables.getData('__dirtyManager__') // if (!dirtyManagerData || dirtyManagerData === null) throw 'dirtyManager not found'; if (dirtyManagerData && dirtyManagerData !== null) { const dirtyManager = (dirtyManagerData as AnyData).value as DirtyManager isDirty = dirtyManager.isDirty() } const result = new PrimitiveData(this.scopeRun.structure.booleanDataType, isDirty) return result } dialogDataType.methods.set("isDirty", methodIsDirty) // logger.debug('addDialogMethods:', dialogDataType.methods) } //---------------------------------------------------------------------- // Confirm function //---------------------------------------------------------------------- addConfirmFunction() { // const resultName = 'confirmed'; const stringDataType = this.scopeRun.structure.stringDataType; if (stringDataType === undefined) return; const functionData = new FunctionData(this.scopeRun); functionData.parametersDefinition = new DictionaryDefinitions(this.scopeRun) functionData.parametersDefinition.addDefinition('MESSAGE', stringDataType, parseXML('confirmFunction', '')); functionData.parametersDefinition.addDefinition('OK', stringDataType, parseXML('confirmFunction', '')); functionData.parametersDefinition.addDefinition('TITLE', stringDataType, parseXML('confirmFunction', '')); // functionData.resultDataType = scope.getDataType('boolean'); // functionData.resultName = resultName; functionData.funct = async (params: Variables) => { const pairsOkCancel = [['OK', 'CANCEL'], ['YES', 'NO'], ['OUI', 'NON'], ['CONFIRMER', 'ANNULER']] let title: string | undefined; const message: string | undefined = params.at(0)?.variable.getString(); const labelOk = params.at(1)?.variable.getString() || 'OK'; const labelCancel = params.at(2)?.variable.getString() || 'CANCEL'; // const pair = pairsOkCancel.find((pair) => pair[0] === labelOk.toUpperCase()) // if (pair !== undefined) { // [labelOk, labelCancel] = pair // } const response = await this.showMessageFunction(title, message, labelOk, labelCancel) // logger.debug('confirm after await new Promise response : ' + response); const booleanDataType = this.scopeRun.structure.booleanDataType; if (booleanDataType === undefined) throw 'boolean datatype not found'; let result: Data if (response === true) { result = this.scopeRun.structure.trueData } else { result = this.scopeRun.structure.falseData } //const result = new PrimitiveData(booleanDataType, response); // const varResult = params.getVariable(resultName); // if (varResult === undefined) { // throw Error(resultName + ' not found in confirmFunction params'); // } // varResult.setValue(result); return result }; const functionDataType = this.scopeRun.structure.functionDataType; if (functionDataType === undefined) { throw new Error('functionDataType not found'); } const variable = this.scopeRun.variables.addVariable('confirm', functionDataType); variable.setValue(functionData); // logger.debug('variable confirm added'); } } //---------------------------------------------------------------------- // AlertnstructionType //---------------------------------------------------------------------- class AlertInstructionType extends InstructionType { windowManager: WindowManager constructor(windowManager: WindowManager) { super('alert'); this.windowManager = windowManager } async parseInstruction(tag: Tag): Promise { const inst = new AlertInstruction(tag, this.windowManager.showMessageFunction); return inst; } } class AlertInstruction extends Instruction { showMessageFunction: ShowMessageFunction constructor(tag: Tag, showMessageFunction: ShowMessageFunction) { super(tag); this.showMessageFunction = showMessageFunction } async execute(scope: Scope): Promise { try { const express = new Expression(scope); let title: string | undefined; let message: string | undefined; for (let index = 0; index < this.tag.childs.length; index++) { const child = this.tag.childs[index]; if (child.name === 'TITLE') { title = (await express.evaluate(child.getText()))?.toString(); } else if (child.name === 'MESSAGE') { message = (await express.evaluate(child.getText()))?.toString(); } } await this.showMessageFunction(title, message) } catch (err) { logger.error(err) throw err } // logger.debug('alert.execute fin'); } dump(): void { throw new Error('Method not implemented.'); } } class SetMenuInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('setmenu'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { const inst = new SetMenuInstruction(tag, this.windowManager); return inst; } } class SetMenuInstruction extends Instruction { windowManager: WindowManager constructor(tag: Tag, windowManager: WindowManager) { super(tag) this.windowManager = windowManager } async execute(scope: Scope): Promise { const scopeLocal = new Scope(scope.structure, scope, undefined); let menuData; for (let index = 0; index < this.tag.childs.length; index++) { const child = this.tag.childs[index]; const declareInstruction = new DeclareInstruction(child, undefined); await declareInstruction.execute(scopeLocal); if ( declareInstruction.variable !== undefined && declareInstruction.variable.data !== null && declareInstruction.variable.data !== undefined && declareInstruction.variable.data.type.isObject()) { menuData = declareInstruction.variable.data; const menuList = new ComponentModel(menuData, undefined, this.windowManager.variableReact); useCykStore().menuList = menuList useCykStore().keyMenuData++ } } if (menuData === undefined) return; } } class SetToolbarInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('settoolbar'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { const inst = new SetToolbarInstruction(tag); return inst; } } class SetToolbarInstruction extends Instruction { constructor(tag: Tag) { super(tag) } async execute(scope: Scope): Promise { const scopeLocal = new Scope(scope.structure, scope, undefined); let toolbarData; for (let index = 0; index < this.tag.childs.length; index++) { const child = this.tag.childs[index]; const declareInstruction = new DeclareInstruction(child, undefined); await declareInstruction.execute(scopeLocal); if ( declareInstruction.variable !== undefined && declareInstruction.variable.data !== null && declareInstruction.variable.data !== undefined && declareInstruction.variable.data.type.isPrimitive() === false) { toolbarData = declareInstruction.variable.data; useCykStore().toolbarData = toolbarData useCykStore().keyToolbarData++ } } if (toolbarData === undefined) return; } } class BrowserHistoryPushInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('browserhistorypush'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { const inst = new BrowserHistoryPushInstruction(tag, this); return inst; } } class BrowserHistoryPushInstruction extends Instruction { instructionType: BrowserHistoryPushInstructionType; exprValue: string | undefined; constructor(tag: Tag, instructionType: BrowserHistoryPushInstructionType) { super(tag) this.instructionType = instructionType this.exprValue = tag.getText(); } async execute(scope: Scope): Promise { if (this.exprValue !== undefined) { const express = new Expression(scope); let value: Data | undefined | null; try { value = await express.evaluate(this.exprValue); } catch (err) { logger.debug(err); throw new XmlError('Expression : ' + this.exprValue, this.tag); } if ( value !== undefined && value !== null ) { this.instructionType.windowManager.browserHistoryPush(value.toString()) } } } } class PrintInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('print'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { const inst = new PrintInstruction(tag, this); return inst; } } class PrintInstruction extends Instruction { instructionType: PrintInstructionType; exprValue: string | undefined; constructor(tag: Tag, instructionType: PrintInstructionType) { super(tag); this.instructionType = instructionType; this.exprValue = tag.getText(); } async execute(scope: Scope): Promise { if (this.exprValue !== undefined) { const express = new Expression(scope); let value: Data | undefined | null; try { value = await express.evaluate(this.exprValue); //logger.trace('print : ' + value) } catch (err) { logger.debug(err); throw new XmlError('Expression : ' + this.exprValue, this.tag); } if ( value !== undefined && value !== null && this.instructionType.windowManager.appendOutput !== undefined ) { this.instructionType.windowManager.appendOutput(value.toString()); logger.info('////// print : ' + value.toString()) } } } } class ShowDialogInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('showDialog'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { return new ShowDialogInstruction(tag, this); } } class ShowDialogInstruction extends Instruction { instructionType: ShowDialogInstructionType; constructor(tag: Tag, instructionType: ShowDialogInstructionType) { super(tag); this.instructionType = instructionType; } async execute(scope: Scope) { const scopeShow = new Scope(scope.structure, scope, undefined); let dialogData: ObjectData | undefined; let result for (let index = 0; index < this.tag.childs.length; index++) { const child = this.tag.childs[index]; const declareInstruction = new DeclareInstruction(child, undefined); await declareInstruction.execute(scopeShow); if ( declareInstruction.variable !== undefined && declareInstruction.variable.dataType.isPrimitive() === false ) { dialogData = declareInstruction.variable.data as ObjectData; // const formDataValidation = new FormDataValidation(formData, this.instructionType.windowManager.variableReact) await this.instructionType.windowManager.pushModalDialog(dialogData) } } if (dialogData === undefined) return; // const result = new Promise((resolve) => { // this.instructionType.windowManager.resolveShowDialog = resolve; // }); return result; } } class CloseDialogInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('closedialog'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { return new CloseDialogInstruction(tag, this); } } class CloseDialogInstruction extends Instruction { instructionType: CloseFormInstructionType; constructor(tag: Tag, instructionType: CloseFormInstructionType) { super(tag); this.instructionType = instructionType; } async execute(): Promise { const windowManager = this.instructionType.windowManager; // windowManager.popModalDialog() this.instructionType.windowManager.dialogStack.pop() await windowManager.closeForm() } } class RefreshDialogInstructionType extends InstructionType { windowManager: WindowManager constructor(windowManager: WindowManager) { super('refreshdialog'); this.windowManager = windowManager } async parseInstruction(tag: Tag): Promise { return new RefreshDialogInstruction(tag, this) } } class RefreshDialogInstruction extends Instruction { instructionType: RefreshDialogInstructionType; constructor(tag: Tag, instructionType: RefreshDialogInstructionType) { super(tag) this.instructionType = instructionType } async execute(): Promise { const windowManager = this.instructionType.windowManager windowManager.refreshModalDialog() } } class ResetDialogDirtyInstructionType extends InstructionType { windowManager: WindowManager constructor(windowManager: WindowManager) { super('resetdialogdirty'); this.windowManager = windowManager } async parseInstruction(tag: Tag): Promise { return new ResetDialogDirtyInstruction(tag, this) } } class ResetDialogDirtyInstruction extends Instruction { instructionType: ResetDialogDirtyInstructionType; constructor(tag: Tag, instructionType: ResetDialogDirtyInstructionType) { super(tag) this.instructionType = instructionType } async execute(): Promise { const windowManager = this.instructionType.windowManager windowManager.resetModalDialogDirty() } } class SendEventInstructionType extends InstructionType { windowManager: WindowManager constructor(windowManager: WindowManager) { super('sendevent'); this.windowManager = windowManager } async parseInstruction(tag: Tag): Promise { return new SendEventInstruction(tag, this) } } class SendEventInstruction extends Instruction { instructionType: SendEventInstructionType; constructor(tag: Tag, instructionType: SendEventInstructionType) { super(tag) this.instructionType = instructionType } async execute(scope: Scope): Promise { const windowManager = this.instructionType.windowManager const scopeParams = new Scope(scope.structure, scope, undefined) for (let index = 0; index < this.tag.childs.length; index++) { const child = this.tag.childs[index]; const declareInstruction = new DeclareInstruction(child, undefined) await declareInstruction.execute(scopeParams) if (declareInstruction.variable !== undefined) { if (declareInstruction.variable.dataType.name !== 'string') { throw Error('sendevent argument should be string but is ' + declareInstruction.variable.dataType.name) } } } const varComponent = scopeParams.variables.getVariable('component') if (varComponent === undefined) { throw Error('sendevent missing component argument') } const varEvent = scopeParams.variables.getVariable('event') if (varEvent === undefined) { throw Error('sendevent missing event arugment') } windowManager.sendEventModalDialog(varComponent.getString() || 'unknown_component', varEvent.getString() || 'unknown_event') } } class ShowFormInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('showform'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { const inst = new ShowFormInstruction(tag, this); return inst; } } class ShowFormInstruction extends Instruction { instructionType: ShowFormInstructionType; constructor(tag: Tag, instructionType: ShowFormInstructionType) { super(tag); this.instructionType = instructionType; } async execute(scope: Scope): Promise { try { const scopeShow = new Scope(scope.structure, scope, undefined); let formData; let toolbarData // let result; for (let index = 0; index < this.tag.childs.length; index++) { const child = this.tag.childs[index]; const declareInstruction = new DeclareInstruction(child, undefined); await declareInstruction.execute(scopeShow); if ( declareInstruction.variable !== undefined && declareInstruction.variable.data !== null && declareInstruction.variable.data !== undefined ) { if (declareInstruction.variable.data.type.name.toLowerCase() === 'form') formData = declareInstruction.variable.data; else if (declareInstruction.variable.data.type.name.toLowerCase() === 'toolbar') { toolbarData = declareInstruction.variable.data as ObjectData } } } if (formData !== undefined) { await this.instructionType.windowManager.setFormComponent(formData, toolbarData, scope) // logger.debug('after setFormComponent ' + formData.tag.attributes.TITLE) } } catch (err) { logger.error(err) if (err instanceof XmlError) throw (err) throw (new XmlError(String(err), this.tag)) } // logger.debug('after setToolbar ') // const result = new Promise((resolve) => { // this.instructionType.windowManager.resolveShowForm = resolve; // }); // return result; } } /** * */ class UnsupportedInstructionType extends InstructionType { constructor(name: string) { super(name) } async parseInstruction(tag: Tag, scope: Scope): Promise { return new UnsupportedInstruction(tag, this) } } class UnsupportedInstruction extends Instruction { instructionType: UnsupportedInstructionType constructor(tag: Tag, instructionType: UnsupportedInstructionType) { super(tag) this.instructionType = instructionType } async execute(scope: Scope): Promise { throw `instruction ${this.instructionType.name} unsupported on client side` } } class DebugInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('debug'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { const inst = new DebugInstruction(tag, this); return inst; } } class DebugInstruction extends Instruction { instructionType: DebugInstructionType; constructor(tag: Tag, instructionType: DebugInstructionType) { super(tag); this.instructionType = instructionType; } async execute(scope: Scope): Promise { // logger.debug('DEBUG BEGIN ' + this.tag.getText()) await this.instructionType.windowManager.debugShowDialog(scope, this.tag) // logger.debug('DEBUG END ' + this.tag.getText()) } } export class CloseFormInstructionType extends InstructionType { windowManager: WindowManager; constructor(windowManager: WindowManager) { super('closeform'); this.windowManager = windowManager; } async parseInstruction(tag: Tag): Promise { return new CloseFormInstruction(tag, this); } } class CloseFormInstruction extends Instruction { instructionType: CloseFormInstructionType; constructor(tag: Tag, instructionType: CloseFormInstructionType) { super(tag); this.instructionType = instructionType; } async execute(): Promise { const windowManager = this.instructionType.windowManager; // windowManager.resetFormComponent() await windowManager.closeForm() } } /** * * @param componentArg * @param result * @returns */ export async function buildComponentArray(componentArg: ComponentModel, components: Ref) { components.value = [] const variables = componentArg.objectData?.variables if (!variables) return await variables.forEachAsync(async ({ variable }) => { if (variable.data !== undefined && variable.data !== null && variable.data.type.isObject()) { const objectData = variable.data; try { // logger.debug('loading component ' + index); let model let modelString if (objectData.tag === undefined) { // logger.debug('buildComponentArray componentArg', componentArg) // logger.debug('buildComponentArray objectData.tag undefined', objectData) } if (objectData.tag.attributes.MODEL !== undefined) { modelString = objectData.tag.attributes.MODEL } const varModel = objectData.variables.getVariable('model') if (varModel !== undefined && varModel.getString() !== undefined) { modelString = varModel.getString() } if (modelString !== undefined) { const express = new Expression(objectData.scope); // logger.debug('buildComponentArray modelString: ' + modelString) model = await express.LValue(modelString); if (!model) throw `${modelString} undefined` } let dirtyManager: DirtyManager | undefined = componentArg.dirtyManager if (objectData.tag.name === 'FORM') { dirtyManager = new DirtyManager(objectData) const varDirtyManager = new Variable(structure.anyDataType, new AnyData(structure.anyDataType, dirtyManager)) objectData.variables.setVariable('__dirtyManager__', varDirtyManager) } components.value.push(new ComponentModel(objectData, model, componentArg.variableReact, dirtyManager)); } catch (err) { AlertException(new XmlError(String(err), objectData.tag)) } } }) }