-
Notifications
You must be signed in to change notification settings - Fork 248
MNTOR-4298 - Announcements ADR #5866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Preview URL 🚀 : https://blurts-server-pr-5866-mgjlpikfea-uk.a.run.app |
@@ -78,6 +78,7 @@ | |||
"@fluent/bundle": "^0.19.1", | |||
"@fluent/langneg": "^0.7.0", | |||
"@fluent/react": "^0.15.2", | |||
"@fluent/syntax": "^0.19.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty safe dependency built for tooling around fluent:
It’s designed to parse, analyze, process, and serialize Fluent files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That link goes to the docs for the Python implementation of Fluent - I think you mean this one :)
src/app/(proper_react)/(redesign)/(authenticated)/admin/announcements/getFluentStrings.ts
Outdated
Show resolved
Hide resolved
@@ -31,6 +33,8 @@ export const AnnouncementsAdmin = (props: Props) => { | |||
const [activeAnnouncementToEdit, setActiveAnnouncementToEdit] = | |||
useState<AnnouncementRow | null>(null); | |||
|
|||
console.log(props.fluentStrings); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
console.log(props.fluentStrings); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alt="Fallback image" | ||
width={500} | ||
height={300} | ||
key={activeAnnouncement.id} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The keys of the small and big images are duplicates: To make sure they don’t collide we should make them unique with for example:
key={activeAnnouncement.id} | |
key={`${activeAnnouncement.id}-small-fallback`} | |
key={`${activeAnnouncement.id}-small`} | |
key={`${activeAnnouncement.id-big-fallback`} | |
key={`${activeAnnouncement.id}-big`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{bigImageUnavailable ? ( | ||
<Image | ||
alt="Fallback image" | ||
width={500} | ||
height={300} | ||
key={activeAnnouncement.id} | ||
className={styles.bigImage} | ||
src="/images/announcements/fallback/big.svg" | ||
onLoadingComplete={() => setBigImageIsLoading(false)} | ||
/> | ||
) : ( | ||
<Image | ||
alt="Announcement preview" | ||
width={500} | ||
height={300} | ||
key={activeAnnouncement.id} | ||
src={bigImagePath} | ||
className={styles.bigImage} | ||
onLoadingComplete={() => setBigImageIsLoading(false)} | ||
onError={() => setBigImageUnavailable(true)} | ||
/> | ||
)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion (non-blocking): The fallback image logic is used a couple of times — it would be nice if we could unify this into a reusable component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
36c6d22 Added ImageWithFallback
which handles repeated logic.
list-style: none; | ||
margin-top: tokens.$spacing-md; | ||
padding-left: 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For list resetting, we have the class .noList
available that you could add to the <ul>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const ftlPath = path.resolve("locales-pending/announcements.ftl"); | ||
const raw = fs.readFileSync(ftlPath, "utf8"); | ||
const resource: Resource = parse(raw, { withSpans: false }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: This part should be wrapped in a try {} catch {}
to handle missing or invalid file contents when parsing the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (field === "title") { | ||
result[id].title = value; | ||
} else if (field === "description") { | ||
result[id].description = value; | ||
} else if (field === "cta-label") { | ||
result[id].ctaLabel = value; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Instead of mapping the string IDs could we also leave them as they are (in kebab-case)? If we still need to map them: Since we are not handling any additional logic we could also map them like this:
if (field === "title") { | |
result[id].title = value; | |
} else if (field === "description") { | |
result[id].description = value; | |
} else if (field === "cta-label") { | |
result[id].ctaLabel = value; | |
} | |
const map: Record<string, keyof AnnouncementGroup> = { | |
title: "title", | |
description": "description", | |
"cta-label": "ctaLabel", | |
}; | |
result[id][map[field]] = value; |
… or maybe parse the IDs to camelCase if we expect them to match otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even when getFluentStrings
is only used for the announcements admin panel, this function would benefit from some initial unit tests to validate the expected behavior. This would be especially helpful when making changes in the future.
import { GroupedFluentAnnouncements } from "./getFluentStrings"; | ||
import { ImageWithFallback } from "./ImageWithFallback"; | ||
import { FluentStringsView } from "./FluentStringsView"; | ||
import { AnnouncementsDocsView } from "./DocsView"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file was getting kind of unwieldy - I split out the tabs into separate components.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started out looking at the changed code, but it was so much, is never exposed to users, and it seems like Florian has also already done a pass on that, so I opted to stop my review of that and leave it to Florian to finish that up on Monday. I will say, though, that I'm impressed that you dove into the depths of the available Fluent packages to be able to display an interface over them :)
Speaking of, that interface looks useful, and having the docs there in context is as well. (Though small nit: it does not Record any Architectural Decisions, so it's not an ADR.) My main suggestion, though, would be to split it up in two: docs for admins using the UI (these docs), and docs for the parts that need to be done by an engineer, which could just live as a Markdown file under /docs/
in the repo (with a reference to it from the UI). Because right now, I imagine Tony would be a bit lost when trying to follow these docs.
@@ -78,6 +78,7 @@ | |||
"@fluent/bundle": "^0.19.1", | |||
"@fluent/langneg": "^0.7.0", | |||
"@fluent/react": "^0.15.2", | |||
"@fluent/syntax": "^0.19.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That link goes to the docs for the Python implementation of Fluent - I think you mean this one :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't care so much because it's just an admin page, but I always do a double-take whenever I type margin
, which I can highly recommend (just like e.g. for float
) 🙂 There's probably times when they're justified, but most of the time they make the layout of the rest of the page unpredictable over time.
> | ||
<div> | ||
<p className={styles.title}> | ||
<div className={styles.tabBar}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, not a blocker since it's "just" an admin page, but react-aria implements tab behaviour - e.g. to make sure you can switch tabs using the arrow keys, and to announce them to screen readers. Just FYI for the future.
<button | ||
className={styles.addButton} | ||
onClick={() => setIsModalOpen(true)} | ||
> | ||
+ Add new announcement | ||
</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A <button>
as a direct child of <ul>
is not valid and would need to be wrapped in an <li>
.
<dt>Big Image</dt> | ||
<dd> | ||
<ImageWithFallback | ||
src={smallImagePath} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be:
src={smallImagePath} | |
src={bigImagePath} |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering this is for admins only and the purpose of these additions, it looks good. There are some open pending comments that deserve a response before finishing this PR up.
References:
Jira: MNTOR-4298
Description
Introduces a Fluent UI section and accompanying documentation to the Announcements admin page, giving Product and QA teams clearer context and improving usability for this feature.
Screenshot (if applicable)
Not applicable.
How to test
Checklist (Definition of Done)