From afca7cece826bf630e54af23ee3e8d71882964e9 Mon Sep 17 00:00:00 2001 From: Aaron Louie Date: Fri, 20 Mar 2020 16:49:17 -0400 Subject: [PATCH] WIP: Moves util methods to sartography-workflow-lib. Attempts to get file dialog working. --- package-lock.json | 6 +- package.json | 2 +- .../file-meta-dialog.component.ts | 85 +++++++++---------- .../open-file-dialog.component.ts | 6 +- ...workflow-spec-category-dialog.component.ts | 2 +- .../workflow-spec-dialog.component.ts | 3 +- src/app/_util/diagram-type.ts | 5 -- src/app/_util/is-number-defined.ts | 3 - src/app/_util/string-clean.spec.ts | 20 ----- src/app/_util/string-clean.ts | 25 ------ src/app/diagram/diagram.component.ts | 9 +- src/app/file-list/file-list.component.html | 14 +++ src/app/file-list/file-list.component.ts | 36 ++++++-- src/app/modeler/modeler.component.ts | 28 +++--- .../workflow-spec-card.component.html | 10 +-- .../workflow-spec-card.component.ts | 8 +- .../workflow-spec-list.component.ts | 7 +- 17 files changed, 123 insertions(+), 146 deletions(-) delete mode 100644 src/app/_util/diagram-type.ts delete mode 100644 src/app/_util/is-number-defined.ts delete mode 100644 src/app/_util/string-clean.spec.ts delete mode 100644 src/app/_util/string-clean.ts diff --git a/package-lock.json b/package-lock.json index 96984f6..3a7b6bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12171,9 +12171,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sartography-workflow-lib": { - "version": "0.0.68", - "resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.68.tgz", - "integrity": "sha512-W5wJ7YIqDu/0ul1AZNazCUNzmxGNTbLd2i/nArYNgf0WwJO2j+zQsxd41TJVjHLp4dHpR/UsnCXGH/cC0Pz23w==" + "version": "0.0.72", + "resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.72.tgz", + "integrity": "sha512-l6153jMOkKPgi2dOODOdTSHdPyyZpYjuylkPt38ct4XYaaF+kiT3GadhZli3sxg8KRkYfiaJ5krZRgl3adNu7A==" }, "sass": { "version": "1.23.3", diff --git a/package.json b/package.json index 939af11..ff428ae 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "ngx-file-drop": "^8.0.8", "ngx-markdown": "^9.0.0", "rxjs": "~6.5.4", - "sartography-workflow-lib": "^0.0.68", + "sartography-workflow-lib": "^0.0.72", "tslib": "^1.11.1", "uuid": "^7.0.2", "zone.js": "^0.10.3" diff --git a/src/app/_dialogs/file-meta-dialog/file-meta-dialog.component.ts b/src/app/_dialogs/file-meta-dialog/file-meta-dialog.component.ts index 541a8b6..c193896 100644 --- a/src/app/_dialogs/file-meta-dialog/file-meta-dialog.component.ts +++ b/src/app/_dialogs/file-meta-dialog/file-meta-dialog.component.ts @@ -2,9 +2,8 @@ import {Component, Inject} from '@angular/core'; import {FormGroup} from '@angular/forms'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {FormlyFieldConfig, FormlyFormOptions} from '@ngx-formly/core'; -import {FileType} from 'sartography-workflow-lib'; +import {cleanUpFilename, FileType} from 'sartography-workflow-lib'; import {FileMetaDialogData} from '../../_interfaces/dialog-data'; -import {cleanUpFilename} from '../../_util/string-clean'; @Component({ selector: 'app-new-file-dialog', @@ -21,55 +20,47 @@ export class FileMetaDialogComponent { public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: FileMetaDialogData ) { - const fileTypeOptions = Object.entries(FileType).map(ft => { - return { - label: ft[0], - value: ft[1] - }; - }); + const fileTypeOptions = Object.entries(FileType).map(ft => { + return { + label: ft[0], + value: ft[1] + }; + }); - this.fields = [ - { - key: 'id', - type: 'input', - defaultValue: this.data.id, - templateOptions: { - hide: true, - }, + this.fields = [ + { + key: 'fileName', + type: 'input', + defaultValue: this.data.fileName, + templateOptions: { + label: 'File Name', + placeholder: 'Name of file', + description: 'Enter a name, in lowercase letters, separated by underscores, that is easy for you to remember.' + + 'It will be converted to all_lowercase_with_underscores when you save.', + required: true, }, - { - key: 'fileName', - type: 'input', - defaultValue: this.data.fileName, - templateOptions: { - label: 'File Name', - placeholder: 'Name of workflow specification', - description: 'Enter a name, in lowercase letters, separated by underscores, that is easy for you to remember.' + - 'It will be converted to all_lowercase_with_underscores when you save.', - required: true, - }, + }, + { + key: 'fileType', + type: 'select', + defaultValue: this.data.fileType, + templateOptions: { + label: 'File Type', + placeholder: 'Extension of file', + required: true, + options: fileTypeOptions, }, - { - key: 'fileType', - type: 'select', - defaultValue: this.data.fileType, - templateOptions: { - label: 'File Type', - placeholder: 'Extension of file', - required: true, - options: fileTypeOptions, - }, + }, + { + key: 'file', + type: 'file', + defaultValue: this.data.file, + templateOptions: { + label: 'File', + required: true, }, - { - key: 'file', - type: 'file', - defaultValue: this.data.file, - templateOptions: { - label: 'File', - required: true, - }, - } - ]; + } + ]; } onNoClick() { diff --git a/src/app/_dialogs/open-file-dialog/open-file-dialog.component.ts b/src/app/_dialogs/open-file-dialog/open-file-dialog.component.ts index ec239a5..363d4f6 100644 --- a/src/app/_dialogs/open-file-dialog/open-file-dialog.component.ts +++ b/src/app/_dialogs/open-file-dialog/open-file-dialog.component.ts @@ -1,8 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import {Component} from '@angular/core'; import {MatDialogRef} from '@angular/material/dialog'; -import {ApiService} from 'sartography-workflow-lib'; -import {getDiagramTypeFromXml} from '../../_util/diagram-type'; -import {cleanUpFilename} from '../../_util/string-clean'; +import {ApiService, cleanUpFilename, getDiagramTypeFromXml} from 'sartography-workflow-lib'; @Component({ selector: 'app-open-file-dialog', diff --git a/src/app/_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component.ts b/src/app/_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component.ts index 7af7f49..ad8331e 100644 --- a/src/app/_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component.ts +++ b/src/app/_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component.ts @@ -2,8 +2,8 @@ import {Component, Inject} from '@angular/core'; import {FormGroup} from '@angular/forms'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {FormlyFieldConfig, FormlyFormOptions} from '@ngx-formly/core'; +import {toSnakeCase} from 'sartography-workflow-lib'; import {WorkflowSpecDialogData} from '../../_interfaces/dialog-data'; -import {toSnakeCase} from '../../_util/string-clean'; @Component({ selector: 'app-workflow-spec-category-dialog', diff --git a/src/app/_dialogs/workflow-spec-dialog/workflow-spec-dialog.component.ts b/src/app/_dialogs/workflow-spec-dialog/workflow-spec-dialog.component.ts index d2062ed..80b5ced 100644 --- a/src/app/_dialogs/workflow-spec-dialog/workflow-spec-dialog.component.ts +++ b/src/app/_dialogs/workflow-spec-dialog/workflow-spec-dialog.component.ts @@ -2,10 +2,9 @@ import {Component, Inject} from '@angular/core'; import {FormGroup} from '@angular/forms'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {FormlyFieldConfig, FormlyFormOptions, FormlyTemplateOptions} from '@ngx-formly/core'; -import {ApiService} from 'sartography-workflow-lib'; +import {ApiService, toSnakeCase} from 'sartography-workflow-lib'; import {v4 as uuidv4} from 'uuid'; import {WorkflowSpecDialogData} from '../../_interfaces/dialog-data'; -import {toSnakeCase} from '../../_util/string-clean'; @Component({ selector: 'app-workflow-spec-dialog', diff --git a/src/app/_util/diagram-type.ts b/src/app/_util/diagram-type.ts deleted file mode 100644 index 875c41f..0000000 --- a/src/app/_util/diagram-type.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {FileType} from 'sartography-workflow-lib'; - -export const getDiagramTypeFromXml = (xml: string): FileType => { - return (xml && xml.includes('dmn.xsd') ? FileType.DMN : FileType.BPMN); -}; diff --git a/src/app/_util/is-number-defined.ts b/src/app/_util/is-number-defined.ts deleted file mode 100644 index ef3d34d..0000000 --- a/src/app/_util/is-number-defined.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const isNumberDefined = (n: number): boolean => { - return (typeof n === 'number') && isFinite(n) && !isNaN(n); -}; diff --git a/src/app/_util/string-clean.spec.ts b/src/app/_util/string-clean.spec.ts deleted file mode 100644 index 2e23221..0000000 --- a/src/app/_util/string-clean.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {cleanUpFilename, toSnakeCase, trimString} from './string-clean'; - -describe('String Cleaning Utilities', () => { - const afterTrimming = `I'm tired of wasting letters when punctuation will do, period. -Steve Martin`; - const beforeTrimming = ` 📌📍🏁 <>?:"{}[] ${afterTrimming} !@#$%^& ✌️👍👆 `; - - it('converts a string to snake case', () => { - expect(toSnakeCase(beforeTrimming)).toEqual('i_m_tired_of_wasting_letters_when_punctuation_will_do_period_steve_martin'); - }); - - it('cleans up a file name and replaces or adds the extension', () => { - expect(cleanUpFilename(beforeTrimming, 'bpmn')).toEqual(`I'm tired of wasting letters when punctuation will do, period.bpmn`); - expect(cleanUpFilename(' no extension ', 'bpmn')).toEqual('no extension.bpmn'); - }); - - it('trims non-word characters from a string', () => { - expect(trimString(beforeTrimming)).toEqual(afterTrimming); - }); - -}); diff --git a/src/app/_util/string-clean.ts b/src/app/_util/string-clean.ts deleted file mode 100644 index 852076b..0000000 --- a/src/app/_util/string-clean.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {FileType} from 'sartography-workflow-lib'; - -export const trimString = (str: string): string => { - return !str ? '' : String(str).replace(/^\W+|\W+$/gi, ''); -}; - -export const toSnakeCase = (str: string): string => { - str = trimString(str); - return !str ? '' : String(str) - .replace(/\W+/gi, '_') - .toLowerCase(); -}; - -export const cleanUpFilename = (str: string, extension: FileType|string): string => { - const arr = trimString(str).split('.'); - - // Add file extension, if necessary - if (arr.length < 2) { - arr.push(extension); - } else { - (arr[arr.length - 1]) = extension; - } - - return arr.join('.'); -}; diff --git a/src/app/diagram/diagram.component.ts b/src/app/diagram/diagram.component.ts index 4fec6e2..ac8f2a1 100644 --- a/src/app/diagram/diagram.component.ts +++ b/src/app/diagram/diagram.component.ts @@ -5,11 +5,16 @@ import {ControlValueAccessor} from '@angular/forms'; import BpmnModeler from 'bpmn-js/lib/Modeler'; import DmnModeler from 'dmn-js/lib/Modeler'; import * as fileSaver from 'file-saver'; -import {ApiService, BPMN_DIAGRAM_DEFAULT, DMN_DIAGRAM_DEFAULT, FileType} from 'sartography-workflow-lib'; +import { + ApiService, + BPMN_DIAGRAM_DEFAULT, + DMN_DIAGRAM_DEFAULT, + FileType, + getDiagramTypeFromXml +} from 'sartography-workflow-lib'; import {v4 as uuidv4} from 'uuid'; import {BpmnWarning} from '../_interfaces/bpmn-warning'; import {ImportEvent} from '../_interfaces/import-event'; -import {getDiagramTypeFromXml} from '../_util/diagram-type'; import {bpmnModelerConfig} from './bpmn-modeler-config'; import {dmnModelerConfig} from './dmn-modeler-config'; diff --git a/src/app/file-list/file-list.component.html b/src/app/file-list/file-list.component.html index e1e5d08..bf4a515 100644 --- a/src/app/file-list/file-list.component.html +++ b/src/app/file-list/file-list.component.html @@ -27,3 +27,17 @@ +
+ + + +
diff --git a/src/app/file-list/file-list.component.ts b/src/app/file-list/file-list.component.ts index eb5a9ad..c1ceef3 100644 --- a/src/app/file-list/file-list.component.ts +++ b/src/app/file-list/file-list.component.ts @@ -1,8 +1,8 @@ import {Component, Input, OnInit} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {MatSnackBar} from '@angular/material/snack-bar'; -import {Router} from '@angular/router'; -import {ApiService, FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib'; +import {ActivatedRoute, Params, Router} from '@angular/router'; +import {ApiService, FileMeta, FileType, isNumberDefined, WorkflowSpec} from 'sartography-workflow-lib'; import {DeleteFileDialogComponent} from '../_dialogs/delete-file-dialog/delete-file-dialog.component'; import {FileMetaDialogComponent} from '../_dialogs/file-meta-dialog/file-meta-dialog.component'; import {DeleteFileDialogData, FileMetaDialogData} from '../_interfaces/dialog-data'; @@ -20,6 +20,7 @@ export class FileListComponent implements OnInit { constructor( private api: ApiService, public dialog: MatDialog, + private route: ActivatedRoute, private router: Router, private snackBar: MatSnackBar, ) { @@ -29,8 +30,8 @@ export class FileListComponent implements OnInit { this._loadFileMetas(); } - editFile(fileMeta: FileMeta) { - if (fileMeta.type === FileType.BPMN ||fileMeta.type === FileType.DMN) { + editFile(fileMeta?: FileMeta) { + if (fileMeta && ((fileMeta.type === FileType.BPMN) || (fileMeta.type === FileType.DMN))) { this.router.navigate([`/modeler/${this.workflowSpec.id}/${fileMeta.id}`]); } else { // Show edit file meta dialog @@ -39,11 +40,30 @@ export class FileListComponent implements OnInit { } editFileMeta(fm: FileMeta) { + // Set route query string + this.router.navigate([], { + relativeTo: this.route, + fragment: this.workflowSpec.id, + queryParams: { + workflow_spec_id: this.workflowSpec.id + }, + queryParamsHandling: 'merge' + }).finally(() => { + // Get file data + if (fm && isNumberDefined(fm.id)) { + this.api.getFileData(fm.id).subscribe(fileData => this._openFileDialog(fm, fileData)); + } else { + this._openFileDialog(); + } + }); + } + + private _openFileDialog(fm?: FileMeta, fileData?: Blob) { const dialogRef = this.dialog.open(FileMetaDialogComponent, { data: { - fileName: fm.name, - fileType: fm.type, - file: fm.file, + fileName: fm ? fm.name : undefined, + fileType: fm ? fm.type : undefined, + file: fileData ? fileData : undefined, } }); @@ -61,6 +81,7 @@ export class FileListComponent implements OnInit { }); } }); + } confirmDelete(fm: FileMeta) { @@ -114,4 +135,5 @@ export class FileListComponent implements OnInit { this.api.getFileData(fm.id).subscribe((fd: File) => fm.file = fd); }); } + } diff --git a/src/app/modeler/modeler.component.ts b/src/app/modeler/modeler.component.ts index 1e1eb30..d73fcb0 100644 --- a/src/app/modeler/modeler.component.ts +++ b/src/app/modeler/modeler.component.ts @@ -3,16 +3,21 @@ import {AfterViewInit, Component, ViewChild} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {MatSnackBar} from '@angular/material/snack-bar'; import {ActivatedRoute, Params, Router} from '@angular/router'; -import {ApiService, FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib'; -import {BpmnWarning} from '../_interfaces/bpmn-warning'; -import {FileMetaDialogData, NewFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data'; -import {ImportEvent} from '../_interfaces/import-event'; -import {getDiagramTypeFromXml} from '../_util/diagram-type'; -import {isNumberDefined} from '../_util/is-number-defined'; -import {DiagramComponent} from '../diagram/diagram.component'; +import { + ApiService, + FileMeta, + FileType, + getDiagramTypeFromXml, + isNumberDefined, + WorkflowSpec +} from 'sartography-workflow-lib'; import {FileMetaDialogComponent} from '../_dialogs/file-meta-dialog/file-meta-dialog.component'; import {NewFileDialogComponent} from '../_dialogs/new-file-dialog/new-file-dialog.component'; import {OpenFileDialogComponent} from '../_dialogs/open-file-dialog/open-file-dialog.component'; +import {BpmnWarning} from '../_interfaces/bpmn-warning'; +import {FileMetaDialogData, NewFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data'; +import {ImportEvent} from '../_interfaces/import-event'; +import {DiagramComponent} from '../diagram/diagram.component'; @Component({ selector: 'app-modeler', @@ -115,7 +120,7 @@ export class ModelerComponent implements AfterViewInit { this.xml = (event.target as FileReader).result.toString(); const diagramType = getDiagramTypeFromXml(this.xml); this.diagramComponent.openDiagram(this.xml, diagramType); - } + }; readFile(file: File) { // FileReader must be instantiated this way so unit test can spy on it. @@ -157,8 +162,7 @@ export class ModelerComponent implements AfterViewInit { } openFileDialog() { - const dialogRef = this.dialog.open(OpenFileDialogComponent, { - }); + const dialogRef = this.dialog.open(OpenFileDialogComponent, {}); dialogRef.afterClosed().subscribe((data: OpenFileDialogData) => { if (data && data.file) { @@ -169,8 +173,7 @@ export class ModelerComponent implements AfterViewInit { } newFileDialog() { - const dialogRef = this.dialog.open(NewFileDialogComponent, { - }); + const dialogRef = this.dialog.open(NewFileDialogComponent, {}); dialogRef.afterClosed().subscribe((data: NewFileDialogData) => { if (data && data.fileType) { @@ -185,6 +188,7 @@ export class ModelerComponent implements AfterViewInit { data: { fileName: this.diagramFile ? this.diagramFile.name : this.fileName || '', fileType: this.diagramType || getDiagramTypeFromXml(this.xml), + file: this.diagramFile || undefined, }, }); diff --git a/src/app/workflow-spec-card/workflow-spec-card.component.html b/src/app/workflow-spec-card/workflow-spec-card.component.html index 14be3cb..d65e11d 100644 --- a/src/app/workflow-spec-card/workflow-spec-card.component.html +++ b/src/app/workflow-spec-card/workflow-spec-card.component.html @@ -1,4 +1,4 @@ - +

{{workflowSpec.display_name}}

@@ -18,13 +18,5 @@ - -
diff --git a/src/app/workflow-spec-card/workflow-spec-card.component.ts b/src/app/workflow-spec-card/workflow-spec-card.component.ts index eb70e06..49e16a0 100644 --- a/src/app/workflow-spec-card/workflow-spec-card.component.ts +++ b/src/app/workflow-spec-card/workflow-spec-card.component.ts @@ -1,5 +1,7 @@ import {Component, Input, OnInit, TemplateRef} from '@angular/core'; -import {WorkflowSpec} from 'sartography-workflow-lib'; +import {MatDialog} from '@angular/material/dialog'; +import {MatSnackBar} from '@angular/material/snack-bar'; +import {ApiService, WorkflowSpec} from 'sartography-workflow-lib'; @Component({ selector: 'app-workflow-spec-card', @@ -16,4 +18,8 @@ export class WorkflowSpecCardComponent implements OnInit { ngOnInit(): void { } + openFileDialog() { + + + } } diff --git a/src/app/workflow-spec-list/workflow-spec-list.component.ts b/src/app/workflow-spec-list/workflow-spec-list.component.ts index 9ed56c0..b9ddfce 100644 --- a/src/app/workflow-spec-list/workflow-spec-list.component.ts +++ b/src/app/workflow-spec-list/workflow-spec-list.component.ts @@ -1,7 +1,7 @@ import {Component, OnInit} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {MatSnackBar} from '@angular/material/snack-bar'; -import {ApiService, WorkflowSpec, WorkflowSpecCategory} from 'sartography-workflow-lib'; +import {ApiService, isNumberDefined, WorkflowSpec, WorkflowSpecCategory} from 'sartography-workflow-lib'; import {DeleteWorkflowSpecCategoryDialogComponent} from '../_dialogs/delete-workflow-spec-category-dialog/delete-workflow-spec-category-dialog.component'; import {DeleteWorkflowSpecDialogComponent} from '../_dialogs/delete-workflow-spec-dialog/delete-workflow-spec-dialog.component'; import {WorkflowSpecCategoryDialogComponent} from '../_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component'; @@ -12,7 +12,6 @@ import { WorkflowSpecCategoryDialogData, WorkflowSpecDialogData } from '../_interfaces/dialog-data'; -import {isNumberDefined} from '../_util/is-number-defined'; interface WorklflowSpecCategoryGroup { id: number; @@ -138,13 +137,13 @@ export class WorkflowSpecListComponent implements OnInit { } private _loadWorkflowSpecs() { - this.api.getWorkflowSpecList().subscribe(wfs => { + this.api.getWorkflowSpecList().subscribe(wfs => { this.workflowSpecs = wfs; this.workflowSpecsByCategory.forEach(cat => { cat.workflow_specs = this.workflowSpecs.filter(wf => wf.workflow_spec_category_id === cat.id); }); }); - } + } private _upsertWorkflowSpecification(data: WorkflowSpecDialogData) { if (data.id && data.name && data.display_name && data.description) {