Skip to content

Commit a694de5

Browse files
committed
add recently updated badge and menu text
1 parent b02fd63 commit a694de5

File tree

5 files changed

+116
-10
lines changed

5 files changed

+116
-10
lines changed

backend/src/types/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@ export type Config = {
22
layout: {
33
desktop: DashboardItem[];
44
mobile: DashboardItem[];
5-
}
5+
},
6+
title?: string;
7+
backgroundImage?: string;
8+
search?: boolean;
9+
searchProvider?: string;
10+
isSetupComplete?: boolean;
11+
lastSeenVersion?: string;
612
}
713

814
export type DashboardLayout = {

frontend/src/components/navbar/ResponsiveAppBar.tsx

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ export const ResponsiveAppBar = ({ children }: Props) => {
5959
isAdmin,
6060
setIsAdmin,
6161
updateAvailable,
62-
latestVersion
62+
latestVersion,
63+
recentlyUpdated,
64+
handleVersionViewed
6365
} = useAppContext();
6466

6567
const location = useLocation();
@@ -68,6 +70,12 @@ export const ResponsiveAppBar = ({ children }: Props) => {
6870

6971
const handleClose = () => setOpenAddModal(false);
7072
const handleCloseUpdateModal = () => setOpenUpdateModal(false);
73+
const handleCloseVersionModal = async () => {
74+
setOpenVersionModal(false);
75+
if (isAdmin && recentlyUpdated) {
76+
await handleVersionViewed();
77+
}
78+
};
7179

7280
const handleEditCancel = () => {
7381
handleCloseDrawer();
@@ -234,6 +242,7 @@ export const ResponsiveAppBar = ({ children }: Props) => {
234242
}}
235243
>
236244
{updateAvailable ? (
245+
// Only update available badge (red) - given priority
237246
<Badge
238247
color='error'
239248
variant='dot'
@@ -246,7 +255,22 @@ export const ResponsiveAppBar = ({ children }: Props) => {
246255
>
247256
<MenuIcon sx={{ color: 'white', fontSize: '2rem' }}/>
248257
</Badge>
258+
) : recentlyUpdated ? (
259+
// Only recently updated badge (blue)
260+
<Badge
261+
sx={{
262+
'& .MuiBadge-badge': {
263+
backgroundColor: '#2196f3', // Blue color
264+
top: 0,
265+
right: -5
266+
}
267+
}}
268+
variant='dot'
269+
>
270+
<MenuIcon sx={{ color: 'white', fontSize: '2rem' }}/>
271+
</Badge>
249272
) : (
273+
// No badges
250274
<MenuIcon sx={{ color: 'white', fontSize: '2rem' }}/>
251275
)}
252276
</IconButton>
@@ -343,14 +367,36 @@ export const ResponsiveAppBar = ({ children }: Props) => {
343367
<ListItem disablePadding>
344368
<ListItemButton onClick={handleOpenVersionModal}>
345369
<ListItemIcon>
346-
<FaInfoCircle style={{ color: theme.palette.text.primary, fontSize: 22, marginLeft: '-4px' }} />
370+
{recentlyUpdated ? (
371+
<Badge
372+
sx={{
373+
'& .MuiBadge-badge': {
374+
backgroundColor: '#2196f3', // Blue color
375+
top: -2,
376+
right: -3
377+
}
378+
}}
379+
variant='dot'
380+
overlap='circular'
381+
>
382+
<FaInfoCircle style={{ color: theme.palette.text.primary, fontSize: 22, marginLeft: '-4px' }} />
383+
</Badge>
384+
) : (
385+
<FaInfoCircle style={{ color: theme.palette.text.primary, fontSize: 22, marginLeft: '-4px' }} />
386+
)}
347387
</ListItemIcon>
348388
<ListItemText
349389
primary={
350390
<Typography>
351-
v{getAppVersion()}
391+
{recentlyUpdated ? 'Recently Updated' : 'Version'}
352392
</Typography>
353393
}
394+
secondary={`v${getAppVersion()}`}
395+
slotProps={{
396+
secondary: {
397+
color: 'text.primary'
398+
}
399+
}}
354400
/>
355401
</ListItemButton>
356402
</ListItem>
@@ -432,7 +478,7 @@ export const ResponsiveAppBar = ({ children }: Props) => {
432478
{/* Version Modal */}
433479
<VersionModal
434480
open={openVersionModal}
435-
handleClose={() => setOpenVersionModal(false)}
481+
handleClose={handleCloseVersionModal}
436482
/>
437483
</AppBar>
438484
<Box sx={{

frontend/src/context/AppContext.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@ export interface IAppContext {
2626
setSetupComplete: Dispatch<SetStateAction<boolean>>;
2727
checkIfUsersExist: () => Promise<void>;
2828
checkLoginStatus: () => Promise<void>;
29+
// Update states
2930
updateAvailable: boolean;
3031
latestVersion: string | null;
3132
releaseUrl: string | null;
3233
checkForAppUpdates: () => Promise<void>;
34+
// Recently updated state
35+
recentlyUpdated: boolean;
36+
handleVersionViewed: () => Promise<void>;
3337
}
3438

3539
export const AppContext = createContext<IAppContext>(null!);

frontend/src/context/AppContextProvider.tsx

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { initialItems } from '../constants/constants';
88
import { theme } from '../theme/theme';
99
import { Config, DashboardItem, DashboardLayout, NewItem } from '../types';
1010
import { checkForUpdates } from '../utils/updateChecker';
11+
import { getAppVersion } from '../utils/version';
1112

1213
type Props = {
1314
children: ReactNode
@@ -31,6 +32,9 @@ export const AppContextProvider = ({ children }: Props) => {
3132
const [latestVersion, setLatestVersion] = useState<string | null>(null);
3233
const [releaseUrl, setReleaseUrl] = useState<string | null>(null);
3334

35+
// Recently updated states
36+
const [recentlyUpdated, setRecentlyUpdated] = useState<boolean>(false);
37+
3438
// Initialize authentication state and check if first time setup
3539
useEffect(() => {
3640
const initializeAuth = async () => {
@@ -68,7 +72,7 @@ export const AppContextProvider = ({ children }: Props) => {
6872
await checkForAppUpdates();
6973

7074
// Set interval to check every 6 hours (6 * 60 * 60 * 1000 ms)
71-
const intervalId = setInterval(checkForAppUpdates, 60 * 60 * 1000);
75+
const intervalId = setInterval(checkForAppUpdates, 6 * 60 * 60 * 1000);
7276

7377
// Clear interval on component unmount
7478
return () => clearInterval(intervalId);
@@ -77,6 +81,29 @@ export const AppContextProvider = ({ children }: Props) => {
7781
checkUpdatesPeriodically();
7882
}, []);
7983

84+
// Check if the app was recently updated
85+
useEffect(() => {
86+
const checkForRecentUpdate = async () => {
87+
// Only proceed if we have the config
88+
if (!config) return;
89+
90+
const currentVersion = getAppVersion();
91+
92+
// Get the last seen version from config, may be undefined
93+
const lastSeenVersion = config.lastSeenVersion;
94+
95+
// If no stored version, or versions differ, the app was updated
96+
if (!lastSeenVersion || lastSeenVersion !== currentVersion) {
97+
console.log('App was updated from', lastSeenVersion, 'to', currentVersion);
98+
setRecentlyUpdated(true);
99+
} else {
100+
setRecentlyUpdated(false);
101+
}
102+
};
103+
104+
checkForRecentUpdate();
105+
}, [config]);
106+
80107
// Function to check for updates
81108
const checkForAppUpdates = async () => {
82109
try {
@@ -91,6 +118,23 @@ export const AppContextProvider = ({ children }: Props) => {
91118
}
92119
};
93120

121+
// Function to mark the current version as viewed
122+
const handleVersionViewed = async (): Promise<void> => {
123+
if (!isAdmin) return; // Only admins can update config
124+
125+
try {
126+
const currentVersion = getAppVersion();
127+
128+
// Update config with the current version as last seen
129+
await updateConfig({ lastSeenVersion: currentVersion });
130+
131+
// Update local state
132+
setRecentlyUpdated(false);
133+
} catch (error) {
134+
console.error('Error updating last seen version:', error);
135+
}
136+
};
137+
94138
// Check if users exist in the system
95139
const checkIfUsersExist = async () => {
96140
try {
@@ -362,31 +406,36 @@ export const AppContextProvider = ({ children }: Props) => {
362406
return (
363407
<Provider value={{
364408
dashboardLayout,
409+
setDashboardLayout,
365410
refreshDashboard,
366411
saveLayout,
367412
addItem,
368-
setDashboardLayout,
369413
updateItem,
370414
editMode,
371415
setEditMode,
372416
config,
373417
updateConfig,
418+
// Authentication states
374419
isLoggedIn,
375420
setIsLoggedIn,
376421
username,
377422
setUsername,
423+
isAdmin,
424+
setIsAdmin,
378425
isFirstTimeSetup,
379426
setIsFirstTimeSetup,
380427
setupComplete,
381428
setSetupComplete,
382429
checkIfUsersExist,
383-
isAdmin,
384-
setIsAdmin,
385430
checkLoginStatus,
431+
// Update states
386432
updateAvailable,
387433
latestVersion,
388434
releaseUrl,
389-
checkForAppUpdates
435+
checkForAppUpdates,
436+
// Recently updated states
437+
recentlyUpdated,
438+
handleVersionViewed
390439
}}>
391440
{children}
392441
</Provider>

frontend/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export type Config = {
5151
search?: boolean;
5252
searchProvider?: SearchProvider;
5353
isSetupComplete?: boolean;
54+
lastSeenVersion?: string;
5455
}
5556

5657
export type UploadImageResponse = {

0 commit comments

Comments
 (0)