From a61b652d80efd29acc198cc52456b5a28a65d09c Mon Sep 17 00:00:00 2001 From: Wentao Kuang Date: Fri, 11 Oct 2024 09:52:18 +1300 Subject: [PATCH] feat(landing): Add new features pop up to alert users for recent releases. BM-1064 (#3356) ### Motivation We want to alert Basemaps users about new features for recent release. To use the @linzjs/lui -> [LuiUpdatesSplashModal](https://github.com/linz/Lui/blob/master/src/components/LuiUpdateSplashModal/LuiUpdatesSplashModal.tsx) which is same with land online search. ### Modifications Initial investigations with @linzjs/lui that it's very hard to import and use react components from it because different tech stacks. - lui build and bundled with nodejs which contains dependencies like `crypto` or `stream` that is not support by browser. We might need to do polyfills to map them into browser friendly dependencies. - lui only bundle everything into one index.js, we don't have individual module file to do direct import, so we have to deal with dependency problem above. As a result, we decide to re-implement the `LuiUpdatesSplashModal` in basemaps just using the assets and css from @linzjs/lui - `FeatureUpdates` is a completely re-implementation of `LuiUpdatesSplashModal` - `NewFeature` is the component that we need to update often when describe new features. - Updated @linzjs/lui to latest ### Verification - Tested new pop up only show once after dismissed. - Tested new pop up stop showing after closing date. - Tested new pop up shows in incognito mode/clearing cache after dismissed. ![image](https://github.com/user-attachments/assets/2440883b-9b00-4bf1-bfdc-a00de6f21fc3) ![image](https://github.com/user-attachments/assets/7061711b-81a5-407c-b442-ea02ef8bf161) --- package-lock.json | 19 +++- packages/landing/package.json | 12 +- .../src/components/feature.updates.tsx | 107 ++++++++++++++++++ .../src/components/new-features/3d.map.tsx | 49 ++++++++ packages/landing/src/index.tsx | 2 + packages/landing/static/index.css | 4 + 6 files changed, 188 insertions(+), 5 deletions(-) create mode 100644 packages/landing/src/components/feature.updates.tsx create mode 100644 packages/landing/src/components/new-features/3d.map.tsx diff --git a/package-lock.json b/package-lock.json index 814a2aa99..a52acd3ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3149,9 +3149,9 @@ } }, "node_modules/@linzjs/lui": { - "version": "21.15.1", - "resolved": "https://registry.npmjs.org/@linzjs/lui/-/lui-21.15.1.tgz", - "integrity": "sha512-O4d7NtP6QU6UkYCjDiGS3aGbyPiUCtmZmrYtBaF5HfcC3z+ndZEyHPDW7f0QbT93NTeQ7s58OSulZbFBspr3rA==", + "version": "21.46.0", + "resolved": "https://registry.npmjs.org/@linzjs/lui/-/lui-21.46.0.tgz", + "integrity": "sha512-8ZuXx556OInxJIvOyYiE9/Bn/o1kN/7L4bCfeiV17MZRjA3nkdsPWGBISWCppSPUJsnkBnRrVxohIqCwdH8/2Q==", "dev": true, "dependencies": { "@fontsource/open-sans": "^4.5.1", @@ -5316,6 +5316,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-modal": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.3.tgz", + "integrity": "sha512-xXuGavyEGaFQDgBv4UVm8/ZsG+qxeQ7f77yNrW3n+1J6XAstUy5rYHeIHPh1KzsGc6IkCIdu6lQ2xWzu1jBTLg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "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", @@ -19571,15 +19580,17 @@ "@basemaps/geo": "^7.11.0", "@basemaps/infra": "^7.11.0", "@basemaps/shared": "^7.11.0", - "@linzjs/lui": "^21.12.1", + "@linzjs/lui": "^21.46.0", "@servie/events": "^3.0.0", "@types/proj4": "^2.5.2", "@types/react-dom": "^18.0.6", + "@types/react-modal": "^3.16.3", "maplibre-gl": "^4.5.0", "mime-types": "^2.1.35", "proj4": "^2.8.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-modal": "^3.16.1", "ulid": "^2.3.0" }, "engines": { diff --git a/packages/landing/package.json b/packages/landing/package.json index 05f21dcf5..96933684e 100644 --- a/packages/landing/package.json +++ b/packages/landing/package.json @@ -33,15 +33,17 @@ "@basemaps/geo": "^7.11.0", "@basemaps/infra": "^7.11.0", "@basemaps/shared": "^7.11.0", - "@linzjs/lui": "^21.12.1", + "@linzjs/lui": "^21.46.0", "@servie/events": "^3.0.0", "@types/proj4": "^2.5.2", "@types/react-dom": "^18.0.6", + "@types/react-modal": "^3.16.3", "maplibre-gl": "^4.5.0", "mime-types": "^2.1.35", "proj4": "^2.8.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-modal": "^3.16.1", "ulid": "^2.3.0" }, "publishConfig": { @@ -60,6 +62,14 @@ "entry": "../../node_modules/@linzjs/lui/dist/assets/images/linz-motif.svg", "outfile": "dist/assets/logo-linz.svg" }, + { + "entry": "../../node_modules/@linzjs/lui/dist/assets/icons/whats_new_updates.svg", + "outfile": "dist/assets/whats_new_updates.svg" + }, + { + "entry": "../../node_modules/@linzjs/lui/dist/assets/icons/clear.svg", + "outfile": "dist/assets/clear.svg" + }, { "entry": "../../node_modules/@linzjs/lui/dist/assets/fonts", "outfile": "dist/assets/fonts" diff --git a/packages/landing/src/components/feature.updates.tsx b/packages/landing/src/components/feature.updates.tsx new file mode 100644 index 000000000..a6c61e807 --- /dev/null +++ b/packages/landing/src/components/feature.updates.tsx @@ -0,0 +1,107 @@ +import { clsx } from 'clsx'; +import { Component, ReactNode } from 'react'; +import ReactModal from 'react-modal'; + +import { Config } from '../config.js'; + +type FeatureUpdatesProps = { + header: string; + wrapperClass?: string; + id: string; + dismissedKey: string; + closingDate: Date; + enabled: boolean; + children?: ReactNode; +} & { bigImage: string; smallImage: string; iframe?: never }; + +type FeatureUpdatesState = { + showModal: boolean; +}; + +/** + * FeatureUpdates is a re-implementation of @linzjs/lui -> LuiUpdatesSplashModal module, + * This use to enable a one off pop up screen for introduce new feature of the recent release. + * + */ +export class FeatureUpdates extends Component { + constructor(props: FeatureUpdatesProps) { + super(props); + + const id = window.localStorage.getItem(this.props.id); + + this.state = { + showModal: this.props.enabled && this.props.dismissedKey !== id && this.props.closingDate >= new Date(), + }; + } + + handleClose = (): void => { + this.setState({ showModal: false }); + window.localStorage.setItem(this.props.id, this.props.dismissedKey); + }; + + override render(): ReactNode { + const { header, wrapperClass, children, bigImage, smallImage } = this.props; + const { showModal } = this.state; + + if (!showModal) return null; + if (Config.map.isDebug) return; + + return ( + +
+
+
+ {this.WhatsNewIcon()} +

{header}

+
+ +
+ {this.FeatureImages(bigImage, smallImage)} +
{children}
+
+
+ ); + } + + FeatureImages(bigImage: string, smallImage: string): ReactNode { + return ( +
+ {"What's + {"What's +
+ ); + } + + // @linzjs/lui whats_new_icon re-implementation + WhatsNewIcon(): ReactNode { + return ( + + whats_new_icon + + ); + } + + // @linzjs/lui cross_icon re-implementation + ClearIcon(): ReactNode { + return ( + + cross_icon + + ); + } +} diff --git a/packages/landing/src/components/new-features/3d.map.tsx b/packages/landing/src/components/new-features/3d.map.tsx new file mode 100644 index 000000000..562bc2091 --- /dev/null +++ b/packages/landing/src/components/new-features/3d.map.tsx @@ -0,0 +1,49 @@ +import { Component, ReactNode } from 'react'; + +import { WindowUrl } from '../../url.js'; +import { FeatureUpdates } from '../feature.updates.js'; + +const baseUrl = WindowUrl.baseUrl(); + +/** + * Please updated the following settings and descriptions for new features pop up + */ +const bigImage = new URL('assets/Lg+3D+Maps+splash.gif', baseUrl).href; // Large gif file location +const smallImage = new URL('assets/Sml+3D+map+splash.gif', baseUrl).href; // Small gif file location +const closingDate = new Date('2024-10-30'); // End date for pop up screen +const id = `LINZ_Basemaps_3D_Map`; // Optional to set as Config.Version to disable Modal as default +const dismissedKey = 'DISMISSED_MODALS_2024_10_3d_map'; // Feature released version can both been major version or minor version +const recentUpdates = { + children: ( + <> +

Basemaps are now viewable in 3D!

+

+ To activate this function, click the mountains icon on the left-hand side then hold right-click to change your + viewpoint. +

+

The new Labels button can also be toggled to show places names.

+ + ), + bigImage, + smallImage, +}; + +export class NewFeature extends Component { + enabled = true; + + override render(): ReactNode { + return ( + + {recentUpdates.children} + + ); + } +} diff --git a/packages/landing/src/index.tsx b/packages/landing/src/index.tsx index f9fbf5883..5bd4c303e 100644 --- a/packages/landing/src/index.tsx +++ b/packages/landing/src/index.tsx @@ -4,6 +4,7 @@ import { createRoot } from 'react-dom/client'; import { Footer } from './components/layout.footer.js'; import { Header } from './components/layout.header.js'; import { Basemaps } from './components/map.js'; +import { NewFeature } from './components/new-features/3d.map.js'; import { Config } from './config.js'; import { WindowUrl } from './url.js'; import { isWebpSupported } from './webp.js'; @@ -13,6 +14,7 @@ class Page extends Component { return (
+