From c957ca2d3d506a590b4b9c2260c002b645f76c1c Mon Sep 17 00:00:00 2001 From: jeafreezy Date: Mon, 23 Dec 2024 17:01:26 +0100 Subject: [PATCH] wip: continuous improvements --- frontend/.env.sample | 14 +- frontend/src/app/router.tsx | 17 +- frontend/src/app/routes/about.tsx | 4 +- frontend/src/app/routes/account/models.tsx | 5 +- frontend/src/app/routes/landing.tsx | 14 +- frontend/src/app/routes/learn.tsx | 7 +- .../src/app/routes/models/confirmation.tsx | 2 +- .../src/app/routes/models/model-details.tsx | 2 +- .../src/app/routes/models/models-list.tsx | 14 +- frontend/src/app/routes/protected-route.tsx | 2 +- frontend/src/assets/images/index.ts | 10 + frontend/src/assets/svgs/index.ts | 7 + frontend/src/components/errors/fallback.tsx | 3 +- frontend/src/components/errors/index.ts | 4 +- .../components/errors/under-construction.tsx | 3 +- .../landing/about-fair/about-fair.tsx | 7 +- .../landing/core-features/core-features.tsx | 4 +- .../landing/core-values/core-values.tsx | 8 +- frontend/src/components/landing/cta/cta.tsx | 7 +- .../src/components/landing/header/header.tsx | 4 +- .../src/components/landing/header/index.ts | 2 +- frontend/src/components/landing/index.ts | 15 +- frontend/src/components/landing/kpi/kpi.tsx | 3 +- .../components/landing/tagline/tagline.tsx | 3 +- .../{ui => layout}/footer/footer.tsx | 5 +- .../src/components/layout/footer/index.ts | 1 + frontend/src/components/layout/index.ts | 2 + .../src/components/layout/navbar/index.ts | 3 + .../{ui => layout}/navbar/nav-logo.tsx | 6 +- .../{ui => layout}/navbar/navbar.module.css | 0 .../src/components/layout/navbar/navbar.tsx | 139 +++++++ .../{ui => layout}/navbar/user-profile.tsx | 6 +- frontend/src/components/layouts/index.ts | 1 - .../components/map/setups/setup-maplibre.ts | 25 +- .../shared/fair-process/fair-process.tsx | 4 +- .../components/shared/faqs/faqs.module.css | 7 - frontend/src/components/shared/index.ts | 6 +- frontend/src/components/shared/pagination.tsx | 4 +- .../{section-header => }/section-header.tsx | 0 .../header.module.css | 3 + .../{header => static-page-header}/header.tsx | 2 +- frontend/src/components/ui/footer/index.ts | 1 - frontend/src/components/ui/icons/index.ts | 1 + .../ui/icons/no-training-area-icon.tsx | 36 ++ frontend/src/components/ui/navbar/index.ts | 3 - frontend/src/components/ui/navbar/navbar.tsx | 12 +- frontend/src/config/env.ts | 17 + frontend/src/enums/index.ts | 1 + frontend/src/enums/training-area.ts | 5 + .../features/model-creation/api/factory.ts | 10 + .../model-creation/api/get-trainings.ts | 13 + .../components/progress-bar.tsx | 21 +- .../training-area/training-area-item.tsx | 389 +++++++++++------- .../training-area/training-area-list.tsx | 43 +- .../model-creation/hooks/use-polling.ts | 69 ++++ .../hooks/use-training-areas.ts | 14 +- .../features/models/api/update-trainings.ts | 2 +- .../dialogs/training-settings-dialog.tsx | 2 +- .../models/components/layout-toggle.tsx | 2 +- .../features/models/components/map-toggle.tsx | 2 +- .../models/components/maps/models-map.tsx | 4 +- .../components/maps/training-area-map.tsx | 10 +- .../features/models/components/model-card.tsx | 2 +- .../models/components/model-details-popup.tsx | 2 +- .../components/training-history-table.tsx | 225 +++++----- .../src/features/models/hooks/use-models.ts | 4 +- .../start-mapping/components/header.tsx | 2 +- frontend/src/hooks/use-map-instance.ts | 11 +- frontend/src/hooks/use-scroll-to-element.ts | 2 +- frontend/src/layouts/index.ts | 2 + .../layouts/model-forms-layout.tsx | 79 ++-- .../{components => }/layouts/root-layout.tsx | 10 +- ...jsonToOsmPolygons.ts => geojson-to-osm.ts} | 0 frontend/src/lib/index.ts | 1 + frontend/src/services/api-routes.ts | 20 +- frontend/src/styles/index.css | 29 +- frontend/src/utils/constants.ts | 14 + frontend/src/utils/general-utils.ts | 2 +- 78 files changed, 963 insertions(+), 474 deletions(-) create mode 100644 frontend/src/assets/images/index.ts create mode 100644 frontend/src/assets/svgs/index.ts rename frontend/src/components/{ui => layout}/footer/footer.tsx (97%) create mode 100644 frontend/src/components/layout/footer/index.ts create mode 100644 frontend/src/components/layout/index.ts create mode 100644 frontend/src/components/layout/navbar/index.ts rename frontend/src/components/{ui => layout}/navbar/nav-logo.tsx (86%) rename frontend/src/components/{ui => layout}/navbar/navbar.module.css (100%) create mode 100644 frontend/src/components/layout/navbar/navbar.tsx rename frontend/src/components/{ui => layout}/navbar/user-profile.tsx (91%) delete mode 100644 frontend/src/components/layouts/index.ts rename frontend/src/components/shared/{section-header => }/section-header.tsx (100%) rename frontend/src/components/shared/{header => static-page-header}/header.module.css (52%) rename frontend/src/components/shared/{header => static-page-header}/header.tsx (85%) delete mode 100644 frontend/src/components/ui/footer/index.ts create mode 100644 frontend/src/components/ui/icons/no-training-area-icon.tsx delete mode 100644 frontend/src/components/ui/navbar/index.ts create mode 100644 frontend/src/enums/training-area.ts create mode 100644 frontend/src/features/model-creation/hooks/use-polling.ts create mode 100644 frontend/src/layouts/index.ts rename frontend/src/{components => }/layouts/model-forms-layout.tsx (78%) rename frontend/src/{components => }/layouts/root-layout.tsx (80%) rename frontend/src/lib/{geojsonToOsmPolygons.ts => geojson-to-osm.ts} (100%) create mode 100644 frontend/src/lib/index.ts diff --git a/frontend/.env.sample b/frontend/.env.sample index 75862b77..2b03dbcb 100644 --- a/frontend/.env.sample +++ b/frontend/.env.sample @@ -114,4 +114,16 @@ VITE_TRAINING_AREAS_AOI_LABELS_OUTLINE_COLOR = "#D73434" # The remote url to JOSM. # Data type: String (e.g., "http://127.0.0.1:8111/"). # Default value: http://127.0.0.1:8111/. -VITE_JOSM_REMOTE_URL = "http://127.0.0.1:8111/" \ No newline at end of file +VITE_JOSM_REMOTE_URL = "http://127.0.0.1:8111/" + + +# The time to poll the backend for the status of the AOI training labels fetching, in milliseconds (ms). +# Data type: Positive Integer (e.g., 900). +# Default value: 5000 milliseconds (5 seconds). +VITE_TRAINING_AREA_LABELS_FETCH_POOLING_INTERVAL_MS = 5000 + + +# The time to poll the backend for the status of the OSM last updated time, in milliseconds (ms). +# Data type: Positive Integer (e.g., 900). +# Default value: 10000 milliseconds (10 seconds). +VITE_OSM_LAST_UPDATED_POOLING_INTERVAL_MS = 10000 \ No newline at end of file diff --git a/frontend/src/app/router.tsx b/frontend/src/app/router.tsx index f464f707..92c5efa8 100644 --- a/frontend/src/app/router.tsx +++ b/frontend/src/app/router.tsx @@ -1,13 +1,12 @@ -import { RootLayout } from "@/components/layouts"; import { APPLICATION_ROUTES } from "@/utils"; import { Navigate, RouterProvider, createBrowserRouter, } from "react-router-dom"; -import { ProtectedPage } from "@/app/routes/protected-route"; +import { ProtectedRoute } from "@/app/routes/protected-route"; import { MainErrorFallback } from "@/components/errors"; -import ModelFormsLayout from "@/components/layouts/model-forms-layout"; +import { ModelFormsLayout, RootLayout } from "@/layouts"; const router = createBrowserRouter([ { @@ -92,9 +91,9 @@ const router = createBrowserRouter([ */ { element: ( - + - + ), children: [ /** @@ -255,9 +254,9 @@ const router = createBrowserRouter([ ); return { Component: () => ( - + - + ), }; }, @@ -278,9 +277,9 @@ const router = createBrowserRouter([ ); return { Component: () => ( - + - + ), }; }, diff --git a/frontend/src/app/routes/about.tsx b/frontend/src/app/routes/about.tsx index 2898ad9a..6530ca48 100644 --- a/frontend/src/app/routes/about.tsx +++ b/frontend/src/app/routes/about.tsx @@ -1,9 +1,9 @@ import { Header } from "@/components/shared"; import { Image } from "@/components/ui/image"; -import HOTTeamLandscape from "@/assets/images/hot_team_landscape.png"; import { Head } from "@/components/seo"; -import AIIcon from "@/assets/svgs/fair_ai_icon.svg"; import { aboutPageContent } from "@/constants"; +import { HOTTeamLandscape } from "@/assets/images"; +import { AIIcon } from "@/assets/svgs"; export const AboutPage = () => { return ( diff --git a/frontend/src/app/routes/account/models.tsx b/frontend/src/app/routes/account/models.tsx index cafd222d..8206295b 100644 --- a/frontend/src/app/routes/account/models.tsx +++ b/frontend/src/app/routes/account/models.tsx @@ -1,6 +1,6 @@ -import Pagination, { PAGE_LIMIT } from "@/components/shared/pagination"; +import { Pagination, } from "@/components/shared"; import { Head } from "@/components/seo"; -import { LayoutView } from "@/enums/models"; +import { LayoutView } from "@/enums"; import { LayoutToggle, PageHeader } from "@/features/models/components"; import { MobileModelFiltersDialog } from "@/features/models/components/dialogs"; import { @@ -24,6 +24,7 @@ import ModelNotFound from "@/features/models/components/model-not-found"; import { SEARCH_PARAMS } from "@/app/routes/models/models-list"; import { useAuth } from "@/app/providers/auth-provider"; import { modelPagesContent } from "@/constants"; +import { PAGE_LIMIT } from "@/components/shared"; export const UserModelsPage = () => { const { isOpened, openDialog, closeDialog } = useDialog(); diff --git a/frontend/src/app/routes/landing.tsx b/frontend/src/app/routes/landing.tsx index f1dab738..134671b1 100644 --- a/frontend/src/app/routes/landing.tsx +++ b/frontend/src/app/routes/landing.tsx @@ -1,12 +1,6 @@ -import { Header } from "@/components/landing/header"; -import WhatIsFAIR from "@/components/landing/about-fair/about-fair"; -import CoreFeatures from "@/components/landing/core-features/core-features"; -import Corevalues from "@/components/landing/core-values/core-values"; -import CallToAction from "@/components/landing/cta/cta"; -import TheFAIRProcess from "@/components/shared/fair-process/fair-process"; import { FAQs } from "@/components/shared"; -import Kpi from "@/components/landing/kpi/kpi"; -import TaglineBanner from "@/components/landing/tagline/tagline"; +import { Header, Kpi, TaglineBanner, TheFAIRProcess, CallToAction, Corevalues, CoreFeatures, WhatIsFAIR } from "@/components/landing"; + import { Head } from "@/components/seo"; export const LandingPage = () => { @@ -19,7 +13,9 @@ export const LandingPage = () => { - +
+ +
diff --git a/frontend/src/app/routes/learn.tsx b/frontend/src/app/routes/learn.tsx index 32e518d8..356cc43e 100644 --- a/frontend/src/app/routes/learn.tsx +++ b/frontend/src/app/routes/learn.tsx @@ -1,16 +1,17 @@ import { TheFAIRProcess } from "@/components/landing"; import { Header, SectionHeader } from "@/components/shared"; import { Image } from "@/components/ui/image"; -import fAIrValues from "@/assets/svgs/fair_values.svg"; + import { ExternalLinkIcon, YouTubePlayCircleIcon } from "@/components/ui/icons"; import { Button } from "@/components/ui/button"; import { Link } from "@/components/ui/link"; import { SHOELACE_SIZES } from "@/enums"; import { Head } from "@/components/seo"; import { useState } from "react"; -import VideoPlaceholderImage from "@/assets/images/header_bg.jpg"; import { learnPageContent } from "@/constants"; import { TGuide, TVideo } from "@/types"; +import { JumbotronBackgroundImage } from "@/assets/images"; +import { fAIrValues } from "@/assets/svgs"; export const LearnPage = () => { return ( @@ -118,7 +119,7 @@ const VideoCard = ({ video }: { video: TVideo }) => {
{video.title} { const { id } = useParams<{ id: string }>(); diff --git a/frontend/src/app/routes/models/models-list.tsx b/frontend/src/app/routes/models/models-list.tsx index 76b7a3d2..0e932e43 100644 --- a/frontend/src/app/routes/models/models-list.tsx +++ b/frontend/src/app/routes/models/models-list.tsx @@ -20,7 +20,7 @@ import { OrderingFilter, SearchFilter, } from "@/features/models/components/filters"; -import Pagination, { PAGE_LIMIT } from "@/components/shared/pagination"; +import { Pagination, PAGE_LIMIT } from "@/components/shared"; import { APP_CONTENT } from "@/utils"; import { PageHeader } from "@/features/models/components/"; import { FeatureCollection } from "@/types"; @@ -28,7 +28,7 @@ import ModelNotFound from "@/features/models/components/model-not-found"; import { useDialog } from "@/hooks/use-dialog"; import { MobileModelFiltersDialog } from "@/features/models/components/dialogs"; import { Head } from "@/components/seo"; -import { LayoutView } from "@/enums/models"; +import { LayoutView } from "@/enums"; import { useScrollToElement, useScrollToTop, @@ -92,7 +92,7 @@ export const ModelsPage = () => { if (mapViewIsActive) { return (
@@ -102,7 +102,7 @@ export const ModelsPage = () => { isError={isError} />
-
+
{modelsMapDataIsPending || modelsMapDataIsError ? (
) : ( @@ -149,8 +149,8 @@ export const ModelsPage = () => {
{/* Filters */} -
-
+
+
@@ -195,7 +195,7 @@ export const ModelsPage = () => { {isPending ? (
) : ( -
+

{data?.count}{" "} diff --git a/frontend/src/app/routes/protected-route.tsx b/frontend/src/app/routes/protected-route.tsx index 48cb6522..2522c498 100644 --- a/frontend/src/app/routes/protected-route.tsx +++ b/frontend/src/app/routes/protected-route.tsx @@ -9,7 +9,7 @@ type ProtectedRouteProps = { children: React.ReactNode; }; -export const ProtectedPage: React.FC = ({ children }) => { +export const ProtectedRoute: React.FC = ({ children }) => { const { isAuthenticated } = useAuth(); const { handleLogin, loading } = useLogin(); diff --git a/frontend/src/assets/images/index.ts b/frontend/src/assets/images/index.ts new file mode 100644 index 00000000..ab6b9253 --- /dev/null +++ b/frontend/src/assets/images/index.ts @@ -0,0 +1,10 @@ +export { default as JumbotronBackgroundImage } from "@/assets/images/header_bg.jpg"; +export { default as CreativeCommonsBadge } from "@/assets/images/cc_by_badge.png"; +export { default as HOTTeamTwo } from "@/assets/images/hot_team_2.jpg"; +export { default as HOTTeamLandscape } from "@/assets/images/hot_team_landscape.png"; +export { default as HOTTeam } from "@/assets/images/hot_team.jpg"; +export { default as MapMarkerIcon } from "@/assets/images/map_marker.png"; +export { default as MapathonOngoing } from "@/assets/images/mapathon_ongoing.jpg"; +export { default as ModelFormConfirmation } from "@/assets/images/model_creation_success.png"; +export { default as FairModelPlaceholderImage } from "@/assets/images/model_placeholder_image.png"; +export { default as TrainingInProgressImage } from "@/assets/images/training_in_progress.png"; \ No newline at end of file diff --git a/frontend/src/assets/svgs/index.ts b/frontend/src/assets/svgs/index.ts new file mode 100644 index 00000000..19c871e2 --- /dev/null +++ b/frontend/src/assets/svgs/index.ts @@ -0,0 +1,7 @@ +export { default as DashedLineConnector } from "@/assets/svgs/dashed_line.svg"; +export { default as AIIcon } from "@/assets/svgs/fair_ai_icon.svg"; +export { default as fAIrValues } from "@/assets/svgs/fair_values.svg"; +export { default as HamburgerIcon } from "@/assets/svgs/hamburger_icon.svg"; +export { default as HOTFairLogo } from "@/assets/svgs/hot_fair_logo.svg"; +export { default as JOSMLogo } from "@/assets/svgs/josm_logo.svg"; +export { default as OSMLogo } from "@/assets/svgs/osm_logo.svg"; \ No newline at end of file diff --git a/frontend/src/components/errors/fallback.tsx b/frontend/src/components/errors/fallback.tsx index d2a767ac..47d20eae 100644 --- a/frontend/src/components/errors/fallback.tsx +++ b/frontend/src/components/errors/fallback.tsx @@ -1,7 +1,7 @@ import { Button } from "@/components/ui/button"; import { APP_CONTENT } from "@/utils"; -const MainErrorFallback = () => { +export const MainErrorFallback = () => { return ( <>

@@ -23,4 +23,3 @@ const MainErrorFallback = () => { ); }; -export default MainErrorFallback; diff --git a/frontend/src/components/errors/index.ts b/frontend/src/components/errors/index.ts index d674f9cd..5bae486d 100644 --- a/frontend/src/components/errors/index.ts +++ b/frontend/src/components/errors/index.ts @@ -1,2 +1,2 @@ -export { default as MainErrorFallback } from "./fallback"; -export { default as PageUnderConstruction } from "./under-construction"; +export { MainErrorFallback } from "./fallback"; +export { PageUnderConstruction } from "./under-construction"; diff --git a/frontend/src/components/errors/under-construction.tsx b/frontend/src/components/errors/under-construction.tsx index 85caf879..fc99ea2e 100644 --- a/frontend/src/components/errors/under-construction.tsx +++ b/frontend/src/components/errors/under-construction.tsx @@ -1,7 +1,7 @@ import { Button } from "@/components/ui/button"; import { APP_CONTENT } from "@/utils"; -const PageUnderConstruction = () => { +export const PageUnderConstruction = () => { return (
@@ -21,4 +21,3 @@ const PageUnderConstruction = () => { ); }; -export default PageUnderConstruction; diff --git a/frontend/src/components/landing/about-fair/about-fair.tsx b/frontend/src/components/landing/about-fair/about-fair.tsx index 6ccb0dc5..bc475696 100644 --- a/frontend/src/components/landing/about-fair/about-fair.tsx +++ b/frontend/src/components/landing/about-fair/about-fair.tsx @@ -1,9 +1,10 @@ -import AIIcon from "@/assets/svgs/fair_ai_icon.svg"; + import styles from "./about-fair.module.css"; import { APP_CONTENT } from "@/utils/content"; import { Image } from "@/components/ui/image"; +import { AIIcon } from "@/assets/svgs"; -const WhatIsFAIR = () => { +export const WhatIsFAIR = () => { return (
@@ -18,4 +19,4 @@ const WhatIsFAIR = () => { ); }; -export default WhatIsFAIR; + diff --git a/frontend/src/components/landing/core-features/core-features.tsx b/frontend/src/components/landing/core-features/core-features.tsx index e1156faf..1abc8763 100644 --- a/frontend/src/components/landing/core-features/core-features.tsx +++ b/frontend/src/components/landing/core-features/core-features.tsx @@ -22,7 +22,7 @@ const coreFeatures: TCoreFeatures[] = [ }, ]; -const CoreFeatures = () => { +export const CoreFeatures = () => { return (
{coreFeatures.map((feature, id) => ( @@ -36,5 +36,3 @@ const CoreFeatures = () => {
); }; - -export default CoreFeatures; diff --git a/frontend/src/components/landing/core-values/core-values.tsx b/frontend/src/components/landing/core-values/core-values.tsx index ac7e0a46..d6068b99 100644 --- a/frontend/src/components/landing/core-values/core-values.tsx +++ b/frontend/src/components/landing/core-values/core-values.tsx @@ -1,11 +1,10 @@ import styles from "./core-values.module.css"; -import HOTTeam from "@/assets/images/hot_team.jpg"; -import MapathonOngoing from "@/assets/images/mapathon_ongoing.jpg"; import { APP_CONTENT } from "@/utils/content"; -import DashedLineConnector from "@/assets/svgs/dashed_line.svg"; import { Image } from "@/components/ui/image"; +import { HOTTeam, MapathonOngoing } from "@/assets/images"; +import { DashedLineConnector } from "@/assets/svgs"; -const Corevalues = () => { +export const Corevalues = () => { return (
@@ -110,4 +109,3 @@ const Corevalues = () => { ); }; -export default Corevalues; diff --git a/frontend/src/components/landing/cta/cta.tsx b/frontend/src/components/landing/cta/cta.tsx index 67d5fd40..919ec53d 100644 --- a/frontend/src/components/landing/cta/cta.tsx +++ b/frontend/src/components/landing/cta/cta.tsx @@ -1,11 +1,11 @@ import { Button } from "@/components/ui/button/"; -import HOTTeam from "@/assets/images/hot_team_2.jpg"; import styles from "./cta.module.css"; import { APP_CONTENT } from "@/utils"; import { Image } from "@/components/ui/image"; import { Link } from "@/components/ui/link"; +import { HOTTeamTwo } from "@/assets/images"; -const CallToAction = () => { +export const CallToAction = () => { return (
@@ -28,7 +28,7 @@ const CallToAction = () => {
{APP_CONTENT.homepage.callToAction.ctaButton} @@ -40,4 +40,3 @@ const CallToAction = () => { ); }; -export default CallToAction; diff --git a/frontend/src/components/landing/header/header.tsx b/frontend/src/components/landing/header/header.tsx index f51617e5..21a72203 100644 --- a/frontend/src/components/landing/header/header.tsx +++ b/frontend/src/components/landing/header/header.tsx @@ -6,7 +6,7 @@ import { Image } from "@/components/ui/image"; import { Link } from "@/components/ui/link"; import { APPLICATION_ROUTES } from "@/utils"; -const Header = () => { +export const Header = () => { return (
@@ -22,7 +22,6 @@ const Header = () => { nativeAnchor={false} > @@ -50,4 +49,3 @@ const Header = () => { ); }; -export default Header; diff --git a/frontend/src/components/landing/header/index.ts b/frontend/src/components/landing/header/index.ts index 5ed4e585..924cc88d 100644 --- a/frontend/src/components/landing/header/index.ts +++ b/frontend/src/components/landing/header/index.ts @@ -1 +1 @@ -export { default as Header } from "./header"; +export { Header } from "./header"; diff --git a/frontend/src/components/landing/index.ts b/frontend/src/components/landing/index.ts index c2c1f6e5..8ebaf391 100644 --- a/frontend/src/components/landing/index.ts +++ b/frontend/src/components/landing/index.ts @@ -1,7 +1,8 @@ -export { default as Kpi } from "./kpi/kpi"; -export { default as WhatIsFAIR } from "./about-fair/about-fair"; -export { default as TheFAIRProcess } from "../shared/fair-process/fair-process"; -export { default as CoreFeatures } from "./core-features/core-features"; -export { default as Corevalues } from "./core-values/core-values"; -export { default as TaglineBanner } from "./tagline/tagline"; -export { default as CallToAction } from "./cta/cta"; +export { Kpi } from "./kpi/kpi"; +export { WhatIsFAIR } from "./about-fair/about-fair"; +export { TheFAIRProcess } from "../shared/fair-process/fair-process"; +export { CoreFeatures } from "./core-features/core-features"; +export { Corevalues } from "./core-values/core-values"; +export { TaglineBanner } from "./tagline/tagline"; +export { CallToAction } from "./cta/cta"; +export * from './header' \ No newline at end of file diff --git a/frontend/src/components/landing/kpi/kpi.tsx b/frontend/src/components/landing/kpi/kpi.tsx index 617a44da..8cedf868 100644 --- a/frontend/src/components/landing/kpi/kpi.tsx +++ b/frontend/src/components/landing/kpi/kpi.tsx @@ -20,7 +20,7 @@ const fetchKPIStats = async (): Promise => { return data; }; -const Kpi = () => { +export const Kpi = () => { const { data, isLoading, isError, error } = useQuery({ queryKey: ["kpis"], queryFn: fetchKPIStats, @@ -71,4 +71,3 @@ const Kpi = () => { ); }; -export default Kpi; diff --git a/frontend/src/components/landing/tagline/tagline.tsx b/frontend/src/components/landing/tagline/tagline.tsx index a52a2dc6..f16505a4 100644 --- a/frontend/src/components/landing/tagline/tagline.tsx +++ b/frontend/src/components/landing/tagline/tagline.tsx @@ -1,7 +1,7 @@ import { APP_CONTENT } from "@/utils/content"; import styles from "./tagline.module.css"; -const TaglineBanner = () => { +export const TaglineBanner = () => { return (

@@ -17,4 +17,3 @@ const TaglineBanner = () => { ); }; -export default TaglineBanner; diff --git a/frontend/src/components/ui/footer/footer.tsx b/frontend/src/components/layout/footer/footer.tsx similarity index 97% rename from frontend/src/components/ui/footer/footer.tsx rename to frontend/src/components/layout/footer/footer.tsx index 31b532de..1539edb9 100644 --- a/frontend/src/components/ui/footer/footer.tsx +++ b/frontend/src/components/layout/footer/footer.tsx @@ -1,4 +1,4 @@ -import CreativeCommonsBadge from "@/assets/images/cc_by_badge.png"; +import { CreativeCommonsBadge } from "@/assets/images"; import FacebookLogo from "@/assets/svgs/socials/facebook_logo.svg"; import GitHubLogo from "@/assets/svgs/socials/github_logo.svg"; import XLogo from "@/assets/svgs/socials/x_logo.svg"; @@ -35,7 +35,7 @@ const socials = [ logo: InstagramLogo, }, ]; -const Footer = () => { +export const Footer = () => { return (

); }; -export default RootLayout; + diff --git a/frontend/src/lib/geojsonToOsmPolygons.ts b/frontend/src/lib/geojson-to-osm.ts similarity index 100% rename from frontend/src/lib/geojsonToOsmPolygons.ts rename to frontend/src/lib/geojson-to-osm.ts diff --git a/frontend/src/lib/index.ts b/frontend/src/lib/index.ts new file mode 100644 index 00000000..d3da8363 --- /dev/null +++ b/frontend/src/lib/index.ts @@ -0,0 +1 @@ +export * from './geojson-to-osm' \ No newline at end of file diff --git a/frontend/src/services/api-routes.ts b/frontend/src/services/api-routes.ts index 14cfc8c2..3b3cc20a 100644 --- a/frontend/src/services/api-routes.ts +++ b/frontend/src/services/api-routes.ts @@ -3,11 +3,13 @@ */ export const API_ENDPOINTS = { // Auth + LOGIN: "auth/login/", AUTH_CALLBACK: "auth/callback/", USER: "auth/me/", // OSM Database + GET_OSM_DATABASE_LAST_UPDATED: "https://api-prod.raw-data.hotosm.org/v1/status/", @@ -23,6 +25,7 @@ export const API_ENDPOINTS = { DELETE_APPROVED_PREDICTION: (id: number) => `approved-prediction/${id}/`, // KPIs + GET_KPI_STATS: "kpi/stats/ ", // GeoJSON to OSM @@ -34,36 +37,39 @@ export const API_ENDPOINTS = { GET_BANNER: "banner", // Models + GET_MODELS: "model/", CREATE_MODEL: "model/", UPDATE_MODEL: (modelId: string) => `model/${modelId}/`, GET_MODEL_DETAILS: (id: string) => `model/${id}`, GET_MODELS_CENTROIDS: "models/centroid", - // Trainings + // Training Areas & Datasets GET_TRAINING_DETAILS: (id: number) => `training/${id}`, GET_TRAINING_DATASETS: (searchQuery: string, ordering: string) => `dataset/?search=${searchQuery}&ordering=${ordering}`, GET_TRAINING_DATASET: (id: number) => `dataset/${id}`, - CREATE_TRAINING_DATASET: "dataset/", GET_TRAINING_AREA_GPX: (aoiId: number) => `aoi/gpx/${aoiId}`, - CREATE_TRAINING_AREA: "aoi/", GET_TRAINING_AREA_LABELS_FROM_OSM: (aoiId: number) => `label/osm/fetch/${aoiId}/`, - CREATE_TRAINING_AREA_LABELS: `label/`, GET_TRAINING_AREA_LABELS: (aoiId: number) => `label/?aoi=${aoiId}`, GET_TRAINING_DATASET_LABELS: (aoiDatasetId: number, bbox: string) => `label/?aoi__dataset=${aoiDatasetId}&in__bbox=${bbox}/`, - CREATE_TRAINING_REQUEST: "training/", - DELETE_TRAINING_AREA: (id: number) => `aoi/${id}/`, GET_TRAINING_AREAS: (datasetId: number, offset: number, limit: number) => `aoi/?dataset=${datasetId}&offset=${offset}&limit=${limit}`, + GET_TRAINING_AREA: (aoiId: number) => `aoi/${aoiId}/`, GET_TRAINING_STATUS: (taskId: string) => `training/status/${taskId}`, - UPDATE_TRAINING: (id: number) => `training/publish/${id}/`, GET_MODEL_TRAINING_HISTORY: (id: string) => `training/?model=${id}`, GET_TRAINING_FEEDBACKS: (trainingId: number) => `feedback/?training=${trainingId}`, + CREATE_TRAINING_AREA_LABELS: `label/`, + CREATE_TRAINING_DATASET: "dataset/", + CREATE_TRAINING_AREA: "aoi/", + CREATE_TRAINING_REQUEST: "training/", + UPDATE_TRAINING: (id: number) => `training/publish/${id}/`, + DELETE_TRAINING_AREA: (id: number) => `aoi/${id}/`, + // Workspace diff --git a/frontend/src/styles/index.css b/frontend/src/styles/index.css index f465f62e..cbcf8bf5 100644 --- a/frontend/src/styles/index.css +++ b/frontend/src/styles/index.css @@ -174,26 +174,47 @@ sl-alert.success::part(base) { /* General scrollbar styles */ ::-webkit-scrollbar { - width: var(--scrollbar-width); + width: var(--scrollbar-width); height: 5px; + opacity: 0; + transition: opacity 0.2s ease; +} + +::-webkit-scrollbar:hover { + opacity: 1; } /* Scrollbar track */ ::-webkit-scrollbar-track { - background: var(--scrollbar-track-bg); + background: var(--scrollbar-track-bg, #f1f1f1); } /* Scrollbar thumb */ ::-webkit-scrollbar-thumb { - background: var(--scrollbar-thumb-bg); + background: var(--scrollbar-thumb-bg, #888); border-radius: 5px; } /* Scrollbar thumb on hover */ ::-webkit-scrollbar-thumb:hover { - background: var(--scrollbar-thumb-hover-bg); + background: var(--scrollbar-thumb-hover-bg, #555); +} + +/* Hide scrollbar by default for specific elements */ +.scrollable::-webkit-scrollbar { + width: var(--scrollbar-width); + display: none; } +/* Show scrollbar when hovering over the scrollable container */ +.scrollable:hover::-webkit-scrollbar { + display: block; + transition: opacity 1.3s ease, display 1.3s ease; +} + +/* General scrollbar ends */ + + /* Popup customization starts */ .maplibregl-popup-content { @apply !rounded-[12px] !flex !flex-col !gap-y-4 !p-0; diff --git a/frontend/src/utils/constants.ts b/frontend/src/utils/constants.ts index 5f40ae1b..5f4ba4d3 100644 --- a/frontend/src/utils/constants.ts +++ b/frontend/src/utils/constants.ts @@ -43,6 +43,7 @@ export const APPLICATION_ROUTES = { EDIT_MODEL_SUMMARY: `${MODELS_ROUTES.EDIT_MODEL_BASE}/${MODELS_ROUTES.MODEL_SUMMARY}`, // Model routes end + TRAINING_DATASETS: "/training-datasets", START_MAPPING_BASE: "/start-mapping/", START_MAPPING: "/start-mapping/:modelId", @@ -250,3 +251,16 @@ export const PREDICTION_API_FILE_EXTENSIONS = { * The remote url to JOSM. */ export const JOSM_REMOTE_URL = ENVS.JOSM_REMOTE_URL || "http://127.0.0.1:8111/"; + +/** + * The time to poll the backend for the status of the AOI training labels fetching, in milliseconds (ms). + * Defaults to 5000 ms (5 seconds). + */ +export const TRAINING_AREA_LABELS_FETCH_POOLING_TIME_MS = ENVS.TRAINING_AREA_LABELS_FETCH_POOLING_INTERVAL_MS || 5000 + +/** +* The time to poll the backend for the status of the OSM last updated time, in milliseconds (ms). +* Data type: Positive Integer (e.g., 900). +* Default value: 10000 milliseconds (10 seconds). +*/ +export const OSM_LAST_UPDATED_POOLING_INTERVAL_MS = ENVS.OSM_LAST_UPDATED_POOLING_INTERVAL_MS || 10000 \ No newline at end of file diff --git a/frontend/src/utils/general-utils.ts b/frontend/src/utils/general-utils.ts index 0115596b..5beedd67 100644 --- a/frontend/src/utils/general-utils.ts +++ b/frontend/src/utils/general-utils.ts @@ -10,7 +10,7 @@ import { } from "@/utils"; import { useToastNotification } from "@/hooks/use-toast-notification"; import { TOAST_NOTIFICATIONS } from "@/constants"; -import { geojsonToOsmPolygons } from "@/lib/geojsonToOsmPolygons"; +import { geojsonToOsmPolygons } from "@/lib"; import bbox from "@turf/bbox"; /**