From e902b70316adf3eccfd5ccda9344891fc927d8ab Mon Sep 17 00:00:00 2001 From: Yinan Zhou Date: Fri, 12 Jul 2024 11:13:24 -0400 Subject: [PATCH 1/2] refactor: optimize mei validation - Move `validateMei` to `MeiTools.ts` - Remove `setProcessStatus` and `setResultStatus` - Refactor validation hooks Resolves: #110 --- src/Editor/CressTable.ts | 42 +++++++------------------------- src/Editor/MeiTools.ts | 52 ++++++++++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/Editor/CressTable.ts b/src/Editor/CressTable.ts index 6cace21..4c0a51b 100644 --- a/src/Editor/CressTable.ts +++ b/src/Editor/CressTable.ts @@ -1,7 +1,6 @@ import Handsontable from 'handsontable'; import { ImageTools } from './ImageTools'; import { MeiTools } from './MeiTools'; -import { ValidationTools } from './ValidationTools'; import { ExportTools } from './ExportTools'; import { ColumnTools } from './ColumnTools'; import { updateAttachment } from '../Dashboard/Storage'; @@ -27,7 +26,6 @@ export class CressTable { private images: any[] = []; // Array to store images private imageTools: ImageTools; private meiTools: MeiTools; - private validationTools: ValidationTools; private exportTools: ExportTools; private columnTools: ColumnTools; @@ -37,7 +35,6 @@ export class CressTable { // Initialize Toolss this.imageTools = new ImageTools(this.images); this.meiTools = new MeiTools(); - this.validationTools = new ValidationTools(); this.exportTools = new ExportTools(); this.columnTools = new ColumnTools(inputHeader); @@ -94,7 +91,9 @@ export class CressTable { dropdownMenu: true, className: 'table-menu-btn', licenseKey: 'non-commercial-and-evaluation', - afterChange: (changes, source) => this.validateMei(changes, source), + afterLoadData: (_, initialLoad) => { + if (initialLoad) setTimeout(this.initValidationListener.bind(this), 0); + }, }); this.initFileListener(id, inputHeader, body, headers); @@ -156,35 +155,10 @@ export class CressTable { }); } - private validateMei(changes, source) { - if (source == 'loadData') { - // Validate mei data and update the validation status - this.meiTools.getMeiData().forEach((mei) => { - this.meiTools.setProcessStatus(mei); - this.validationTools - .meiValidator(mei.mei) - .then(([isValid, errorMsg]) => { - this.meiTools.updateMeiData(mei.row, mei.mei, isValid, errorMsg); - this.table.render(); - this.meiTools.setResultStatus(); - }); - }); - } else { - changes?.forEach(([row, prop, oldValue, newValue]) => { - if (prop === 'mei' && oldValue !== newValue) { - // validate the new edited mei data and update the validation status - this.meiTools.setProcessStatus(newValue); - this.meiTools.updateMeiData(row, newValue, undefined, undefined); - this.table.render(); - this.validationTools - .meiValidator(newValue) - .then(([isValid, errorMsg]) => { - this.meiTools.updateMeiData(row, undefined, isValid, errorMsg); - this.table.render(); - this.meiTools.setResultStatus(); - }); - } - }); - } + private initValidationListener() { + this.meiTools.validateMei(this.table, 'afterLoadData'); + this.table.addHook('afterChange', (changes, _) => { + this.meiTools.validateMei(this.table, 'afterChange', changes); + }); } } diff --git a/src/Editor/MeiTools.ts b/src/Editor/MeiTools.ts index a471a9f..c111018 100644 --- a/src/Editor/MeiTools.ts +++ b/src/Editor/MeiTools.ts @@ -1,5 +1,5 @@ import Handsontable from 'handsontable'; -import { updateStatus } from './ValidationTools'; +import { updateStatus, ValidationTools } from './ValidationTools'; import * as Notification from '../utils/Notification'; import { MeiData } from '../Types'; @@ -7,8 +7,10 @@ export class MeiTools { private meiData: MeiData; public validationInProgress = false; public pendingValidations = 0; + private validationTools: ValidationTools; constructor() { + this.validationTools = new ValidationTools(); this.meiData = []; } @@ -60,24 +62,48 @@ export class MeiTools { } } - public setProcessStatus(value: any) { - if (!this.validationInProgress) { - this.validationInProgress = true; - updateStatus('processing'); + public validateMei(cressTable, hook, changes?) { + updateStatus('processing'); + + let validationPromises = []; + + switch (hook) { + case 'afterLoadData': + this.getMeiData().forEach((mei) => { + if (mei) { + const validationPromise = this.validationTools + .meiValidator(mei.mei) + .then(([isValid, errorMsg]) => { + this.updateMeiData(mei.row, mei.mei, isValid, errorMsg); + }); + validationPromises.push(validationPromise); + } + }); + break; + + case 'afterChange': + changes?.forEach(([row, prop, oldValue, newValue]) => { + if (prop === 'mei' && oldValue !== newValue && newValue) { + // validate the new edited mei data and update the validation status + this.updateMeiData(row, newValue, undefined, undefined); + const validationPromise = this.validationTools + .meiValidator(newValue) + .then(([isValid, errorMsg]) => { + this.updateMeiData(row, undefined, isValid, errorMsg); + }); + validationPromises.push(validationPromise); + } + }); } - // Update `pendingValidations` if value is not empty - if (value) this.pendingValidations++; - } - public setResultStatus() { - this.pendingValidations--; - if (this.pendingValidations === 0) { - this.validationInProgress = false; + Promise.all(validationPromises).then(() => { + cressTable.render(); + const hasInvalid = this.meiData.some( (element) => element.isValid === false, ); updateStatus('done', hasInvalid); - } + }); } // Mei Renderer Functions From dac125943e966ac33d9565f70a97c994fa4882c6 Mon Sep 17 00:00:00 2001 From: Yinan Zhou Date: Fri, 12 Jul 2024 11:47:15 -0400 Subject: [PATCH 2/2] fix: call `updateMeiData` when MEI cell is empty Resolves: #117 --- src/Editor/MeiTools.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Editor/MeiTools.ts b/src/Editor/MeiTools.ts index c111018..9804310 100644 --- a/src/Editor/MeiTools.ts +++ b/src/Editor/MeiTools.ts @@ -83,15 +83,18 @@ export class MeiTools { case 'afterChange': changes?.forEach(([row, prop, oldValue, newValue]) => { - if (prop === 'mei' && oldValue !== newValue && newValue) { - // validate the new edited mei data and update the validation status - this.updateMeiData(row, newValue, undefined, undefined); - const validationPromise = this.validationTools - .meiValidator(newValue) - .then(([isValid, errorMsg]) => { - this.updateMeiData(row, undefined, isValid, errorMsg); - }); - validationPromises.push(validationPromise); + if (prop === 'mei' && oldValue !== newValue) { + if (newValue) { + // validate the new edited mei data and update the validation status + const validationPromise = this.validationTools + .meiValidator(newValue) + .then(([isValid, errorMsg]) => { + this.updateMeiData(row, newValue, isValid, errorMsg); + }); + validationPromises.push(validationPromise); + } else { + this.updateMeiData(row, newValue, undefined, undefined); + } } }); }