From bf0bf3c144fc29cb3c0ae65c4f1085b6ec7a3e81 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 12:38:30 +0545 Subject: [PATCH 01/27] feat(osm-logo): logo add to mapper --- src/mapper/src/assets/images/osm-logo.png | Bin 0 -> 8804 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/mapper/src/assets/images/osm-logo.png diff --git a/src/mapper/src/assets/images/osm-logo.png b/src/mapper/src/assets/images/osm-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bd23812c89154431a759b808ee856812692508c4 GIT binary patch literal 8804 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 aqW=r~uM@_eW6L7|0000 Date: Wed, 20 Nov 2024 12:39:40 +0545 Subject: [PATCH 02/27] feat(login): login store add --- src/mapper/src/store/login.svelte.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/mapper/src/store/login.svelte.ts diff --git a/src/mapper/src/store/login.svelte.ts b/src/mapper/src/store/login.svelte.ts new file mode 100644 index 0000000000..7e9e67c0a7 --- /dev/null +++ b/src/mapper/src/store/login.svelte.ts @@ -0,0 +1,23 @@ +type authDetailsType = { + id: number; + username: string; + profile_img: string; + role: string; + project_roles: string | null; + orgs_managed: number[]; +}; + +let authDetails: authDetailsType | null = null; + +function getLoginStore() { + return { + get getAuthDetails() { + return authDetails; + }, + setAuthDetails: (authData: authDetailsType) => { + authDetails = authData; + }, + }; +} + +export { getLoginStore }; From 36db3ea25e7937533e6b73692916c4bd44363222 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 12:40:19 +0545 Subject: [PATCH 03/27] fix(layer-switcher): close layer-switcher by default --- src/mapper/src/lib/components/map/layer-switcher.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mapper/src/lib/components/map/layer-switcher.svelte b/src/mapper/src/lib/components/map/layer-switcher.svelte index 77f0e2e0c3..dd8276f89b 100644 --- a/src/mapper/src/lib/components/map/layer-switcher.svelte +++ b/src/mapper/src/lib/components/map/layer-switcher.svelte @@ -37,7 +37,7 @@ map = new Map({ let allStyles: MapLibreStylePlusMetadata[] | [] = $state([]); let selectedStyleUrl: string | undefined = $state(undefined); let isClosed = $state(true); - let isOpen = $state(true); + let isOpen = $state(false); $effect(() => { if (extraStyles.length > 0) { From 5c15753c01eeeef314e0a1ddfdbd896bee9f3022 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 13:11:11 +0545 Subject: [PATCH 04/27] feat(login): login dialog popup add --- src/mapper/src/lib/components/login.svelte | 128 +++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/mapper/src/lib/components/login.svelte diff --git a/src/mapper/src/lib/components/login.svelte b/src/mapper/src/lib/components/login.svelte new file mode 100644 index 0000000000..0e3eb7c0ec --- /dev/null +++ b/src/mapper/src/lib/components/login.svelte @@ -0,0 +1,128 @@ + + + { + toggleOpen(false); + }} + noHeader +> +
+
+

Sign In

+ toggleOpen(false)} + role="button" + tabindex="0" + onkeydown={(e: KeyboardEvent) => { + if (e.key === 'Enter') toggleOpen(false); + }} + > +
+
Select an account type to sign in
+
+ {#each loginOptions as option} +
handleSignIn(option.id)} + role="button" + onkeydown={(e: KeyboardEvent) => { + if (e.key === 'Enter') { + handleSignIn(option.id); + } + }} + tabindex="0" + class="option-card bg-[#F5F5F5] text-gray-700 p-3 rounded-md duration-300 hover:border-primaryRed hover:text-red-600 cursor-pointer text-sm flex items-start gap-3 group" + > +
+ {#if option?.image} + personal osm account + {:else} + + {/if} +
+
+
{option.name}
+
{option.description}
+
+
+ {/each} +
+
+
+ + From ee8c818a7257477c9c3188916ba7e83eefd3bbd4 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 13:12:30 +0545 Subject: [PATCH 05/27] fix(login): util functions add for login --- src/mapper/src/lib/utils/login.ts | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/mapper/src/lib/utils/login.ts diff --git a/src/mapper/src/lib/utils/login.ts b/src/mapper/src/lib/utils/login.ts new file mode 100644 index 0000000000..b79b30a4d7 --- /dev/null +++ b/src/mapper/src/lib/utils/login.ts @@ -0,0 +1,42 @@ +export const getUserDetailsFromApi = async () => { + const resp = await fetch(`${import.meta.env.VITE_API_URL}/auth/me`, { + credentials: 'include', + }); + + if (resp.status !== 200) { + return false; + } + + const apiUser = await resp.json(); + + if (!apiUser) return false; + + return apiUser; +}; + +export const osmLoginRedirect = async () => { + try { + const resp = await fetch(`${import.meta.env.VITE_API_URL}/auth/osm-login`); + const data = await resp.json(); + window.location = data.login_url; + } catch (error) {} +}; + +export const revokeCookie = async () => { + try { + const response = await fetch(`${import.meta.env.VITE_API_URL}/auth/logout`, { credentials: 'include' }); + if (!response.ok) { + console.error('/auth/logout endpoint did not return 200 response'); + } + } catch (error) { + throw error; + } +}; + +export const TemporaryLoginService: Function = async (url: string) => { + // Sets a cookie in the browser that is used for auth + await fetch(url, { credentials: 'include' }); + + const apiUser = await getUserDetailsFromApi(); + return apiUser; +}; From 37e1afb564c58d82300cf4a763cd73da2701d743 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 16:39:25 +0545 Subject: [PATCH 06/27] fix(login): store current path on localStorage --- src/mapper/src/lib/components/login.svelte | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mapper/src/lib/components/login.svelte b/src/mapper/src/lib/components/login.svelte index 0e3eb7c0ec..00a0e7faeb 100644 --- a/src/mapper/src/lib/components/login.svelte +++ b/src/mapper/src/lib/components/login.svelte @@ -39,6 +39,8 @@ const handleSignIn = async (selectedOption: string) => { if (selectedOption === 'osm_account') { + // store current url in local storage so that the user can be redirected to current page after login + localStorage.setItem('requestedPath', window.location.pathname); osmLoginRedirect(); } else { const userDetailResp = await TemporaryLoginService(`${import.meta.env.VITE_API_URL}/auth/temp-login`); From b0ee2bf9aef80135b2dd31f4e496f7e2a4ec3313 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 16:43:51 +0545 Subject: [PATCH 07/27] fix(osmAuth): if user request redirection to mapper frontend then treat as external url --- src/frontend/src/views/OsmAuth.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/views/OsmAuth.tsx b/src/frontend/src/views/OsmAuth.tsx index a6a7837638..21e6fa8527 100644 --- a/src/frontend/src/views/OsmAuth.tsx +++ b/src/frontend/src/views/OsmAuth.tsx @@ -43,8 +43,13 @@ function OsmAuth() { dispatch(LoginActions.setLoginModalOpen(false)); if (requestedPath) { - navigate(`${requestedPath}`); - localStorage.removeItem('requestedPath'); + if (requestedPath.includes('mapnow')) { + // redirect to mapper frontend (navigate doesn't work as it's on svelte) + window.location.href = `${window.location.origin}${requestedPath}`; + } else { + navigate(`${requestedPath}`); + localStorage.removeItem('requestedPath'); + } } }; loginRedirect(); From 7af73f8282687a1de55daf5c81f760d340c1c051 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 17:57:15 +0545 Subject: [PATCH 08/27] feat(logo): hot logo add --- src/mapper/src/assets/images/hot-logo-text.svg | 1 + src/mapper/src/assets/images/hot-logo.svg | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/mapper/src/assets/images/hot-logo-text.svg create mode 100644 src/mapper/src/assets/images/hot-logo.svg diff --git a/src/mapper/src/assets/images/hot-logo-text.svg b/src/mapper/src/assets/images/hot-logo-text.svg new file mode 100644 index 0000000000..35eaf88801 --- /dev/null +++ b/src/mapper/src/assets/images/hot-logo-text.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/mapper/src/assets/images/hot-logo.svg b/src/mapper/src/assets/images/hot-logo.svg new file mode 100644 index 0000000000..548554865d --- /dev/null +++ b/src/mapper/src/assets/images/hot-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file From bd07a722d5eaf64932bae410e203806b2ab4a65c Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 18:01:07 +0545 Subject: [PATCH 09/27] fix(header): header component ui slice --- src/mapper/src/lib/components/header.svelte | 43 +++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/mapper/src/lib/components/header.svelte diff --git a/src/mapper/src/lib/components/header.svelte b/src/mapper/src/lib/components/header.svelte new file mode 100644 index 0000000000..5e0322da47 --- /dev/null +++ b/src/mapper/src/lib/components/header.svelte @@ -0,0 +1,43 @@ + + +
+
+ hot-logo + hot-logo +
+
+ { + loginStore.toggleLoginModal(true); + }} + onkeydown={(e: KeyboardEvent) => { + if (e.key === 'Enter') { + loginStore.toggleLoginModal(true); + } + }} + role="button" + tabindex="0" + > + SIGN IN + + {}} + onkeydown={() => {}} + role="button" + tabindex="0" + > +
+
+ From 02aae8a03b75d32bf8f45431d45a9ed53293bb3e Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 18:03:15 +0545 Subject: [PATCH 10/27] feat(login): toggle modal state add --- src/mapper/src/store/login.svelte.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/mapper/src/store/login.svelte.ts b/src/mapper/src/store/login.svelte.ts index 7e9e67c0a7..50e73345cb 100644 --- a/src/mapper/src/store/login.svelte.ts +++ b/src/mapper/src/store/login.svelte.ts @@ -7,16 +7,23 @@ type authDetailsType = { orgs_managed: number[]; }; -let authDetails: authDetailsType | null = null; +let authDetails: authDetailsType | null = $state(null); +let isLoginModalOpen: boolean = $state(false); function getLoginStore() { return { get getAuthDetails() { return authDetails; }, + get isLoginModalOpen() { + return isLoginModalOpen; + }, setAuthDetails: (authData: authDetailsType) => { authDetails = authData; }, + toggleLoginModal: (status: boolean) => { + isLoginModalOpen = status; + }, }; } From 683f7371dcf4cfd8bc3c9e13e75b97ba0ca16b28 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 18:06:02 +0545 Subject: [PATCH 11/27] fix(layout): replace hot-header with custom header component --- src/mapper/src/routes/+layout.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mapper/src/routes/+layout.svelte b/src/mapper/src/routes/+layout.svelte index fed93165b1..075870ca92 100644 --- a/src/mapper/src/routes/+layout.svelte +++ b/src/mapper/src/routes/+layout.svelte @@ -3,6 +3,7 @@ import '@hotosm/ui/dist/hotosm-ui'; import { setBasePath } from '@hotosm/ui/dist/hotosm-ui'; import Toast from '$lib/components/toast.svelte'; + import Header from '$lib/components/header.svelte'; setBasePath('/mapnow'); @@ -10,7 +11,7 @@
- +
{@render children?.({ data })}
From 788f7e8c4d933565723e3431a748a0fff37aba61 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Wed, 20 Nov 2024 18:08:01 +0545 Subject: [PATCH 12/27] fix(login): replace modalOpen state on parent with stores --- src/mapper/src/lib/components/login.svelte | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/mapper/src/lib/components/login.svelte b/src/mapper/src/lib/components/login.svelte index 00a0e7faeb..4d49c46efc 100644 --- a/src/mapper/src/lib/components/login.svelte +++ b/src/mapper/src/lib/components/login.svelte @@ -33,7 +33,6 @@ ]; let dialogRef; - let { open, toggleOpen }: Props = $props(); const loginStore = getLoginStore(); const alertStore = getAlertStore(); @@ -67,9 +66,9 @@ { - toggleOpen(false); + loginStore.toggleLoginModal(false); }} noHeader > @@ -78,12 +77,12 @@

Sign In

toggleOpen(false)} + class="text-[1.5rem] text-gray-500 cursor-pointer" + onclick={() => loginStore.toggleLoginModal(false)} role="button" tabindex="0" onkeydown={(e: KeyboardEvent) => { - if (e.key === 'Enter') toggleOpen(false); + if (e.key === 'Enter') loginStore.toggleLoginModal(false); }} > From 67c3071c14e187f75704ad5292966a5b1a3004a2 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 10:20:02 +0545 Subject: [PATCH 13/27] fix(+layout): barlow font add to root --- src/mapper/src/routes/+layout.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mapper/src/routes/+layout.svelte b/src/mapper/src/routes/+layout.svelte index 075870ca92..07fd712614 100644 --- a/src/mapper/src/routes/+layout.svelte +++ b/src/mapper/src/routes/+layout.svelte @@ -10,7 +10,7 @@ let { data, children } = $props(); -
+
{@render children?.({ data })} From b35f8da3319e576ae2fe33b21362b475bcd92992 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 10:24:11 +0545 Subject: [PATCH 14/27] feat(header): display username and profile image if user logged in --- src/mapper/src/lib/components/header.svelte | 62 +++++++++++++++------ 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/src/mapper/src/lib/components/header.svelte b/src/mapper/src/lib/components/header.svelte index 5e0322da47..39fda8ea70 100644 --- a/src/mapper/src/lib/components/header.svelte +++ b/src/mapper/src/lib/components/header.svelte @@ -1,10 +1,18 @@
@@ -13,23 +21,45 @@ hot-logo
- { - loginStore.toggleLoginModal(true); - }} - onkeydown={(e: KeyboardEvent) => { - if (e.key === 'Enter') { + {#if loginStore?.getAuthDetails} +
+ {#if !loginStore?.getAuthDetails?.profile_img} + {}} + onkeydown={() => {}} + role="button" + tabindex="0" + > + {:else} + profile + {/if} +

{loginStore?.getAuthDetails?.username}

+
+ {:else} + { loginStore.toggleLoginModal(true); - } - }} - role="button" - tabindex="0" - > - SIGN IN - + }} + onkeydown={(e: KeyboardEvent) => { + if (e.key === 'Enter') { + loginStore.toggleLoginModal(true); + } + }} + role="button" + tabindex="0" + > + SIGN IN +
+ {/if} Date: Thu, 21 Nov 2024 13:10:18 +0545 Subject: [PATCH 15/27] fix(login): signOut add --- src/mapper/src/store/login.svelte.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mapper/src/store/login.svelte.ts b/src/mapper/src/store/login.svelte.ts index 50e73345cb..2d4b49636d 100644 --- a/src/mapper/src/store/login.svelte.ts +++ b/src/mapper/src/store/login.svelte.ts @@ -24,6 +24,10 @@ function getLoginStore() { toggleLoginModal: (status: boolean) => { isLoginModalOpen = status; }, + signOut: () => { + localStorage.removeItem('persist:login'); + authDetails = null; + }, }; } From 6201053909b3b3207f4524a272b57ca332610a4e Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 13:12:01 +0545 Subject: [PATCH 16/27] feat(drawerItems): drawer menu items add --- src/mapper/src/constants/drawerItems.ts | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/mapper/src/constants/drawerItems.ts diff --git a/src/mapper/src/constants/drawerItems.ts b/src/mapper/src/constants/drawerItems.ts new file mode 100644 index 0000000000..714ac2beca --- /dev/null +++ b/src/mapper/src/constants/drawerItems.ts @@ -0,0 +1,27 @@ +type drawerItemsType = { + name: string; + path: string; +}; + +export const drawerItems: drawerItemsType[] = [ + { + name: 'Explore Projects', + path: `${window.location.origin}`, + }, + { + name: 'Learn', + path: 'https://hotosm.github.io/fmtm', + }, + { + name: 'About', + path: 'https://docs.fmtm.dev/About/', + }, + { + name: 'Support', + path: 'https://github.com/hotosm/fmtm/issues/', + }, + { + name: 'Download Custom ODK Collect', + path: 'https://github.com/hotosm/odkcollect/releases/download/v2024.2.4-entity-select/ODK-Collect-v2024.2.4-FMTM.apk', + }, +]; From 7cd63ad89ddc47da9e885c796fe9934c36553b8b Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 13:12:40 +0545 Subject: [PATCH 17/27] feat(header): drawer comp add, signout func add --- src/mapper/src/lib/components/header.svelte | 53 ++++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/src/mapper/src/lib/components/header.svelte b/src/mapper/src/lib/components/header.svelte index 39fda8ea70..de77ac3c7f 100644 --- a/src/mapper/src/lib/components/header.svelte +++ b/src/mapper/src/lib/components/header.svelte @@ -4,8 +4,13 @@ import HotLogoText from '$assets/images/hot-logo-text.svg'; import Login from '$lib/components/login.svelte'; import { getLoginStore } from '$store/login.svelte.ts'; + import { drawerItems as menuItems } from '$constants/drawerItems.ts'; + import { revokeCookie } from '$lib/utils/login'; + import { getAlertStore } from '$store/common.svelte'; + let drawerRef: any = $state(); const loginStore = getLoginStore(); + const alertStore = getAlertStore(); onMount(() => { // retrieve persisted auth details from local storage and set auth details to store @@ -13,6 +18,16 @@ if (!persistedAuth) return; loginStore.setAuthDetails(JSON.parse(JSON.parse(persistedAuth).authDetails)); }); + + const handleSignOut = async () => { + try { + await revokeCookie(); + loginStore.signOut(); + window.location.href = window.location.origin; + } catch (error) { + alertStore.setAlert({ variant: 'danger', message: 'Sign Out Failed' }); + } + };
@@ -21,6 +36,7 @@ hot-logo
+ {#if loginStore?.getAuthDetails}
{#if !loginStore?.getAuthDetails?.profile_img} @@ -60,14 +76,47 @@ SIGN IN {/if} + + {}} - onkeydown={() => {}} + onclick={() => { + drawerRef.show(); + }} + onkeydown={() => { + drawerRef.show(); + }} role="button" tabindex="0" >
+ +
+ {#each menuItems as menu} + {menu.name} + {/each} + { + if (e.key === 'Enter') { + handleSignOut(); + } + }} + role="button" + tabindex="0" + > + SIGN OUT + +
+
From ed25d689e64bad507774f04745019077259df305 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 13:54:16 +0545 Subject: [PATCH 18/27] fix(layerSwitchMenu): width & height fix --- .../OpenLayersComponent/LayerSwitcher/LayerSwitchMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/components/MapComponent/OpenLayersComponent/LayerSwitcher/LayerSwitchMenu.tsx b/src/frontend/src/components/MapComponent/OpenLayersComponent/LayerSwitcher/LayerSwitchMenu.tsx index fdec42c47a..3f13dc8427 100644 --- a/src/frontend/src/components/MapComponent/OpenLayersComponent/LayerSwitcher/LayerSwitchMenu.tsx +++ b/src/frontend/src/components/MapComponent/OpenLayersComponent/LayerSwitcher/LayerSwitchMenu.tsx @@ -126,7 +126,7 @@ const LayerSwitchMenu = ({ map, pmTileLayerData = null }: { map: any; pmTileLaye backgroundImage: activeLayer === 'None' ? 'none' : `url(${layerIcons[activeLayer] || satelliteImg})`, backgroundColor: 'white', }} - className={`fmtm-relative fmtm-group fmtm-order-4 fmtm-w-10 fmtm-h-10 fmtm-border-[1px] fmtm-border-primaryRed hover:fmtm-border-[2px] fmtm-duration-75 fmtm-cursor-pointer fmtm-bg-contain fmtm-rounded-full ${ + className={`fmtm-relative fmtm-group fmtm-order-4 fmtm-w-9 fmtm-h-9 fmtm-border-[1px] fmtm-border-primaryRed hover:fmtm-border-[2px] fmtm-duration-75 fmtm-cursor-pointer fmtm-bg-contain fmtm-rounded-full ${ activeLayer === 'None' ? '!fmtm-border-primaryRed' : '' }`} >
From 090865807b663f0f69f40d4003c6af2899a63e38 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 13:55:22 +0545 Subject: [PATCH 19/27] fix(mapLegends): fix(mapLegends): show map legend in dropdown --- src/frontend/src/components/MapLegends.tsx | 42 ++++++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/frontend/src/components/MapLegends.tsx b/src/frontend/src/components/MapLegends.tsx index 426e7dbe40..13fa5dbae0 100755 --- a/src/frontend/src/components/MapLegends.tsx +++ b/src/frontend/src/components/MapLegends.tsx @@ -1,5 +1,12 @@ import React from 'react'; import AssetModules from '@/shared/AssetModules'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, + DropdownMenuPortal, +} from '@/components/common/Dropdown'; +import { Tooltip } from '@mui/material'; type mapDetialsType = { value: string; @@ -66,13 +73,34 @@ const MapLegends = ({ defaultTheme }: { defaultTheme: any }) => { }; return ( -
-
- {MapDetails.map((data, index) => { - return ; - })} -
-
+ + + +
+ +
+
+
+ + +
+

Legend

+
+ {MapDetails.map((data, index) => { + return ; + })} +
+
{' '} +
+
+
); }; From 0557d67f946fdd9e2b1ae304a91064a0aec9aef2 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 13:56:06 +0545 Subject: [PATCH 20/27] fix(mapControlComponent): add mapLegend to mapControlComponent --- .../src/components/ProjectDetailsV2/MapControlComponent.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/components/ProjectDetailsV2/MapControlComponent.tsx b/src/frontend/src/components/ProjectDetailsV2/MapControlComponent.tsx index ccfbba0225..4461329eec 100644 --- a/src/frontend/src/components/ProjectDetailsV2/MapControlComponent.tsx +++ b/src/frontend/src/components/ProjectDetailsV2/MapControlComponent.tsx @@ -10,6 +10,7 @@ import ProjectOptions from '@/components/ProjectDetailsV2/ProjectOptions'; import useOutsideClick from '@/hooks/useOutsideClick'; import LayerSwitchMenu from '../MapComponent/OpenLayersComponent/LayerSwitcher/LayerSwitchMenu'; import { Tooltip } from '@mui/material'; +import MapLegends from '@/components/MapLegends'; type mapControlComponentType = { map: any; @@ -45,6 +46,7 @@ const MapControlComponent = ({ map, projectName, pmTileLayerData }: mapControlCo const dispatch = CoreModules.useAppDispatch(); const [toggleCurrentLoc, setToggleCurrentLoc] = useState(false); const geolocationStatus = useAppSelector((state) => state.project.geolocationStatus); + const defaultTheme = useAppSelector((state) => state.theme.hotTheme); const [divRef, toggle, handleToggle] = useOutsideClick(); const handleOnClick = (btnId) => { @@ -88,13 +90,14 @@ const MapControlComponent = ({ map, projectName, pmTileLayerData }: mapControlCo ))} + {/* download options */}
handleToggle()} - className="fmtm-bg-white fmtm-rounded-full fmtm-p-2 hover:fmtm-bg-gray-100 fmtm-cursor-pointer fmtm-duration-300 " + className="fmtm-bg-white fmtm-rounded-full hover:fmtm-bg-gray-100 fmtm-cursor-pointer fmtm-duration-300 fmtm-w-9 fmtm-h-9 fmtm-min-h-9 fmtm-min-w-9 fmtm-max-w-9 fmtm-max-h-9 fmtm-flex fmtm-justify-center fmtm-items-center" >
@@ -108,6 +111,7 @@ const MapControlComponent = ({ map, projectName, pmTileLayerData }: mapControlCo
+ ); }; From 9a5de991b9ea2cc2e60abbbbfd772f36e620224e Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 13:57:34 +0545 Subject: [PATCH 21/27] fix(projectDetailsV2): remove showing map legend on accordion, btn linking to mapper frontend add --- src/frontend/src/views/ProjectDetailsV2.tsx | 32 +++++++-------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/frontend/src/views/ProjectDetailsV2.tsx b/src/frontend/src/views/ProjectDetailsV2.tsx index a8d44f85fe..1cb4e49a3f 100644 --- a/src/frontend/src/views/ProjectDetailsV2.tsx +++ b/src/frontend/src/views/ProjectDetailsV2.tsx @@ -25,8 +25,6 @@ import MapControlComponent from '@/components/ProjectDetailsV2/MapControlCompone import { VectorLayer } from '@/components/MapComponent/OpenLayersComponent/Layers'; import { geojsonObjectModel } from '@/constants/geojsonObjectModal'; import getTaskStatusStyle, { getFeatureStatusStyle } from '@/utilfunctions/getTaskStatusStyle'; -import MapLegends from '@/components/MapLegends'; -import Accordion from '@/components/common/Accordion'; import AsyncPopup from '@/components/MapComponent/OpenLayersComponent/AsyncPopup/AsyncPopup'; import Button from '@/components/common/Button'; import ProjectInfo from '@/components/ProjectDetailsV2/ProjectInfo'; @@ -41,7 +39,6 @@ import DebugConsole from '@/utilities/DebugConsole'; import { CustomCheckbox } from '@/components/common/Checkbox'; import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; import QrcodeComponent from '@/components/QrcodeComponent'; -import { createDropdownMenuScope } from '@radix-ui/react-dropdown-menu'; const ProjectDetailsV2 = () => { useDocumentTitle('Project Details'); @@ -50,9 +47,7 @@ const ProjectDetailsV2 = () => { const navigate = useNavigate(); const { windowSize } = WindowDimension(); const [divRef, toggle, handleToggle] = useOutsideClick(); - const [legendRef, legendToggle, handleLegendToggle] = useOutsideClick(); - const [mainView, setView] = useState(); const [selectedTaskArea, setSelectedTaskArea] = useState | null>(null); const [selectedTaskFeature, setSelectedTaskFeature] = useState(); const [dataExtractUrl, setDataExtractUrl] = useState(); @@ -511,30 +506,25 @@ const ProjectDetailsV2 = () => { className="fmtm-w-[235px]" />
- } - header={ -
-

LEGEND

-
- } - onToggle={() => { - handleLegendToggle(); +
From fc91a5e9c282534638ca45747796e89895cc3e90 Mon Sep 17 00:00:00 2001 From: NSUWAL123 Date: Thu, 21 Nov 2024 14:11:40 +0545 Subject: [PATCH 22/27] remove(login): remove temporary login from react frontend --- src/frontend/src/api/Login.ts | 30 ---------------------- src/frontend/src/components/LoginPopup.tsx | 20 +++------------ 2 files changed, 3 insertions(+), 47 deletions(-) delete mode 100644 src/frontend/src/api/Login.ts diff --git a/src/frontend/src/api/Login.ts b/src/frontend/src/api/Login.ts deleted file mode 100644 index e954220ffb..0000000000 --- a/src/frontend/src/api/Login.ts +++ /dev/null @@ -1,30 +0,0 @@ -import axios from 'axios'; -import { getUserDetailsFromApi } from '@/utilfunctions/login'; -import { CommonActions } from '@/store/slices/CommonSlice'; -import { LoginActions } from '@/store/slices/LoginSlice'; - -export const TemporaryLoginService: Function = (url: string) => { - return async (dispatch) => { - const getTemporaryLogin = async (url: string) => { - // Sets a cookie in the browser that is used for auth - await axios.get(url); - - const apiUser = await getUserDetailsFromApi(); - if (!apiUser) { - dispatch( - CommonActions.SetSnackBar({ - open: true, - message: 'Temp login failed. Try OSM.', - variant: 'error', - duration: 2000, - }), - ); - return; - } - - dispatch(LoginActions.setAuthDetails(apiUser)); - }; - - await getTemporaryLogin(url); - }; -}; diff --git a/src/frontend/src/components/LoginPopup.tsx b/src/frontend/src/components/LoginPopup.tsx index a144e2a65e..9031430305 100644 --- a/src/frontend/src/components/LoginPopup.tsx +++ b/src/frontend/src/components/LoginPopup.tsx @@ -1,12 +1,10 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import CoreModules from '@/shared/CoreModules'; import { Modal } from '@/components/common/Modal'; import { useDispatch } from 'react-redux'; -import { useLocation, useNavigate } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; import { LoginActions } from '@/store/slices/LoginSlice'; import { osmLoginRedirect } from '@/utilfunctions/login'; -import { TemporaryLoginService } from '@/api/Login'; -import AssetModules from '@/shared/AssetModules'; import OSMImg from '@/assets/images/osm-logo.png'; type loginOptionsType = { @@ -24,17 +22,10 @@ const loginOptions: loginOptionsType[] = [ image: OSMImg, description: 'Edits made in FMTM will be credited to your OSM account.', }, - { - id: 'temp_account', - name: 'Temporary Account', - icon: , - description: "If you're not an OSM user or prefer not to create an OSM account.", - }, ]; const LoginPopup = () => { const dispatch = useDispatch(); - const navigate = useNavigate(); const location = useLocation(); const from = location.state?.from || '/'; @@ -44,18 +35,13 @@ const LoginPopup = () => { if (selectedOption === 'osm_account') { localStorage.setItem('requestedPath', from); osmLoginRedirect(); - } else { - await dispatch(TemporaryLoginService(`${import.meta.env.VITE_API_URL}/auth/temp-login`, from)); - dispatch(LoginActions.setLoginModalOpen(false)); - navigate(from); } }; const LoginDescription = () => { return (
-
Sign In
-
Select an account type to sign in
+
Sign In
{loginOptions?.map((option) => (
Date: Wed, 27 Nov 2024 10:14:40 +0545 Subject: [PATCH 23/27] test: persist osm login across playwright tests (temp login removed) (#1910) * test: wip persist osm login across playwright tests * test: add temp auth config as a playwright workaround --- src/backend/app/auth/auth_routes.py | 1 - src/frontend/.gitignore | 4 +-- .../e2e/01-create-new-project.spec.ts | 8 ++--- src/frontend/e2e/02-mapper-flow.spec.ts | 7 ++-- src/frontend/e2e/auth.setup.ts | 16 ++++++++++ src/frontend/e2e/helpers.ts | 6 ---- src/frontend/playwright.config.ts | 20 ++++++++++-- src/frontend/src/routes.jsx | 11 +++++++ .../src/views/PlaywrightTempLogin.tsx | 32 +++++++++++++++++++ 9 files changed, 82 insertions(+), 23 deletions(-) create mode 100644 src/frontend/e2e/auth.setup.ts create mode 100644 src/frontend/src/views/PlaywrightTempLogin.tsx diff --git a/src/backend/app/auth/auth_routes.py b/src/backend/app/auth/auth_routes.py index 0482e2b4e4..91df93c4a0 100644 --- a/src/backend/app/auth/auth_routes.py +++ b/src/backend/app/auth/auth_routes.py @@ -315,7 +315,6 @@ async def temp_login( setting it as a cookie. Args: - request (Request): The incoming request object. email: email of non-osm user. Returns: diff --git a/src/frontend/.gitignore b/src/frontend/.gitignore index 4ea574bbeb..2c08d8c2b4 100755 --- a/src/frontend/.gitignore +++ b/src/frontend/.gitignore @@ -122,5 +122,5 @@ dist /playwright-report/ /blob-report/ /playwright/.cache/ - -playwright/.auth +/e2e/.cache/ +e2e/.auth diff --git a/src/frontend/e2e/01-create-new-project.spec.ts b/src/frontend/e2e/01-create-new-project.spec.ts index 2d72ad9e88..184875f308 100644 --- a/src/frontend/e2e/01-create-new-project.spec.ts +++ b/src/frontend/e2e/01-create-new-project.spec.ts @@ -3,18 +3,14 @@ import { test, expect } from '@playwright/test'; -import { tempLogin } from './helpers'; - test('create new project', async ({ browserName, page }) => { // Specific for this large test, only run in one browser // (playwright.config.ts is configured to run all browsers by default) test.skip(browserName !== 'chromium', 'Test only for chromium!'); - // 0. Temp Login - await tempLogin(page); - await page.getByRole('button', { name: '+ Create New Project' }).click(); - // 1. Project Details Step + await page.goto('/'); + await page.getByRole('button', { name: '+ Create New Project' }).click(); await page.getByRole('button', { name: 'NEXT' }).click(); await expect(page.getByText('Project Name is Required.')).toBeVisible(); await expect(page.getByText('Short Description is Required.', { exact: true })).toBeVisible(); diff --git a/src/frontend/e2e/02-mapper-flow.spec.ts b/src/frontend/e2e/02-mapper-flow.spec.ts index 942ff9d347..87f17e618f 100644 --- a/src/frontend/e2e/02-mapper-flow.spec.ts +++ b/src/frontend/e2e/02-mapper-flow.spec.ts @@ -3,7 +3,7 @@ import { test, expect } from '@playwright/test'; -import { tempLogin, openTestProject } from './helpers'; +import { openTestProject } from './helpers'; test.describe('mapper flow', () => { test('task actions', async ({ browserName, page }) => { @@ -11,11 +11,8 @@ test.describe('mapper flow', () => { // (playwright.config.ts is configured to run all browsers by default) test.skip(browserName !== 'chromium', 'Test only for chromium!'); - // 0. Temp Login - await tempLogin(page); - await openTestProject(page); - // 1. Click on task area on map + await openTestProject(page); await page.locator('canvas').click({ position: { x: 445, diff --git a/src/frontend/e2e/auth.setup.ts b/src/frontend/e2e/auth.setup.ts new file mode 100644 index 0000000000..17f9c20584 --- /dev/null +++ b/src/frontend/e2e/auth.setup.ts @@ -0,0 +1,16 @@ +import { test as setup } from '@playwright/test'; +import path from 'path'; + +const authFile = path.join(__dirname, './.auth/user.json'); + +setup('authenticate', async ({ page }) => { + // Note this sets a token so we can proceed, but the login will be + // overwritten by svcfmtm localadmin user (as DEBUG=True) + await page.goto('/playwright-temp-login/'); + + // Now check we are signed in as localadmin + await page.waitForSelector('text=localadmin'); + + // Save authentication state + await page.context().storageState({ path: authFile }); +}); diff --git a/src/frontend/e2e/helpers.ts b/src/frontend/e2e/helpers.ts index 5c5a3d26da..54b9b92fe9 100644 --- a/src/frontend/e2e/helpers.ts +++ b/src/frontend/e2e/helpers.ts @@ -1,11 +1,5 @@ import { Page } from '@playwright/test'; -export async function tempLogin(page: Page) { - await page.goto('/'); - await page.getByRole('button', { name: 'Sign in' }).click(); - await page.getByText('Temporary Account').click(); -} - export async function openTestProject(page: Page) { // open project card with regex text 'Project Create Playwright xxx' await page diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts index dfa5cf7cbf..4c4446bfe1 100644 --- a/src/frontend/playwright.config.ts +++ b/src/frontend/playwright.config.ts @@ -28,17 +28,31 @@ export default defineConfig({ /* Configure projects for major browsers */ projects: [ + // Setup project + { name: 'setup', testMatch: /.*\.setup\.ts/ }, { name: 'chromium', - use: { browserName: 'chromium' }, + use: { + browserName: 'chromium', + storageState: 'e2e/.auth/user.json', + }, + dependencies: ['setup'], }, { name: 'firefox', - use: { browserName: 'firefox' }, + use: { + browserName: 'firefox', + storageState: 'e2e/.auth/user.json', + }, + dependencies: ['setup'], }, { name: 'webkit', - use: { browserName: 'webkit' }, + use: { + browserName: 'webkit', + storageState: 'playwright/.auth/user.json', + }, + dependencies: ['setup'], }, /* Test against mobile viewports. */ diff --git a/src/frontend/src/routes.jsx b/src/frontend/src/routes.jsx index d7953927a4..72dd940813 100755 --- a/src/frontend/src/routes.jsx +++ b/src/frontend/src/routes.jsx @@ -8,6 +8,7 @@ import Organisation from '@/views/Organisation'; import CreateEditOrganization from '@/views/CreateEditOrganization'; import ApproveOrganization from '@/views/ApproveOrganization'; import OsmAuth from '@/views/OsmAuth'; +import PlaywrightTempLogin from '@/views/PlaywrightTempLogin'; import SubmissionDetails from '@/views/SubmissionDetails'; import CreateNewProject from '@/views/CreateNewProject'; import UnderConstruction from '@/views/UnderConstruction'; @@ -187,6 +188,16 @@ const routes = createBrowserRouter([ ), }, + { + path: '/playwright-temp-login/', + element: ( + Loading...
}> + + + + + ), + }, { path: '/under-construction/', element: ( diff --git a/src/frontend/src/views/PlaywrightTempLogin.tsx b/src/frontend/src/views/PlaywrightTempLogin.tsx new file mode 100644 index 0000000000..d23bdf550b --- /dev/null +++ b/src/frontend/src/views/PlaywrightTempLogin.tsx @@ -0,0 +1,32 @@ +// This file is a workaround to populate state.login.authDetails +// the auth is overridden when testing due to DEBUG=True on the backend, +// but we need to update the frontend state to show we are logged in + +import axios from 'axios'; +import { getUserDetailsFromApi } from '@/utilfunctions/login'; +import { CommonActions } from '@/store/slices/CommonSlice'; +import CoreModules from '@/shared/CoreModules.js'; +import { LoginActions } from '@/store/slices/LoginSlice'; + +async function PlaywrightTempAuth() { + const dispatch = CoreModules.useAppDispatch(); + // Sets a cookie in the browser that is used for auth + await axios.get(`${import.meta.env.VITE_API_URL}/auth/temp-login`); + + const apiUser = await getUserDetailsFromApi(); + if (!apiUser) { + dispatch( + CommonActions.SetSnackBar({ + open: true, + message: 'Temp login failed. Try OSM.', + variant: 'error', + duration: 2000, + }), + ); + return; + } + + dispatch(LoginActions.setAuthDetails(apiUser)); +} + +export default PlaywrightTempAuth; From defa9b2263857a8e0a1d052dc73f30b0cd45cc25 Mon Sep 17 00:00:00 2001 From: spwoodcock Date: Wed, 27 Nov 2024 04:34:35 +0000 Subject: [PATCH 24/27] test: fix mapper flow tests, first open page, then click card --- src/frontend/e2e/02-mapper-flow.spec.ts | 8 +------- src/frontend/e2e/helpers.ts | 1 + 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/frontend/e2e/02-mapper-flow.spec.ts b/src/frontend/e2e/02-mapper-flow.spec.ts index 87f17e618f..031fcf29f9 100644 --- a/src/frontend/e2e/02-mapper-flow.spec.ts +++ b/src/frontend/e2e/02-mapper-flow.spec.ts @@ -104,12 +104,9 @@ test.describe('mapper flow', () => { // (playwright.config.ts is configured to run all browsers by default) test.skip(browserName !== 'chromium', 'Test only for chromium!'); - // 0. Temp Login - await tempLogin(page); - await openTestProject(page); - // 1. Click on task area on map // click on task & assert task popup visibility + await openTestProject(page); await page.locator('canvas').click({ position: { x: 388, @@ -173,10 +170,7 @@ test.describe('mapper flow', () => { // (playwright.config.ts is configured to run all browsers by default) test.skip(browserName !== 'chromium', 'Test only for chromium!'); - // 0. Temp Login - await tempLogin(page); await openTestProject(page); - await page.locator('canvas').click({ position: { x: 475, diff --git a/src/frontend/e2e/helpers.ts b/src/frontend/e2e/helpers.ts index 54b9b92fe9..7c11160181 100644 --- a/src/frontend/e2e/helpers.ts +++ b/src/frontend/e2e/helpers.ts @@ -1,6 +1,7 @@ import { Page } from '@playwright/test'; export async function openTestProject(page: Page) { + await page.goto('/'); // open project card with regex text 'Project Create Playwright xxx' await page .getByText(/^Project Create Playwright/) From 0d8d9167768226905df31ba3977302489703cd15 Mon Sep 17 00:00:00 2001 From: spwoodcock Date: Wed, 27 Nov 2024 05:29:20 +0000 Subject: [PATCH 25/27] test: disable firefox and webkit tests entirely for now --- src/frontend/playwright.config.ts | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts index 4c4446bfe1..0ae733f208 100644 --- a/src/frontend/playwright.config.ts +++ b/src/frontend/playwright.config.ts @@ -38,22 +38,22 @@ export default defineConfig({ }, dependencies: ['setup'], }, - { - name: 'firefox', - use: { - browserName: 'firefox', - storageState: 'e2e/.auth/user.json', - }, - dependencies: ['setup'], - }, - { - name: 'webkit', - use: { - browserName: 'webkit', - storageState: 'playwright/.auth/user.json', - }, - dependencies: ['setup'], - }, + // { + // name: 'firefox', + // use: { + // browserName: 'firefox', + // storageState: 'e2e/.auth/user.json', + // }, + // dependencies: ['setup'], + // }, + // { + // name: 'webkit', + // use: { + // browserName: 'webkit', + // storageState: 'playwright/.auth/user.json', + // }, + // dependencies: ['setup'], + // }, /* Test against mobile viewports. */ // { From 9d4b8be6fbb2695813dbb5469dc3d8ed30bd6bc0 Mon Sep 17 00:00:00 2001 From: spwoodcock Date: Wed, 27 Nov 2024 05:29:45 +0000 Subject: [PATCH 26/27] docs: add note about attempting test auth with webkit --- src/frontend/e2e/auth.setup.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/frontend/e2e/auth.setup.ts b/src/frontend/e2e/auth.setup.ts index 17f9c20584..da517e29a6 100644 --- a/src/frontend/e2e/auth.setup.ts +++ b/src/frontend/e2e/auth.setup.ts @@ -3,7 +3,14 @@ import path from 'path'; const authFile = path.join(__dirname, './.auth/user.json'); -setup('authenticate', async ({ page }) => { +setup('authenticate', async ({ browserName, page }) => { + // Note here we only run in chromium, to avoid running this setup step + // for Firefox and Webkit. + // This is because Webkit does not respect 'secure' cookies on http contexts. + // For this to work we would need to configure https for testing + // https://github.com/hotosm/fmtm/pull/1920 + setup.skip(browserName !== 'chromium', 'Test only for chromium!'); + // Note this sets a token so we can proceed, but the login will be // overwritten by svcfmtm localadmin user (as DEBUG=True) await page.goto('/playwright-temp-login/'); From 13801d117214795404214cc0c7755c5abbcfe0c6 Mon Sep 17 00:00:00 2001 From: spwoodcock Date: Wed, 27 Nov 2024 05:30:05 +0000 Subject: [PATCH 27/27] test: use btnTestId prop to identify specific button during tests --- src/frontend/e2e/02-mapper-flow.spec.ts | 6 +++--- src/frontend/src/components/DialogTaskActions.tsx | 1 + src/frontend/src/components/common/Button.tsx | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/frontend/e2e/02-mapper-flow.spec.ts b/src/frontend/e2e/02-mapper-flow.spec.ts index 031fcf29f9..7ad4450089 100644 --- a/src/frontend/e2e/02-mapper-flow.spec.ts +++ b/src/frontend/e2e/02-mapper-flow.spec.ts @@ -32,8 +32,8 @@ test.describe('mapper flow', () => { }); // 2. Lock task for mapping - await expect(page.getByRole('button', { name: 'START MAPPING' })).toBeVisible(); - await page.getByRole('button', { name: 'START MAPPING' }).click(); + await expect(page.getByTestId('StartMapping')).toBeVisible(); + await page.getByTestId('StartMapping').click(); await page.waitForSelector('div:has-text("updated to LOCKED_FOR_MAPPING"):nth-of-type(1)'); await expect( page @@ -114,7 +114,7 @@ test.describe('mapper flow', () => { }, }); await expect(page.getByText('Status: UNLOCKED_TO_MAP')).toBeVisible(); - await expect(page.getByRole('button', { name: 'START MAPPING' })).toBeVisible(); + await expect(page.getByTestId('StartMapping')).toBeVisible(); // 2. Click on a specific feature / Entity within a task // assert feature popup visibility diff --git a/src/frontend/src/components/DialogTaskActions.tsx b/src/frontend/src/components/DialogTaskActions.tsx index e44b203134..a81d211feb 100755 --- a/src/frontend/src/components/DialogTaskActions.tsx +++ b/src/frontend/src/components/DialogTaskActions.tsx @@ -184,6 +184,7 @@ export default function Dialog({ taskId, feature }: dialogPropType) { return list_of_task_actions?.length != 0 ? (