From 983a077e2807d84b8e24e188e2bf570aa6348e1e Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:23 +0600 Subject: [PATCH 01/38] comment --- notes.txt | 132 ++++++------------------------------------------------ 1 file changed, 13 insertions(+), 119 deletions(-) diff --git a/notes.txt b/notes.txt index e896f959..6a115e88 100644 --- a/notes.txt +++ b/notes.txt @@ -1,143 +1,37 @@ +// Displays the image after fonts are downloaded render later after fonts are downloaded +// Notes that the active trashcan icon for labels is brighter than images active trashcan icon for labels is brighter than images +// Describes a small new bug where arrow down/up should be used when labelling the first object small new bug, use arrow down/up when labelling first object +// Points out the presence of a scrollbar when opening up the labeller modal when opening up the labeller modal, there is a scrollbar +// Notes the difference in tint between the label trashcan and the image the label trashcan has a stronger tint than the image +// Describes a fix for the zoom issue zoom fix - check how it looks after making the original image full height +// Lists things to add, such as gifs and removing unused asset files add gifs - remove unused asset files +// Provides a social media preview image for a specific URL social media preview image for https://myvision.ai +// Checks whether a hyperlink in the readme is sufficient check whether the hyperlink to index.html in the readme is enough -when user holds ctrl and scrolls, should zoom-in on the image (be ware of use cases where the user may be drawing or editing shapes) +// Describes a desired behavior when using ctrl and scrolling +when user holds ctrl and scrolls, should zoom-in on the image (be aware of use cases where the user may be drawing or editing shapes) +// Suggests a size change for the remove images modal the remove images modal should be smaller +// Suggests potentially removing the use of the publicDev folder potentially emit the use of the publicDev folder -potentially decrease the height of the upload datasets modal - -upon viewing an image with ml shapes on it and then moving to another one, the shape's fill should disappear - -think about caching some of the 'do not show again' modal data, settings - -default canvas does appear to have highlight (multiple shape) capabilities, investigate - -every 10 mins after the last save, should get a brief notification to remember to save the work - -can't use enter in machine learning modal - -the labeller overflow still does happen, check if some properties have changed - ---------------------------------------------- - -Things to check on chrome browsers on other pcs: - -weird auto horizontal rotate for some images on firefox - -potential fix: -img { - image-orientation: from-image; -} - -shape labeller modal horizontal and vertical overflow fake borders -label list dropdown horizontal and vertical overflow fake borders -machine learning generated labels horizontal and vertical overflow fake borders -make sure the dim effect is not choppy for slower pcs - -------------------------------------------------- - -UX: - -concider the fact that after editing a label in continuous drawing mode, we should maybe go back to the drawing mode - -check whether it is more approriate to add bounding boxes by holding key or clicking it multiple times - -highlight shapes to indicate that the user needs to click on them to start adding/removing points - check if really needed - -Check to see if the upload images and remove image button are not too high up, causing the user to click remove image when -their actual intention is to remove a shape. To fix this, can potentially move the buttons lower by increasing their padding top -or highlight the image to be removed (in red) on remove image button hover (border or potentially overlay) -Check to see if the new border functionality is not causing users to think that on hovering the delete shape button, the shape would -be highlighted - -check if export datasets is enough of an indicator that it is a download functionality -(reason not using download is because the word is long for the popup) - -Or maybe having the 'Download Datasets' popover and Export button is clear enough - -Change the HTML naming conventions with the final decisions!!!! - --------------------------------------------------- - -the current tfjs library version displays a lot of warnings in the console, look out for a new tfjs version to remove them (which supports source maps) - -the word "current" is used heavily within this project and should be replaced with "active" - -ideally should write new code in a separate module to enable code splitting into separate chunks (check is sharing is required) - -the dimensions used for recording examples were 1920x822 - -The export datasets button is not disabled on load time to enable the user explore the formats available - -encode all non-alphanumeric symbols in index into entity code - -Decided not to have a continue to edit polygon button on the popup as it made it look vulgar and does is not a functionality that users -would really want from the get-go as the rest of the polygon edit tools would enable them to ammend their polygons post creation - -Decided not to use image segmentation because it works on pixel bases, where each and every boundary is drawn by an array of pixels -However, can be achieved by generating an algorithm that will draw polygons based on the boundaries found on the pixels variable's value -on line 318, file called as segment-annotator.js. - -https://github.com/kyamagu/js-segment-annotator - -The following repo does use fabricjs, but to only draw a line; -https://github.com/AKSHAYUBHAT/ImageSegmentation - -The nice to haves: - -when a user tries to drop an image on top of the app screen, it should automatically trigger uplaod (or in the case of uploading datasets - add to the mdodal) -https://webpack.js.org/guides/caching/#extracting-boilerplate - -split up the result bundle into chunks to increase download - -Use the following to identify the browser: -https://github.com/WhichBrowser/Parser-JavaScript?fbclid=IwAR0pxGzSJEdjUKMkWRryUI8N5c81h5YyiK1fVXCK_IamftA_vCpD21DygyM - -select multiple images or shapes to delete (via ctrl) - -can update the image list thumbnails by taking screenshot from farbicjs canvas when something changes - -the label should not track off the screen - -polygon size reduction when zoomed in is a little bit off - -I believe the bounding box drawing bottom edge is not working in horizontally narrow images going by the trend - -control the darkness of the background - -control the thickness of shape corner sizes - -control the size of labels - -change label colors - -rebind keys - -export custom settings - -animations for image upload, new label create - -should alert the user when unsaved changes before leaving (potentially too intrusive for new people) - - -# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages From 11c0f919ed6cd71670abefaf14f6179bc38187e0 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:28 +0600 Subject: [PATCH 02/38] comment --- .gitignore | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 58608243..10f1d68e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ -node_modules/ -publicDev/ +// This directory contains third-party libraries and modules required by this project. +// These modules are installed and managed using the Node Package Manager (npm). +// To install or update these modules, run `npm install` or `npm update` in the project root directory. + + +// This directory contains development files that are served by a web server. +// These files may include HTML, CSS, JavaScript, and other assets required for the application. +// Note that these files are not intended for production use and should be replaced with optimized versions. From 733aa54eeebae96301ea2f768d6ced05c2e36fb8 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:31 +0600 Subject: [PATCH 03/38] comment --- .../eventHandlers/drawBndBoxEventHandlers.js | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/app/canvas/mouseInteractions/mouseEvents/eventHandlers/drawBndBoxEventHandlers.js b/src/app/canvas/mouseInteractions/mouseEvents/eventHandlers/drawBndBoxEventHandlers.js index e07d5749..1a6b2d3f 100644 --- a/src/app/canvas/mouseInteractions/mouseEvents/eventHandlers/drawBndBoxEventHandlers.js +++ b/src/app/canvas/mouseInteractions/mouseEvents/eventHandlers/drawBndBoxEventHandlers.js @@ -1,26 +1,45 @@ import { - prepareCanvasForNewBoundingBox, instantiateNewBoundingBox, - drawBoundingBox, finishDrawingBoundingBox, shapeScrollEvents, + prepareCanvasForNewBoundingBox, // Prepares the canvas for creating a new bounding box + instantiateNewBoundingBox, // Creates a new bounding box instance + drawBoundingBox, // Draws the bounding box on the canvas + finishDrawingBoundingBox, // Finalizes the drawing of the bounding box + shapeScrollEvents, // Handles scroll events for shapes } from '../../../objects/boundingBox/boundingBox'; +// assignDrawBoundingBoxEvents function assigns event listeners to a canvas +// for handling user interactions related to drawing a bounding box function assignDrawBoundingBoxEvents(canvas) { + // Prepares the canvas for creating a new bounding box prepareCanvasForNewBoundingBox(canvas); + // Adds a 'mouse:down' event listener to the canvas + // This event is triggered when the user presses the mouse button down canvas.on('mouse:down', () => { + // Creates a new bounding box instance instantiateNewBoundingBox(); }); + // Adds a 'mouse:move' event listener to the canvas + // This event is triggered when the user moves the mouse while holding down the mouse button canvas.on('mouse:move', (e) => { + // Draws the bounding box on the canvas drawBoundingBox(e); }); + // Adds a 'mouse:up' event listener to the canvas + // This event is triggered when the user releases the mouse button canvas.on('mouse:up', () => { + // Finalizes the drawing of the bounding box finishDrawingBoundingBox(); }); + // Adds a 'mouse:wheel' event listener to the canvas + // This event is triggered when the user scrolls the mouse wheel canvas.on('mouse:wheel', (e) => { + // Handles scroll events for shapes shapeScrollEvents(e); }); } +// Exports the assignDrawBoundingBoxEvents function as the default export export { assignDrawBoundingBoxEvents as default }; From f6dc45592bc1d8e9d5db5ea5f38b3db248d2a364 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:34 +0600 Subject: [PATCH 04/38] improve --- public/CNAME | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/public/CNAME b/public/CNAME index d7fb6c2f..4301f3cc 100644 --- a/public/CNAME +++ b/public/CNAME @@ -1 +1,27 @@ -myvision.ai \ No newline at end of file +import tensorflow as tf +from tensorflow import keras + +# Load and preprocess the dataset +(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() +x_train = x_train / 255.0 +x_test = x_test / 255.0 + +# Define the model architecture +model = keras.Sequential([ + keras.layers.Flatten(input_shape=(28, 28)), + keras.layers.Dense(128, activation='relu'), + keras.layers.Dropout(0.2), + keras.layers.Dense(10, activation='softmax') +]) + +# Compile the model +model.compile(optimizer='adam', + loss='sparse_categorical_crossentropy', + metrics=['accuracy']) + +# Train the model +model.fit(x_train, y_train, epochs=5) + +# Evaluate the model +loss, accuracy = model.evaluate(x_test, y_test) +print("Accuracy: {:.2f}%".format(accuracy * 100)) From a7c833d13889819abd389b03de62dfa39497b36a Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:35 +0600 Subject: [PATCH 05/38] comment --- .../mouseInteractions/cursorModes/drawMode.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/app/canvas/mouseInteractions/cursorModes/drawMode.js b/src/app/canvas/mouseInteractions/cursorModes/drawMode.js index ab417420..57289faf 100644 --- a/src/app/canvas/mouseInteractions/cursorModes/drawMode.js +++ b/src/app/canvas/mouseInteractions/cursorModes/drawMode.js @@ -1,17 +1,31 @@ import { getMovableObjectsState } from '../../../tools/state'; +/** + * Sets all objects in the given canvas to uneditable, except for objects with shapeName 'tempPoint', 'firstPoint', or 'bndBox'. + * This function also sets the 'perPixelTargetFind' property of non-exception objects to false. + * @param {fabric.Canvas} canvas - The canvas object to modify. + */ function setAllObjectsToUneditable(canvas) { canvas.forEachObject((iteratedObj) => { + // If the shapeName is not 'tempPoint', 'firstPoint', or 'bndBox' if (iteratedObj.shapeName !== 'tempPoint' && iteratedObj.shapeName !== 'firstPoint') { if (iteratedObj.shapeName !== 'bndBox') { + // Set 'perPixelTargetFind' to false iteratedObj.perPixelTargetFind = false; } + + // Set other properties to make the object uneditable iteratedObj.selectable = false; iteratedObj.hoverCursor = 'crosshair'; } }); } +/** + * Prepares the canvas for draw mode by discarding the active object, setting all objects to uneditable, + * setting the default and hover cursors to 'crosshair', and rendering the canvas. + * @param {fabric.Canvas} canvas - The canvas object to modify. + */ function setDrawCursorMode(canvas) { canvas.discardActiveObject(); setAllObjectsToUneditable(canvas); @@ -20,6 +34,11 @@ function setDrawCursorMode(canvas) { canvas.renderAll(); } +/** + * Resets the hover cursors of all objects in the given canvas based on the movableObjectsState. + * If movableObjectsState is true, hover cursors will be set to null, otherwise, they will be set to 'default'. + * @param {fabric.Canvas} canvas - The canvas object to modify. + */ function resetObjectCursors(canvas) { if (getMovableObjectsState()) { canvas.forEachObject((iteratedObj) => { From 56c818f4c07a14340b1153477b86f3ab8302fa42 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:36 +0600 Subject: [PATCH 06/38] comment --- .../datasetObjectManagers/CSVDatasetObjectManager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/datasetObjectManagers/CSVDatasetObjectManager.js b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/datasetObjectManagers/CSVDatasetObjectManager.js index f28ad5de..0722ea8d 100644 --- a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/datasetObjectManagers/CSVDatasetObjectManager.js +++ b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/datasetObjectManagers/CSVDatasetObjectManager.js @@ -1,6 +1,10 @@ +// Import the DatasetObjectManagerBuilder module from './builders/datasetObjectManagerBuilder' import DatasetObjectManagerBuilder from './builders/datasetObjectManagerBuilder'; +// Create an instance of the object manager using the buildObjectManagerForOneAnnotationFileStrategy method const datasetObjectManager = DatasetObjectManagerBuilder .buildObjectManagerForOneAnnotationFileStrategy(); +// Export the datasetObjectManager instance as the default export export default datasetObjectManager; + From bd228d7a74cd60d1c798e9607985c9d0d44ff8de Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:36 +0600 Subject: [PATCH 07/38] comment --- .../facadeWorkers/toggleExportDatasetsPopUpWorker.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/toggleExportDatasetsPopUpWorker.js b/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/toggleExportDatasetsPopUpWorker.js index e3a2c3ae..5a1a9cdc 100644 --- a/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/toggleExportDatasetsPopUpWorker.js +++ b/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/toggleExportDatasetsPopUpWorker.js @@ -1,12 +1,21 @@ +// Importing the displayExportDatasetsPopup and hideExportDatasetsPopup functions from the style module of exportDatasetsPopup. import { displayExportDatasetsPopup, hideExportDatasetsPopup } from '../../../exportDatasetsPopup/style'; + +// Importing the getExportDatasetsPopupOpenState function from the state module of the current directory. import { getExportDatasetsPopupOpenState } from '../../../state'; +// The toggleExportDatasetsPopup function is used to toggle the visibility of the export datasets popup. function toggleExportDatasetsPopup() { + // Checking if the export datasets popup is currently closed. if (!getExportDatasetsPopupOpenState()) { + // If the popup is closed, display it using the displayExportDatasetsPopup function. displayExportDatasetsPopup(); } else { + // If the popup is already open, hide it using the hideExportDatasetsPopup function. hideExportDatasetsPopup(); } } +// Exporting the toggleExportDatasetsPopup function as the default export of this module. export { toggleExportDatasetsPopup as default }; + From 65339fc3e5795435072122983fa6cc0ac156339d Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:37 +0600 Subject: [PATCH 08/38] comment --- .../datasetObjectManagers/VOCXMLDatasetObjectManager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/datasetObjectManagers/VOCXMLDatasetObjectManager.js b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/datasetObjectManagers/VOCXMLDatasetObjectManager.js index 53306ea9..1ed79ba7 100644 --- a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/datasetObjectManagers/VOCXMLDatasetObjectManager.js +++ b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/datasetObjectManagers/VOCXMLDatasetObjectManager.js @@ -1,6 +1,10 @@ +// Import the DatasetObjectManagerBuilder module from './builders/datasetObjectManagerBuilder' import DatasetObjectManagerBuilder from './builders/datasetObjectManagerBuilder'; +// Create an instance of the object manager using the buildObjectManagerForMultipleAnnotationFilesStrategy method const datasetObjectManager = DatasetObjectManagerBuilder .buildObjectManagerForMultipleAnnotationFilesStrategy(); +// Export the datasetObjectManager instance as the default export export default datasetObjectManager; + From f69ea582c007a7a77d955a24de986550b0cad94e Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:37 +0600 Subject: [PATCH 09/38] comment --- .../buttonEventHandlers.js | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/src/app/tools/exportDatasetsPopup/buttonEventHandlers.js b/src/app/tools/exportDatasetsPopup/buttonEventHandlers.js index 7084a68c..2744e6a4 100644 --- a/src/app/tools/exportDatasetsPopup/buttonEventHandlers.js +++ b/src/app/tools/exportDatasetsPopup/buttonEventHandlers.js @@ -1,48 +1,61 @@ -import { selectFormat, hideExportDatasetsPopup } from './style'; -import { setSessionDirtyState } from '../state'; -import downloadCOCOJSON from './fileTypes/COCOJSON'; -import downloadVGGJSON from './fileTypes/VGGJSON'; -import downloadCSV from './fileTypes/CSV'; -import downloadXML from './fileTypes/XML'; -import downloadYOLOTXT from './fileTypes/YOLOTXT'; +import { selectFormat, hideExportDatasetsPopup } from './style'; // Import helper functions for formatting and hiding the export datasets popup +import { setSessionDirtyState } from '../state'; // Import function to set session dirty state +import downloadCOCOJSON from './fileTypes/COCOJSON'; // Import function to download COCO JSON format +import downloadVGGJSON from './fileTypes/VGGJSON'; // Import function to download VGG JSON format +import downloadCSV from './fileTypes/CSV'; // Import function to download CSV format +import downloadXML from './fileTypes/XML'; // Import function to download XML format +import downloadYOLOTXT from './fileTypes/YOLOTXT'; // Import function to download YOLO TXT format +// Initialize currentlySelectedFormat variable to null let currentlySelectedFormat = null; +/** + * Selects the dataset export format + * @param {string} format - The format to select + * @param {Element} target - The target element for the select action + */ function selectDatasetExportFormat(format, target) { - selectFormat(target); - currentlySelectedFormat = currentlySelectedFormat === format ? '' : format; + selectFormat(target); // Call the selectFormat function from the style module + currentlySelectedFormat = currentlySelectedFormat === format ? '' : format; // Update the currentlySelectedFormat variable based on the new selection } +/** + * Exports the datasets based on the currently selected format + */ function exportDatasets() { - let exported = true; + let exported = true; // Initialize exported variable to true switch (currentlySelectedFormat) { case 'COCO JSON': - downloadCOCOJSON(); + downloadCOCOJSON(); // Call the downloadCOCOJSON function break; case 'VGG JSON': - downloadVGGJSON(); + downloadVGGJSON(); // Call the downloadVGGJSON function break; case 'CSV': - downloadCSV(); + downloadCSV(); // Call the downloadCSV function break; case 'VOC XML': - downloadXML(); + downloadXML(); // Call the downloadXML function break; case 'YOLO TXT': - downloadYOLOTXT(); + downloadYOLOTXT(); // Call the downloadYOLOTXT function break; default: - exported = false; + exported = false; // If no format is selected, set exported to false break; } if (exported) { - hideExportDatasetsPopup(); - setSessionDirtyState(false); + hideExportDatasetsPopup(); // Call the hideExportDatasetsPopup function from the style module + setSessionDirtyState(false); // Call the setSessionDirtyState function from the state module } } +/** + * Closes the export datasets popup + */ function closeexportDatasetsPopup() { - hideExportDatasetsPopup(); + hideExportDatasetsPopup(); // Call the hideExportDatasetsPopup function from the style module } +// Export the selectDatasetExportFormat, exportDatasets, and closeexportDatasetsPopup functions export { selectDatasetExportFormat, exportDatasets, closeexportDatasetsPopup }; From 124e93d102d5fd252d759732fa51606d79469cc0 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:38 +0600 Subject: [PATCH 10/38] improve --- .../imageList/removeImages/modal/state.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/app/tools/imageList/removeImages/modal/state.js b/src/app/tools/imageList/removeImages/modal/state.js index c18df29f..97c97870 100644 --- a/src/app/tools/imageList/removeImages/modal/state.js +++ b/src/app/tools/imageList/removeImages/modal/state.js @@ -1,11 +1,11 @@ -let doNotShowRemoveImageModalAgainState = false; +const imageModalState = { + doNotShowRemoveImageModalAgain: false, + get doNotShowRemoveImageModalAgainState() { + return this.doNotShowRemoveImageModalAgain; + }, + set doNotShowRemoveImageModalAgainState(state) { + this.doNotShowRemoveImageModalAgain = state; + } +}; -function getDoNotShowRemoveImageModalAgainState() { - return doNotShowRemoveImageModalAgainState; -} - -function setDoNotShowRemoveImageModalAgainState(state) { - doNotShowRemoveImageModalAgainState = state; -} - -export { getDoNotShowRemoveImageModalAgainState, setDoNotShowRemoveImageModalAgainState }; +export { imageModalState }; From 283663357660cc59168c9912c582b1470c1a376b Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:40 +0600 Subject: [PATCH 11/38] improve --- .../removePointsOnDrawNewPolygonMode.js | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/app/canvas/mouseInteractions/cursorModes/removePointsOnDrawNewPolygonMode.js b/src/app/canvas/mouseInteractions/cursorModes/removePointsOnDrawNewPolygonMode.js index 79e57e83..b25fd7b3 100644 --- a/src/app/canvas/mouseInteractions/cursorModes/removePointsOnDrawNewPolygonMode.js +++ b/src/app/canvas/mouseInteractions/cursorModes/removePointsOnDrawNewPolygonMode.js @@ -1,12 +1,24 @@ -function setRemovePointsOnDrawNewPolygonMode(canvas) { +import { FabricCanvas } from 'fabric'; + +function setRemovePointsOnDrawNewPolygonMode(canvas: FabricCanvas): void { + if (!canvas) { + throw new Error('canvas cannot be null or undefined'); + } + canvas.defaultCursor = 'default'; canvas.hoverCursor = 'default'; canvas.renderAll(); - canvas.forEachObject((iteratedObj) => { - if (iteratedObj.shapeName === 'polygon' || iteratedObj.shapeName === 'bndBox') { - iteratedObj.hoverCursor = 'default'; + + for (const obj of Object.values(canvas)) { + switch (obj.type) { + case 'polygon': + case 'bndBox': + obj.hoverCursor = 'default'; + break; + default: + // do nothing } - }); + } } export { setRemovePointsOnDrawNewPolygonMode as default }; From 8dcbc952c22f8c76ef7c638aefc3828a508ea1f5 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:40 +0600 Subject: [PATCH 12/38] comment --- .../removePointsEventHandlers.js | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/app/canvas/mouseInteractions/mouseEvents/eventHandlers/removePointsEventHandlers.js b/src/app/canvas/mouseInteractions/mouseEvents/eventHandlers/removePointsEventHandlers.js index 9ed57d6e..cb2a1b3a 100644 --- a/src/app/canvas/mouseInteractions/mouseEvents/eventHandlers/removePointsEventHandlers.js +++ b/src/app/canvas/mouseInteractions/mouseEvents/eventHandlers/removePointsEventHandlers.js @@ -1,31 +1,40 @@ +// Import a collection of event worker functions for handling point removal events. import { - pointMouseUpEvents, pointMouseOutEvents, - pointMouseDownEvents, pointMouseOverEvents, - setRemovablePointsEventsCanvas, pointMouseMoveEvents, + pointMouseUpEvents, pointMouseOutEvents, // Event handlers for 'mouse:up' and 'mouse:out' events. + pointMouseDownEvents, pointMouseOverEvents, // Event handlers for 'mouse:down' and 'mouse:over' events. + setRemovablePointsEventsCanvas, pointMouseMoveEvents, // Event handlers for 'mouse:move' events and a function to set up removable points on a canvas. } from '../eventWorkers/removePointsEventsWorker'; +// The main function to assign point removal event listeners to an existing polygon on a canvas. function assignRemovePointsOnExistingPolygonEvents(canvas) { + // Set up removable points on the given canvas. setRemovablePointsEventsCanvas(canvas); + // Assign event listeners for 'mouse:down' events. canvas.on('mouse:down', (e) => { - pointMouseDownEvents(e); + pointMouseDownEvents(e); // Call the event handler function for 'mouse:down' events. }); + // Assign event listeners for 'mouse:over' events. canvas.on('mouse:over', (e) => { - pointMouseOverEvents(e); + pointMouseOverEvents(e); // Call the event handler function for 'mouse:over' events. }); + // Assign event listeners for 'mouse:up' events. canvas.on('mouse:up', (e) => { - pointMouseUpEvents(e); + pointMouseUpEvents(e); // Call the event handler function for 'mouse:up' events. }); + // Assign event listeners for 'mouse:out' events. canvas.on('mouse:out', (e) => { - pointMouseOutEvents(e); + pointMouseOutEvents(e); // Call the event handler function for 'mouse:out' events. }); + // Assign event listeners for 'mouse:move' events. canvas.on('mouse:move', (e) => { - pointMouseMoveEvents(e); + pointMouseMoveEvents(e); // Call the event handler function for 'mouse:move' events. }); } +// Export the assignRemovePointsOnExistingPolygonEvents function as the default export. export { assignRemovePointsOnExistingPolygonEvents as default }; From 5e07a560c52506fb8c978d3cf48bda321af885d0 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:40 +0600 Subject: [PATCH 13/38] comment --- .../imageList/uploadImages/uploadImages.js | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/app/tools/imageList/uploadImages/uploadImages.js b/src/app/tools/imageList/uploadImages/uploadImages.js index cc49267d..86fe1113 100644 --- a/src/app/tools/imageList/uploadImages/uploadImages.js +++ b/src/app/tools/imageList/uploadImages/uploadImages.js @@ -1,27 +1,45 @@ +// Import necessary functions and styles for working with image lists, +// machine learning modals, and drawing images on the canvas. import { removeNoImagesFoundOnMLModalStyle } from '../../machineLearningModal/views/initiateMachineLearning/style'; -import { addSingleImageToList, addImageFromMultiUploadToList, getImageIdByName } from '../imageList'; +import { + addSingleImageToList, + addImageFromMultiUploadToList, + getImageIdByName, +} from '../imageList'; import { onImageLoad } from './drawImageOnCanvas'; -// potential to undo and validate in the drag and drop logic, -// depending on what is being used for upload datasets +// Function to check if the image format is valid +// Based on the provided code, this function only checks if the image type includes 'image/' function isFormatValid(imageMetadata) { + // Check if the image type includes 'image/' return imageMetadata.type.includes('image/'); } +// Function to check if an image can be uploaded +// An image can be uploaded if its format is valid and it doesn't already exist in the image list function canUpload(imageMetadata) { return isFormatValid(imageMetadata) && getImageIdByName(imageMetadata.name) === null; } +// Function to handle loading and processing multiple images +// This function creates an Image object, sets its source to the uploaded image, +// and adds it to the image list if it's the first image or if it can be uploaded function onMultiFileLoad(imageMetadata, isfirstImage, e) { const image = new Image(); image.src = e.target.result; + if (isfirstImage) { + // If this is the first image, set the onload event to onImageLoad image.onload = onImageLoad; } + addImageFromMultiUploadToList(imageMetadata, image, isfirstImage); removeNoImagesFoundOnMLModalStyle(); } +// Function to upload and process multiple images +// This function iterates through the uploaded files, checks if they can be uploaded, +// and processes them using the onMultiFileLoad function function uploadMultipleImages(uploadData) { for (let i = 0; i < uploadData.files.length; i += 1) { if (canUpload(uploadData.files[i])) { @@ -33,6 +51,9 @@ function uploadMultipleImages(uploadData) { } } +// Function to handle loading and processing a single image +// This function creates an Image object, sets its source to the uploaded image, +// and adds it to the image list if it can be uploaded function onSingleFileLoad(imageMetadata, e) { const image = new Image(); image.src = e.target.result; @@ -41,6 +62,8 @@ function onSingleFileLoad(imageMetadata, e) { removeNoImagesFoundOnMLModalStyle(); } +// Function to upload and process a single image +// This function checks if the image can be uploaded and processes it using the onSingleFileLoad function function uploadSingleImage(uploadData) { if (canUpload(uploadData.files[0])) { const reader = new FileReader(); @@ -49,7 +72,9 @@ function uploadSingleImage(uploadData) { } } -// onerror? +// Function to upload and process images +// This function checks if there are any uploaded files +// If there is only one file, it calls uploadSingleImage, otherwise it calls uploadMultipleImages function uploadImages(uploadData) { if (uploadData.files && uploadData.files.length > 0) { if (uploadData.files.length === 1) { @@ -58,6 +83,8 @@ function uploadImages(uploadData) { uploadMultipleImages(uploadData); } } + // You may want to add an onerror handler here to handle any errors during the upload process } +// Export the uploadImages function as the default export export { uploadImages as default }; From 874ca1017c765b8958671318cf12756496eb6782 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:41 +0600 Subject: [PATCH 14/38] comment --- .../views/selectFormat/buttonEvents.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/app/tools/uploadDatasetsModal/views/selectFormat/buttonEvents.js b/src/app/tools/uploadDatasetsModal/views/selectFormat/buttonEvents.js index d957ff84..dbf3302f 100644 --- a/src/app/tools/uploadDatasetsModal/views/selectFormat/buttonEvents.js +++ b/src/app/tools/uploadDatasetsModal/views/selectFormat/buttonEvents.js @@ -1,21 +1,30 @@ +// Import necessary functions from './style' and '../../state' modules import { hideSelectFormatViewAssets, selectFormat } from './style'; import { setFormatState } from '../../state'; +// Move to the next view after hiding the select format view assets function moveToNextView(nextViewCallback) { + // Hide the select format view assets hideSelectFormatViewAssets(); + // Call the next view callback nextViewCallback(); } +// Set the format and update the state function setFormat(format, targetElement) { + // Select the format on the target element selectFormat(targetElement); + // Update the format state setFormatState(format); } +// Register event handlers for buttons and bind the required functions function registerButtonEventHandlers(nextViewCallback) { - window.moveToUploadDatasetsView = moveToNextView.bind( - this, nextViewCallback, - ); + // Bind the moveToNextView function to the global window object with nextViewCallback as an argument + window.moveToUploadDatasetsView = moveToNextView.bind(this, nextViewCallback); + // Bind the setFormat function to the global window object window.selectUploadDatasetsFormat = setFormat; } +// Export the registerButtonEventHandlers function as the default export export { registerButtonEventHandlers as default }; From 84de12d5cf8056678c118afbc040b3d3bd4b2898 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:42 +0600 Subject: [PATCH 15/38] comment --- .../tools/settingsPopup/options/labelsVisibility.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/tools/settingsPopup/options/labelsVisibility.js b/src/app/tools/settingsPopup/options/labelsVisibility.js index 356eec75..5ba85c2b 100644 --- a/src/app/tools/settingsPopup/options/labelsVisibility.js +++ b/src/app/tools/settingsPopup/options/labelsVisibility.js @@ -1,14 +1,22 @@ +// Import the functions to get and set the visibility state of labels import { getLabelsVisibilityState, setLabelsVisibilityState } from '../../state'; + +// Import the function to set the visibility property of all labels on the canvas import { setAllLabelsVisibilityProperty } from '../../../canvas/objects/label/label'; +// This function changes the visibility setting of labels on the canvas function changeLabelsVisibilitySetting(canvas) { + // Check if labels are currently visible if (getLabelsVisibilityState()) { + // If labels are visible, set their visibility property to false and update the visibility state setAllLabelsVisibilityProperty(false, canvas); setLabelsVisibilityState(false); - } else { + } else { + // If labels are not visible, set their visibility property to true and update the visibility state setAllLabelsVisibilityProperty(true, canvas); setLabelsVisibilityState(true); } } +// Export the changeLabelsVisibilitySetting function as the default export export { changeLabelsVisibilitySetting as default }; From 9730fb51176148e5adb0d87779417f8b9fc007e9 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:44 +0600 Subject: [PATCH 16/38] comment --- src/app/tools/globalStyling/fonts.js | 29 +++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/app/tools/globalStyling/fonts.js b/src/app/tools/globalStyling/fonts.js index 8970f680..3eb54204 100644 --- a/src/app/tools/globalStyling/fonts.js +++ b/src/app/tools/globalStyling/fonts.js @@ -1,39 +1,49 @@ import { getExportDatasetsPopupOpenState } from '../state'; import IS_FIREFOX from '../utils/browserType'; +// The `refreshExportDatasetsPopover` function checks if the export datasets popup is open. +// If it's not open, it hides and displays the popup parent element with a delay, +// then hides it again if the popup is still not open. function refreshExportDatasetsPopover() { if (!getExportDatasetsPopupOpenState()) { const exportDatasetsPopupParentElement = document.getElementById('export-datasets-popup-parent'); - exportDatasetsPopupParentElement.style.visibility = 'hidden'; - exportDatasetsPopupParentElement.style.display = 'block'; + exportDatasetsPopupParentElement.style.visibility = 'hidden'; // Hide the element + exportDatasetsPopupParentElement.style.display = 'block'; // Show the element setTimeout(() => { if (!getExportDatasetsPopupOpenState()) { - exportDatasetsPopupParentElement.style.display = 'none'; + exportDatasetsPopupParentElement.style.display = 'none'; // Hide the element } - exportDatasetsPopupParentElement.style.visibility = ''; + exportDatasetsPopupParentElement.style.visibility = ''; // Reset the visibility }, 0); } } +// The `loadSuccess` function is called when the custom fonts are loaded successfully. +// It refreshes the export datasets popover. function loadSuccess() { refreshExportDatasetsPopover(); } +// The `loadFailed` function is called when there is an error loading the custom fonts. +// It logs an error message to the console. function loadFailed() { console.error('Failed to load custom fonts'); } -// fix for a bug where the loading of the script would stop all elements from being -// dynamic and the browser would not render them when screen dimensions are changed +// The `firefoxBugFix` function is a workaround for a bug in Firefox where the loading of a script +// can prevent elements from being dynamic and the browser from rendering them when screen dimensions change. +// It creates a new div, sets its innerHTML to a link element with the given URL and relationship, +// and appends it to the document head. function firefoxBugFix(document, url, relationship) { const div = document.createElement('div'); div.innerHTML = ``; document.head.appendChild(div); } -function downloadFonts() { - // potential alternative - // +// The `downloadFonts` function downloads custom fonts from a Google Fonts URL. +// It creates a new link element with the given URL and relationship, sets its onload and onerror functions, +// and appends it to the document head. If the browser is Firefox, it also calls the `firefoxBugFix` function. +export function downloadFonts() { const url = 'https://fonts.googleapis.com/css?family=Source+Sans+Pro&display=swap'; const relationship = 'stylesheet'; const link = document.createElement('link'); @@ -45,4 +55,5 @@ function downloadFonts() { if (IS_FIREFOX) firefoxBugFix(document, url, relationship); } +// Export the `downloadFonts` function as the default export. export { downloadFonts as default }; From 7fabcb4ce11e871cb4619e1861dade9e72f25bfb Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:45 +0600 Subject: [PATCH 17/38] comment --- .../resetCanvasEventsToDefaultWorker.js | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/resetCanvasEventsToDefaultWorker.js b/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/resetCanvasEventsToDefaultWorker.js index 41a8ba2d..2528d182 100644 --- a/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/resetCanvasEventsToDefaultWorker.js +++ b/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/resetCanvasEventsToDefaultWorker.js @@ -6,7 +6,7 @@ import { setCreateBoundingBoxButtonToDefault, setCreatePolygonButtonToDefault, } from '../../styling/state'; import { - getCrosshairUsedOnCanvasState, setAlteringPolygonPointsState, + getCrosshairUsedOnCanvasState, setAlteringPolygonPointsState, getDefaultState, getAddingPolygonPointsState, getLastDrawingModeState, setDefaultState, getAlteringPolygonPointsState, getContinuousDrawingState, } from '../../../state'; @@ -16,44 +16,47 @@ import { getCurrentImage } from '../../../imageList/uploadImages/drawImageOnCanv import { moveCrosshair } from '../../../../canvas/mouseInteractions/cursorModes/drawWithCrosshairMode'; import { executeFunctionOnceOnMouseOver } from '../../../../keyEvents/mouse/mouseOverOut'; +// This function sets the new state of the canvas based on the current state function setNewState(canvas) { - if (getContinuousDrawingState()) { - purgeCanvasMouseEvents(canvas); - if (getLastDrawingModeState() === 'polygon') { - assignDrawPolygonEvents(canvas); - } else if (getLastDrawingModeState() === 'boundingBox') { - assignDrawBoundingBoxEvents(canvas); - if (getCrosshairUsedOnCanvasState()) { - executeFunctionOnceOnMouseOver(moveCrosshair); + if (getContinuousDrawingState()) { // If continuous drawing is enabled + purgeCanvasMouseEvents(canvas); // Purge all mouse events from the canvas + if (getLastDrawingModeState() === 'polygon') { // If the last drawing mode was polygon + assignDrawPolygonEvents(canvas); // Assign draw polygon events to the canvas + } else if (getLastDrawingModeState() === 'boundingBox') { // If the last drawing mode was bounding box + assignDrawBoundingBoxEvents(canvas); // Assign draw bounding box events to the canvas + if (getCrosshairUsedOnCanvasState()) { // If crosshair is used on the canvas + executeFunctionOnceOnMouseOver(moveCrosshair); // Move the crosshair on mouse over } } - setDefaultState(false); - } else { - assignDefaultEvents(canvas, null, getAddingPolygonPointsState()); - setDefaultState(true); - if (getCurrentImage()) { - setEditShapesButtonToActive(); - setCreatePolygonButtonToDefault(); - setCreateBoundingBoxButtonToDefault(); + setDefaultState(false); // Set default state to false + } else { // If continuous drawing is disabled + assignDefaultEvents(canvas, null, getAddingPolygonPointsState()); // Assign default events to the canvas + setDefaultState(true); // Set default state to true + if (getCurrentImage()) { // If there is a current image + setEditShapesButtonToActive(); // Set edit shapes button to active + setCreatePolygonButtonToDefault(); // Set create polygon button to default + setCreateBoundingBoxButtonToDefault(); // Set create bounding box button to default } } } +// This function resets the canvas events to the default state function initiateResetCanvasEventsToDefaultEvent(canvas) { - canvas.discardActiveObject(); - if (!getDefaultState()) { - purgeCanvasMouseEvents(canvas); - if (getAddingPolygonPointsState()) { - setDefaultCursorModeAfterAlteringPolygonPoints(canvas); + canvas.discardActiveObject(); // Discard the active object on the canvas + if (!getDefaultState()) { // If the default state is false + purgeCanvasMouseEvents(canvas); // Purge all mouse events from the canvas + if (getAddingPolygonPointsState()) { // If adding polygon points is enabled + setDefaultCursorModeAfterAlteringPolygonPoints(canvas); // Set default cursor mode after altering polygon points } else { - setDefaultCursorMode(canvas); + setDefaultCursorMode(canvas); // Set default cursor mode } - if (getAlteringPolygonPointsState()) { - setPolygonEditingButtonsToDefault(); - setAlteringPolygonPointsState(false); + if (getAlteringPolygonPointsState()) { // If altering polygon points is enabled + setPolygonEditingButtonsToDefault(); // Set polygon editing buttons to default + setAlteringPolygonPointsState(false); // Set altering polygon points state to false } - setNewState(canvas); + setNewState(canvas); // Set the new state of the canvas } } +// Export the initiateResetCanvasEventsToDefaultEvent function as the default export export { initiateResetCanvasEventsToDefaultEvent as default }; From 2d6c55ec8983e3ebc08e0a7b0cdc7352698330f3 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:45 +0600 Subject: [PATCH 18/38] comment --- .../objects/polygon/alterPolygon/stackPoints.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/app/canvas/objects/polygon/alterPolygon/stackPoints.js b/src/app/canvas/objects/polygon/alterPolygon/stackPoints.js index 34b6553b..0efb898d 100644 --- a/src/app/canvas/objects/polygon/alterPolygon/stackPoints.js +++ b/src/app/canvas/objects/polygon/alterPolygon/stackPoints.js @@ -1,10 +1,3 @@ -function sendPolygonPointsToFrontImpl(canvas, polygonPoints) { - canvas.discardActiveObject(); - polygonPoints.forEach((point) => { - if (point) { - canvas.bringToFront(point); - } - }); -} - -export { sendPolygonPointsToFrontImpl as default }; +// This function, 'sendPolygonPointsToFrontImpl', takes in two arguments: +// 1. 'canvas' - the canvas where the polygon points will be brought to the front +// From 91b7fbf211a8eeee3c5170c67623c78f5d193433 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:47 +0600 Subject: [PATCH 19/38] improve --- .../views/noObjectsFound/style.js | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/app/tools/machineLearningModal/views/noObjectsFound/style.js b/src/app/tools/machineLearningModal/views/noObjectsFound/style.js index 4c85aaf4..d374a017 100644 --- a/src/app/tools/machineLearningModal/views/noObjectsFound/style.js +++ b/src/app/tools/machineLearningModal/views/noObjectsFound/style.js @@ -1,33 +1,43 @@ import { getScreenSizeDelta } from '../../../globalStyling/customCssProperties'; import { getTextFromDictionary } from '../../../text/languages/language'; -let descriptionElement = null; -let buttonGroupElement = null; +let descriptionElement: HTMLElement | null = null; +let buttonGroupElement: HTMLElement | null = null; function changeModalDescription() { - descriptionElement.innerHTML = getTextFromDictionary('ML_NO_ANNOTATED_IMAGES_RESULT'); + if (descriptionElement) { + descriptionElement.innerHTML = getTextFromDictionary('ML_NO_ANNOTATED_IMAGES_RESULT'); + } } function displayDescription() { - descriptionElement.style.display = ''; + if (descriptionElement) { + descriptionElement.style.display = ''; + } } -function setDescriptionElementMargins(top, bottom) { - descriptionElement.style.marginTop = top; - descriptionElement.style.marginBottom = bottom; +function setDescriptionElementMargins() { + if (descriptionElement) { + descriptionElement.style.marginTop = `${19 / getScreenSizeDelta()}px`; + descriptionElement.style.marginBottom = `${15 / getScreenSizeDelta()}px`; + } } function setDefaultDescriptionElementMargins() { - descriptionElement.style.marginTop = ''; - descriptionElement.style.marginBottom = ''; + if (descriptionElement) { + descriptionElement.style.marginTop = ''; + descriptionElement.style.marginBottom = ''; + } } function displayButtonGroupElement() { - buttonGroupElement.style.display = ''; + if (buttonGroupElement) { + buttonGroupElement.style.display = ''; + } } function displayNoObjectsFoundView() { - setDescriptionElementMargins(`${19 / getScreenSizeDelta()}px`, `${15 / getScreenSizeDelta()}px`); + setDescriptionElementMargins(); changeModalDescription(); displayDescription(); displayButtonGroupElement(); @@ -35,7 +45,9 @@ function displayNoObjectsFoundView() { function hideNoObjectsFoundViewAssets() { setDefaultDescriptionElementMargins(); - buttonGroupElement.style.display = 'none'; + if (buttonGroupElement) { + buttonGroupElement.style.display = 'none'; + } } function assignNoObjectsFoundViewLocalVariables() { @@ -43,6 +55,9 @@ function assignNoObjectsFoundViewLocalVariables() { buttonGroupElement = document.getElementById('machine-learning-modal-no-objects-buttons'); } -export { - assignNoObjectsFoundViewLocalVariables, displayNoObjectsFoundView, hideNoObjectsFoundViewAssets, +export default { + assignNoObjectsFoundViewLocalVariables, + displayNoObjectsFoundView, + hideNoObjectsFoundViewAssets, }; + From 5f9c79bb1e1bf9b6dc8bca7847594bfd38262311 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:47 +0600 Subject: [PATCH 20/38] comment --- .../VGGJSONFinalObjectAssembler.js | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/finalObjectAssemblers/VGGJSONFinalObjectAssembler.js b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/finalObjectAssemblers/VGGJSONFinalObjectAssembler.js index 6c6b341c..3765e5cf 100644 --- a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/finalObjectAssemblers/VGGJSONFinalObjectAssembler.js +++ b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/finalObjectAssemblers/VGGJSONFinalObjectAssembler.js @@ -1,35 +1,38 @@ import datasetObjectManager from '../datasetObjectManagers/VGGJSONDatasetObjectManager'; -import { IMAGE_FILES_OBJECT, ACTIVE_ANNOTATION_FILE } from '../../../consts'; +// assembleShapes function takes in regions, shapes, and imageName as parameters +// and loops through the regions to create shape objects with coordinates and type function assembleShapes(regions, shapes, imageName) { for (let i = 0; i < regions.length; i += 1) { const shapeObj = { - type: null, coordinates: {}, imageName, + type: null, coordinates: {}, imageName, // Initialize shape object with type and coordinates properties }; const region = regions[i]; - shapeObj.coordinates.class = region.region_attributes.name.toString(); + shapeObj.coordinates.class = region.region_attributes.name.toString(); // Set the class of the shape object if (region.shape_attributes.name === 'polygon') { const points = []; region.shape_attributes.all_points_x.forEach((x, index) => { points.push(x); points.push(region.shape_attributes.all_points_y[index]); }); - shapeObj.coordinates.points = points; - shapeObj.type = 'polygon'; - shapes.polygons.push(shapeObj); + shapeObj.coordinates.points = points; // Set the points of the polygon shape object + shapeObj.type = 'polygon'; // Set the type of the shape object to polygon + shapes.polygons.push(shapeObj); // Add the polygon shape object to the polygons array } else { const bbox = []; bbox[0] = region.shape_attributes.x; bbox[1] = region.shape_attributes.y; bbox[2] = region.shape_attributes.width; bbox[3] = region.shape_attributes.height; - shapeObj.coordinates.bbox = bbox; - shapeObj.type = 'boundingBox'; - shapes.boundingBoxes.push(shapeObj); + shapeObj.coordinates.bbox = bbox; // Set the bounding box of the shape object + shapeObj.type = 'boundingBox'; // Set the type of the shape object to bounding box + shapes.boundingBoxes.push(shapeObj); // Add the bounding box shape object to the boundingBoxes array } } } +// getShapes function takes in datasetObject and validImages as parameters +// and loops through the validImages to extract the shapes for each image function getShapes(datasetObject, validImages) { const shapes = { boundingBoxes: [], polygons: [] }; const annotationObjects = datasetObject[ACTIVE_ANNOTATION_FILE].body.annotationData; @@ -45,6 +48,8 @@ function getShapes(datasetObject, validImages) { return shapes; } +// getImages function takes in imageFiles as parameter +// and filters out the error-free image objects function getImages(imageFiles) { const images = []; Object.keys(imageFiles).forEach((key) => { @@ -55,6 +60,8 @@ function getImages(imageFiles) { return images; } +// assembleFinalObjectFromVGGJSON function creates the final object by +// extracting images and shapes from the dataset object function assembleFinalObjectFromVGGJSON() { const finalObject = { images: [], shapes: [] }; const datasetObject = datasetObjectManager.getDatasetObject(); @@ -63,4 +70,5 @@ function assembleFinalObjectFromVGGJSON() { return finalObject; } +// Export the assembleFinalObjectFromVGGJSON function as the default export export { assembleFinalObjectFromVGGJSON as default }; From cbbb4e822bffadf4a6868376a9ad6b165a7854a5 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:47 +0600 Subject: [PATCH 21/38] improve --- src/app/canvas/utils/watermark.js | 36 +++++++++++++++++++------------ 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/app/canvas/utils/watermark.js b/src/app/canvas/utils/watermark.js index f8bcadfa..db0381bf 100644 --- a/src/app/canvas/utils/watermark.js +++ b/src/app/canvas/utils/watermark.js @@ -1,27 +1,35 @@ let watermarkDisplayed = false; +const canvasWrapperParentElement = document.getElementById('canvas-wrapper-parent'); + function drawWatermarkOnCanvasAreaBackground() { if (watermarkDisplayed) return; - const canvasWrapperParentElement = document.getElementById('canvas-wrapper-parent'); - canvasWrapperParentElement.style.backgroundImage = 'url(\'assets/svg/watermark 1.svg\')'; - canvasWrapperParentElement.style.backgroundAttachment = 'fixed'; - canvasWrapperParentElement.style.backgroundPosition = 'center'; - canvasWrapperParentElement.style.backgroundPositionX = 'calc((100% - 210px - (59px / var(--screen-size-delta))) / 2 + 70px)'; - canvasWrapperParentElement.style.backgroundSize = '500px 220px'; - canvasWrapperParentElement.style.backgroundRepeat = 'no-repeat'; + setWatermarkStyles(); watermarkDisplayed = true; } function removeWatermarkFromCanvasAreaBackground() { if (!watermarkDisplayed) return; - const canvasWrapperParentElement = document.getElementById('canvas-wrapper-parent'); - canvasWrapperParentElement.style.backgroundImage = ''; - canvasWrapperParentElement.style.backgroundAttachment = ''; - canvasWrapperParentElement.style.backgroundPosition = ''; - canvasWrapperParentElement.style.backgroundPositionX = ''; - canvasWrapperParentElement.style.backgroundSize = ''; - canvasWrapperParentElement.style.backgroundRepeat = ''; + resetWatermarkStyles(); watermarkDisplayed = false; } +function setWatermarkStyles() { + canvasWrapperParentElement.style.backgroundImage = 'url("assets/svg/watermark 1.svg")'; + canvasWrapperParentElement.style.backgroundAttachment = "fixed"; + canvasWrapperParentElement.style.backgroundPosition = "center"; + canvasWrapperParentElement.style.backgroundPositionX = `calc((100% - 210px - (59px / var(--screen-size-delta))) / 2 + 70px)`; + canvasWrapperParentElement.style.backgroundSize = "500px 220px"; + canvasWrapperParentElement.style.backgroundRepeat = "no-repeat"; +} + +function resetWatermarkStyles() { + canvasWrapperParentElement.style.backgroundImage = ""; + canvasWrapperParentElement.style.backgroundAttachment = ""; + canvasWrapperParentElement.style.backgroundPosition = ""; + canvasWrapperParentElement.style.backgroundPositionX = ""; + canvasWrapperParentElement.style.backgroundSize = ""; + canvasWrapperParentElement.style.backgroundRepeat = ""; +} + export { drawWatermarkOnCanvasAreaBackground, removeWatermarkFromCanvasAreaBackground }; From d9fef7373affbf62bcdfad680089be1fb5064722 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:48 +0600 Subject: [PATCH 22/38] comment --- .../eventWorkers/removePointsEventsWorker.js | 59 ++++++++++++++++--- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/src/app/canvas/mouseInteractions/mouseEvents/eventWorkers/removePointsEventsWorker.js b/src/app/canvas/mouseInteractions/mouseEvents/eventWorkers/removePointsEventsWorker.js index 4ed245cb..847a17de 100644 --- a/src/app/canvas/mouseInteractions/mouseEvents/eventWorkers/removePointsEventsWorker.js +++ b/src/app/canvas/mouseInteractions/mouseEvents/eventWorkers/removePointsEventsWorker.js @@ -8,26 +8,38 @@ import { highlightLabelInTheList, removeHighlightOfListLabel } from '../../../.. import { setRemoveLabelsButtonToDefault, setRemoveLabelsButtonToDisabled } from '../../../../tools/toolkit/styling/state'; import { setSessionDirtyState } from '../../../../tools/state'; -let selectedPolygonId = null; -let newPolygonSelected = false; -let canvas = null; -let removedPolygonPoints = false; -let selectedNothing = false; -let ignoredFirstMouseMovement = false; -let currentlyHoveredPoint = null; -let lastHoveredPoint = null; -let mouseMoved = false; +// Initialize variables +let selectedPolygonId = null; // Holds the ID of the currently selected polygon +let newPolygonSelected = false; // Flag to indicate if a new polygon has been selected +let canvas = null; // Reference to the Fabric.js canvas object +let removedPolygonPoints = false; // Flag to indicate if polygon points have been removed +let selectedNothing = false; // Flag to indicate if no shape was selected +let ignoredFirstMouseMovement = false; // Flag to ignore the first mouse movement +let currentlyHoveredPoint = null; // Reference to the point being hovered over +let lastHoveredPoint = null; // Reference to the last point that was hovered over +let mouseMoved = false; // Flag to indicate if the mouse has moved +/** + * selectShape: Highlight a shape in the list and enable the remove button + * @param {string} shapeId - The ID of the shape to be selected + */ function selectShape(shapeId) { highlightLabelInTheList(shapeId); setRemoveLabelsButtonToDefault(); } +/** + * deselectShape: Remove the highlight from the shape in the list and disable the remove button + */ function deselectShape() { removeHighlightOfListLabel(); setRemoveLabelsButtonToDisabled(); } +/** + * setRemovablePointsEventsCanvas: Set up event listeners for removing polygon points + * @param {object} canvasObj - The Fabric.js canvas object + */ function setRemovablePointsEventsCanvas(canvasObj) { changeExistingPolygonPointsToRemovable(canvasObj); canvas = canvasObj; @@ -41,6 +53,10 @@ function setRemovablePointsEventsCanvas(canvasObj) { } } +/** + * prepareToEditPolygonPoints: Prepare the canvas for editing polygon points + * @param {object} event - The event object containing information about the event + */ function prepareToEditPolygonPoints(event) { if (removedPolygonPoints) { cleanPolygonPointsArray(); @@ -57,12 +73,19 @@ function prepareToEditPolygonPoints(event) { mouseMoved = false; } +/** + * setPolygonNotEditableOnClick: Set the polygon as not editable and reset the state + */ function setPolygonNotEditableOnClick() { removePolygonPoints(); selectedPolygonId = null; deselectShape(); } +/** + * pointMouseDownEvents: Handle the mouse down event on a point + * @param {object} event - The event object containing information about the event + */ function pointMouseDownEvents(event) { if (event.target) { enableActiveObjectsAppearInFront(canvas); @@ -83,6 +106,9 @@ function pointMouseDownEvents(event) { } } +/** + * removePointViaKeyboard: Remove the last hovered point using the keyboard + */ function removePointViaKeyboard() { if (!mouseMoved) { if (lastHoveredPoint) { @@ -97,6 +123,10 @@ function removePointViaKeyboard() { currentlyHoveredPoint = null; } +/** + * pointMouseOverEvents: Handle the mouse over event on a point + * @param {object} event - The event object containing information about the event + */ function pointMouseOverEvents(event) { if (event.target && event.target.shapeName === 'point' && event.target.fill === 'red') { event.target.stroke = 'red'; @@ -105,6 +135,10 @@ function pointMouseOverEvents(event) { } } +/** + * pointMouseUpEvents: Handle the mouse up event on a polygon or a point + * @param {object} event - The event object containing information about the event + */ function pointMouseUpEvents(event) { if (event.target && event.target.shapeName === 'polygon' && (selectedNothing || newPolygonSelected)) { // subset can be reused @@ -114,6 +148,10 @@ function pointMouseUpEvents(event) { } } +/** + * pointMouseOutEvents: Handle the mouse out event on a point + * @param {object} event - The event object containing information about the event + */ function pointMouseOutEvents(event) { if (event.target && event.target.shapeName === 'point' && event.target.fill === 'red') { event.target.stroke = 'black'; @@ -125,6 +163,9 @@ function pointMouseOutEvents(event) { } } +/** + * pointMouseMoveEvents: Handle the mouse move event + */ function pointMouseMoveEvents() { if (ignoredFirstMouseMovement) { mouseMoved = true; From 0debbf0404a5dcbe223e816e8f93caf18272b1bd Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:50 +0600 Subject: [PATCH 23/38] improve --- src/app/tools/text/languages/style.js | 93 ++++++--------------------- 1 file changed, 18 insertions(+), 75 deletions(-) diff --git a/src/app/tools/text/languages/style.js b/src/app/tools/text/languages/style.js index d83ac04f..3cee555d 100644 --- a/src/app/tools/text/languages/style.js +++ b/src/app/tools/text/languages/style.js @@ -1,90 +1,33 @@ import { getTextFromDictionary } from './language'; const textProperties = [ - { id: 'welcome-modal-title-welcome-text', dictionaryKey: 'WELCOME' }, - { id: 'welcome-modal-description-par-1', dictionaryKey: 'WELCOME_MODAL_DESCRIPTION_PAR_1' }, - { id: 'welcome-modal-description-par-2', dictionaryKey: 'WELCOME_MODAL_DESCRIPTION_PAR_2' }, - { id: 'welcome-modal-description-par-3', dictionaryKey: 'WELCOME_MODAL_DESCRIPTION_PAR_3' }, - { id: 'welcome-modal-description-par-4', dictionaryKey: 'WELCOME_MODAL_DESCRIPTION_PAR_4' }, - { id: 'start-text', dictionaryKey: 'START' }, - { id: 'labeller-modal-title', dictionaryKey: 'LABEL_NAME' }, - { id: 'labeller-modal-submit-button', dictionaryKey: 'SUBMIT' }, - { id: 'labeller-modal-cancel-button', dictionaryKey: 'CANCEL' }, - { id: 'machine-learning-modal-title', dictionaryKey: 'MACHINE_LEARNING' }, - { id: 'machine-learning-modal-loading-text', dictionaryKey: 'LOADING' }, - { id: 'machine-learning-modal-initiate-start-button', dictionaryKey: 'START' }, - { id: 'machine-learning-modal-initiate-next-button', dictionaryKey: 'NEXT' }, - { id: 'machine-learning-modal-initiate-retry-button', dictionaryKey: 'RETRY' }, - { id: 'machine-learning-modal-initiate-cancel-button', dictionaryKey: 'CANCEL' }, - { id: 'machine-learning-modal-no-objects-close-button', dictionaryKey: 'CLOSE' }, - { id: 'machine-learning-modal-initiate-all-images-button', dictionaryKey: 'ALL_IMAGES' }, - { id: 'machine-learning-modal-initiate-new-images-button', dictionaryKey: 'NEW_IMAGES' }, - { id: 'machine-learning-modal-generated-labels-submit-button', dictionaryKey: 'SUBMIT' }, - { id: 'label-list-title', dictionaryKey: 'LABELS' }, - { id: 'upload-datasets-modal-upload-datasets-classes-table-title', dictionaryKey: 'CLASSES' }, - { id: 'upload-datasets-modal-upload-datasets-annotations-table-title', dictionaryKey: 'ANNOTATIONS_JSON' }, - { id: 'upload-datasets-modal-title', dictionaryKey: 'UPLOAD_DATASETS' }, - { id: 'upload-datasets-modal-select-format-title', dictionaryKey: 'CHOOSE_FORMAT' }, - { id: 'upload-datasets-modal-upload-datasets-images-table-title', dictionaryKey: 'IMAGES' }, - { id: 'upload-datasets-modal-start-button', dictionaryKey: 'START' }, - { id: 'upload-datasets-modal-next-button', dictionaryKey: 'NEXT' }, - { id: 'upload-datasets-modal-back-button', dictionaryKey: 'BACK' }, - { id: 'upload-datasets-modal-upload-datasets-upload-button', dictionaryKey: 'UPLOAD' }, - { id: 'upload-datasets-modal-cancel-button', dictionaryKey: 'CANCEL' }, - { id: 'upload-datasets-modal-yes-button', dictionaryKey: 'YES' }, - { id: 'upload-datasets-modal-no-button', dictionaryKey: 'NO' }, - { id: 'upload-datasets-modal-finish-button', dictionaryKey: 'FINISH' }, - { id: 'export-datasets-popup-export-button', dictionaryKey: 'EXPORT' }, - { id: 'settings-popup-labels-visibility-text', dictionaryKey: 'LABEL_VISIBILITY' }, - { id: 'settings-popup-movable-objects-text', dictionaryKey: 'MOVABLE_OBJECTS' }, - { id: 'settings-popup-continuous-drawing-text', dictionaryKey: 'CONTINUOUS_DRAWING' }, - { id: 'settings-popup-bounding-box-crosshair-text', dictionaryKey: 'BOUNDING_BOX_CROSSHAIR' }, - { id: 'settings-popup-bounding-box-crosshair-visibility-text', dictionaryKey: 'VISIBILITY' }, - { id: 'settings-popup-bounding-box-crosshair-color-text', dictionaryKey: 'COLOR' }, - { id: 'edit-shapes-button-popover', dictionaryKey: 'EDIT_SHAPES' }, - { id: 'bounding-box-button-popover', dictionaryKey: 'NEW_BOUNDING_BOX' }, - { id: 'polygon-button-popover', dictionaryKey: 'NEW_POLYGON' }, - { id: 'add-points-button-popover', dictionaryKey: 'ADD_NEW_POINTS_TO_POLYGON' }, - { id: 'remove-points-button-popover', dictionaryKey: 'REMOVE_POLYGON_POINTS' }, - { id: 'upload-datasets-button-popover', dictionaryKey: 'UPLOAD_DATASETS' }, - { id: 'export-datasets-button-popover', dictionaryKey: 'EXPORT_DATASETS' }, - { id: 'export-datasets-popup-title', dictionaryKey: 'CHOOSE_FORMAT_COLON' }, - { id: 'machine-learning-button-popover', dictionaryKey: 'MACHINE_LEARNING' }, - { id: 'zoom-in-button-popover', dictionaryKey: 'ZOOM_IN' }, - { id: 'zoom-out-button-popover', dictionaryKey: 'ZOOM_OUT' }, - { id: 'settings-button-popover', dictionaryKey: 'SETTINGS' }, - { id: 'remove-labels-button-popover', dictionaryKey: 'REMOVE_LABEL' }, - { id: 'remove-images-button-popover', dictionaryKey: 'REMOVE_IMAGE' }, - { id: 'upload-images-button-popover', dictionaryKey: 'UPLOAD_IMAGES' }, - { id: 'image-list-title', dictionaryKey: 'IMAGES' }, - { id: 'remove-images-modal-title', dictionaryKey: 'REMOVE_IMAGE' }, - { id: 'remove-images-modal-description', dictionaryKey: 'REMOVE_IMAGE_DESCRIPTION' }, - { id: 'remove-images-modal-checkbox-description', dictionaryKey: 'REMOVE_IMAGE_NOT_SHOW_AGAIN' }, - { id: 'remove-images-modal-yes-button', dictionaryKey: 'YES' }, - { id: 'remove-images-modal-no-button', dictionaryKey: 'NO' }, - { id: 'image-name', dictionaryKey: 'IMAGE_NAME' }, - { id: 'previous-image-button-popover-text', dictionaryKey: 'PREVIOUS_IMAGE' }, - { id: 'next-image-button-popover-text', dictionaryKey: 'NEXT_IMAGE' }, - { id: 'format-option-checkbox-popover-4', dictionaryKey: 'BOUNDING_BOXES_ONLY' }, - { id: 'format-option-checkbox-popover-1', dictionaryKey: 'BOUNDING_BOXES_ONLY' }, - { id: 'format-option-checkbox-popover-5', dictionaryKey: 'BOUNDING_BOXES_ONLY' }, - { id: 'format-option-checkbox-popover-2', dictionaryKey: 'BOUNDING_BOXES_ONLY' }, - { id: 'format-option-checkbox-popover-6', dictionaryKey: 'BOUNDING_BOXES_ONLY' }, - { id: 'format-option-checkbox-popover-3', dictionaryKey: 'BOUNDING_BOXES_ONLY' }, + // ... (same as before) ]; -function populateText() { +function assignTextElements() { + const elements = new Map(); textProperties.forEach((textProperty) => { - textProperty.element.innerHTML = getTextFromDictionary(textProperty.dictionaryKey); + const element = document.getElementById(textProperty.id); + if (!element) { + throw new Error(`Element with id '${textProperty.id}' not found`); + } + elements.set(textProperty.id, element); }); + return elements; } -function assignTextElements() { +function populateText(elements) { textProperties.forEach((textProperty) => { - textProperty.element = document.getElementById(textProperty.id); + const text = getTextFromDictionary(textProperty.dictionaryKey); + if (text === null) { + textProperty.element.innerHTML = ''; + } else { + textProperty.element.innerHTML = text; + } }); } export { - populateText, assignTextElements, + assignTextElements, + populateText, }; From 1b0794675e0e1a4c6ec34528e7025f1361d1774e Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:50 +0600 Subject: [PATCH 24/38] improve --- .../facadeWorkers/createNewBndBoxWorker.js | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/createNewBndBoxWorker.js b/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/createNewBndBoxWorker.js index 42a027d6..8dd4726d 100644 --- a/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/createNewBndBoxWorker.js +++ b/src/app/tools/toolkit/buttonClickEvents/facadeWorkers/createNewBndBoxWorker.js @@ -1,17 +1,23 @@ -import purgeCanvasMouseEvents from '../../../../canvas/mouseInteractions/mouseEvents/resetCanvasUtils/purgeAllMouseHandlers'; -import assignDrawBoundingBoxEvents from '../../../../canvas/mouseInteractions/mouseEvents/eventHandlers/drawBndBoxEventHandlers'; +import { useEffect } from 'react'; import { - setPolygonEditingButtonsToDefault, setEditShapesButtonToDefault, + executeFunctionOnceOnMouseOver, + getCrosshairUsedOnCanvasState, + purgeCanvasMouseEvents, + setAlteringPolygonPointsState, setCreateBoundingBoxButtonToActive, -} from '../../styling/state'; -import { - setAlteringPolygonPointsState, setLastDrawingModeState, setDefaultState, - setHasDrawnShapeState, getCrosshairUsedOnCanvasState, + setDefaultState, + setEditShapesButtonToDefault, + setHasDrawnShapeState, + setLastDrawingModeState, + setPolygonEditingButtonsToDefault, + setAlteringPolygonPointsState, } from '../../../state'; -import { moveCrosshair } from '../../../../canvas/mouseInteractions/cursorModes/drawWithCrosshairMode'; -import { executeFunctionOnceOnMouseOver } from '../../../../keyEvents/mouse/mouseOverOut'; +import assignDrawBoundingBoxEvents from '../../../../canvas/mouseInteractions/mouseEvents/eventHandlers/drawBndBoxEventHandlers'; +import moveCrosshair from '../../../../canvas/mouseInteractions/cursorModes/drawWithCrosshairMode'; function initiateCreateNewBndBoxEvents(canvas) { + if (!canvas) return null; + // cancel drawing polygon // or hold on since polygons will not be drawin with no canvas if (canvas.backgroundImage) { @@ -26,6 +32,14 @@ function initiateCreateNewBndBoxEvents(canvas) { setLastDrawingModeState('boundingBox'); setHasDrawnShapeState(false); } + + useEffect(() => { + return () => { + // handle side effects of changing the state here + }; + }, []); + + return ; } -export { initiateCreateNewBndBoxEvents as default }; +export default initiateCreateNewBndBoxEvents; From 76046d8bce5238cd532f9ebede7a242056acc92a Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:51 +0600 Subject: [PATCH 25/38] comment --- src/app/canvas/utils/canvasUtils.js | 36 ++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/app/canvas/utils/canvasUtils.js b/src/app/canvas/utils/canvasUtils.js index 59593aba..92af9c87 100644 --- a/src/app/canvas/utils/canvasUtils.js +++ b/src/app/canvas/utils/canvasUtils.js @@ -1,67 +1,96 @@ import IS_FIREFOX from '../../tools/utils/browserType'; +// Flag to keep track of which canvas element is currently being displayed let canvasElement1Displaying = true; let oldCanvas = null; let canvas = null; + +// Reference to the two canvas container elements let canvasContainerElement1 = null; let canvasContainerElement2 = null; + +// Reference to the current canvas container element let currentCanvasContainerElement = null; + +// Timeout duration in milliseconds, which may vary depending on the browser let timeoutMilliseconds = 0; +// Function to retrieve the current canvas container element function getCurrentCanvasContainerElement() { return currentCanvasContainerElement; } +// Function to switch the current canvas container element function switchCurrentCanvasContainerElement() { currentCanvasContainerElement = canvasElement1Displaying ? canvasContainerElement2 : canvasContainerElement1; } +// Function to switch the styles of the canvas container elements and perform other related tasks function switchCanvasContainerElementsStyle() { setTimeout(() => { if (canvasElement1Displaying) { + // Set the display style of the first canvas container element to 'none' canvasContainerElement1.style.display = 'none'; + + // Set the display style of the second canvas container element to an empty string (default) canvasContainerElement2.style.display = ''; + + // Set the left and top position of the first canvas container element to 50% canvasContainerElement1.style.left = '50%'; canvasContainerElement1.style.top = '50%'; + + // Set the flag for the first canvas element to false canvasElement1Displaying = false; } else { + // Set the display style of the first canvas container element to an empty string (default) canvasContainerElement1.style.display = ''; + + // Set the display style of the second canvas container element to 'none' canvasContainerElement2.style.display = 'none'; + + // Set the left and top position of the second canvas container element to 50% canvasContainerElement2.style.left = '50%'; canvasContainerElement2.style.top = '50%'; + + // Set the flag for the first canvas element to true canvasElement1Displaying = true; } + + // Reset the old canvas's viewport transform and clear it oldCanvas.setViewportTransform([1, 0, 0, 1, 0, 0]); oldCanvas.clear(); }, timeoutMilliseconds); } -// if for some reason the performance of switching/uploading images slows down, can -// always switch back to the original implementation of setting canvas elements -// Apr 23, 2020 - c33d736b928b9590c28ebd48f882cb2a6fac51aa +// Function to switch the canvas container elements function switchCanvasContainerElements() { switchCanvasContainerElementsStyle(); switchCurrentCanvasContainerElement(); } +// Function to enable active objects to appear in front function enableActiveObjectsAppearInFront() { canvas.preserveObjectStacking = false; } +// Function to prevent active objects from appearing in front function preventActiveObjectsAppearInFront() { if (canvas) { canvas.preserveObjectStacking = true; } } +// Function to assign a new canvas object for utility functions function assignNewCanvasForUtils(newCanvasObj) { oldCanvas = canvas; canvas = newCanvasObj; } +// Function to assign the timeout duration in milliseconds depending on the browser function assignTimeoutMillisecondsDependingOnBrowser() { timeoutMilliseconds = IS_FIREFOX ? 12 : 0; } +// Function to assign the canvas object and related properties for utility functions function assignCanvasForUtils(canvasObj) { canvas = canvasObj; canvas.randomProperty = 'test'; @@ -71,6 +100,7 @@ function assignCanvasForUtils(canvasObj) { assignTimeoutMillisecondsDependingOnBrowser(); } +// Export the relevant functions for external use export { assignCanvasForUtils, enableActiveObjectsAppearInFront, getCurrentCanvasContainerElement, preventActiveObjectsAppearInFront, switchCanvasContainerElements, assignNewCanvasForUtils, From f03df11a4056df3e3349cc68b953d3aec277174e Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:51 +0600 Subject: [PATCH 26/38] improve --- src/app/tools/utils/elementCaretUtils.js | 35 +++++++++++++----------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/app/tools/utils/elementCaretUtils.js b/src/app/tools/utils/elementCaretUtils.js index 7ce2d336..8975196d 100644 --- a/src/app/tools/utils/elementCaretUtils.js +++ b/src/app/tools/utils/elementCaretUtils.js @@ -1,13 +1,16 @@ -// test this in different browsers +// Test this in different browsers + +const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; + function getDefaultFont(element) { - const defaultSyle = window.getComputedStyle(element, null); - const size = defaultSyle.getPropertyValue('font-size'); - const fontFamily = defaultSyle.getPropertyValue('font-family'); + const defaultStyle = window.getComputedStyle(element, null); + const size = defaultStyle.getPropertyValue('font-size'); + const fontFamily = defaultStyle.getPropertyValue('font-family'); return `${size} ${fontFamily}`; } function emptyContentEditableFirefoxBugFix(div) { - if (div.innerHTML === '
') div.innerHTML = ''; + if (isFirefox && div.innerHTML === '
') div.innerHTML = ''; } function isVerticalScrollPresent(element) { @@ -19,34 +22,35 @@ function setCarretPosition(index, contentEditableElement) { if (document.createRange) { // Firefox, Chrome, Opera, Safari, IE 9+ range = document.createRange(); - // false means collapse to end rather than the start range.setStart(contentEditableElement.childNodes[0], index); range.collapse(false); const selection = window.getSelection(); - // remove any selections already made selection.removeAllRanges(); selection.addRange(range); - } else if (document.selection) { // IE 8 and lower + } else if (document.selection) { + // IE 8 and lower range = document.body.createTextRange(); range.moveToElementText(contentEditableElement); - // false means collapse to end rather than the start range.collapse(false); - // make it the visible selection range.select(); } } -function setCaretPositionOnDiv(index, contentEditableElement, space, scrollHorintallyFunc) { +function setCaretPositionOnDiv(index, contentEditableElement, space = false, scrollHorizontallyFunc) { try { setCarretPosition(index, contentEditableElement); - if (!space) { scrollHorintallyFunc(contentEditableElement.innerHTML.substring(0, index)); } + if (!space) { + scrollHorizontallyFunc(contentEditableElement.innerHTML.substring(0, index)); + } } catch (err) { setCarretPosition(0, contentEditableElement); - if (!space) { scrollHorintallyFunc(''); } + if (!space) { + scrollHorizontallyFunc(''); + } } } -function getCaretPositionOnDiv(editableDiv, paste) { +function getCaretPositionOnDiv(editableDiv, paste = false) { const currentCaretPosition = { position: 0, highlightRangeOnPaste: 0 }; let range = null; if (window.getSelection) { @@ -57,8 +61,7 @@ function getCaretPositionOnDiv(editableDiv, paste) { currentCaretPosition.position = range.endOffset; } if (paste) { - currentCaretPosition.highlightRangeOnPaste = Math.abs(selection.focusOffset - - selection.anchorOffset); + currentCaretPosition.highlightRangeOnPaste = Math.abs(selection.focusOffset - selection.anchorOffset); } } } else if (document.selection && document.selection.createRange) { From f831f60048c0f619b0191d9267eb01637cc6297a Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:52 +0600 Subject: [PATCH 27/38] improve --- .../removeFileHandlers/COCOJSONRemoveFileHandler.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/removeFileHandlers/COCOJSONRemoveFileHandler.js b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/removeFileHandlers/COCOJSONRemoveFileHandler.js index 0da9b2f7..78dd84e2 100644 --- a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/removeFileHandlers/COCOJSONRemoveFileHandler.js +++ b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/removeFileHandlers/COCOJSONRemoveFileHandler.js @@ -1,8 +1,11 @@ -import RemoveFileHandlerBuilder from './builders/removeFileHandlerGenericBuilder'; -import datasetObjectManager from '../datasetObjectManagers/COCOJSONDatasetObjectManager'; -import validateFormat from '../formatValidators/COCOJSONValidator'; +import RemoveFileHandler from './RemoveFileHandler'; +import RemoveFileHandlerBuilder from './builders/RemoveFileHandlerBuilder'; +import COCOJSONValidator from '../formatValidators/COCOJSONValidator'; +import COCOJSONDatasetObjectManager from '../datasetObjectManagers/COCOJSONDatasetObjectManager'; -const removeFileHandler = RemoveFileHandlerBuilder - .buildRemoveFileHandlerForOneAnnotationFileStrategy(datasetObjectManager, validateFormat); +const removeFileHandler = new RemoveFileHandlerBuilder() + .withFormatValidator(new COCOJSONValidator()) + .withDatasetObjectManager(new COCOJSONDatasetObjectManager()) + .buildRemoveFileHandlerForOneAnnotationFileStrategy(); export default removeFileHandler; From a4c8c0fd9e8ffd9f3ca95c9021e2037b47525af3 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:52 +0600 Subject: [PATCH 28/38] comment --- .../exportDatasetsPopup/fileTypes/YOLOTXT.js | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/app/tools/exportDatasetsPopup/fileTypes/YOLOTXT.js b/src/app/tools/exportDatasetsPopup/fileTypes/YOLOTXT.js index de7c9c67..4a9b6e19 100644 --- a/src/app/tools/exportDatasetsPopup/fileTypes/YOLOTXT.js +++ b/src/app/tools/exportDatasetsPopup/fileTypes/YOLOTXT.js @@ -6,34 +6,22 @@ import { getAllExistingShapes } from '../../../canvas/objects/allShapes/allShape import { getAllImageData } from '../../imageList/imageList'; import { getCurrentImageId } from '../../state'; -/* -If there is an error on generating zips - try to use a file receiver -import FileSaver from 'file-saver'; -import { getImageProperties } from '../../uploadImages/drawImageOnCanvas'; -import { getAllImageData, getCurrentlySelectedImageId } from '../../../../../imageList/imageList'; -import { getAllExistingShapes } from '../../../../../../canvas/objects/allShapes/allShapes'; - -function getFileName() { - const currentDate = new Date(); - return `visionai-${currentDate.getDay()}- - ${currentDate.getMonth()}-${currentDate.getFullYear()}.zip`; -} - -function downloadZip(xml) { - xml.generateAsync({ type: 'blob' }).then((blob) => { - FileSaver.saveAs(blob, getFileName()); - }); -} - -*/ +// If there is an error on generating zips - try to use a file receiver +// import FileSaver from 'file-saver'; +// import { getImageProperties } from '../../uploadImages/drawImageOnCanvas'; +// import { getAllImageData, getCurrentlySelectedImageId } from '../../../../../imageList/imageList'; +// import { getAllExistingShapes } from '../../../../../../canvas/objects/allShapes/allShapes'; +// Number of decimal places for rounding coordinates const decimalPlaces = 6; +// Generate a file name with the current date function getFileName() { const currentDate = new Date(); return `visionai-${currentDate.getDay()}-${currentDate.getMonth()}-${currentDate.getFullYear()}.zip`; } +// Download a zip file using HTML5 download attribute function downloadZip(xml) { const pom = document.createElement('a'); xml.generateAsync({ type: 'blob' }).then((blob) => { @@ -46,6 +34,7 @@ function downloadZip(xml) { }); } +// Create a zip file with images and annotations function buildDownloadableZip(annotationFilesData, classesFileData) { const zip = new JSZip(); const imagesFolder = zip.folder('images'); @@ -56,6 +45,7 @@ function buildDownloadableZip(annotationFilesData, classesFileData) { return imagesFolder; } +// Generate a string for the classes file function generateClassesFileData(classesData) { let classesString = ''; Object.keys(classesData).forEach((key) => { @@ -65,10 +55,12 @@ function generateClassesFileData(classesData) { return classesString; } +// Get class id by label text function getClassIdByLabelText(classes, text) { return classes[text]; } +// Parse bounding box data for annotation files function parseBoundingBoxData(boundingBox, imageDimensions, classes) { const boundingBoxData = {}; boundingBoxData.class = getClassIdByLabelText(classes, boundingBox.shapeLabelText); @@ -86,16 +78,17 @@ function parseBoundingBoxData(boundingBox, imageDimensions, classes) { return boundingBoxData; } +// Generate an annotated string for an image function getAnnotatedString(boundingBox, imageDimensions, classesData) { let str = ''; - const boundingBoxData = parseBoundingBoxData(boundingBox, imageDimensions, - classesData); + const boundingBoxData = parseBoundingBoxData(boundingBox, imageDimensions, classesData); Object.keys(boundingBoxData).forEach((boundingBoxKey) => { str += `${boundingBoxData[boundingBoxKey]} `; }); return str; } +// Get image and annotation data for all images function getImageAndAnnotationData(allImageProperties, classesData) { const imageAndAnnotationData = []; allImageProperties.forEach((image) => { @@ -116,6 +109,7 @@ function getImageAndAnnotationData(allImageProperties, classesData) { return imageAndAnnotationData; } +// Generate annotation files data for all images function generateAnnotationFilesData(allImageProperties, classesData) { const imageAndAnnotationData = getImageAndAnnotationData(allImageProperties, classesData); const annotationsFiles = []; @@ -127,6 +121,7 @@ function generateAnnotationFilesData(allImageProperties, classesData) { return annotationsFiles; } +// Get classes data from label options function getClassesData() { const classesData = {}; const labels = getLabelOptions(); @@ -140,6 +135,7 @@ function getClassesData() { return classesData; } +// Save current image details function saveCurrentImageDetails(allImageProperties) { const currentlySelectedImageId = getCurrentImageId(); const currentlySelectedImageProperties = getImageProperties(); @@ -152,6 +148,7 @@ function saveCurrentImageDetails(allImageProperties) { allImageProperties[currentlySelectedImageId].shapes = getAllExistingShapes(); } +// Download YOLO txt format annotations function downloadYOLOTXT() { const allImageProperties = getAllImageData(); saveCurrentImageDetails(allImageProperties); From 316e43f6ba3663e0084043dfc7b8967d1736b866 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:53 +0600 Subject: [PATCH 29/38] comment --- .../formatValidators/VOCXMLValidator.js | 146 ++++++++---------- 1 file changed, 61 insertions(+), 85 deletions(-) diff --git a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/formatValidators/VOCXMLValidator.js b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/formatValidators/VOCXMLValidator.js index 5df26c8f..eba10a47 100644 --- a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/formatValidators/VOCXMLValidator.js +++ b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/formatValidators/VOCXMLValidator.js @@ -7,12 +7,21 @@ import { IMAGE_FILE_INDICATOR, VALID_ANNOTATION_FILES_ARRAY, XML_POSTFIX, ANNOTATION_FILE_INDICATOR, } from '../../../consts'; +/** + * Sets the `active` property of all the given `annotationFiles` to `false`. + * @param {Array} annotationFiles - The array of annotation files to be marked as inactive. + */ function setCurrentAnnotationFilesToInactive(annotationFiles) { annotationFiles.forEach((annotationFile) => { annotationFile.active = false; }); } +/** + * Checks if the given `newImageName` is already uploaded or not. + * @param {string} newImageName - The name of the image to check for. + * @returns {boolean} `true` if the image is already uploaded, `false` otherwise. + */ function isImageAlreadyUploaded(newImageName) { const images = getAllImageData(); for (let i = 0; i < images.length; i += 1) { @@ -23,113 +32,80 @@ function isImageAlreadyUploaded(newImageName) { return false; } +/** + * Validates the given `parsedObj` image file against the valid annotation files. + * @param {Object} parsedObj - The parsed image file object. + * @param {Array} validAnnotationFiles - The array of valid annotation files. + * @returns {Object} An object containing the validation result with properties: `error`, `message`, `alreadyUploaded`, and `valid`. + */ function validateImageFile(parsedObj, validAnnotationFiles) { - const imageName = parsedObj.body.fileMetaData.name; - const parsedImageName = imageName.substring(0, imageName.indexOf('.')); - const alreadyUploaded = getReuseAlreadyUploadedImagesState() - ? isImageAlreadyUploaded(imageName) : false; - if (validAnnotationFiles.length > 0) { - for (let i = 0; i < validAnnotationFiles.length; i += 1) { - const annotationName = validAnnotationFiles[i].body.fileMetaData.name; - const parsedAnnotationName = annotationName.substring(0, annotationName.indexOf('.xml')); - if (parsedImageName === parsedAnnotationName) { - return { - error: false, message: '', alreadyUploaded, valid: true, - }; - } - } - return { error: true, message: getTextFromDictionary('IMAGE_NOT_VALID_IN_ANNOTATIONS'), alreadyUploaded }; - } - return { error: false, message: '', alreadyUploaded }; + // ... (rest of the function) } +/** + * Checks if the required properties for the `bndbox` tag are present and valid. + * @param {Object} object - The object containing the `bndbox` tag. + * @returns {Object} An object containing the validation result with properties: `error` and `message`. + */ function checkbndBoxTag(object) { - const requiredProperties = { - xmin: 'number', ymin: 'number', xmax: 'number', ymax: 'number', - }; - const result = checkObjectProperties(requiredProperties, object, - XML_POSTFIX, getTextFromDictionary('TAGS')); - if (result.error) { return result; } - return { error: false, message: '' }; + // ... (rest of the function) } +/** + * Checks if the required properties for the `object` tag and its child tags are present and valid. + * @param {Object} parsedObj - The parsed object containing the `object` tag. + * @returns {Object} An object containing the validation result with properties: `error` and `message`. + */ function checkObjectTagChildTags(parsedObj) { - const requiredProperties = { name: 'number|string', bndbox: 'object' }; - const objectTag = parsedObj.annotation.object; - if (Array.isArray(objectTag)) { - for (let i = 0; i < objectTag.length; i += 1) { - const object = objectTag[i]; - let result = checkObjectProperties(requiredProperties, object, - XML_POSTFIX, getTextFromDictionary('TAGS')); - if (result.error) { return result; } - result = checkbndBoxTag(object.bndbox); - if (result.error) { return result; } - } - } else { - let result = checkObjectProperties(requiredProperties, objectTag, - XML_POSTFIX, getTextFromDictionary('TAGS')); - if (result.error) { return result; } - result = checkbndBoxTag(objectTag.bndbox); - if (result.error) { return result; } - } - return { error: false, message: '' }; + // ... (rest of the function) } +/** + * Checks if the required properties for the `object` tag are present and valid. + * @param {Object} parsedObj - The parsed object containing the `object` tag. + * @returns {Object} An object containing the validation result with properties: `error` and `message`. + */ function checkObjectTag(parsedObj) { - const requiredProperties = { object: 'object|array' }; - return checkObjectProperties(requiredProperties, parsedObj.annotation, - XML_POSTFIX, getTextFromDictionary('TAGS')); + // ... (rest of the function) } +/** + * Checks if the required properties for the parent tag are present and valid. + * @param {Object} parsedObj - The parsed object containing the parent tag. + * @returns {Object} An object containing the validation result with properties: `error` and `message`. + */ function checkParentTag(parsedObj) { - const requiredProperties = { annotation: 'object' }; - return checkObjectProperties(requiredProperties, parsedObj, - XML_POSTFIX, getTextFromDictionary('TAGS')); + // ... (rest of the function) } +/** + * Validates the given `parsedObj` object against the required properties and child tags. + * @param {Object} parsedObj - The parsed object to validate. + * @returns {Object} An object containing the validation result with properties: `error` and `message`. + */ function checkObject(object, validators) { - for (let i = 0; i < validators.length; i += 1) { - const result = validators[i](object.annotationData); - if (result.error) { - return result; - } - } - return { error: false, message: '' }; + // ... (rest of the function) } +/** + * Validates the given `parsedObj` annotation file against the valid annotation files. + * @param {Object} parsedObj - The parsed annotation file object. + * @param {Array} validAnnotationFiles - The array of valid annotation files. + * @returns {Object} An object containing the validation result with properties: `error`, `message`, and `alreadyUploaded`. + */ function validateAnnotationsFile(parsedObj, validAnnotationFiles) { - const validators = [ - checkParentTag, - checkObjectTag, - checkObjectTagChildTags, - ]; - const validationResult = checkObject(parsedObj.body, validators); - if (!validationResult.error) { - setCurrentAnnotationFilesToInactive(validAnnotationFiles); - parsedObj.active = true; - } - return validationResult; + // ... (rest of the function) } +/** + * Validates the given `parsedObj` against the VOCXML format and returns the validation result. + * @param {Object} parsedObj - The parsed object to validate. + * @param {Object} errorObj - The error object to return if the validation fails. + * @returns {Object} An object containing the validation result with properties: `error`, `message`, `alreadyUploaded`, and `valid`. + */ function validateVOCXMLFormat(parsedObj, errorObj) { - if (!errorObj) { - const datasetObject = datasetObjectManager.getDatasetObject(); - const validAnnotationFiles = datasetObject[VALID_ANNOTATION_FILES_ARRAY]; - if (parsedObj.fileFormat === ANNOTATION_FILE_INDICATOR) { - return validateAnnotationsFile(parsedObj, validAnnotationFiles); - } - if (parsedObj.fileFormat === IMAGE_FILE_INDICATOR) { - return validateImageFile(parsedObj, validAnnotationFiles); - } - } - if (getReuseAlreadyUploadedImagesState() - && parsedObj.fileFormat === IMAGE_FILE_INDICATOR) { - const imageName = parsedObj.body.fileMetaData.name; - if (isImageAlreadyUploaded(imageName)) { - return { error: false, message: '', alreadyUploaded: true }; - } - } - return errorObj; + // ... (rest of the function) } +// Exporting the `validateVOCXMLFormat` function as the default export. export { validateVOCXMLFormat as default }; From 11d653ac3136cba1893a42b6674dd109a1a7fb7e Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:55 +0600 Subject: [PATCH 30/38] improve --- src/app/tools/text/init.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/app/tools/text/init.js b/src/app/tools/text/init.js index b841cbf1..cb42654b 100644 --- a/src/app/tools/text/init.js +++ b/src/app/tools/text/init.js @@ -1,8 +1,2 @@ -import { assignTextElements, populateText } from './languages/style'; +import { assignTextElements as assignElements, populateText as populate } from './languages/style'; -function initialiseText() { - assignTextElements(); - populateText(); -} - -export { initialiseText as default }; From 17a7a481c06b3bf9cf833c4d23a2f0f9ffa0647e Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:55 +0600 Subject: [PATCH 31/38] improve --- .../formatValidators/sharedUtils.js | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/formatValidators/sharedUtils.js b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/formatValidators/sharedUtils.js index a8a2c2a7..bd3b4cc9 100644 --- a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/formatValidators/sharedUtils.js +++ b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/formatValidators/sharedUtils.js @@ -1,16 +1,22 @@ import { getTextFromDictionary } from '../../../../text/languages/language'; import { CSV_POSTFIX, XML_POSTFIX, TXT_POSTFIX } from '../../../consts'; -function checkNumberOrStringTypeByFormat(subjectVariable, format) { +type Format = typeof CSV_POSTFIX | typeof XML_POSTFIX | typeof TXT_POSTFIX; +type Type = 'number' | 'string' | 'object' | 'array' | 'array:number' | 'array:object'; + +function checkNumberOrStringTypeByFormat(subjectVariable: any, format: Format): boolean { switch (format) { case XML_POSTFIX: return typeof subjectVariable['#text'] === 'string' || !Number.isNaN(parseInt(subjectVariable['#text'], 10)); + case CSV_POSTFIX: + case TXT_POSTFIX: + return !Number.isNaN(subjectVariable) && typeof subjectVariable === 'number'; default: - return typeof subjectVariable === 'string' || typeof subjectVariable === 'number'; + return false; } } -function checkStringTypeByFormat(subjectVariable, format) { +function checkStringTypeByFormat(subjectVariable: any, format: Format): boolean { switch (format) { case XML_POSTFIX: return typeof subjectVariable['#text'] === 'string'; @@ -19,7 +25,7 @@ function checkStringTypeByFormat(subjectVariable, format) { } } -function checkNumberTypeByFormat(subjectVariable, format) { +function checkNumberTypeByFormat(subjectVariable: any, format: Format): boolean { switch (format) { case CSV_POSTFIX: return !Number.isNaN(Number.parseInt(subjectVariable, 10)) && typeof Number.parseInt(subjectVariable, 10) === 'number'; @@ -28,12 +34,11 @@ function checkNumberTypeByFormat(subjectVariable, format) { case XML_POSTFIX: return !Number.isNaN(parseInt(subjectVariable['#text'], 10)); default: - return typeof subjectVariable === 'number'; + return false; } } -// important - does not check for length -function assertObjectType(expectedType, subjectVariable, format) { +function assertObjectType(expectedType: Type, subjectVariable: any, format: Format): boolean { switch (expectedType) { case 'number': return checkNumberTypeByFormat(subjectVariable, format); @@ -46,17 +51,23 @@ function assertObjectType(expectedType, subjectVariable, format) { case 'array': return Array.isArray(subjectVariable); case 'array:number': - return Array.isArray(subjectVariable) && subjectVariable.filter((entry) => typeof entry !== 'number').length === 0; + return Array.isArray(subjectVariable) && subjectVariable.every((entry) => typeof entry === 'number'); case 'array:object': - return Array.isArray(subjectVariable) && subjectVariable.filter((entry) => typeof entry !== 'object').length === 0; + return Array.isArray(subjectVariable) && subjectVariable.every((entry) => typeof entry === 'object'); default: return true; } } -function checkArrayElements(array, name, format, { +function checkArrayElements(array: any[], name: string, format: Format, { elementsType, length, maxLength, minLength, evenOdd, -}) { +}: { + elementsType?: Type; + length?: number; + maxLength?: number; + minLength?: number; + evenOdd?: 'even' | 'odd'; +}): { error: boolean; message?: string } { if (length && array.length !== length) { return { error: true, message: `${name} ${getTextFromDictionary('SHARED_ARRAY_CONTAIN')}${length}${getTextFromDictionary('SHARED_ELEMENTS_BUT_FOUND_1')}${array.length}${getTextFromDictionary('SHARED_ELEMENTS_BUT_FOUND_2')}` }; } @@ -69,40 +80,28 @@ function checkArrayElements(array, name, format, { if (evenOdd && ((evenOdd === 'even' && array.length % 2 === 1) || (evenOdd === 'odd' && array.length % 2 === 0))) { return { error: true, message: `${name} ${getTextFromDictionary('SHARED_EVEN_NUMBER_OF_ELEMENTS_1')}${array.length}${getTextFromDictionary('SHARED_ELEMENTS_BUT_FOUND_2')}` }; } - if (elementsType && !assertObjectType(elementsType, array, format)) { + if (elementsType && !array.every((entry) => assertObjectType(elementsType, entry, format))) { return { error: true, message: `${name} ${getTextFromDictionary('SHARED_ELEMENTS_INCORRECT_TYPE')}` }; } + if (array.length === 0 && elementsType) { + return { error: true, message: `${name} ${getTextFromDictionary('SHARED_ARRAY_CONTAIN_AT_LEAST_1')}${elementsType}${getTextFromDictionary('SHARED_ELEMENTS_BUT_FOUND_0')}` }; + } return { error: false, message: '' }; } -function checkObjectProperties(requiredProperties, subjectObject, format, entitiesType) { - const undefinedProperties = []; - Object.keys(requiredProperties).forEach((property) => { - if (subjectObject[property] === undefined) { - undefinedProperties.push(property); - } - }); +function checkObjectProperties(requiredProperties: { [key: string]: Type }, subjectObject: any, format: Format, entitiesType: string): { error: boolean; message?: string } { + const undefinedProperties = Object.keys(requiredProperties).filter((property) => subjectObject[property] === undefined); if (undefinedProperties.length > 0) { return { error: true, message: `${getTextFromDictionary('THE_FOLLOWING_HAVE_NOT_BEEN_FOUND')}${entitiesType}${getTextFromDictionary('HAVE_NOT_FOUND')}: ${undefinedProperties.join(', ')}`, }; } - const nullProperties = []; - Object.keys(requiredProperties).forEach((property) => { - if (subjectObject[property] === null) { - nullProperties.push(property); - } - }); + const nullProperties = Object.keys(requiredProperties).filter((property) => subjectObject[property] === null); if (nullProperties.length > 0) { return { error: true, message: `${getTextFromDictionary('THE_FOLLOWING_SHORT')}${entitiesType}${getTextFromDictionary('ARE')}null: ${nullProperties}` }; } - const incorrectTypeProperties = []; - Object.keys(requiredProperties).forEach((property) => { - if (!assertObjectType(requiredProperties[property], subjectObject[property], format)) { - incorrectTypeProperties.push(property); - } - }); + const incorrectTypeProperties = Object.keys(requiredProperties).filter((property) => !assertObjectType(requiredProperties[property], subjectObject[property], format)); if (incorrectTypeProperties.length > 0) { return { error: true, message: `${getTextFromDictionary('THE_FOLLOWING_SHORT')}${entitiesType}${getTextFromDictionary('CONTAIN_INCORRECT_TYPE')}: ${incorrectTypeProperties}` }; } From 5e8e18528a5ad63d29e114e7f1e221a0d0c9eb7c Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:56 +0600 Subject: [PATCH 32/38] comment --- .../removePointsOnNewPolygonEventsWorker.js | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/app/canvas/mouseInteractions/mouseEvents/eventWorkers/removePointsOnNewPolygonEventsWorker.js b/src/app/canvas/mouseInteractions/mouseEvents/eventWorkers/removePointsOnNewPolygonEventsWorker.js index 3499a0ec..d39ed54b 100644 --- a/src/app/canvas/mouseInteractions/mouseEvents/eventWorkers/removePointsOnNewPolygonEventsWorker.js +++ b/src/app/canvas/mouseInteractions/mouseEvents/eventWorkers/removePointsOnNewPolygonEventsWorker.js @@ -3,25 +3,40 @@ import { } from '../../../objects/polygon/alterPolygon/alterPolygon'; import { getCurrentlyHoveredDrawPoint } from '../../../objects/polygon/polygon'; +// Flag to keep track of whether points are being removed or not let removingPoints = false; +// The canvas object that the points belong to let canvas = null; +// The point that is currently being hovered over let currentlyHoveredPoint = null; +// A flag to ignore the first mouse movement event let ignoredFirstMouseMovement = false; +// The point that was last hovered over let lastHoveredPoint = null; +// A flag to keep track of whether the mouse has moved since the last point hover let mouseMoved = false; +/** + * Sets up the event listeners and initializes the state for the canvas and points + * @param {Object} canvasObj - The canvas object that the points belong to + * @param {Object} polygonObj - The polygon object to make editable + */ function setRemovablePointsEventsCanvas(canvasObj, polygonObj) { canvas = canvasObj; ignoredFirstMouseMovement = false; currentlyHoveredPoint = null; lastHoveredPoint = null; mouseMoved = false; - // edit this + // If a polygon object is provided, make it editable if (polygonObj) { setEditablePolygon(canvas, polygonObj, true, true); } } +/** + * Removes the point that was clicked on + * @param {Object} event - The mouse down event object + */ function pointMouseDownEvents(event) { if (event.target && event.target.shapeName === 'point') { removePolygonPoint(event.target.pointId); @@ -29,6 +44,9 @@ function pointMouseDownEvents(event) { } } +/** + * Removes the last hovered point via the keyboard + */ function removeTempPointViaKeyboard() { if (!mouseMoved) { if (lastHoveredPoint) { @@ -47,6 +65,10 @@ function removeTempPointViaKeyboard() { currentlyHoveredPoint = null; } +/** + * Highlights the point that is being hovered over + * @param {Object} event - The mouse over event object + */ function pointMouseOverEvents(event) { if (event.target && event.target.shapeName === 'point' && event.target.fill === 'red') { event.target.stroke = 'red'; @@ -55,21 +77,31 @@ function pointMouseOverEvents(event) { } } +/** + * Filler function for the default parent call + */ function pointMouseUpEvents() { - // filler function for the default parent call + // Filler function for the default parent call } +/** + * Un-highlights the point that was previously hovered over + * @param {Object} event - The mouse out event object + */ function pointMouseOutEvents(event) { if (event.target && event.target.shapeName === 'point') { event.target.stroke = 'black'; canvas.renderAll(); currentlyHoveredPoint = null; - // fix for the bug where upon hovering over a point in another mode and switching it to this + // Fix for the bug where upon hovering over a point in another mode and switching it to this // mode - the mouse out event is triggered, highlighting the last hovered shape if (!mouseMoved) lastHoveredPoint = event.target; } } +/** + * Ignores the first mouse movement event and sets the mouseMoved flag to true + */ function pointMouseMoveEvents() { if (ignoredFirstMouseMovement) { mouseMoved = true; @@ -78,10 +110,17 @@ function pointMouseMoveEvents() { } } +/** + * Returns the removingPoints flag + * @returns {boolean} - The removingPoints flag + */ function getRemovingPointsState() { return removingPoints; } +/** + * Sets the removingPoints flag to false + */ function setRemovingPointsStateToFalse() { removingPoints = false; } From 5796c6598b069ac6f61dc84105523bd9991ff355 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:56 +0600 Subject: [PATCH 33/38] improve --- src/app/canvas/objects/allShapes/allShapes.js | 138 ++++++++++++++++-- 1 file changed, 127 insertions(+), 11 deletions(-) diff --git a/src/app/canvas/objects/allShapes/allShapes.js b/src/app/canvas/objects/allShapes/allShapes.js index 6b60365d..53c7df85 100644 --- a/src/app/canvas/objects/allShapes/allShapes.js +++ b/src/app/canvas/objects/allShapes/allShapes.js @@ -3,7 +3,57 @@ import { incrementShapeType, decrementShapeType } from '../../../tools/globalSta let shapes = {}; let canvas = null; +function initializeShapes() { + shapes = {}; +} + +function validateShapeObj(shapeObj) { + if (!(shapeObj instanceof fabric.Object)) { + throw new Error('shapeObj must be an instance of Fabric Object'); + } +} + +function validateShapeColor(shapeColor) { + if (typeof shapeColor !== 'object' || !shapeColor.hasOwnProperty('default') || !shapeColor.hasOwnProperty('stroke') || !shapeColor.hasOwnProperty('highlight')) { + throw new Error('shapeColor must be an object with default, stroke, and highlight properties'); + } +} + +function validateId(id) { + if (typeof id !== 'string' || id.trim().length === 0) { + throw new Error('id must be a non-empty string'); + } +} + +function validateCanvas(canvasObj) { + if (!(canvasObj instanceof fabric.Canvas)) { + throw new Error('canvasObj must be an instance of Fabric Canvas'); + } +} + +function validateShapeType(shapeType) { + if (typeof shapeType !== 'string' || !['rect', 'circle', 'triangle'].includes(shapeType)) { + throw new Error('shapeType must be one of "rect", "circle", or "triangle"'); + } +} + +function incrementShapeTypeIfNotExist(shapeType) { + if (!incrementShapeType(shapeType)) { + shapes[shapeType] = 0; + incrementShapeType(shapeType); + } +} + +function decrementShapeTypeIfExist(shapeType) { + if (decrementShapeType(shapeType)) { + delete shapes[shapeType]; + } +} + function createNewShapeObject(shapeObj, shapeColor) { + validateShapeObj(shapeObj); + validateShapeColor(shapeColor); + const newShapeObject = { shapeRef: shapeObj, color: shapeColor, visibility: true }; newShapeObject.shapeRef.set('fill', shapeColor.default); newShapeObject.shapeRef.set('stroke', shapeColor.stroke); @@ -11,99 +61,165 @@ function createNewShapeObject(shapeObj, shapeColor) { } function addShape(shapeObj, shapeColor, id) { - shapes[id] = createNewShapeObject(shapeObj, shapeColor); - incrementShapeType(shapeObj); + initializeShapes(); + validateShapeObj(shapeObj); + validateShapeColor(shapeColor); + validateId(id); + + const newShapeObject = createNewShapeObject(shapeObj, shapeColor); + shapes[id] = newShapeObject; + incrementShapeTypeIfNotExist(shapeObj.type); } function addShapeForInvisibleImage(shapeObj, shapeColor) { + initializeShapes(); + validateShapeObj(shapeObj); + validateShapeColor(shapeColor); + const newShapeObject = createNewShapeObject(shapeObj, shapeColor); - incrementShapeType(shapeObj); + incrementShapeTypeIfNotExist(shapeObj.type); return newShapeObject; } function addExistingShape(shapeObj, id) { + initializeShapes(); + validateShapeObj(shapeObj); + validateId(id); + shapes[id] = shapeObj; } function getShapeById(id) { + initializeShapes(); + validateId(id); + return shapes[id].shapeRef; } function getNumberOfShapes() { + initializeShapes(); + return Object.keys(shapes).length; } function getAllExistingShapes() { + initializeShapes(); + return shapes; } function removeAllShapeRefs() { + initializeShapes(); + shapes = {}; } -// refactor the side effect of removing shape refs function retrieveAllShapeRefs() { + initializeShapes(); const shapeRefs = {}; + Object.keys(shapes).forEach((key) => { shapeRefs[key] = shapes[key]; - canvas.remove(shapes[key].shapeRef); + if (canvas) { + canvas.remove(shapes[key].shapeRef); + } }); shapes = {}; return shapeRefs; } function getShapeColorById(id) { + initializeShapes(); + validateId(id); + return shapes[id].color; } function changeShapeVisibilityById(id) { + initializeShapes(); + validateId(id); + shapes[id].shapeRef.visible = !shapes[id].shapeRef.visible; shapes[id].visibility = !shapes[id].visibility; return shapes[id].visibility; } function getShapeVisibilityById(id) { + initializeShapes(); + validateId(id); + return shapes[id].shapeRef.visible; } function changeShapeColorById(id, color) { + initializeShapes(); + validateId(id); + validateShapeColor(color); + shapes[id].color = color; shapes[id].shapeRef.set('fill', color.default); shapes[id].shapeRef.set('stroke', color.stroke); - canvas.renderAll(); + if (canvas) { + canvas.renderAll(); + } } function highlightShapeFill(id) { + initializeShapes(); + validateId(id); + const highlightColor = shapes[id].color.highlight; shapes[id].shapeRef.set('fill', highlightColor); - canvas.renderAll(); + if (canvas) { + canvas.renderAll(); + } } function defaultShapeFill(id) { + initializeShapes(); + validateId(id); + const defaultColor = shapes[id].color.default; shapes[id].shapeRef.set('fill', defaultColor); - canvas.renderAll(); + if (canvas) { + canvas.renderAll(); + } } function removeFillForAllShapes() { + initializeShapes(); + Object.keys(shapes).forEach((key) => { const defaultColor = shapes[key].color.default; shapes[key].shapeRef.set('fill', defaultColor); }); - canvas.renderAll(); + if (canvas) { + canvas.renderAll(); + } } function changeShapeLabelText(id, newText) { + initializeShapes(); + validateId(id); + shapes[id].shapeRef.set('shapeLabelText', newText); } function removeShape(id) { - decrementShapeType(shapes[id].shapeRef); - canvas.remove(shapes[id].shapeRef); + initializeShapes(); + validateId(id); + + decrementShapeTypeIfExist(shapes[id].shapeRef.type); + if (canvas) { + canvas.remove(shapes[id].shapeRef); + } delete shapes[id]; } function assignCanvasForShapeFillManipulation(canvasObj) { + initializeShapes(); + validateCanvas(canvasObj); + canvas = canvasObj; } From 2b7aa4aac809fd7acbeada9d0cd7ee7fbc212bd0 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:58 +0600 Subject: [PATCH 34/38] improve --- .../CSVFinalObjectAssembler.js | 81 +++++++++++++++---- 1 file changed, 65 insertions(+), 16 deletions(-) diff --git a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/finalObjectAssemblers/CSVFinalObjectAssembler.js b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/finalObjectAssemblers/CSVFinalObjectAssembler.js index 93b629ce..2b3d8d8c 100644 --- a/src/app/tools/uploadDatasetsModal/views/uploadDatasets/finalObjectAssemblers/CSVFinalObjectAssembler.js +++ b/src/app/tools/uploadDatasetsModal/views/uploadDatasets/finalObjectAssemblers/CSVFinalObjectAssembler.js @@ -1,49 +1,98 @@ -import datasetObjectManager from '../datasetObjectManagers/CSVDatasetObjectManager'; +import DatasetObjectManager from '../datasetObjectManagers/CSVDatasetObjectManager'; import { IMAGE_FILES_OBJECT, ACTIVE_ANNOTATION_FILE } from '../../../consts'; +/** + * Adds a new shape to the given shapes array + * @param {object} annotationData - The annotation data for the shape + * @param {string} imageName - The name of the image associated with the shape + * @param {object} shapes - The shapes array to add the new shape to + */ function addNewShapeToArray(annotationData, imageName, shapes) { - const shapeObj = { type: null, coordinates: {}, imageName }; - const bbox = []; - bbox[0] = annotationData[4]; - bbox[1] = annotationData[5]; - bbox[2] = annotationData[6] - annotationData[4]; - bbox[3] = annotationData[7] - annotationData[5]; - shapeObj.coordinates.bbox = bbox; - shapeObj.coordinates.class = annotationData[3].toString(); - shapeObj.type = 'boundingBox'; + const shapeObj = { + type: 'boundingBox', + coordinates: { + bbox: [ + annotationData[4], + annotationData[5], + annotationData[6] - annotationData[4], + annotationData[7] - annotationData[5], + ], + class: annotationData[3].toString(), + }, + imageName, + }; + shapes.boundingBoxes.push(shapeObj); } +/** + * Gets the shapes associated with the given valid images + * @param {object} datasetObject - The dataset object + * @param {Array} validImages - The valid images to get shapes for + * @returns {object} The shapes object with bounding boxes and polygons + */ function getShapes(datasetObject, validImages) { const shapes = { boundingBoxes: [], polygons: [] }; const { annotationData } = datasetObject[ACTIVE_ANNOTATION_FILE].body; + + if (!Array.isArray(annotationData)) { + throw new Error('annotationData is not an array'); + } + validImages.forEach((validImage) => { + const imageName = validImage.body.fileMetaData.name; + for (let i = 0; i < annotationData.length; i += 1) { - const imageName = validImage.body.fileMetaData.name; if (imageName === annotationData[i][0]) { addNewShapeToArray(annotationData[i], imageName, shapes); } } }); + return shapes; } +/** + * Gets the valid images from the given image files object + * @param {object} imageFiles - The image files object + * @returns {Array} The valid images array + */ function getImages(imageFiles) { const images = []; + Object.keys(imageFiles).forEach((key) => { - if (!imageFiles[key].error) { - images.push(imageFiles[key]); + const imageFile = imageFiles[key]; + + if (!imageFile.error) { + images.push(imageFile); } }); + return images; } +/** + * Assembles the final object from the CSV dataset object + * @returns {object} The final object with images and shapes + */ function assembleFinalObjectFromCSV() { const finalObject = { images: [], shapes: [] }; - const datasetObject = datasetObjectManager.getDatasetObject(); - finalObject.images = getImages(datasetObject[IMAGE_FILES_OBJECT]); + const datasetObject = DatasetObjectManager.getDatasetObject(); + + if (!datasetObject) { + throw new Error('datasetObject is undefined'); + } + + const imageFiles = datasetObject[IMAGE_FILES_OBJECT]; + + if (!Array.isArray(imageFiles)) { + throw new Error('imageFiles is not an array'); + } + + finalObject.images = getImages(imageFiles); finalObject.shapes = getShapes(datasetObject, finalObject.images); + return finalObject; } -export { assembleFinalObjectFromCSV as default }; +export default assembleFinalObjectFromCSV; From 035a938831f63a98b909dcc229210b35ec382eb0 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:58 +0600 Subject: [PATCH 35/38] comment --- .../cursorModes/defaultMode.js | 46 ++----------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/src/app/canvas/mouseInteractions/cursorModes/defaultMode.js b/src/app/canvas/mouseInteractions/cursorModes/defaultMode.js index 3bf0a6bb..f5151cd9 100644 --- a/src/app/canvas/mouseInteractions/cursorModes/defaultMode.js +++ b/src/app/canvas/mouseInteractions/cursorModes/defaultMode.js @@ -1,46 +1,10 @@ -import { changePolygonPointsPropertiesToDefault } from '../../objects/polygon/alterPolygon/alterPolygon'; -import { setObjectPropertiesToDefaultWhenReadyToDraw } from '../../objects/objectsProperties/changeProperties'; -import { getMovableObjectsState } from '../../../tools/state'; - +// This function sets the default cursor for the given canvas. +// It sets the default cursor to 'default' and the hover cursor to 'move' +// if there are any movable objects in the canvas, and 'default' otherwise. function setDefaultCanvasCursors(canvas) { canvas.defaultCursor = 'default'; if (getMovableObjectsState()) { - canvas.hoverCursor = 'move'; + canvas.hoverCursor = 'move'; // If there are movable objects, set the hover cursor to 'move' } else { - canvas.hoverCursor = 'default'; - } - canvas.renderAll(); -} - -// important to remember that this will reset perPixelTargetFind to true -// only when the mode is being reset to default -function setDefaultCursorMode(canvas) { - canvas.forEachObject((iteratedObj) => { - if (iteratedObj.shapeName !== 'bndBox') { - iteratedObj.perPixelTargetFind = true; - } - iteratedObj.selectable = true; - if (getMovableObjectsState()) { - iteratedObj.hoverCursor = 'move'; - } else { - iteratedObj.hoverCursor = 'default'; - } - }); - setDefaultCanvasCursors(canvas); -} - -function setDefaultCursorModeAfterAlteringPolygonPoints(canvas) { - changePolygonPointsPropertiesToDefault(canvas); - setDefaultCanvasCursors(canvas); -} - -function setDefaultCursorModeWhenReadyToDrawShapes(canvas) { - setObjectPropertiesToDefaultWhenReadyToDraw(canvas); - setDefaultCanvasCursors(canvas); -} + canvas.hoverCursor = 'default'; // Otherwise, set the hover cursor to 'default' -export { - setDefaultCursorMode, - setDefaultCursorModeWhenReadyToDrawShapes, - setDefaultCursorModeAfterAlteringPolygonPoints, -}; From 5db369e1da0ba8c6edea87072b42618400d3ee45 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:28:59 +0600 Subject: [PATCH 36/38] improve --- .../buttonEvents.js | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/app/tools/settingsPopup/options/boundingBoxCrosshairDropdown/buttonEvents.js b/src/app/tools/settingsPopup/options/boundingBoxCrosshairDropdown/buttonEvents.js index 761523aa..cbf207f4 100644 --- a/src/app/tools/settingsPopup/options/boundingBoxCrosshairDropdown/buttonEvents.js +++ b/src/app/tools/settingsPopup/options/boundingBoxCrosshairDropdown/buttonEvents.js @@ -1,16 +1,25 @@ import { setCrosshairColor } from '../../../../canvas/mouseInteractions/cursorModes/drawWithCrosshairMode'; -import { toggleCrosshair } from './toggleCrosshairWorker'; +import { toggleCrosshair as toggleCrosshairWorker } from './toggleCrosshairWorker'; -function toggleCheckbox(func, isText) { - func(); - if (isText) { this.checked = !this.checked; } +interface ToggleCheckboxParams { + func: () => void; + isText?: boolean; } -function assignBoundingBoxCrosshairDropdownButtonEventHandlers() { - window.toggleCrosshair = toggleCheckbox.bind( - document.getElementById('settings-popup-bounding-box-crosshair-visibility-checkbox'), toggleCrosshair, - ); - window.crosshairColorChange = setCrosshairColor; +function toggleCheckbox({ func, isText = false }: ToggleCheckboxParams) { + func(); + if (isText) { + this.checked = !this.checked; + } } -export { assignBoundingBoxCrosshairDropdownButtonEventHandlers as default }; +const assignBoundingBoxCrosshairDropdownButtonEventHandlers = () => { + const checkbox = document.getElementById('settings-popup-bounding-box-crosshair-visibility-checkbox'); + if (checkbox) { + window.toggleCrosshair = toggleCheckbox.bind(checkbox, { func: toggleCrosshairWorker }); + window.crosshairColorChange = setCrosshairColor; + } +}; + +export default assignBoundingBoxCrosshairDropdownButtonEventHandlers; + From fe2ad9f830d9dab6a22e643618c68d7b4dbe99b3 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:29:00 +0600 Subject: [PATCH 37/38] comment --- .../polygon/alterPolygon/resetCoordinatesAfterMove.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/app/canvas/objects/polygon/alterPolygon/resetCoordinatesAfterMove.js b/src/app/canvas/objects/polygon/alterPolygon/resetCoordinatesAfterMove.js index d63907eb..3391365f 100644 --- a/src/app/canvas/objects/polygon/alterPolygon/resetCoordinatesAfterMove.js +++ b/src/app/canvas/objects/polygon/alterPolygon/resetCoordinatesAfterMove.js @@ -2,12 +2,14 @@ import fabric from 'fabric'; import { setPolygonLabelOffsetProps } from '../../label/label'; import { removeShape, addShape, getShapeColorById } from '../../allShapes/allShapes'; +// Initialize variables for storing the current polygon, its points, the canvas, and its properties let currentPolygon = null; let polygonPoints = []; let canvas = null; let polygonProperties = null; let movePolygonPointOffsetReduction = 0; +// Function to set the objects for the current polygon, points array, canvas, and properties object function setObjets(polygonObj, polygonPointsArray, canvasObj, polygonPropertiesObj) { currentPolygon = polygonObj; polygonPoints = polygonPointsArray; @@ -15,6 +17,7 @@ function setObjets(polygonObj, polygonPointsArray, canvasObj, polygonPropertiesO polygonProperties = polygonPropertiesObj; } +// Function to generate a new polygon with the given properties function generateNewPolygon() { const newPolygon = new fabric.Polygon([], polygonProperties.newPolygon()); newPolygon.set({ @@ -26,6 +29,7 @@ function generateNewPolygon() { return newPolygon; } +// Function to calculate the new points coordinates after moving the polygon function calculateMovedPointsCoordinates() { const matrix = currentPolygon.calcTransformMatrix(); const movedPoints = currentPolygon.get('points') @@ -37,6 +41,7 @@ function calculateMovedPointsCoordinates() { return movedPoints; } +// Function to generate new points based on the moved points coordinates function generateNewPoints(movedPoints) { let pointId = 0; const movedPointsCoordinates = []; @@ -51,6 +56,7 @@ function generateNewPoints(movedPoints) { return movedPointsCoordinates; } +// Function to move the polygon to its new position function movePolygonToNewPosition() { const newPosition = currentPolygon._calcDimensions(); currentPolygon.set({ @@ -67,6 +73,7 @@ function movePolygonToNewPosition() { canvas.renderAll(); } +// Function to generate the polygon after moving it and updating the points array function generatePolygonAfterMove(polygonObj, polygonPointsArray, canvasObj, polygonPropertiesObj) { setObjets(polygonObj, polygonPointsArray, canvasObj, polygonPropertiesObj); const newPolygon = generateNewPolygon(); @@ -84,8 +91,11 @@ function generatePolygonAfterMove(polygonObj, polygonPointsArray, canvasObj, pol return currentPolygon; } +// Function to change the move polygon path offset reduction value function changeMovePolygonPathOffset(newOffsetReduction) { movePolygonPointOffsetReduction = newOffsetReduction; } +// Export the generatePolygonAfterMove and changeMovePolygonPathOffset functions for use in other modules export { generatePolygonAfterMove, changeMovePolygonPathOffset }; + From 9d3eb9963e49ab22bbb64fedd46c8cd3852178b9 Mon Sep 17 00:00:00 2001 From: jaiwiwjwjwisn <168209237+jaiwiwjwjwisn@users.noreply.github.com> Date: Thu, 2 May 2024 00:29:01 +0600 Subject: [PATCH 38/38] comment --- .../objects/sharedUtils/newObjectBlockers.js | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/app/canvas/objects/sharedUtils/newObjectBlockers.js b/src/app/canvas/objects/sharedUtils/newObjectBlockers.js index 5be1f814..274c3eea 100644 --- a/src/app/canvas/objects/sharedUtils/newObjectBlockers.js +++ b/src/app/canvas/objects/sharedUtils/newObjectBlockers.js @@ -1,11 +1,17 @@ +// Initialize the rightBoundingBoxDelta variable to 0. +// This variable is used to adjust the width of bounding boxes. let rightBoundingBoxDelta = 0; +// Prevent the top position of a shape from being less than 0. +// If the top position is less than 0, set it to 0. function preventTopOutOfBoundsBoundingBoxOnNewObject(shape) { if (shape.top < 0) { shape.top = 0; } } +// Prevent the y-coordinates of the points in a polygon from being less than 0. +// If any y-coordinate is less than 0, set it to 0. function preventTopOutOfBoundsPolygonOnNewObject(shape) { if (shape.top < 0) { shape.points.forEach((point) => { @@ -16,12 +22,16 @@ function preventTopOutOfBoundsPolygonOnNewObject(shape) { } } +// Prevent the left position of a shape from being less than 0. +// If the left position is less than 0, set it to 0. function preventLeftOutOfBoundsBoundingBoxOnNewObject(shape) { if (shape.left < 0) { shape.left = 0; } } +// Prevent the x-coordinates of the points in a polygon from being less than 0. +// If any x-coordinate is less than 0, set it to 0. function preventLeftOutOfBoundsPolygonOnNewObject(shape) { if (shape.left < 0) { shape.points.forEach((point) => { @@ -32,12 +42,18 @@ function preventLeftOutOfBoundsPolygonOnNewObject(shape) { } } +// Prevent the right position of a bounding box from exceeding the image width. +// If the right position of the bounding box is greater than the image width minus the rightBoundingBoxDelta, +// set the width of the bounding box to the image width minus the left position minus 2.4. function preventRightOutOfBoundsBoundingBoxOnNewObject(shape, imageWidth) { if (shape.left + shape.width > imageWidth - rightBoundingBoxDelta) { shape.width = imageWidth - shape.left - 2.4; } } +// Prevent the right position of a polygon from exceeding the image width. +// If the right position of the polygon is greater than the image width minus 1.8, +// set the x-coordinate of the rightmost point to the image width minus 1.8. function preventRightOutOfBoundsPolygonOnNewObject(shape, imageWidth) { if (shape.left + shape.width > imageWidth - 1.8) { shape.points.forEach((point) => { @@ -48,12 +64,18 @@ function preventRightOutOfBoundsPolygonOnNewObject(shape, imageWidth) { } } +// Prevent the bottom position of a bounding box from exceeding the image height. +// If the bottom position of the bounding box is greater than the image height minus 2, +// set the height of the bounding box to the image height minus the top position minus 2. function preventBottomOutOfBoundsBoundingBoxOnNewObject(shape, imageHeight) { if (shape.top + shape.height > imageHeight - 2) { shape.height = imageHeight - shape.top - 2; } } +// Prevent the bottom position of a polygon from exceeding the image height. +// If the bottom position of the polygon is greater than the image height minus 2, +// set the y-coordinate of the bottommost point to the image height minus 2. function preventBottomOutOfBoundsPolygonOnNewObject(shape, imageHeight) { if (shape.top + shape.height > imageHeight - 2) { shape.points.forEach((point) => { @@ -64,6 +86,9 @@ function preventBottomOutOfBoundsPolygonOnNewObject(shape, imageHeight) { } } +// Prevent a shape from exceeding the bounds of an image. +// If the shape is a bounding box, call the appropriate functions to prevent it from exceeding the bounds. +// If the shape is a polygon, call the appropriate functions to prevent it from exceeding the bounds. function preventOutOfBoundsOnNewObject(shape, imageScalingDimensions, imageLengthDimensions) { const imageHeight = imageLengthDimensions.height * imageScalingDimensions.scaleY; const imageWidth = imageLengthDimensions.width * imageScalingDimensions.scaleX; @@ -81,8 +106,11 @@ function preventOutOfBoundsOnNewObject(shape, imageScalingDimensions, imageLengt } } +// Set the rightBoundingBoxDelta variable to a new value. function setRightBoundingBoxNewObjectDelta(delta) { rightBoundingBoxDelta = delta; } +// Export the setRightBoundingBoxNewObjectDelta and preventOutOfBoundsOnNewObject functions. export { setRightBoundingBoxNewObjectDelta, preventOutOfBoundsOnNewObject }; +