Refactors dialogs
This commit is contained in:
parent
35ec329f9e
commit
5d53350adc
|
@ -0,0 +1,21 @@
|
||||||
|
import {FileType} from 'sartography-workflow-lib';
|
||||||
|
|
||||||
|
export interface FileMetaDialogData {
|
||||||
|
fileName: string;
|
||||||
|
fileType: FileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NewFileDialogData {
|
||||||
|
fileType: FileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OpenFileDialogData {
|
||||||
|
file: File;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkflowSpecDialogData {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
display_name: string;
|
||||||
|
description: string;
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
import {FileType} from 'sartography-workflow-lib';
|
|
||||||
|
|
||||||
export interface FileMetaDialogData {
|
|
||||||
fileName: string;
|
|
||||||
fileType: FileType;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
export interface WorkflowSpecDialogData {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
display_name: string;
|
|
||||||
description: string;
|
|
||||||
}
|
|
|
@ -6,10 +6,10 @@ describe('GetIconCodePipe', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
pipe = new GetIconCodePipe();
|
pipe = new GetIconCodePipe();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('create an instance', () => {
|
it('create an instance', () => {
|
||||||
expect(pipe).toBeTruthy()
|
expect(pipe).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get an icon code for each file type', () => {
|
it('should get an icon code for each file type', () => {
|
||||||
|
|
|
@ -8,8 +8,7 @@ import {WorkflowSpecListComponent} from './workflow-spec-list/workflow-spec-list
|
||||||
const appRoutes: Routes = [
|
const appRoutes: Routes = [
|
||||||
{ path: 'modeler/:workflowSpecId', component: ModelerComponent },
|
{ path: 'modeler/:workflowSpecId', component: ModelerComponent },
|
||||||
{ path: 'modeler/:workflowSpecId/:fileMetaId', component: ModelerComponent },
|
{ path: 'modeler/:workflowSpecId/:fileMetaId', component: ModelerComponent },
|
||||||
{ path: 'workflow-specs', component: WorkflowSpecListComponent },
|
{ path: '', component: WorkflowSpecListComponent },
|
||||||
{ path: '', redirectTo: '/workflow-specs', pathMatch: 'full' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -29,6 +29,8 @@ import {ModelerComponent} from './modeler/modeler.component';
|
||||||
import {WorkflowSpecDialogComponent} from './workflow-spec-dialog/workflow-spec-dialog.component';
|
import {WorkflowSpecDialogComponent} from './workflow-spec-dialog/workflow-spec-dialog.component';
|
||||||
import {WorkflowSpecListComponent} from './workflow-spec-list/workflow-spec-list.component';
|
import {WorkflowSpecListComponent} from './workflow-spec-list/workflow-spec-list.component';
|
||||||
import { GetIconCodePipe } from './_pipes/get-icon-code.pipe';
|
import { GetIconCodePipe } from './_pipes/get-icon-code.pipe';
|
||||||
|
import { NewFileDialogComponent } from './new-file-dialog/new-file-dialog.component';
|
||||||
|
import { OpenFileDialogComponent } from './open-file-dialog/open-file-dialog.component';
|
||||||
|
|
||||||
export class ThisEnvironment implements AppEnvironment {
|
export class ThisEnvironment implements AppEnvironment {
|
||||||
production = environment.production;
|
production = environment.production;
|
||||||
|
@ -47,6 +49,8 @@ export class ThisEnvironment implements AppEnvironment {
|
||||||
FileListComponent,
|
FileListComponent,
|
||||||
WorkflowSpecDialogComponent,
|
WorkflowSpecDialogComponent,
|
||||||
GetIconCodePipe,
|
GetIconCodePipe,
|
||||||
|
NewFileDialogComponent,
|
||||||
|
OpenFileDialogComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
|
@ -78,7 +82,9 @@ export class ThisEnvironment implements AppEnvironment {
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
FileMetaDialogComponent,
|
FileMetaDialogComponent,
|
||||||
WorkflowSpecDialogComponent
|
NewFileDialogComponent,
|
||||||
|
OpenFileDialogComponent,
|
||||||
|
WorkflowSpecDialogComponent,
|
||||||
],
|
],
|
||||||
providers: [{provide: 'APP_ENVIRONMENT', useClass: ThisEnvironment}]
|
providers: [{provide: 'APP_ENVIRONMENT', useClass: ThisEnvironment}]
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit {
|
||||||
@ViewChild('containerRef', {static: true}) containerRef: ElementRef;
|
@ViewChild('containerRef', {static: true}) containerRef: ElementRef;
|
||||||
@ViewChild('propertiesRef', {static: true}) propertiesRef: ElementRef;
|
@ViewChild('propertiesRef', {static: true}) propertiesRef: ElementRef;
|
||||||
@Output() private importDone: EventEmitter<ImportEvent> = new EventEmitter();
|
@Output() private importDone: EventEmitter<ImportEvent> = new EventEmitter();
|
||||||
private diagramType: FileType = FileType.BPMN;
|
private diagramType: FileType;
|
||||||
private modeler: BpmnModeler | DmnModeler;
|
private modeler: BpmnModeler | DmnModeler;
|
||||||
private xml = '';
|
private xml = '';
|
||||||
private disabled = false;
|
private disabled = false;
|
||||||
|
|
|
@ -5,8 +5,7 @@ import {MatFormFieldModule} from '@angular/material/form-field';
|
||||||
import {MatInputModule} from '@angular/material/input';
|
import {MatInputModule} from '@angular/material/input';
|
||||||
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
|
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
|
||||||
import {FileType} from 'sartography-workflow-lib';
|
import {FileType} from 'sartography-workflow-lib';
|
||||||
import {FileMetaDialogData} from '../_interfaces/file-meta-dialog-data';
|
import {FileMetaDialogData} from '../_interfaces/dialog-data';
|
||||||
|
|
||||||
import {FileMetaDialogComponent} from './file-meta-dialog.component';
|
import {FileMetaDialogComponent} from './file-meta-dialog.component';
|
||||||
|
|
||||||
describe('EditFileMetaDialogComponent', () => {
|
describe('EditFileMetaDialogComponent', () => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {Component, Inject} from '@angular/core';
|
import {Component, Inject} from '@angular/core';
|
||||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||||
import {FileMetaDialogData} from '../_interfaces/file-meta-dialog-data';
|
import {FileMetaDialogData} from '../_interfaces/dialog-data';
|
||||||
import {cleanUpFilename, toSnakeCase, trimString} from '../_util/string-clean';
|
import {cleanUpFilename} from '../_util/string-clean';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-new-file-dialog',
|
selector: 'app-new-file-dialog',
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
({{workflowSpec.name}})
|
({{workflowSpec.name}})
|
||||||
</mat-toolbar-row>
|
</mat-toolbar-row>
|
||||||
<mat-toolbar-row>
|
<mat-toolbar-row>
|
||||||
<button mat-button [matMenuTriggerFor]="newMenu" title="Open diagram">
|
<button #newMenuTrigger="matMenuTrigger" mat-button [matMenuTriggerFor]="newMenu" title="Open diagram">
|
||||||
<mat-icon>insert_drive_file</mat-icon>
|
<mat-icon>insert_drive_file</mat-icon>
|
||||||
<mat-icon>arrow_drop_down</mat-icon>
|
<mat-icon>arrow_drop_down</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<button mat-button [matMenuTriggerFor]="importMenu" title="Open diagram">
|
<button #importMenuTrigger="matMenuTrigger" mat-button [matMenuTriggerFor]="importMenu" title="Open diagram">
|
||||||
<mat-icon>folder</mat-icon>
|
<mat-icon>folder</mat-icon>
|
||||||
<mat-icon>arrow_drop_down</mat-icon>
|
<mat-icon>arrow_drop_down</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
<button
|
<button
|
||||||
mat-menu-item
|
mat-menu-item
|
||||||
*ngFor="let bf of bpmnFiles"
|
*ngFor="let bf of bpmnFiles"
|
||||||
(click)="loadDbFile(bf)"
|
[routerLink]="['/modeler', workflowSpec.id, bf.id]"
|
||||||
[matTooltip]="getFileMetaTooltipText(bf)"
|
[matTooltip]="getFileMetaTooltipText(bf)"
|
||||||
matTooltipClass="tooltip-text"
|
matTooltipClass="tooltip-text"
|
||||||
matTooltipPosition="right"
|
matTooltipPosition="right"
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
} from 'sartography-workflow-lib';
|
} from 'sartography-workflow-lib';
|
||||||
import {BPMN_DIAGRAM, BPMN_DIAGRAM_WITH_WARNINGS} from '../../testing/mocks/diagram.mocks';
|
import {BPMN_DIAGRAM, BPMN_DIAGRAM_WITH_WARNINGS} from '../../testing/mocks/diagram.mocks';
|
||||||
import {BpmnWarning} from '../_interfaces/bpmn-warning';
|
import {BpmnWarning} from '../_interfaces/bpmn-warning';
|
||||||
import {FileMetaDialogData} from '../_interfaces/file-meta-dialog-data';
|
import {DialogData} from '../_interfaces/dialog-data';
|
||||||
import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe';
|
import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe';
|
||||||
import {DiagramComponent} from '../diagram/diagram.component';
|
import {DiagramComponent} from '../diagram/diagram.component';
|
||||||
import {FileMetaDialogComponent} from '../file-meta-dialog/file-meta-dialog.component';
|
import {FileMetaDialogComponent} from '../file-meta-dialog/file-meta-dialog.component';
|
||||||
|
@ -268,7 +268,7 @@ describe('ModelerComponent', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open file metadata dialog', () => {
|
it('should open file metadata dialog', () => {
|
||||||
const data: FileMetaDialogData = {
|
const data: DialogData = {
|
||||||
fileName: 'after',
|
fileName: 'after',
|
||||||
fileType: FileType.BPMN,
|
fileType: FileType.BPMN,
|
||||||
};
|
};
|
||||||
|
@ -283,7 +283,7 @@ describe('ModelerComponent', () => {
|
||||||
|
|
||||||
it('should update file metadata for existing file', () => {
|
it('should update file metadata for existing file', () => {
|
||||||
const newXml = '<xml>New Value</xml>';
|
const newXml = '<xml>New Value</xml>';
|
||||||
const data: FileMetaDialogData = {
|
const data: DialogData = {
|
||||||
fileName: mockFileMeta0.name,
|
fileName: mockFileMeta0.name,
|
||||||
fileType: FileType.BPMN,
|
fileType: FileType.BPMN,
|
||||||
};
|
};
|
||||||
|
@ -315,7 +315,7 @@ describe('ModelerComponent', () => {
|
||||||
|
|
||||||
it('should create new file metadata for new file', () => {
|
it('should create new file metadata for new file', () => {
|
||||||
const newXml = '<xml>New Value</xml>';
|
const newXml = '<xml>New Value</xml>';
|
||||||
const data: FileMetaDialogData = {
|
const data: DialogData = {
|
||||||
fileName: mockFileMeta0.name,
|
fileName: mockFileMeta0.name,
|
||||||
fileType: FileType.BPMN,
|
fileType: FileType.BPMN,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,14 +2,16 @@ import {DatePipe} from '@angular/common';
|
||||||
import {AfterViewInit, Component, ViewChild} from '@angular/core';
|
import {AfterViewInit, Component, ViewChild} from '@angular/core';
|
||||||
import {MatDialog} from '@angular/material/dialog';
|
import {MatDialog} from '@angular/material/dialog';
|
||||||
import {MatSnackBar} from '@angular/material/snack-bar';
|
import {MatSnackBar} from '@angular/material/snack-bar';
|
||||||
import {ActivatedRoute} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
import {ApiService, FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib';
|
import {ApiService, FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib';
|
||||||
import {BpmnWarning} from '../_interfaces/bpmn-warning';
|
import {BpmnWarning} from '../_interfaces/bpmn-warning';
|
||||||
import {FileMetaDialogData} from '../_interfaces/file-meta-dialog-data';
|
import {FileMetaDialogData, NewFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data';
|
||||||
import {ImportEvent} from '../_interfaces/import-event';
|
import {ImportEvent} from '../_interfaces/import-event';
|
||||||
import {getDiagramTypeFromXml} from '../_util/diagram-type';
|
import {getDiagramTypeFromXml} from '../_util/diagram-type';
|
||||||
import {DiagramComponent} from '../diagram/diagram.component';
|
import {DiagramComponent} from '../diagram/diagram.component';
|
||||||
import {FileMetaDialogComponent} from '../file-meta-dialog/file-meta-dialog.component';
|
import {FileMetaDialogComponent} from '../file-meta-dialog/file-meta-dialog.component';
|
||||||
|
import {NewFileDialogComponent} from '../new-file-dialog/new-file-dialog.component';
|
||||||
|
import {OpenFileDialogComponent} from '../open-file-dialog/open-file-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-modeler',
|
selector: 'app-modeler',
|
||||||
|
@ -42,21 +44,19 @@ export class ModelerComponent implements AfterViewInit {
|
||||||
private snackBar: MatSnackBar,
|
private snackBar: MatSnackBar,
|
||||||
public dialog: MatDialog,
|
public dialog: MatDialog,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
this.route.queryParams.subscribe(q => {
|
this.route.queryParams.subscribe(q => {
|
||||||
if (q && q.action) {
|
if (q && q.action) {
|
||||||
if (q.action === 'openFile') {
|
if (q.action === 'openFile') {
|
||||||
this.expandToolbar = true;
|
this.openFileDialog();
|
||||||
this.openMethod = 'file';
|
|
||||||
} else if (q.action === 'newFile') {
|
} else if (q.action === 'newFile') {
|
||||||
|
this.newFileDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
this.route.paramMap.subscribe(paramMap => {
|
this.route.paramMap.subscribe(paramMap => {
|
||||||
console.log('paramMap', paramMap);
|
|
||||||
this.workflowSpecId = paramMap.get('workflowSpecId');
|
this.workflowSpecId = paramMap.get('workflowSpecId');
|
||||||
this.fileMetaId = parseInt(paramMap.get('fileMetaId'), 10);
|
this.fileMetaId = parseInt(paramMap.get('fileMetaId'), 10);
|
||||||
this.loadFilesFromDb();
|
this.loadFilesFromDb();
|
||||||
|
@ -163,14 +163,35 @@ export class ModelerComponent implements AfterViewInit {
|
||||||
this.diagramComponent.openDiagram(undefined, diagramType);
|
this.diagramComponent.openDiagram(undefined, diagramType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openFileDialog() {
|
||||||
|
const dialogRef = this.dialog.open(OpenFileDialogComponent, {
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe((data: OpenFileDialogData) => {
|
||||||
|
if (data && data.file) {
|
||||||
|
this.diagramFile = data.file;
|
||||||
|
this.onSubmitFileToOpen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
newFileDialog() {
|
||||||
|
const dialogRef = this.dialog.open(NewFileDialogComponent, {
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe((data: NewFileDialogData) => {
|
||||||
|
if (data && data.fileType) {
|
||||||
|
this.diagramType = data.fileType;
|
||||||
|
this.newDiagram(data.fileType);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
editFileMeta() {
|
editFileMeta() {
|
||||||
// Open new filename/workflow spec dialog
|
|
||||||
const dialogRef = this.dialog.open(FileMetaDialogComponent, {
|
const dialogRef = this.dialog.open(FileMetaDialogComponent, {
|
||||||
height: '400px',
|
|
||||||
width: '400px',
|
|
||||||
data: {
|
data: {
|
||||||
fileName: this.diagramFile ? this.diagramFile.name : this.fileName || '',
|
fileName: this.diagramFile ? this.diagramFile.name : this.fileName || '',
|
||||||
fileType: getDiagramTypeFromXml(this.xml),
|
fileType: this.diagramType || getDiagramTypeFromXml(this.xml),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -215,39 +236,36 @@ export class ModelerComponent implements AfterViewInit {
|
||||||
|
|
||||||
private loadFilesFromDb() {
|
private loadFilesFromDb() {
|
||||||
this.api.getWorkflowSpecList().subscribe(wfs => {
|
this.api.getWorkflowSpecList().subscribe(wfs => {
|
||||||
this.workflowSpecs = wfs;
|
this.workflowSpecs = wfs;
|
||||||
this.workflowSpecs.forEach(w => {
|
this.workflowSpecs.forEach(w => {
|
||||||
if (w.id === this.workflowSpecId) {
|
if (w.id === this.workflowSpecId) {
|
||||||
this.workflowSpec = w;
|
this.workflowSpec = w;
|
||||||
this.api.listBpmnFiles(w.id).subscribe(files => {
|
this.api.listBpmnFiles(w.id).subscribe(files => {
|
||||||
this.bpmnFiles = [];
|
this.bpmnFiles = [];
|
||||||
files.forEach(f => {
|
files.forEach(f => {
|
||||||
this.api.getFileData(f.id).subscribe(d => {
|
this.api.getFileData(f.id).subscribe(d => {
|
||||||
if ((f.type === FileType.BPMN) || (f.type === FileType.DMN)) {
|
if ((f.type === FileType.BPMN) || (f.type === FileType.DMN)) {
|
||||||
f.content_type = 'text/xml';
|
f.content_type = 'text/xml';
|
||||||
f.file = new File([d], f.name, {type: f.content_type});
|
f.file = new File([d], f.name, {type: f.content_type});
|
||||||
this.bpmnFiles.push(f);
|
this.bpmnFiles.push(f);
|
||||||
|
|
||||||
if (f.id === this.fileMetaId) {
|
if (f.id === this.fileMetaId) {
|
||||||
this.diagramFileMeta = f;
|
this.diagramFileMeta = f;
|
||||||
this.diagramFile = f.file;
|
this.diagramFile = f.file;
|
||||||
this.onSubmitFileToOpen();
|
this.onSubmitFileToOpen();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _upsertFileMeta(data: FileMetaDialogData) {
|
private _upsertFileMeta(data: FileMetaDialogData) {
|
||||||
if (data.fileName) {
|
if (data.fileName) {
|
||||||
this.xml = this.draftXml;
|
this.xml = this.draftXml;
|
||||||
|
|
||||||
// Save old workflow spec id, if user wants to change it
|
|
||||||
const specId = this.workflowSpec ? this.workflowSpec.id : undefined;
|
|
||||||
const fileMetaId = this.diagramFileMeta ? this.diagramFileMeta.id : undefined;
|
const fileMetaId = this.diagramFileMeta ? this.diagramFileMeta.id : undefined;
|
||||||
const fileType = this.diagramFileMeta ? this.diagramFileMeta.type : FileType.BPMN;
|
const fileType = this.diagramFileMeta ? this.diagramFileMeta.type : FileType.BPMN;
|
||||||
this.diagramFileMeta = {
|
this.diagramFileMeta = {
|
||||||
|
@ -259,17 +277,17 @@ export class ModelerComponent implements AfterViewInit {
|
||||||
workflow_spec_id: this.workflowSpec.id,
|
workflow_spec_id: this.workflowSpec.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (specId && fileMetaId) {
|
if (this.workflowSpec && fileMetaId) {
|
||||||
// Update existing file meta
|
// Update existing file meta
|
||||||
this.api.updateFileMeta(specId, this.diagramFileMeta).subscribe(fileMeta => {
|
this.api.updateFileMeta(this.workflowSpec.id, this.diagramFileMeta).subscribe(fileMeta => {
|
||||||
this.loadFilesFromDb();
|
this.loadFilesFromDb();
|
||||||
this.snackBar.open('Saved changes to workflow spec and file.', 'Ok', {duration: 5000});
|
this.snackBar.open(`Saved changes to file ${fileMeta.name}.`, 'Ok', {duration: 5000});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Add new file meta
|
// Add new file meta
|
||||||
this.api.addFileMeta(specId, this.diagramFileMeta).subscribe(fileMeta => {
|
this.api.addFileMeta(this.workflowSpec.id, this.diagramFileMeta).subscribe(fileMeta => {
|
||||||
this.loadFilesFromDb();
|
this.router.navigate(['/modeler', this.workflowSpec.id, fileMeta.id]);
|
||||||
this.snackBar.open('Saved new workflow spec and file.', 'Ok', {duration: 5000});
|
this.snackBar.open(`Saved new file ${fileMeta.name} to workflow spec ${this.workflowSpec.name}.`, 'Ok', {duration: 5000});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,7 +305,7 @@ export class ModelerComponent implements AfterViewInit {
|
||||||
this.xml = this.draftXml;
|
this.xml = this.draftXml;
|
||||||
this.diagramFileMeta.file = new File([this.xml], this.diagramFileMeta.name, {type: 'text/xml'});
|
this.diagramFileMeta.file = new File([this.xml], this.diagramFileMeta.name, {type: 'text/xml'});
|
||||||
this.api.updateFileMeta(this.workflowSpec.id, this.diagramFileMeta).subscribe(() => {
|
this.api.updateFileMeta(this.workflowSpec.id, this.diagramFileMeta).subscribe(() => {
|
||||||
this.snackBar.open('Saved changes to file.', 'Ok', {duration: 5000});
|
this.snackBar.open(`Saved changes to file ${this.diagramFileMeta.name}.`, 'Ok', {duration: 5000});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<div mat-dialog-title>
|
||||||
|
<button mat-icon-button mat-dialog-close=""><mat-icon>close</mat-icon></button>
|
||||||
|
</div>
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<div *ngIf="!mode" class="select-mode" fxLayoutAlign="center center">
|
||||||
|
<button (click)="onSubmit(fileType.DMN)" color="primary" mat-flat-button>
|
||||||
|
<mat-icon>{{fileType.DMN | getIconCode}}</mat-icon>
|
||||||
|
New DMN Diagram
|
||||||
|
</button>
|
||||||
|
<button (click)="onSubmit(fileType.BPMN)" color="primary" mat-flat-button>
|
||||||
|
<mat-icon>{{fileType.BPMN | getIconCode}}</mat-icon>
|
||||||
|
New BPMN Diagram
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,9 @@
|
||||||
|
.select-mode {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 1em;
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { NewFileDialogComponent } from './new-file-dialog.component';
|
||||||
|
|
||||||
|
describe('NewFileDialogComponent', () => {
|
||||||
|
let component: NewFileDialogComponent;
|
||||||
|
let fixture: ComponentFixture<NewFileDialogComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ NewFileDialogComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(NewFileDialogComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {MatDialogRef} from '@angular/material/dialog';
|
||||||
|
import {FileType} from 'sartography-workflow-lib';
|
||||||
|
import {NewFileDialogData} from '../_interfaces/dialog-data';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-new-file-dialog',
|
||||||
|
templateUrl: './new-file-dialog.component.html',
|
||||||
|
styleUrls: ['./new-file-dialog.component.scss']
|
||||||
|
})
|
||||||
|
export class NewFileDialogComponent {
|
||||||
|
mode: string;
|
||||||
|
fileType = FileType;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<NewFileDialogComponent>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
onNoClick() {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(fileType: FileType) {
|
||||||
|
const data: NewFileDialogData = {fileType: fileType};
|
||||||
|
this.dialogRef.close(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<div *ngIf="!mode" class="select-mode" fxLayoutAlign="center center">
|
||||||
|
<button (click)="mode = 'local'" color="primary" mat-flat-button>
|
||||||
|
<mat-icon>code</mat-icon>
|
||||||
|
Upload a local BPMN/DMN file
|
||||||
|
</button>
|
||||||
|
<button (click)="mode = 'remote'" color="primary" mat-flat-button>
|
||||||
|
<mat-icon>link</mat-icon>
|
||||||
|
Open a BPMN/DMN file from URL
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="mode === 'local'">
|
||||||
|
<h1>Upload a local file</h1>
|
||||||
|
<mat-form-field (click)="fileInput.click()">
|
||||||
|
<mat-icon matPrefix>folder_open</mat-icon>
|
||||||
|
<input [value]="getFileName()" disabled matInput type="text">
|
||||||
|
</mat-form-field>
|
||||||
|
<input #fileInput (change)="onFileSelected($event)" accept=".bpmn,.dmn,.xml,application/xml,text/xml" hidden id="file"
|
||||||
|
type="file">
|
||||||
|
<button (click)="onSubmit()" [disabled]="!diagramFile" color="primary" mat-flat-button>Upload File</button>
|
||||||
|
<button (click)="mode = undefined" mat-flat-button>Cancel</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="mode === 'remote'">
|
||||||
|
<h1>Open a file from a URL</h1>
|
||||||
|
<mat-form-field>
|
||||||
|
<input [(ngModel)]="url" matInput placeholder="BPMN/DMN File URL" type="url">
|
||||||
|
</mat-form-field>
|
||||||
|
<button (click)="onSubmitUrl()" [disabled]="!isValidUrl()" color="primary" mat-flat-button>Fetch File</button>
|
||||||
|
<button (click)="mode = undefined" mat-flat-button>Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,17 @@
|
||||||
|
.select-mode {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-dialog-content {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-form-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { OpenFileDialogComponent } from './open-file-dialog.component';
|
||||||
|
|
||||||
|
describe('OpenFileDialogComponent', () => {
|
||||||
|
let component: OpenFileDialogComponent;
|
||||||
|
let fixture: ComponentFixture<OpenFileDialogComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ OpenFileDialogComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(OpenFileDialogComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { Component, OnInit } 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';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-open-file-dialog',
|
||||||
|
templateUrl: './open-file-dialog.component.html',
|
||||||
|
styleUrls: ['./open-file-dialog.component.scss']
|
||||||
|
})
|
||||||
|
export class OpenFileDialogComponent {
|
||||||
|
mode: string;
|
||||||
|
diagramFile: File;
|
||||||
|
url: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<OpenFileDialogComponent>,
|
||||||
|
private api: ApiService
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
onNoClick() {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.dialogRef.close({file: this.diagramFile});
|
||||||
|
}
|
||||||
|
|
||||||
|
onFileSelected($event: Event) {
|
||||||
|
this.diagramFile = ($event.target as HTMLFormElement).files[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
getFileName() {
|
||||||
|
return this.diagramFile ? this.diagramFile.name : 'No file selected';
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmitUrl() {
|
||||||
|
if (this.url) {
|
||||||
|
this.api.getStringFromUrl(this.url).subscribe(s => {
|
||||||
|
const fileArray = this.url.split('/');
|
||||||
|
const fileName = fileArray[fileArray.length - 1];
|
||||||
|
const fileType = getDiagramTypeFromXml(s);
|
||||||
|
const name = cleanUpFilename(fileName, fileType);
|
||||||
|
this.diagramFile = new File([s], name, {type: 'text/xml'});
|
||||||
|
this.onSubmit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isValidUrl() {
|
||||||
|
// tslint:disable-next-line:max-line-length
|
||||||
|
const re = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i;
|
||||||
|
return re.test(this.url);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ import {FormGroup} from '@angular/forms';
|
||||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||||
import {FormlyFieldConfig, FormlyFormOptions} from '@ngx-formly/core';
|
import {FormlyFieldConfig, FormlyFormOptions} from '@ngx-formly/core';
|
||||||
import {v4 as uuidv4} from 'uuid';
|
import {v4 as uuidv4} from 'uuid';
|
||||||
import {WorkflowSpecDialogData} from '../_interfaces/workflow-spec-dialog-data';
|
import {WorkflowSpecDialogData} from '../_interfaces/dialog-data';
|
||||||
import {toSnakeCase} from '../_util/string-clean';
|
import {toSnakeCase} from '../_util/string-clean';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Component, OnInit} from '@angular/core';
|
||||||
import {MatDialog} from '@angular/material/dialog';
|
import {MatDialog} from '@angular/material/dialog';
|
||||||
import {MatSnackBar} from '@angular/material/snack-bar';
|
import {MatSnackBar} from '@angular/material/snack-bar';
|
||||||
import {ApiService, WorkflowSpec} from 'sartography-workflow-lib';
|
import {ApiService, WorkflowSpec} from 'sartography-workflow-lib';
|
||||||
import {WorkflowSpecDialogData} from '../_interfaces/workflow-spec-dialog-data';
|
import {WorkflowSpecDialogData} from '../_interfaces/dialog-data';
|
||||||
import {WorkflowSpecDialogComponent} from '../workflow-spec-dialog/workflow-spec-dialog.component';
|
import {WorkflowSpecDialogComponent} from '../workflow-spec-dialog/workflow-spec-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
Loading…
Reference in New Issue