Skip to content

Commit 827ec3c

Browse files
Content snackbar and page 3 layout update (#419)
* Remove content ID from snackbar messages * Add slide-in and clean disappear to snackbars on content page * Make content edit/creation snackbar independent of URL * Update to "Query Topics" and update logos * Refactor dashboard page 3 layout components * Hide AI summary box if discovery has never been run * Button now says Run Discovery if never ran, "Rerun" if ran before. Updated to LoadingButton with magic wand logo. --------- Co-authored-by: Mark Botterill <markbotters@gmail.com>
1 parent e76dbf3 commit 827ec3c

File tree

7 files changed

+123
-91
lines changed

7 files changed

+123
-91
lines changed

admin_app/src/app/content/edit/page.tsx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ const ContentBox = ({
160160
const [highlightedOption, setHighlightedOption] = React.useState<Tag | null>();
161161
const [isSaving, setIsSaving] = React.useState(false);
162162

163+
const setMainPageSnackMessage = (message: string): void => {
164+
localStorage.setItem("editPageSnackMessage", message);
165+
};
166+
163167
const router = useRouter();
164168
React.useEffect(() => {
165169
const fetchTags = async () => {
@@ -181,6 +185,7 @@ const ContentBox = ({
181185

182186
fetchTags();
183187
}, [refreshKey]);
188+
184189
const saveContent = async (content: Content): Promise<number | null> => {
185190
setIsSaving(true);
186191

@@ -215,6 +220,19 @@ const ContentBox = ({
215220
setIsSaving(false);
216221
}
217222
};
223+
224+
const handleSaveContent = async (content: Content) => {
225+
const content_id = await saveContent(content);
226+
if (content_id) {
227+
{
228+
content.content_id
229+
? setMainPageSnackMessage("Content edited successfully")
230+
: setMainPageSnackMessage("Content created successfully");
231+
}
232+
router.push(`/content`);
233+
}
234+
};
235+
218236
function createEmptyContent(contentTags: Tag[]): Content {
219237
return {
220238
content_id: null,
@@ -228,6 +246,7 @@ const ContentBox = ({
228246
content_metadata: {},
229247
};
230248
}
249+
231250
const handleChange = (
232251
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
233252
key: keyof Content,
@@ -242,6 +261,7 @@ const ContentBox = ({
242261
: setContent({ ...emptyContent, [key]: e.target.value });
243262
setIsSaved(false);
244263
};
264+
245265
const handleTagsChange = (updatedTags: Tag[]) => {
246266
setContentTags(updatedTags);
247267
setIsSaved(false);
@@ -272,6 +292,7 @@ const ContentBox = ({
272292
setSnackMessage(`Tag "${tag}" already exists`);
273293
}
274294
};
295+
275296
const openDeleteConfirmModal = (tag: Tag) => {
276297
setTagToDelete(tag);
277298
setOpenDeleteModal(true);
@@ -289,6 +310,7 @@ const ContentBox = ({
289310
});
290311
}
291312
};
313+
292314
return (
293315
<Layout.FlexBox>
294316
<Dialog
@@ -500,15 +522,6 @@ const ContentBox = ({
500522
} else if (content.content_text === "") {
501523
setIsContentEmpty(true);
502524
} else {
503-
const handleSaveContent = async (content: Content) => {
504-
const content_id = await saveContent(content);
505-
if (content_id) {
506-
const actionType = content.content_id ? "edit" : "add";
507-
router.push(
508-
`/content/?content_id=${content_id}&action=${actionType}`,
509-
);
510-
}
511-
};
512525
handleSaveContent(content);
513526
}
514527
}}

admin_app/src/app/content/page.tsx

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import {
1515
Menu,
1616
MenuItem,
1717
Paper,
18+
Slide,
19+
SlideProps,
1820
Snackbar,
1921
TextField,
2022
Tooltip,
@@ -30,7 +32,7 @@ import type { Content } from "@/app/content/edit/page";
3032
import ContentCard from "./components/ContentCard";
3133
import { DownloadModal } from "./components/DownloadModal";
3234
import { Layout } from "@/components/Layout";
33-
import { appStyles, appColors, LANGUAGE_OPTIONS, sizes } from "@/utils";
35+
import { appColors, LANGUAGE_OPTIONS, sizes } from "@/utils";
3436
import { apiCalls } from "@/utils/api";
3537
import { useAuth } from "@/utils/auth";
3638
import { ImportModal } from "./components/ImportModal";
@@ -101,6 +103,10 @@ const CardsPage = () => {
101103
}
102104
}, [accessLevel, token]);
103105

106+
const SnackbarSlideTransition = (props: SlideProps) => {
107+
return <Slide {...props} direction="up" />;
108+
};
109+
104110
return (
105111
<>
106112
<Grid container>
@@ -205,10 +211,11 @@ const CardsPage = () => {
205211
</Grid>
206212
<Snackbar
207213
open={snackMessage.message !== null}
208-
autoHideDuration={6000}
214+
autoHideDuration={4000}
209215
onClose={() => {
210216
setSnackMessage({ message: null, color: snackMessage.color });
211217
}}
218+
TransitionComponent={SnackbarSlideTransition}
212219
>
213220
<Alert
214221
onClose={() => {
@@ -414,8 +421,6 @@ const CardsGrid = ({
414421
const [isLoading, setIsLoading] = React.useState<boolean>(true);
415422

416423
const searchParams = useSearchParams();
417-
const action = searchParams.get("action") || null;
418-
const content_id = Number(searchParams.get("content_id")) || null;
419424

420425
const calculateMaxCardsPerPage = () => {
421426
// set rows as per height of each card and height of grid (approximated from window height)
@@ -445,41 +450,20 @@ const CardsGrid = ({
445450
return () => window.removeEventListener("resize", calculateMaxCardsPerPage);
446451
}, []);
447452

448-
const getSnackMessage = React.useCallback(
449-
(action: string | null, content_id: number | null): string | null => {
450-
if (action === "edit") {
451-
return `Content #${content_id} updated`;
452-
} else if (action === "add") {
453-
return `Content #${content_id} created`;
454-
}
455-
return null;
456-
},
457-
[],
458-
);
459-
460-
React.useEffect(() => {
461-
if (action) {
462-
setSnackMessage({
463-
message: getSnackMessage(action, content_id),
464-
color: "success",
465-
});
466-
}
467-
}, [action, content_id, getSnackMessage]);
468-
469453
const [refreshKey, setRefreshKey] = React.useState(0);
470454
const onSuccessfulArchive = (content_id: number) => {
471455
setIsLoading(true);
472456
setRefreshKey((prevKey) => prevKey + 1);
473457
setSnackMessage({
474-
message: `Content #${content_id} removed successfully`,
458+
message: `Content removed successfully`,
475459
color: "success",
476460
});
477461
};
478462
const onSuccessfulDelete = (content_id: number) => {
479463
setIsLoading(true);
480464
setRefreshKey((prevKey) => prevKey + 1);
481465
setSnackMessage({
482-
message: `Content #${content_id} deleted successfully`,
466+
message: `Content deleted successfully`,
483467
color: "success",
484468
});
485469
};
@@ -504,6 +488,15 @@ const CardsGrid = ({
504488
setCards(filteredData);
505489
setMaxPages(Math.ceil(filteredData.length / maxCardsPerPage));
506490
setIsLoading(false);
491+
492+
const message = localStorage.getItem("editPageSnackMessage");
493+
if (message) {
494+
setSnackMessage({
495+
message: message,
496+
color: "success",
497+
});
498+
localStorage.removeItem("editPageSnackMessage");
499+
}
507500
})
508501
.catch((error) => {
509502
console.error("Failed to fetch content:", error);
@@ -618,7 +611,7 @@ const CardsGrid = ({
618611
onSuccessfulArchive={onSuccessfulArchive}
619612
onFailedArchive={(content_id: number) => {
620613
setSnackMessage({
621-
message: `Failed to remove content #${content_id}`,
614+
message: `Failed to remove content`,
622615
color: "error",
623616
});
624617
}}

admin_app/src/app/dashboard/components/Insights.tsx

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useState } from "react";
77
import { QueryData, Period, TopicModelingResponse } from "../types";
88
import { generateNewTopics, fetchTopicsData } from "../api";
99
import { useAuth } from "@/utils/auth";
10+
import { Paper } from "@mui/material";
1011

1112
interface InsightProps {
1213
timePeriod: Period;
@@ -76,44 +77,64 @@ const Insight: React.FC<InsightProps> = ({ timePeriod }) => {
7677
);
7778

7879
return (
79-
<Grid container sx={{ bgcolor: "grey.100", borderRadius: 2, mx: 0.5 }}>
80-
<Grid
81-
container
82-
md={12}
83-
columnSpacing={{ xs: 2 }}
84-
sx={{ bgcolor: "white", borderRadius: 2, mx: 0.5, mt: 2, height: 400 }}
80+
<Box
81+
sx={{
82+
display: "flex",
83+
flexDirection: "column",
84+
}}
85+
>
86+
<Paper
87+
elevation={0}
88+
sx={{
89+
display: "flex",
90+
flexDirection: "row",
91+
height: 600,
92+
width: "100%",
93+
border: 0.5,
94+
borderColor: "lightgrey",
95+
}}
8596
>
86-
<Grid
87-
md={3}
88-
sx={{ p: 2, borderRight: 1, borderColor: "grey.300", borderWidth: 2 }}
97+
<Box
98+
sx={{
99+
width: "25%",
100+
padding: 2,
101+
borderRight: 1,
102+
borderColor: "grey.300",
103+
borderWidth: 2,
104+
}}
89105
>
90106
<Topics
91107
data={topics}
92108
selectedTopicId={selectedTopicId}
93109
onClick={setSelectedTopicId}
94-
topicsPerPage={4}
110+
topicsPerPage={8}
95111
/>
96-
</Grid>
97-
<Grid md={9} sx={{ p: 2 }}>
112+
</Box>
113+
<Box
114+
sx={{
115+
padding: 2,
116+
width: "75%",
117+
}}
118+
>
98119
<Queries
99120
data={topicQueries}
100121
onRefreshClick={runRefresh}
101122
aiSummary={aiSummary}
102123
lastRefreshed={dataFromBackend.refreshTimeStamp}
103124
refreshing={refreshing}
104125
/>
105-
</Grid>
106-
</Grid>
107-
<Grid
108-
md={12}
109-
height={400}
126+
</Box>
127+
</Paper>
128+
<Paper
129+
elevation={0}
110130
sx={{
111-
bgcolor: "white",
112-
borderRadius: 2,
113-
mx: 0.5,
114-
mt: 2,
131+
width: "100%",
132+
height: "400px",
133+
marginTop: 2,
115134
justifyItems: "center",
116135
justifySelf: "stretch",
136+
border: 0.5,
137+
borderColor: "lightgrey",
117138
}}
118139
>
119140
<Box
@@ -125,10 +146,10 @@ const Insight: React.FC<InsightProps> = ({ timePeriod }) => {
125146
justifyContent: "center",
126147
}}
127148
>
128-
-- Chart - Coming Soon! --
149+
Chart coming soon!
129150
</Box>
130-
</Grid>
131-
</Grid>
151+
</Paper>
152+
</Box>
132153
);
133154
};
134155

admin_app/src/app/dashboard/components/Sidebar.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React from "react";
22

33
import {
4-
BarChart,
4+
Category,
55
ChevronLeft,
66
ChevronRight,
77
Dashboard,
8-
Insights,
8+
QueryStats,
99
} from "@mui/icons-material";
1010
import {
1111
Box,
@@ -27,16 +27,16 @@ interface SideBarProps {
2727
selectedDashboardPage: PageName;
2828
}
2929

30-
type PageName = "Overview" | "Content Performance" | "Content Gaps";
30+
type PageName = "Overview" | "Content Performance" | "Query Topics";
3131

3232
interface MenuItem {
3333
name: PageName;
3434
icon: React.ReactNode;
3535
}
3636
const menuItems: MenuItem[] = [
3737
{ name: "Overview", icon: <Dashboard /> },
38-
{ name: "Content Performance", icon: <BarChart /> },
39-
{ name: "Content Gaps", icon: <Insights /> },
38+
{ name: "Content Performance", icon: <QueryStats /> },
39+
{ name: "Query Topics", icon: <Category /> },
4040
];
4141
const openedMixin = (theme: Theme): CSSObject => ({
4242
width: drawerWidth,

0 commit comments

Comments
 (0)