Skip to content

Commit b41864b

Browse files
committed
feat(cwn-dashboard): added a preview of the customizable navbar
1 parent e19842c commit b41864b

5 files changed

Lines changed: 176 additions & 69 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
describe('navbarPreview', { defaultCommandTimeout: 5000 }, () => {
2+
beforeEach(() => {
3+
cy.viewport(1440, 1080);
4+
});
5+
it('should not exist yet', () => {
6+
cy.visit('/admin/global');
7+
cy.get('My Test Link').should('not.exist');
8+
});
9+
it('should add a new tab', () => {
10+
// Add first tab
11+
cy.get('[data-cy="addNavButton"]').click();
12+
cy.get('[data-cy="customizeNavName"]').contains('New Url').click();
13+
cy.get('input[name="title"][value="New Url"]').clear().type('My Test Link');
14+
cy.get('input[name="url"][value="/new-url"]').clear().type('/My-Test-Link');
15+
cy.contains('Update').click();
16+
17+
// Add second tab
18+
cy.get('[data-cy="addNavButton"]').click();
19+
cy.get('[data-cy="customizeNavName"]').contains('New Url').click();
20+
cy.get('input[name="title"][value="New Url"]')
21+
.clear()
22+
.type('My Test Link 2');
23+
cy.get('input[name="url"][value="/new-url"]')
24+
.clear()
25+
.type('/My-Test-Link-2');
26+
cy.get('[data-cy="customizeNavName"]')
27+
.siblings()
28+
.find('button')
29+
.contains('Update')
30+
.click();
31+
});
32+
33+
it('should remove a tab', () => {
34+
cy.contains('My Test Link 2')
35+
.siblings()
36+
.find('[data-testid="DeleteIcon"]')
37+
.click();
38+
cy.contains('My Test Link 2').should('not.exist');
39+
});
40+
41+
it('should update a tab', () => {
42+
cy.get('input[name="title"][value="My Test Link"]')
43+
.clear()
44+
.type('UpdatedLink');
45+
cy.get('input[name="url"][value="/My-Test-Link"]')
46+
.clear()
47+
.type('/UpdatedLink');
48+
cy.get('[data-cy="customizeNavName"]')
49+
.siblings()
50+
.find('button')
51+
.contains('Update')
52+
.click();
53+
});
54+
55+
it('should navigate to new url tab', () => {
56+
cy.get('[data-cy="addNavButton"]').click();
57+
cy.get('[data-cy="customizeNavName"]').contains('New Url').click();
58+
cy.get('input[name="title"][value="New Url"]').clear().type('Home');
59+
cy.get('input[name="url"][value="/new-url"]')
60+
.clear()
61+
.type('https://greenstand.org/home');
62+
cy.get('[data-cy="customizeNavName"]')
63+
.siblings()
64+
.find('button')
65+
.contains('Update')
66+
.click();
67+
cy.get('a[href="https://greenstand.org/home"]').click();
68+
});
69+
});

src/components/Navbar.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import {
88
Typography,
99
} from '@mui/material';
1010
import Image from 'next/image';
11-
import { useState } from 'react';
11+
import { useState, useEffect } from 'react';
1212
import { initialState } from 'context/configContext';
13+
import { getStorageValue } from 'hooks/globalHooks/useLocalStorage';
1314
import MenuBar from 'images/MenuBar';
1415
import { makeStyles } from 'models/makeStyles';
1516
import ChangeThemeButton from './ChangeThemeButton';
@@ -60,11 +61,11 @@ const useStyles = makeStyles()((theme) => ({
6061
},
6162
}));
6263

