Enables user to mark a file as primary

This commit is contained in:
Aaron Louie 2020-01-31 09:41:37 -05:00
parent 30a91b58af
commit 297b198f1a
3 changed files with 78 additions and 4 deletions

View File

@ -1,6 +1,16 @@
<mat-list>
<mat-list-item *ngFor="let fm of fileMetas">
<mat-icon mat-list-icon (click)="editFile(fm.id)">{{fm.type | getIconCode}}</mat-icon>
<ng-container *ngIf="fm.type === fileType.BPMN">
<button mat-flat-button *ngIf="!fm.primary" (click)="makePrimary(fm)">
<mat-icon>radio_button_unchecked</mat-icon>
Make primary process
</button>
<button mat-flat-button *ngIf="fm.primary">
<mat-icon>radio_button_checked</mat-icon>
Primary process
</button>
</ng-container>
<h4 mat-line (click)="editFile(fm.id)">{{fm.name}}</h4>
<p mat-line (click)="editFile(fm.id)">{{fm.last_updated | date}}</p>
<button mat-icon-button color="primary" (click)="editFile(fm.id)" class="mat-elevation-z0"><mat-icon>edit</mat-icon></button>

View File

@ -8,7 +8,14 @@ import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/tes
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {RouterTestingModule} from '@angular/router/testing';
import {of} from 'rxjs';
import {ApiService, MockEnvironment, mockFileMeta0, mockFileMetas, mockWorkflowSpec0} from 'sartography-workflow-lib';
import {
ApiService,
FileMeta,
MockEnvironment,
mockFileMeta0,
mockFileMetas,
mockWorkflowSpec0
} from 'sartography-workflow-lib';
import {DeleteFileDialogComponent} from '../_dialogs/delete-file-dialog/delete-file-dialog.component';
import {DeleteFileDialogData} from '../_interfaces/dialog-data';
import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe';
@ -64,10 +71,27 @@ describe('FileListComponent', () => {
component.workflowSpec = mockWorkflowSpec0;
fixture.detectChanges();
const justFiles: File[] = [];
const fmsNoFiles: FileMeta[] = mockFileMetas.map(fm => {
justFiles.push(fm.file);
delete fm['file'];
return fm;
});
expect(justFiles.length).toEqual(mockFileMetas.length);
expect(fmsNoFiles.every(fm => !fm.file)).toEqual(true);
expect(justFiles.every(f => !!f.name)).toEqual(true);
const fmsReq = httpMock.expectOne(`apiRoot/file?spec_id=${mockWorkflowSpec0.id}`);
expect(fmsReq.request.method).toEqual('GET');
fmsReq.flush(mockFileMetas);
fmsReq.flush(fmsNoFiles);
expect(component.fileMetas.length).toBeGreaterThan(0);
fmsNoFiles.forEach((fm, i) => {
const fReq = httpMock.expectOne(`apiRoot/file/${fm.id}/data`);
expect(fReq.request.method).toEqual('GET');
fReq.flush(justFiles[i]);
expect(component.fileMetas[i].file).toBeTruthy();
});
});
afterEach(() => {
@ -116,4 +140,17 @@ describe('FileListComponent', () => {
component.editFile(mockFileMeta0.id);
expect(routerNavigateSpy).toHaveBeenCalledWith([`/modeler/${mockWorkflowSpec0.id}/${mockFileMeta0.id}`]);
});
it('should flag a file as primary', () => {
const updateFileMetaSpy = spyOn((component as any).api, 'updateFileMeta').and.returnValue(of(mockFileMeta0));
const _loadFileMetasSpy = spyOn((component as any), '_loadFileMetas').and.stub();
expect(component.fileMetas.length).toEqual(mockFileMetas.length);
component.makePrimary(mockFileMeta0);
expect(updateFileMetaSpy).toHaveBeenCalledTimes(mockFileMetas.length);
expect(component.fileMetas.length).toEqual(mockFileMetas.length);
expect(component.fileMetas.every(fm => !!fm.file)).toEqual(true);
expect(component.fileMetas.reduce((sum, fm) => fm.primary ? sum + 1 : sum, 0)).toEqual(1);
expect(_loadFileMetasSpy).toHaveBeenCalled();
});
});

View File

@ -2,7 +2,7 @@ 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, WorkflowSpec} from 'sartography-workflow-lib';
import {ApiService, FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib';
import {DeleteFileDialogComponent} from '../_dialogs/delete-file-dialog/delete-file-dialog.component';
import {DeleteFileDialogData} from '../_interfaces/dialog-data';
@ -14,6 +14,7 @@ import {DeleteFileDialogData} from '../_interfaces/dialog-data';
export class FileListComponent implements OnInit {
@Input() workflowSpec: WorkflowSpec;
fileMetas: FileMeta[];
fileType = FileType;
constructor(
private api: ApiService,
@ -46,6 +47,23 @@ export class FileListComponent implements OnInit {
});
}
makePrimary(fm: FileMeta) {
if (fm.type === FileType.BPMN) {
let numUpdated = 0;
this.fileMetas.forEach(f => {
f.primary = (fm.id === f.id);
this.api.updateFileMeta(this.workflowSpec.id, f).subscribe(() => {
numUpdated++;
// Reload all fileMetas when all have been updated.
if (numUpdated === this.fileMetas.length) {
this._loadFileMetas();
}
});
});
}
}
private _deleteFile(fileMeta: FileMeta) {
this.api.deleteFileMeta(fileMeta.id).subscribe(() => {
this._loadFileMetas();
@ -54,6 +72,15 @@ export class FileListComponent implements OnInit {
}
private _loadFileMetas() {
this.api.listBpmnFiles(this.workflowSpec.id).subscribe(fms => this.fileMetas = fms);
this.api.listBpmnFiles(this.workflowSpec.id).subscribe(fms => {
this.fileMetas = fms;
this._loadFileData();
});
}
private _loadFileData() {
this.fileMetas.forEach(fm => {
this.api.getFileData(fm.id).subscribe((fd: File) => fm.file = fd);
});
}
}