diff --git a/MisplaceAI/item_detector/utils.py b/MisplaceAI/item_detector/utils.py index b9d54643b52bccc789908dc031c181f010027d3c..279853f00f75695452839e014f1815a5921b9567 100644 --- a/MisplaceAI/item_detector/utils.py +++ b/MisplaceAI/item_detector/utils.py @@ -1,3 +1,4 @@ +# MisplaceAI/item_detector/utils.py import os import glob import numpy as np diff --git a/MisplaceAI/placement_rules/models.py b/MisplaceAI/placement_rules/models.py index bd488e2cd6f19fbc01d27f67873d1c138ff6e5e9..5c9036996b11d5ac26753fd5dc1d6a18c169447b 100644 --- a/MisplaceAI/placement_rules/models.py +++ b/MisplaceAI/placement_rules/models.py @@ -1,3 +1,5 @@ +#MisplaceAI/placement_rules/models.py + from django.db import models class PlacementRule(models.Model): diff --git a/MisplaceAI/placement_rules/urls.py b/MisplaceAI/placement_rules/urls.py index 2f4a42a232a9766507e7df5e271779ad52ad1790..070ee401425bd64496324ace40ff2d4419677ed6 100644 --- a/MisplaceAI/placement_rules/urls.py +++ b/MisplaceAI/placement_rules/urls.py @@ -1,3 +1,4 @@ +# MisplaceAi/placement_rules/urls.py from django.urls import path from . import views diff --git a/MisplaceAI/placement_rules/utils.py b/MisplaceAI/placement_rules/utils.py index 3b5d2e0d37baf8e47630b50102642edf71cd5e56..e04857c80a91df8a5f3806a6311168ec7a8e2722 100644 --- a/MisplaceAI/placement_rules/utils.py +++ b/MisplaceAI/placement_rules/utils.py @@ -1,3 +1,5 @@ +# MisplaceAi/placement_rules/utils.py + from rules.models import Rule class PlacementRules: diff --git a/MisplaceAI/placement_rules/views.py b/MisplaceAI/placement_rules/views.py index abdd4aebdd19f977011806aeec1724e883b02500..a3b2083a8c4b13b9d0981f9751c65216f86f4e0d 100644 --- a/MisplaceAI/placement_rules/views.py +++ b/MisplaceAI/placement_rules/views.py @@ -1,3 +1,4 @@ +# MispplaceAI/placement_rules/views.py from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from rest_framework.decorators import api_view, permission_classes diff --git a/MisplaceAI/process_misplaced_manager/forms.py b/MisplaceAI/process_misplaced_manager/forms.py index 47b2ce438ef5a2e9971c55e393a9805f941f6514..0dfcd476b297f1acb0deeaa1a7d3a41420b379aa 100644 --- a/MisplaceAI/process_misplaced_manager/forms.py +++ b/MisplaceAI/process_misplaced_manager/forms.py @@ -1,3 +1,5 @@ +# MisplaceAI/process_misplaced_manager/forms.py + from django import forms from .models import UploadedImage, UploadedVideo diff --git a/MisplaceAI/process_misplaced_manager/models.py b/MisplaceAI/process_misplaced_manager/models.py index 3671483996fb361b26f1468d9fa9ad641aa16b1e..eff9fe303826f704c79cf0c237cccfb6db7c294d 100644 --- a/MisplaceAI/process_misplaced_manager/models.py +++ b/MisplaceAI/process_misplaced_manager/models.py @@ -1,3 +1,5 @@ +# MisplaceAI/process_misplaced_manager/models.py + from django.db import models class UploadedImage(models.Model): diff --git a/MisplaceAI/process_misplaced_manager/serializers.py b/MisplaceAI/process_misplaced_manager/serializers.py index 1fd67f26ac2cd61f24be964f2ad650785b4eb1cc..a071586d25537956e0aa34fe899d40fff132ada1 100644 --- a/MisplaceAI/process_misplaced_manager/serializers.py +++ b/MisplaceAI/process_misplaced_manager/serializers.py @@ -1,4 +1,5 @@ -# process_misplaced_manager/serializers.py +# MisplaceAI/process_misplaced_manager/serializers.py + from rest_framework import serializers from .models import UploadedImage, UploadedVideo diff --git a/MisplaceAI/process_misplaced_manager/urls.py b/MisplaceAI/process_misplaced_manager/urls.py index 529d411f38f6519cc3b5edeef4e1db8f0da791c6..9d410686acde72b829122104533e0c2b3951a687 100644 --- a/MisplaceAI/process_misplaced_manager/urls.py +++ b/MisplaceAI/process_misplaced_manager/urls.py @@ -1,4 +1,4 @@ -# process_misplaced_manager/urls.py +# MisplaceAI/process_misplaced_manager/urls.py from django.urls import path, include from rest_framework.routers import DefaultRouter from .views import ( diff --git a/MisplaceAI/process_misplaced_manager/views.py b/MisplaceAI/process_misplaced_manager/views.py index ac9dada05686d8f31954687ea5f5ae15abe0d08d..8fb50e25e8032132ffcd5339bbf2b2a61007ab1e 100644 --- a/MisplaceAI/process_misplaced_manager/views.py +++ b/MisplaceAI/process_misplaced_manager/views.py @@ -1,3 +1,5 @@ +# MisplaceAI/process_misplaced_manager/views.py + from rest_framework import viewsets, status from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated diff --git a/MisplaceAI/results_viewer/urls.py b/MisplaceAI/results_viewer/urls.py index da720e4baa2bf256151bc7db2d3bcecefc5cab59..1f9e8dfc110baed73ae227610bafa73ea1deeac5 100644 --- a/MisplaceAI/results_viewer/urls.py +++ b/MisplaceAI/results_viewer/urls.py @@ -1,3 +1,5 @@ +# MisplaceAI/results_viewer/urls.py + from django.urls import path from .views import generate_annotated_image diff --git a/MisplaceAI/results_viewer/utils.py b/MisplaceAI/results_viewer/utils.py index 4fc050448612a9e4df75309e676de679f2e6f5b9..e0b08f59a8f23096efa80623b3b8213628069cb3 100644 --- a/MisplaceAI/results_viewer/utils.py +++ b/MisplaceAI/results_viewer/utils.py @@ -1,3 +1,4 @@ +# MisplaceAi/results_viewer/utils.py from PIL import Image import matplotlib.pyplot as plt import matplotlib.patches as patches diff --git a/MisplaceAI/results_viewer/views.py b/MisplaceAI/results_viewer/views.py index 4518dc0c219851f6f1b719c19c3e26f5cdbb8720..78a205a2ed0082c91d2318f0ffdc7aa75d44d5c5 100644 --- a/MisplaceAI/results_viewer/views.py +++ b/MisplaceAI/results_viewer/views.py @@ -1,4 +1,4 @@ -# results_viewer/views.py +# MisplaceAi/results_viewer/views.py from django.http import JsonResponse from .utils import visualize_misplaced_objects diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c8b96d722dfc85ab0d0b9cf07aa2e744a18a222c..7e36288c36bb4090d87ce04bf8124b5bda5a364b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,6 +13,7 @@ "axios": "^1.7.2", "bootstrap": "^5.3.3", "react": "^18.0.0", + "react-bootstrap": "^2.10.2", "react-dom": "^18.0.0", "react-router-dom": "^6.23.1", "react-scripts": "5.0.0", @@ -3554,12 +3555,26 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" } }, + "node_modules/@react-aria/ssr": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.4.tgz", + "integrity": "sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, "node_modules/@remix-run/router": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz", @@ -3569,6 +3584,48 @@ "node": ">=14.0.0" } }, + "node_modules/@restart/hooks": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.9.tgz", + "integrity": "sha512-mUbygUsJcRurjZCt1f77gg4DpheD1D+Sc7J3JjAkysUj7t8m4EBJVOqWC9788Qtbc69cJ+HlJc6jBguKwS8Mcw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.4.9", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.14.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3911,6 +3968,15 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@swc/helpers": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", + "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@tensorflow-models/coco-ssd": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/@tensorflow-models/coco-ssd/-/coco-ssd-2.2.3.tgz", @@ -4434,6 +4500,12 @@ "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "license": "MIT" }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "license": "MIT" + }, "node_modules/@types/q": { "version": "1.5.8", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", @@ -4452,6 +4524,25 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "license": "MIT" }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -4530,6 +4621,12 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT" }, + "node_modules/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==", + "license": "MIT" + }, "node_modules/@types/webgl-ext": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz", @@ -6301,6 +6398,12 @@ "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", "license": "MIT" }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -7042,6 +7145,12 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "license": "MIT" }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -7362,6 +7471,16 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -10045,6 +10164,15 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", @@ -15608,6 +15736,25 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "license": "MIT", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/prop-types-extra/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -15806,6 +15953,36 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "license": "MIT" }, + "node_modules/react-bootstrap": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.2.tgz", + "integrity": "sha512-UvB7mRqQjivdZNxJNEA2yOQRB7L9N43nBnKc33K47+cH90/ujmnMwatTCwQLu83gLhrzAl8fsa6Lqig/KLghaA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.6.8", + "@types/react-transition-group": "^4.4.6", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -16018,6 +16195,12 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "license": "MIT" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "license": "MIT" + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -16132,6 +16315,22 @@ } } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -18288,6 +18487,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/underscore": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", @@ -18540,6 +18754,15 @@ "makeerror": "1.0.12" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/watchpack": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index c2d211bbe97d2b889a91f3a65206eb62903118e5..fe6e6b29320cae1b63dc3604f7cfa9c12fea2515 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,6 +8,7 @@ "axios": "^1.7.2", "bootstrap": "^5.3.3", "react": "^18.0.0", + "react-bootstrap": "^2.10.2", "react-dom": "^18.0.0", "react-router-dom": "^6.23.1", "react-scripts": "5.0.0", diff --git a/frontend/src/assets/loading.gif b/frontend/src/assets/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e7af01d960069018acfb0b77a8d5e8456660cae Binary files /dev/null and b/frontend/src/assets/loading.gif differ diff --git a/frontend/src/index.js b/frontend/src/index.js index 47bbb7b39a56a0d8a7dbb974ac430ec22a9ca84d..2c349a9fe401f502c8eba981f7db7deb00b62d9f 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -1,3 +1,4 @@ +// src/index.js import 'bootstrap/dist/css/bootstrap.min.css'; import React from 'react'; import ReactDOM from 'react-dom'; diff --git a/frontend/src/pages/Home/Home.js b/frontend/src/pages/Home/Home.js index 2391bf1f8104fde51f8ef80160451c8f5e21a38e..2f76531040d4a68b217094466ea7fea419c8c1e9 100644 --- a/frontend/src/pages/Home/Home.js +++ b/frontend/src/pages/Home/Home.js @@ -1,3 +1,4 @@ +// src/pages/Home/Home.js import React from 'react'; import './Home.css'; diff --git a/frontend/src/pages/NormalDetection/NormalDetectionPage.css b/frontend/src/pages/NormalDetection/NormalDetectionPage.css index 27102eb4a115d9abe392fdf3388fc51f64c1e4c8..e1107d7f20fbeb7fe30146166af29966fa3c4ae8 100644 --- a/frontend/src/pages/NormalDetection/NormalDetectionPage.css +++ b/frontend/src/pages/NormalDetection/NormalDetectionPage.css @@ -1,9 +1,27 @@ /* src/pages/NormalDetection/NormalDetectionPage.css */ -.container { - max-width: 600px; + +.card { margin: auto; } -.btn-lg i { - margin-right: 8px; +@media (max-width: 576px) { + .card-body { + padding: 1rem; + } + + .btn-lg { + font-size: 1rem; + padding: 0.5rem 1rem; + } +} + +@media (min-width: 1200px) { + .card-body { + padding: 3rem; + } + + .btn-lg { + font-size: 1.25rem; + padding: 0.75rem 1.5rem; + } } \ No newline at end of file diff --git a/frontend/src/pages/NormalDetection/NormalDetectionPage.js b/frontend/src/pages/NormalDetection/NormalDetectionPage.js index 6c01bd3ab5be9008a1baa7e5340f6fb1e488db27..f1c3a4000f603fae0a2ac51f309ce449f64e558a 100644 --- a/frontend/src/pages/NormalDetection/NormalDetectionPage.js +++ b/frontend/src/pages/NormalDetection/NormalDetectionPage.js @@ -1,12 +1,17 @@ // src/pages/NormalDetection/NormalDetectionPage.js + import React, { useState } from 'react'; +import { Modal, Button } from 'react-bootstrap'; import { normalDetection } from '../../services/processMisplacedManagerApi'; import './NormalDetectionPage.css'; +import loadingGif from '../../assets/loading.gif'; // Import your downloaded GIF const NormalDetectionPage = () => { const [imageFile, setImageFile] = useState(null); const [resultImageUrl, setResultImageUrl] = useState(null); const [misplacedObjects, setMisplacedObjects] = useState([]); + const [isLoading, setIsLoading] = useState(false); // Add loading state + const [showModal, setShowModal] = useState(false); // State to control modal visibility const handleCameraClick = () => { document.getElementById('cameraInput').click(); @@ -23,6 +28,7 @@ const NormalDetectionPage = () => { const handleSubmit = async (event) => { event.preventDefault(); if (imageFile) { + setIsLoading(true); // Set loading to true when processing starts const formData = new FormData(); formData.append('image', imageFile); @@ -32,50 +38,73 @@ const NormalDetectionPage = () => { setMisplacedObjects(response.misplaced_objects); } catch (error) { console.error('Upload failed', error); + } finally { + setIsLoading(false); // Set loading to false when processing is complete } } else { alert('Please select an image to upload.'); } }; + const handleImageClick = () => { + setShowModal(true); + }; + + const handleCloseModal = () => { + setShowModal(false); + }; + return ( <div className="container mt-5"> <div className="row justify-content-center"> - <div className="col-md-8"> + <div className="col-12 col-md-10 col-lg-8"> <div className="card shadow-lg border-0"> <div className="card-header text-center bg-primary text-white py-4"> <h1 className="mb-0">Upload Image for Normal Detection</h1> </div> <div className="card-body p-5"> - <form id="uploadForm" className="text-center" onSubmit={handleSubmit}> - <div className="form-group"> - <label className="h5 d-block"> - <button type="button" id="openCameraBtn" className="btn btn-primary btn-lg" onClick={handleCameraClick}> - <i className="fas fa-camera-retro fa-3x mb-3"></i> Take Photo - </button> - </label> - <input type="file" id="cameraInput" name="image" accept="image/*" capture="environment" - className="form-control-file d-none" onChange={handleFileChange} /> + {isLoading ? ( // Show loading GIF or message while loading + <div className="text-center"> + <img src={loadingGif} alt="Loading..." className="img-fluid" /> + <p>Your photo is being processed, please wait...</p> </div> + ) : ( + <form id="uploadForm" className="text-center" onSubmit={handleSubmit}> + <div className="form-group"> + <label className="h5 d-block"> + <button type="button" id="openCameraBtn" className="btn btn-primary btn-lg" onClick={handleCameraClick}> + <i className="fas fa-camera-retro fa-3x mb-3"></i> Take Photo + </button> + </label> + <input type="file" id="cameraInput" name="image" accept="image/*" capture="environment" + className="form-control-file d-none" onChange={handleFileChange} /> + </div> - <div className="form-group"> - <label className="h5 d-block"> - <button type="button" id="openGalleryBtn" className="btn btn-secondary btn-lg" onClick={handleGalleryClick}> - <i className="fas fa-folder-open fa-3x mb-3"></i> Choose from Gallery - </button> - </label> - <input type="file" id="galleryInput" name="image" accept="image/*" - className="form-control-file d-none" onChange={handleFileChange} /> - </div> + <div className="form-group"> + <label className="h5 d-block"> + <button type="button" id="openGalleryBtn" className="btn btn-secondary btn-lg" onClick={handleGalleryClick}> + <i className="fas fa-folder-open fa-3x mb-3"></i> Choose from Gallery + </button> + </label> + <input type="file" id="galleryInput" name="image" accept="image/*" + className="form-control-file d-none" onChange={handleFileChange} /> + </div> - <button type="submit" className="btn btn-success btn-lg mt-4"> - <i className="fas fa-upload"></i> Upload - </button> - </form> - {resultImageUrl && ( + <button type="submit" className="btn btn-success btn-lg mt-4"> + <i className="fas fa-upload"></i> Upload + </button> + </form> + )} + {resultImageUrl && !isLoading && ( // Show results if not loading <div className="mt-5"> <h2>Detection Results</h2> - <img src={resultImageUrl} alt="Detected Objects" className="img-fluid" /> + <img + src={resultImageUrl} + alt="Detected Objects" + className="img-fluid" + onClick={handleImageClick} + style={{ cursor: 'pointer' }} + /> <h3 className="mt-4">Misplaced Objects</h3> <ul className="list-group"> {misplacedObjects.map((obj, index) => ( @@ -95,6 +124,20 @@ const NormalDetectionPage = () => { </div> </div> </div> + {/* Modal for full-size image */} + <Modal show={showModal} onHide={handleCloseModal} size="xl" centered> + <Modal.Header closeButton> + <Modal.Title>Full-Size Image</Modal.Title> + </Modal.Header> + <Modal.Body style={{ padding: '20px', textAlign: 'center' }}> + <img src={resultImageUrl} alt="Full Size Detected Objects" className="img-fluid" style={{ maxWidth: '100%' }} /> + </Modal.Body> + <Modal.Footer> + <Button variant="secondary" onClick={handleCloseModal}> + Close + </Button> + </Modal.Footer> + </Modal> </div> ); };