63-
function Navbar() {
64+
function Navbar({ preview }) {
6465
const [anchorEl, setAnchorEl] = useState(null);
6566
const isMobile = useMobile();
6667
const [webMapConfig] = useLocalStorage('config', initialState);
67-
const { items: navItems } = webMapConfig.navbar;
68+
const [navItems, setNavItems] = useState(webMapConfig.navbar.items);
6869

6970
const open = Boolean(anchorEl);
7071
const handleMenuClick = (event) => {
@@ -74,10 +75,24 @@ function Navbar() {
7475
setAnchorEl(null);
7576
};
7677
const { classes } = useStyles();
78+
79+
// Detect webMapConfig changes. Reactively update the nav-items;
80+
useEffect(() => {
81+
const updateFunction = () => {
82+
const localWebMapConfig = getStorageValue('config', initialState);
83+
setNavItems(localWebMapConfig.navbar.items);
84+
};
85+
window.addEventListener('storage', updateFunction);
86+
return () => {
87+
window.removeEventListener('storage', updateFunction);
88+
};
89+
}, []);
90+
7791
return (
7892
<AppBar
7993
elevation={4}
8094
className={classes.navContainer}
95+
sx={preview ? { width: '100%!important' } : null}
8196
color="default"
8297
position="static"
8398
>

src/components/dashboard/CustomizeNavbar.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,13 @@ function CustomAccordion({ item: defaultItem, index }) {
137137
<div {...provided.dragHandleProps}>
138138
<DragIndicatorIcon />
139139
</div>
140-
<Typography>{item.title}</Typography>
140+
<Typography data-cy="customizeNavName">{item.title}</Typography>
141141
<Box>
142-
{hasItemChanged && <Button onClick={handleUpdate}>Update</Button>}
142+
{hasItemChanged && (
143+
<Button data-cy="UpdateButton" onClick={handleUpdate}>
144+
Update
145+
</Button>
146+
)}
143147
<SquareIconButton
144148
icon={<DeleteIcon />}
145149
onClick={handleDelete}
@@ -197,7 +201,9 @@ function CustomizeNavbar() {
197201
)}
198202
</Droppable>
199203
</DragDropContext>
200-
<Button onClick={onAddNewItem}>New Item</Button>
204+
<Button onClick={onAddNewItem} data-cy="addNavButton">
205+
New Item
206+
</Button>
201207
</>
202208
);
203209
}

src/hooks/globalHooks/useLocalStorage.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
33
const KEY_PREFIX = 'greenstand-web-map-client-';
44

55
// Get value from localStorage if possible, otherwise return provided default
6-
function getStorageValue(key, defaultValue) {
6+
export function getStorageValue(key, defaultValue) {
77
if (typeof window !== 'undefined') {
88
const value = localStorage.getItem(KEY_PREFIX + key);
99
let saved;
@@ -23,6 +23,7 @@ const useLocalStorage = (key, defaultValue) => {
2323

2424
useEffect(() => {
2525
localStorage.setItem(KEY_PREFIX + key, JSON.stringify(value));
26+
window.dispatchEvent(new Event('storage'));
2627
}, [key, value]);
2728

2829
return [value, setValue];

src/pages/admin/global.js

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { Box, Typography, Divider, List } from '@mui/material';
22
import dynamic from 'next/dynamic';
33
import { useEffect, useState } from 'react';
44
import HeadTag from 'components/HeadTag';
5+
import Navbar from 'components/Navbar';
56
import ChangeLogoSection from 'components/dashboard/ChangeLogoSection';
67
import ChangeNavSection from 'components/dashboard/ChangeNavSection';
78
import { Tab, TabPanel } from 'components/dashboard/Tabs';
89
import { ConfigProvider, useConfigContext } from 'context/configContext';
10+
import { CustomThemeProvider } from 'context/themeContext';
911
import { getOrganizationById } from 'models/api';
1012
import { updateLogoUrl } from 'models/config.reducer';
1113
import { wrapper } from 'models/utils';
@@ -47,79 +49,93 @@ function Global({ organization }) {
4749
}, [mapContext, organization, state.map.initialLocation]);
4850

4951
return (
50-
<>
51-
<HeadTag title="Admin Dashboard" />
52-
<Box
53-
sx={{
54-
display: 'flex',
55-
height: '100vh',
56-
}}
57-
>
52+
<CustomThemeProvider>
53+
<HeadTag title="Admin Dashboard" />
5854
<Box
5955
sx={{
60-
minWidth: '220px',
61-
p: 2,
62-
backgroundColor: '#f5f5f3',
56+
display: 'flex',
57+
height: '100vh',
6358
}}
6459
>
65-
<Typography
66-
variant="h6"
60+
<Box
6761
sx={{
68-
textAlign: 'center',
62+
minWidth: '220px',
63+
p: 2,
64+
backgroundColor: '#f5f5f3',
6965
}}
7066
>
71-
Dashboard
72-
</Typography>
73-
<Divider
74-
sx={{
75-
my: 2,
76-
}}
77-
/>
78-
<List
79-
sx={{
80-
p: 0,
81-
}}
82-
>
83-
<Tab value={currentTab} index={0} onClick={handleSidebarClick}>
84-
<Typography>Navbar Settings</Typography>
85-
</Tab>
86-
<Tab value={currentTab} index={1} onClick={handleSidebarClick}>
87-
<Typography>Theme Settings</Typography>
88-
</Tab>
89-
<Tab value={currentTab} index={2} onClick={handleSidebarClick}>
90-
<Typography>Map Settings</Typography>
91-
</Tab>
92-
</List>
93-
</Box>
94-
<Box
95-
sx={{
96-
flex: 1,
97-
p: 2,
98-
}}
99-
>
100-
<TabPanel value={currentTab} index={0}>
101-
<Typography variant="h5">Navbar View</Typography>
102-
<Box
67+
<Typography
68+
variant="h6"
10369
sx={{
104-
display: 'flex',
105-
flexDirection: 'row',
106-
justifyContent: 'space-between',
70+
textAlign: 'center',
10771
}}
10872
>
109-
<ChangeLogoSection />
110-
<ChangeNavSection />
111-
</Box>
112-
</TabPanel>
113-
<TabPanel value={currentTab} index={1}>
114-
<Typography variant="h5">Theme View</Typography>
115-
</TabPanel>
116-
<TabPanel value={currentTab} index={2}>
117-
<Typography variant="h5">Map View</Typography>
118-
<MapLayout />
119-
</TabPanel>
73+
Dashboard
74+
</Typography>
75+
<Divider
76+
sx={{
77+
my: 2,
78+
}}
79+
/>
80+
<List
81+
sx={{
82+
p: 0,
83+
}}
84+
>
85+
<Tab value={currentTab} index={0} onClick={handleSidebarClick}>
86+
<Typography>Navbar Settings</Typography>
87+
</Tab>
88+
<Tab value={currentTab} index={1} onClick={handleSidebarClick}>
89+
<Typography>Theme Settings</Typography>
90+
</Tab>
91+
<Tab value={currentTab} index={2} onClick={handleSidebarClick}>
92+
<Typography>Map Settings</Typography>
93+
</Tab>
94+
</List>
95+
</Box>
96+
<Box
97+
sx={{
98+
flex: 1,
99+
p: 2,
100+
}}
101+
>
102+
<TabPanel value={currentTab} index={0}>
103+
<Typography variant="h4">Navbar Preview</Typography>
104+
<Box
105+
sx={{
106+
display: 'flex',
107+
flexDirection: 'column',
108+
justifyContent: 'center',
109+
paddingY: '50px;',
110+
backgroundColor: 'background.paperDark',
111+
borderRadius: '8px',
112+
marginBottom: '24px',
113+
}}
114+
>
115+
<Navbar preview />
116+
</Box>
117+
118+
<Box
119+
sx={{
120+
display: 'flex',
121+
flexDirection: 'row',
122+
justifyContent: 'space-between',
123+
}}
124+
>
125+
<ChangeLogoSection />
126+
<ChangeNavSection />
127+
</Box>
128+
</TabPanel>
129+
<TabPanel value={currentTab} index={1}>
130+
<Typography variant="h5">Theme View</Typography>
131+
</TabPanel>
132+
<TabPanel value={currentTab} index={2}>
133+
<Typography variant="h5">Map View</Typography>
134+
<MapLayout />
135+
</TabPanel>
136+
</Box>
120137
</Box>
121-
</Box>
122-
</>
138+
</CustomThemeProvider>
123139
);
124140
}
125141

0 commit comments

Comments
 (0)