Skip to content

Commit a61b652

Browse files
authored
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)
1 parent 5b207de commit a61b652

File tree

6 files changed

+188
-5
lines changed

6 files changed

+188
-5
lines changed

package-lock.json

Lines changed: 15 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/landing/package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,17 @@
3333
"@basemaps/geo": "^7.11.0",
3434
"@basemaps/infra": "^7.11.0",
3535
"@basemaps/shared": "^7.11.0",
36-
"@linzjs/lui": "^21.12.1",
36+
"@linzjs/lui": "^21.46.0",
3737
"@servie/events": "^3.0.0",
3838
"@types/proj4": "^2.5.2",
3939
"@types/react-dom": "^18.0.6",
40+
"@types/react-modal": "^3.16.3",
4041
"maplibre-gl": "^4.5.0",
4142
"mime-types": "^2.1.35",
4243
"proj4": "^2.8.0",
4344
"react": "^18.2.0",
4445
"react-dom": "^18.2.0",
46+
"react-modal": "^3.16.1",
4547
"ulid": "^2.3.0"
4648
},
4749
"publishConfig": {
@@ -60,6 +62,14 @@
6062
"entry": "../../node_modules/@linzjs/lui/dist/assets/images/linz-motif.svg",
6163
"outfile": "dist/assets/logo-linz.svg"
6264
},
65+
{
66+
"entry": "../../node_modules/@linzjs/lui/dist/assets/icons/whats_new_updates.svg",
67+
"outfile": "dist/assets/whats_new_updates.svg"
68+
},
69+
{
70+
"entry": "../../node_modules/@linzjs/lui/dist/assets/icons/clear.svg",
71+
"outfile": "dist/assets/clear.svg"
72+
},
6373
{
6474
"entry": "../../node_modules/@linzjs/lui/dist/assets/fonts",
6575
"outfile": "dist/assets/fonts"
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { clsx } from 'clsx';
2+
import { Component, ReactNode } from 'react';
3+
import ReactModal from 'react-modal';
4+
5+
import { Config } from '../config.js';
6+
7+
type FeatureUpdatesProps = {
8+
header: string;
9+
wrapperClass?: string;
10+
id: string;
11+
dismissedKey: string;
12+
closingDate: Date;
13+
enabled: boolean;
14+
children?: ReactNode;
15+
} & { bigImage: string; smallImage: string; iframe?: never };
16+
17+
type FeatureUpdatesState = {
18+
showModal: boolean;
19+
};
20+
21+
/**
22+
* FeatureUpdates is a re-implementation of @linzjs/lui -> LuiUpdatesSplashModal module,
23+
* This use to enable a one off pop up screen for introduce new feature of the recent release.
24+
*
25+
*/
26+
export class FeatureUpdates extends Component<FeatureUpdatesProps, FeatureUpdatesState> {
27+
constructor(props: FeatureUpdatesProps) {
28+
super(props);
29+
30+
const id = window.localStorage.getItem(this.props.id);
31+
32+
this.state = {
33+
showModal: this.props.enabled && this.props.dismissedKey !== id && this.props.closingDate >= new Date(),
34+
};
35+
}
36+
37+
handleClose = (): void => {
38+
this.setState({ showModal: false });
39+
window.localStorage.setItem(this.props.id, this.props.dismissedKey);
40+
};
41+
42+
override render(): ReactNode {
43+
const { header, wrapperClass, children, bigImage, smallImage } = this.props;
44+
const { showModal } = this.state;
45+
46+
if (!showModal) return null;
47+
if (Config.map.isDebug) return;
48+
49+
return (
50+
<ReactModal
51+
isOpen={showModal}
52+
shouldCloseOnEsc={true}
53+
onRequestClose={this.handleClose}
54+
shouldCloseOnOverlayClick={true}
55+
contentLabel="Recent updates"
56+
className="lui-splash-content lui-box-shadow"
57+
overlayClassName="splash_overlay"
58+
appElement={document.getElementById('main') || undefined}
59+
>
60+
<div className={clsx('lui-large-feature-notification', wrapperClass)}>
61+
<div className="lui-feature-header">
62+
<div className="lui-feature-title-wrapper">
63+
{this.WhatsNewIcon()}
64+
<h1>{header}</h1>
65+
</div>
66+
<button aria-label="Close dialog" onClick={this.handleClose}>
67+
{this.ClearIcon()}
68+
</button>
69+
</div>
70+
{this.FeatureImages(bigImage, smallImage)}
71+
<div className="lui-feature-text">{children}</div>
72+
</div>
73+
</ReactModal>
74+
);
75+
}
76+
77+
FeatureImages(bigImage: string, smallImage: string): ReactNode {
78+
return (
79+
<div className="lui-feature-img">
80+
<img className="lui-hide-xs lui-hide-sm" alt={"What's new"} src={bigImage} />
81+
<img className="lui-hide-md lui-hide-lg lui-hide-xl" alt={"What's new"} src={smallImage} />
82+
</div>
83+
);
84+
}
85+
86+
// @linzjs/lui whats_new_icon re-implementation
87+
WhatsNewIcon(): ReactNode {
88+
return (
89+
<span
90+
className={'LuiIcon LuiIcon--md lui-feature-title-icon '}
91+
data-icon={'ic_whats_new_updates'}
92+
aria-label={'whats_new_icon'}
93+
>
94+
<img src="assets/whats_new_updates.svg" alt="whats_new_icon" />
95+
</span>
96+
);
97+
}
98+
99+
// @linzjs/lui cross_icon re-implementation
100+
ClearIcon(): ReactNode {
101+
return (
102+
<span className="LuiIcon LuiIcon--md LuiIcon--interactive" data-icon="ic_clear" aria-label="cross_icon">
103+
<img src="/assets/clear.svg" alt="cross_icon" />
104+
</span>
105+
);
106+
}
107+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Component, ReactNode } from 'react';
2+
3+
import { WindowUrl } from '../../url.js';
4+
import { FeatureUpdates } from '../feature.updates.js';
5+
6+
const baseUrl = WindowUrl.baseUrl();
7+
8+
/**
9+
* Please updated the following settings and descriptions for new features pop up
10+
*/
11+
const bigImage = new URL('assets/Lg+3D+Maps+splash.gif', baseUrl).href; // Large gif file location
12+
const smallImage = new URL('assets/Sml+3D+map+splash.gif', baseUrl).href; // Small gif file location
13+
const closingDate = new Date('2024-10-30'); // End date for pop up screen
14+
const id = `LINZ_Basemaps_3D_Map`; // Optional to set as Config.Version to disable Modal as default
15+
const dismissedKey = 'DISMISSED_MODALS_2024_10_3d_map'; // Feature released version can both been major version or minor version
16+
const recentUpdates = {
17+
children: (
18+
<>
19+
<h2>Basemaps are now viewable in 3D!</h2>
20+
<p>
21+
To activate this function, click the mountains icon on the left-hand side then hold right-click to change your
22+
viewpoint.
23+
</p>
24+
<p>The new Labels button can also be toggled to show places names.</p>
25+
</>
26+
),
27+
bigImage,
28+
smallImage,
29+
};
30+
31+
export class NewFeature extends Component {
32+
enabled = true;
33+
34+
override render(): ReactNode {
35+
return (
36+
<FeatureUpdates
37+
id={id}
38+
header="What's new"
39+
dismissedKey={dismissedKey}
40+
closingDate={closingDate}
41+
bigImage={recentUpdates.bigImage}
42+
smallImage={recentUpdates.smallImage}
43+
enabled={this.enabled}
44+
>
45+
{recentUpdates.children}
46+
</FeatureUpdates>
47+
);
48+
}
49+
}

packages/landing/src/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { createRoot } from 'react-dom/client';
44
import { Footer } from './components/layout.footer.js';
55
import { Header } from './components/layout.header.js';
66
import { Basemaps } from './components/map.js';
7+
import { NewFeature } from './components/new-features/3d.map.js';
78
import { Config } from './config.js';
89
import { WindowUrl } from './url.js';
910
import { isWebpSupported } from './webp.js';
@@ -13,6 +14,7 @@ class Page extends Component {
1314
return (
1415
<Fragment>
1516
<Header />
17+
<NewFeature />
1618
<Basemaps />
1719
<Footer />
1820
</Fragment>

packages/landing/static/index.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,4 +257,8 @@ have higher specifity than the default styles of the react-select component
257257

258258
.display-none {
259259
display: none!important;
260+
}
261+
262+
.lui-feature-img img {
263+
padding: 20px;
260264
}

0 commit comments

Comments
 (0)