Skip to content

Commit

Permalink
Merge pull request #103 from DDMAL/mei-err-msg
Browse files Browse the repository at this point in the history
Add Copy Button to Error Message Tooltip and Update Validation Status Handling
  • Loading branch information
yinanazhou authored Jul 5, 2024
2 parents 8ed5054 + a0f2d14 commit ebec7ef
Show file tree
Hide file tree
Showing 10 changed files with 390 additions and 169 deletions.
45 changes: 45 additions & 0 deletions assets/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -665,3 +665,48 @@ a:hover {
width: 100%;
height: 100%;
}

/* ----------------------- */
/* Section: Invalid Cell
/* ----------------------- */

.invalid-container {
display: flex;
align-items: flex-start;
justify-content: space-between;
}

.tooltip-container {
display: flex;
align-items: flex-start;
justify-content: end;
max-width: 50%;
}

.tooltip-container .tooltip-text {
display: none;
position: relative;
background-color: #fff8c5;
border: 1px solid #d4a72c;
padding: 5px;
margin-top: 5px;
margin-bottom: 5px;
z-index: 10;
color: black;
border-radius: 5px;
}

.tooltip-container:hover .tooltip-text {
display: flex;
flex-direction: column;
align-items: flex-end;
}

.tooltip-container .tooltip-icon {
width: 20px;
margin: 5px;
}

.tooltip-copy:hover {
cursor: pointer;
}
3 changes: 3 additions & 0 deletions assets/img/copy-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/img/info-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 1 addition & 8 deletions src/Editor/ColumnTools.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import * as Validation from '../Validation';

export class ColumnTools {
public validationInProgress = false;
public pendingValidations = 0;
public hasInvalid = false;

constructor(private inputHeader: string[]) {}

getColumns(headers: string[]) {
Expand All @@ -22,8 +16,7 @@ export class ColumnTools {
} else if (headers[i].includes('mei')) {
columns.push({
data: headers[i],
validator: Validation.meiValidator,
allowInvalid: true,
renderer: 'meiRenderer',
});
} else {
columns.push({
Expand Down
110 changes: 66 additions & 44 deletions src/Editor/CressTable.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Handsontable from 'handsontable';
import * as Validation from '../Validation';
import { ImageHandler } from './ImageHandler';
import { ExportHandler } from './ExportHandler';
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';
import { setSavedStatus } from '../utils/Unsaved';
Expand All @@ -24,36 +25,50 @@ const changeHooks: TableEvent[] = [
export class CressTable {
private table: Handsontable;
private images: any[] = []; // Array to store images
private imageHandler: ImageHandler;
private exportHandler: ExportHandler;
private ColumnTools: ColumnTools;
private imageTools: ImageTools;
private meiTools: MeiTools;
private validationTools: ValidationTools;
private exportTools: ExportTools;
private columnTools: ColumnTools;

constructor(id: string, inputHeader: string[], body: any[]) {
const container = document.getElementById('hot-container');

// Initialize handlers
this.imageHandler = new ImageHandler(this.images);
this.exportHandler = new ExportHandler();
this.ColumnTools = new ColumnTools(inputHeader);
// 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);

// Convert all quote signs to inch marks in mei data
this.ColumnTools.convertMeiQuoteSign(body);
this.columnTools.convertMeiQuoteSign(body);

// Register the custom image renderer
Handsontable.renderers.registerRenderer(
'imgRenderer',
this.imageHandler.imgRender.bind(this.imageHandler),
this.imageTools.imgRender.bind(this.imageTools),
);

// Register the custom mei renderer
Handsontable.renderers.registerRenderer(
'meiRenderer',
this.meiTools.meiRender.bind(this.meiTools),
);

// Prepare table configuration
const headers = ['image', 'name', 'classification', 'mei'];
const columns = this.ColumnTools.getColumns(headers);
const colWidths = this.ColumnTools.getColWidths(headers);
const indices = this.ColumnTools.getIndices(body).map(String);
const columns = this.columnTools.getColumns(headers);
const colWidths = this.columnTools.getColWidths(headers);
const indices = this.columnTools.getIndices(body).map(String);

// Process images
let inputImgHeader = inputHeader.find((header) => header.includes('image'));
this.imageHandler.storeImages(inputImgHeader, body);
this.imageTools.storeImages(inputImgHeader, body);

// Process mei data
let inputMeiHeader = inputHeader.find((header) => header.includes('mei'));
this.meiTools.initMeiData(inputMeiHeader, body);

// Initialize table
this.table = new Handsontable(container, {
Expand All @@ -79,13 +94,7 @@ export class CressTable {
dropdownMenu: true,
className: 'table-menu-btn',
licenseKey: 'non-commercial-and-evaluation',
afterChange(_, source) {
if (source == 'loadData') {
this.validateCells();
}
},
beforeValidate: (value) => this.setProcessStatus(value),
afterValidate: (isValid) => this.setResultStatus(isValid),
afterChange: (changes, source) => this.validateMei(changes, source),
});

this.initFileListener(id, inputHeader, body, headers);
Expand All @@ -100,13 +109,13 @@ export class CressTable {
) {
const exportPlugin = this.table.getPlugin('exportFile');
document.getElementById('export-to-csv').addEventListener('click', () => {
this.exportHandler.exportToCsv(exportPlugin);
this.exportTools.exportToCsv(exportPlugin);
});

document
.getElementById('export-to-excel')
.addEventListener('click', async () => {
await this.exportHandler.exportToExcel(
await this.exportTools.exportToExcel(
inputHeader,
body,
headers,
Expand Down Expand Up @@ -139,30 +148,43 @@ export class CressTable {
});
}

private setProcessStatus(value: any) {
if (!this.ColumnTools.validationInProgress) {
this.ColumnTools.validationInProgress = true;
Validation.updateStatus('processing');
}
// Update `pendingValidations` if value is not empty
if (value) this.ColumnTools.pendingValidations++;
}

private setResultStatus(isValid: boolean) {
if (!isValid) this.ColumnTools.hasInvalid = true;
this.ColumnTools.pendingValidations--;
if (this.ColumnTools.pendingValidations === 0) {
this.ColumnTools.validationInProgress = false;
Validation.updateStatus('done', this.ColumnTools.hasInvalid);
this.ColumnTools.hasInvalid = false;
}
}

private initChangeListener() {
changeHooks.forEach((hook) => {
this.table.addHook(hook, (source) => {
if (source != 'loadData') setSavedStatus(false);
});
});
}

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(isValid);
});
});
} 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(isValid);
});
}
});
}
}
}
2 changes: 1 addition & 1 deletion src/Editor/ExportHandler.ts → src/Editor/ExportTools.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { saveAs } from 'file-saver';

export class ExportHandler {
export class ExportTools {
exportToCsv(exportPlugin: any) {
exportPlugin.downloadFile('csv', {
bom: true,
Expand Down
2 changes: 1 addition & 1 deletion src/Editor/ImageHandler.ts → src/Editor/ImageTools.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Handsontable from 'handsontable';

export class ImageHandler {
export class ImageTools {
private images: any[];

constructor(images: any[]) {
Expand Down
Loading

0 comments on commit ebec7ef

Please sign in to comment.