From 3d6f3f1a467f05ab2a51cba6c0c536452882af38 Mon Sep 17 00:00:00 2001 From: QuanGiap Date: Sat, 9 Sep 2023 10:33:09 -0700 Subject: [PATCH 1/2] feat: add new handle for view coordinate (lat,lng,zoomLevel) --- package-lock.json | 4 +- src/components/Home.js | 13 +-- src/models/pathResolver.js | 40 ++++++++- src/models/pathResolver.test.js | 98 ++++++++++++++++++++- src/models/utils.js | 40 +++++++++ src/pages/organizations/[organizationid].js | 12 +-- src/pages/planters/[planterid].js | 4 +- src/pages/wallets/[walletid].js | 17 ++-- 8 files changed, 189 insertions(+), 39 deletions(-) diff --git a/package-lock.json b/package-lock.json index 670f5e1bc..3f39e8689 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "client", - "version": "2.3.3", + "version": "2.6.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "client", - "version": "2.3.3", + "version": "2.6.6", "dependencies": { "@emotion/cache": "^11.5.0", "@emotion/react": "^11.5.0", diff --git a/src/components/Home.js b/src/components/Home.js index 37179a949..ee8ba7eda 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -4,10 +4,10 @@ import Typography from '@mui/material/Typography'; import log from 'loglevel'; import { useRouter } from 'next/router'; import React from 'react'; +import { useMapContext } from 'mapContext'; import { makeStyles } from 'models/makeStyles'; -import * as pathResolver from 'models/pathResolver'; +import { moveMapByUrl } from 'models/utils'; import Link from './Link'; -import { useMapContext } from '../mapContext'; const backgroundImage = `${process.env.NEXT_PUBLIC_BASE}/images/bg.webp`; const useStyles = makeStyles()((theme) => ({ @@ -66,14 +66,7 @@ export default function Home(props) { await map.setFilters({}); log.warn('location:', window.location); log.warn('router:', router); - const bounds = pathResolver.getBounds(router); - if (bounds) { - log.warn('goto bounds found in url'); - await map.gotoBounds(bounds); - } else { - log.warn('goto global view'); - await map.gotoView(0, 0, 2); - } + moveMapByUrl({ map, router }); } } reload(); diff --git a/src/models/pathResolver.js b/src/models/pathResolver.js index edf557a54..4d303caf5 100644 --- a/src/models/pathResolver.js +++ b/src/models/pathResolver.js @@ -79,8 +79,13 @@ function getPathWhenClickTree(tree, location, router, map, options = {}) { query: optionalParams, }; } - -function updatePathWhenMapMoveEnd(location, map, router) { +/** + * if {isView} is true,view's is used (lat,long,zoomLevel z) + * + * else bounds is used (southWestLng, southWestLat, northEastLng, northEastLat) + * @returns string url + */ +function updatePathWhenMapMoveEnd(location, map, router, isView = true) { log.warn( 'updatePathWhenMapMoveEnd: location:', location, @@ -89,7 +94,17 @@ function updatePathWhenMapMoveEnd(location, map, router) { ' router:', router, ); - let result = `${location.pathname}?bounds=${map.getCurrentBounds()}${ + + // determine to use which format to use for coordinate + let coordinate = ''; + if (!isView) { + coordinate = `bounds=${map.getCurrentBounds()}`; + } else { + const { center, zoomLevel } = map.getCurrentView(); + coordinate = `view=${center.lat},${center.lng},${zoomLevel}z`; + } + + let result = `${location.pathname}?${coordinate}${ router.query.timeline ? `&timeline=${router.query.timeline}` : '' }${router.query.embed ? `&embed=true` : ''}`; if (router.query.tree_id) { @@ -133,9 +148,28 @@ function getContext(router, options = {}) { function getBounds(router) { return router.query.bounds; } + +function getView(router) { + const { view } = router.query; + try { + if (view) { + const [lat, lon, zoomLevel] = view.split(','); + return { + lat: parseFloat(lat), + lon: parseFloat(lon), + zoomLevel: parseFloat(zoomLevel.substring(0, zoomLevel.length - 1)), + }; + } + } catch (e) { + console.warn("view's format is not correct"); + } + return null; +} + export { getPathWhenClickTree, updatePathWhenMapMoveEnd, getContext, getBounds, + getView, }; diff --git a/src/models/pathResolver.test.js b/src/models/pathResolver.test.js index af6a21fb8..3a2e61748 100644 --- a/src/models/pathResolver.test.js +++ b/src/models/pathResolver.test.js @@ -141,7 +141,7 @@ describe('Test pathResolver', () => { }); }); - describe('updatePathWhenMapMoveEnd', () => { + describe('updatePathWhenMapMoveEnd bounds coordinate ', () => { it('update path when ', () => { const result = pathResolver.updatePathWhenMapMoveEnd( { @@ -154,6 +154,7 @@ describe('Test pathResolver', () => { { query: {}, }, + false, ); expect(result).toBe( '/wallets/0cdf4219-869a-41ce-953a-a8421d8353f7?bounds=37.44990348815919,-3.315482794386477,37.46535301208497,-3.307471024919109', @@ -174,6 +175,7 @@ describe('Test pathResolver', () => { tree_id: '14615', }, }, + false, ); expect(result).toBe( '/wallets/0cdf4219-869a-41ce-953a-a8421d8353f7?bounds=37.44990348815919,-3.315482794386477,37.46535301208497,-3.307471024919109&tree_id=14615', @@ -194,6 +196,7 @@ describe('Test pathResolver', () => { tree_id: '5413738', }, }, + false, ); expect(result).toBe( '/wallets/5f5939ae-91ce-49cd-81ba-7fdba81e250a/tokens?bounds=46.38155221939087,-15.762146918354096,46.3908863067627,-15.74444839985392&tree_id=5413738', @@ -201,6 +204,84 @@ describe('Test pathResolver', () => { }); }); + describe('updatePathWhenMapMoveEnd view coordinate ', () => { + it('update path when ', () => { + const result = pathResolver.updatePathWhenMapMoveEnd( + { + pathname: '/wallets/0cdf4219-869a-41ce-953a-a8421d8353f7', + }, + { + getCurrentView: () => ({ + center: { + lat: 2.4601811810210052, + lng: 32.16796875000001, + }, + zoomLevel: 2, + }), + }, + { + query: {}, + }, + true, + ); + expect(result).toBe( + '/wallets/0cdf4219-869a-41ce-953a-a8421d8353f7?view=2.4601811810210052,32.16796875000001,2z', + ); + }); + + it('update path when /wallets/1f2a0862-66d1-4b42-8216-5a5cb9c6eca5/tokens?tree_id=14615', () => { + const result = pathResolver.updatePathWhenMapMoveEnd( + { + pathname: '/wallets/0cdf4219-869a-41ce-953a-a8421d8353f7', + }, + { + getCurrentView: () => ({ + center: { + lat: 2.4601811810210052, + lng: 32.16796875000001, + }, + zoomLevel: 2, + }), + }, + { + query: { + tree_id: '14615', + }, + }, + true, + ); + expect(result).toBe( + '/wallets/0cdf4219-869a-41ce-953a-a8421d8353f7?view=2.4601811810210052,32.16796875000001,2z&tree_id=14615', + ); + }); + + it('update path when /wallets/5f5939ae-91ce-49cd-81ba-7fdba81e250a/tokens?tree_id=5413738', () => { + const result = pathResolver.updatePathWhenMapMoveEnd( + { + pathname: '/wallets/5f5939ae-91ce-49cd-81ba-7fdba81e250a/tokens', + }, + { + getCurrentView: () => ({ + center: { + lat: 2.4601811810210052, + lng: 32.16796875000001, + }, + zoomLevel: 2, + }), + }, + { + query: { + tree_id: '5413738', + }, + }, + true, + ); + expect(result).toBe( + '/wallets/5f5939ae-91ce-49cd-81ba-7fdba81e250a/tokens?view=2.4601811810210052,32.16796875000001,2z&tree_id=5413738', + ); + }); + }); + describe('getContext', () => { it('org context', () => { const result = pathResolver.getContext({ @@ -259,4 +340,19 @@ describe('Test pathResolver', () => { ); }); }); + + describe('getView', () => { + it('?view=2.4601811810210052,32.16796875000001,2z', () => { + const bounds = pathResolver.getView({ + query: { + view: '2.4601811810210052,32.16796875000001,2z', + }, + }); + expect(bounds).toMatchObject({ + lat: 2.4601811810210052, + lon: 32.16796875000001, + zoomLevel: 2, + }); + }); + }); }); diff --git a/src/models/utils.js b/src/models/utils.js index 3e2652c03..ff487a6dd 100644 --- a/src/models/utils.js +++ b/src/models/utils.js @@ -304,6 +304,45 @@ const abbreviateNumber = (number) => notation: 'compact', }).format(number); +/** + * @param map + * @param router + * + * @description move the position view of the map base on the url + */ +const moveMapByUrl = async ({ map, router, initLat, initLon, initZoom }) => { + const { bounds } = router.query; + const { view } = router.query; + console.log('Moving in map'); + console.log(bounds); + console.log(view); + if (bounds) { + log.warn('goto bounds found in url'); + await map.gotoBounds(bounds); + } else if (view) { + log.warn('goto view found in url'); + + const [lat, lon, zoomLevel] = view.split(','); + await map.gotoView( + parseFloat(lat), + parseFloat(lon), + parseFloat(zoomLevel.substring(0, zoomLevel.length - 1)), + ); + } else { + try { + const initView = await map.getInitialView(); + await map.gotoView( + initView.center.lat, + initView.center.lon, + initView.center.zoomLevel, + ); + } catch (err) { + console.warn('Goto global view'); + await map.gotoView(0, 0, 2); + } + } +}; + export { hideLastName, parseDomain, @@ -326,4 +365,5 @@ export { setPropByPath, getPropByPath, abbreviateNumber, + moveMapByUrl, }; diff --git a/src/pages/organizations/[organizationid].js b/src/pages/organizations/[organizationid].js index 84cca8650..1f9e0ed25 100644 --- a/src/pages/organizations/[organizationid].js +++ b/src/pages/organizations/[organizationid].js @@ -28,8 +28,7 @@ import imagePlaceholder from 'images/image-placeholder.png'; import SearchIcon from 'images/search.svg'; import { useMapContext } from 'mapContext'; import { getOrganizationById, getOrgLinks } from 'models/api'; -import * as pathResolver from 'models/pathResolver'; -import { getLocationString, getContinent, wrapper } from 'models/utils'; +import { getLocationString, getContinent, wrapper, moveMapByUrl } from 'models/utils'; export default function Organization(props) { log.warn('props for org page:', props); @@ -69,14 +68,7 @@ export default function Organization(props) { await map.setFilters({ map_name: organization.map_name, }); - const bounds = pathResolver.getBounds(router); - if (bounds) { - log.warn('goto bounds found in url'); - await map.gotoBounds(bounds); - } else { - const view = await map.getInitialView(); - await map.gotoView(view.center.lat, view.center.lon, view.zoomLevel); - } + await moveMapByUrl({ map, router }); } else { log.warn('no data:', map, organization); } diff --git a/src/pages/planters/[planterid].js b/src/pages/planters/[planterid].js index 0106d52d4..75d288660 100644 --- a/src/pages/planters/[planterid].js +++ b/src/pages/planters/[planterid].js @@ -35,7 +35,7 @@ import { useMapContext } from 'mapContext'; import { getPlanterById, getOrgLinks } from 'models/api'; import { makeStyles } from 'models/makeStyles'; import * as pathResolver from 'models/pathResolver'; -import { getLocationString, getPlanterName, wrapper } from 'models/utils'; +import { getLocationString, getPlanterName, moveMapByUrl, wrapper } from 'models/utils'; // make styles for component with material-ui const useStyles = makeStyles()((theme) => ({ @@ -123,7 +123,9 @@ export default function Planter(props) { log.warn('goto bounds found in url'); await map.gotoBounds(bounds); } else { + console.log('get initial'); const view = await map.getInitialView(); + console.log(view); map.gotoView(view.center.lat, view.center.lon, view.zoomLevel); } } diff --git a/src/pages/wallets/[walletid].js b/src/pages/wallets/[walletid].js index f06bfe6d0..95ce81826 100644 --- a/src/pages/wallets/[walletid].js +++ b/src/pages/wallets/[walletid].js @@ -31,7 +31,7 @@ import SearchIcon from 'images/search.svg'; import { useMapContext } from 'mapContext'; import { getWalletById, getSpeciesByWalletId } from 'models/api'; import * as pathResolver from 'models/pathResolver'; -import { requestAPI, wrapper } from 'models/utils'; +import { requestAPI, wrapper, moveMapByUrl } from 'models/utils'; const placeholderText = `Lorem ipsum dolor sit amet consectetur adipisicing elit. Culpa iusto nesciunt quasi praesentium non cupiditate ratione nihil. Perferendis, @@ -80,18 +80,11 @@ export default function Wallet(props) { await map.setFilters({ wallet: wallet.name, }); - const bounds = pathResolver.getBounds(router); - if (bounds) { - log.warn('goto bounds found in url'); - await map.gotoBounds(bounds); - } else { - const view = await map.getInitialView(); - - if (view.zoomLevel < 2) { - view.zoomLevel = 2; - } - await map.gotoView(view.center.lat, view.center.lon, view.zoomLevel); + const view = await map.getCurrentView(); + if (view.zoomLevel < 2) { + view.zoomLevel = 2; } + await moveMapByUrl({ map, router, initZoom: view.zoomLevel }); } } reload(); From 42ac9a203f89fecca0c49fb8575167aea4593b9b Mon Sep 17 00:00:00 2001 From: QuanGiap Date: Sat, 9 Sep 2023 13:58:46 -0700 Subject: [PATCH 2/2] fix: not auto zoom the map when clicking planter, organize and wallet --- src/models/utils.js | 36 ++++++++------------- src/pages/organizations/[organizationid].js | 9 ++++-- src/pages/planters/[planterid].js | 18 ++++------- src/pages/wallets/[walletid].js | 6 +--- 4 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/models/utils.js b/src/models/utils.js index ff487a6dd..734a99cb1 100644 --- a/src/models/utils.js +++ b/src/models/utils.js @@ -305,41 +305,33 @@ const abbreviateNumber = (number) => }).format(number); /** - * @param map - * @param router - * - * @description move the position view of the map base on the url + * @description move the position view of the map base on the url. + * If not found, move to the global view */ -const moveMapByUrl = async ({ map, router, initLat, initLon, initZoom }) => { - const { bounds } = router.query; - const { view } = router.query; - console.log('Moving in map'); - console.log(bounds); - console.log(view); +const moveMapByUrl = async ({ map, router, getInitial = false }) => { + const { bounds, view } = router.query; + if (bounds) { log.warn('goto bounds found in url'); await map.gotoBounds(bounds); } else if (view) { log.warn('goto view found in url'); - const [lat, lon, zoomLevel] = view.split(','); await map.gotoView( parseFloat(lat), parseFloat(lon), parseFloat(zoomLevel.substring(0, zoomLevel.length - 1)), ); + } else if (getInitial) { + const initView = await map.getInitialView(); + await map.gotoView( + initView.center.lat, + initView.center.lon, + initView.zoomLevel, + ); } else { - try { - const initView = await map.getInitialView(); - await map.gotoView( - initView.center.lat, - initView.center.lon, - initView.center.zoomLevel, - ); - } catch (err) { - console.warn('Goto global view'); - await map.gotoView(0, 0, 2); - } + console.warn('Goto global view'); + await map.gotoView(0, 0, 2); } }; diff --git a/src/pages/organizations/[organizationid].js b/src/pages/organizations/[organizationid].js index 1f9e0ed25..5549d07fc 100644 --- a/src/pages/organizations/[organizationid].js +++ b/src/pages/organizations/[organizationid].js @@ -28,7 +28,12 @@ import imagePlaceholder from 'images/image-placeholder.png'; import SearchIcon from 'images/search.svg'; import { useMapContext } from 'mapContext'; import { getOrganizationById, getOrgLinks } from 'models/api'; -import { getLocationString, getContinent, wrapper, moveMapByUrl } from 'models/utils'; +import { + getLocationString, + getContinent, + wrapper, + moveMapByUrl, +} from 'models/utils'; export default function Organization(props) { log.warn('props for org page:', props); @@ -68,7 +73,7 @@ export default function Organization(props) { await map.setFilters({ map_name: organization.map_name, }); - await moveMapByUrl({ map, router }); + await moveMapByUrl({ map, router, getInitial: true }); } else { log.warn('no data:', map, organization); } diff --git a/src/pages/planters/[planterid].js b/src/pages/planters/[planterid].js index 75d288660..e69a8bcad 100644 --- a/src/pages/planters/[planterid].js +++ b/src/pages/planters/[planterid].js @@ -35,7 +35,12 @@ import { useMapContext } from 'mapContext'; import { getPlanterById, getOrgLinks } from 'models/api'; import { makeStyles } from 'models/makeStyles'; import * as pathResolver from 'models/pathResolver'; -import { getLocationString, getPlanterName, moveMapByUrl, wrapper } from 'models/utils'; +import { + getLocationString, + getPlanterName, + moveMapByUrl, + wrapper, +} from 'models/utils'; // make styles for component with material-ui const useStyles = makeStyles()((theme) => ({ @@ -118,16 +123,7 @@ export default function Planter(props) { await map.setFilters({ userid: planter.id, }); - const bounds = pathResolver.getBounds(router); - if (bounds) { - log.warn('goto bounds found in url'); - await map.gotoBounds(bounds); - } else { - console.log('get initial'); - const view = await map.getInitialView(); - console.log(view); - map.gotoView(view.center.lat, view.center.lon, view.zoomLevel); - } + moveMapByUrl({ map, router, getInitial: true }); } } reload(); diff --git a/src/pages/wallets/[walletid].js b/src/pages/wallets/[walletid].js index 95ce81826..2bdffbbe4 100644 --- a/src/pages/wallets/[walletid].js +++ b/src/pages/wallets/[walletid].js @@ -80,11 +80,7 @@ export default function Wallet(props) { await map.setFilters({ wallet: wallet.name, }); - const view = await map.getCurrentView(); - if (view.zoomLevel < 2) { - view.zoomLevel = 2; - } - await moveMapByUrl({ map, router, initZoom: view.zoomLevel }); + await moveMapByUrl({ map, router, getInitial: true }); } } reload();