-
Notifications
You must be signed in to change notification settings - Fork 48
Vertex:(Migration)Update Network Management Module to use InfoBanners #3558
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
Changes from all commits
abf573d
cdd64ca
0f68b2d
0163fe5
713d074
cd0f1ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,18 +9,19 @@ import { Form, FormField } from "@/components/ui/form"; | |
| import ReusableDialog from "@/components/shared/dialog/ReusableDialog"; | ||
| import ReusableInputField from "@/components/shared/inputfield/ReusableInputField"; | ||
| import ReusableButton from "@/components/shared/button/ReusableButton"; | ||
| import ReusableToast from "@/components/shared/toast/ReusableToast"; | ||
| import { AqPlus } from "@airqo/icons-react"; | ||
| import { getApiErrorMessage } from "@/core/utils/getApiErrorMessage"; | ||
| import ReusableSelectInput from "@/components/shared/select/ReusableSelectInput"; | ||
|
|
||
| import { useBanner } from "@/context/banner-context"; | ||
| import { useBannerWithDelay } from "@/core/hooks/useBannerWithDelay"; | ||
| import { networkFormSchema, NetworkFormValues } from "./schema"; | ||
|
|
||
| export function CreateNetworkForm() { | ||
| const [open, setOpen] = useState(false); | ||
| const [isPending, setIsPending] = useState(false); | ||
| const queryClient = useQueryClient(); | ||
|
|
||
| const { showBanner } = useBanner(); | ||
| const { showBannerWithDelay } = useBannerWithDelay(); | ||
| const form = useForm<NetworkFormValues>({ | ||
| resolver: zodResolver(networkFormSchema), | ||
| defaultValues: { | ||
|
|
@@ -48,19 +49,18 @@ export function CreateNetworkForm() { | |
| try { | ||
| await axios.post('/api/network', values, { | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| }); | ||
|
|
||
| ReusableToast({ message: 'Sensor Manufacturer created successfully!', type: 'SUCCESS' }); | ||
| }); | ||
| queryClient.invalidateQueries({ queryKey: ["networks"] }); | ||
| handleClose(); | ||
| showBannerWithDelay({ severity: 'success', message: 'Sensor Manufacturer created successfully!', scoped: false }); | ||
| } catch (error: unknown) { | ||
| const errorMessage = getApiErrorMessage(error); | ||
| ReusableToast({ message: errorMessage, type: 'ERROR' }); | ||
| const errorMessage = getApiErrorMessage(error); | ||
| showBanner({ severity: 'error', message: errorMessage, scoped: true }); | ||
|
Comment on lines
+57
to
+58
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Comment on lines
+55
to
+58
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copilot ReusableDialog already includes internally no changes needed. |
||
| } finally { | ||
| setIsPending(false); | ||
| } | ||
| }, | ||
| [handleClose, queryClient] | ||
| [handleClose, queryClient, showBanner, showBannerWithDelay] | ||
| ); | ||
|
|
||
| return ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,8 +9,9 @@ import ReusableDialog from "@/components/shared/dialog/ReusableDialog"; | |||||||||||||||||||||||||||||||||
| import ReusableInputField from "@/components/shared/inputfield/ReusableInputField"; | ||||||||||||||||||||||||||||||||||
| import { networkRequestSchema, NetworkRequestValues } from "./schema"; | ||||||||||||||||||||||||||||||||||
| import { useAppSelector } from "@/core/redux/hooks"; | ||||||||||||||||||||||||||||||||||
| import ReusableToast from "@/components/shared/toast/ReusableToast"; | ||||||||||||||||||||||||||||||||||
| import { getApiErrorMessage } from "@/core/utils/getApiErrorMessage"; | ||||||||||||||||||||||||||||||||||
| import { useBanner } from "@/context/banner-context"; | ||||||||||||||||||||||||||||||||||
| import { useBannerWithDelay } from "@/core/hooks/useBannerWithDelay"; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| interface NetworkRequestDialogProps { | ||||||||||||||||||||||||||||||||||
| open: boolean; | ||||||||||||||||||||||||||||||||||
|
|
@@ -20,6 +21,8 @@ interface NetworkRequestDialogProps { | |||||||||||||||||||||||||||||||||
| export function NetworkRequestDialog({ open, onOpenChange }: NetworkRequestDialogProps) { | ||||||||||||||||||||||||||||||||||
| const userDetails = useAppSelector((state) => state.user.userDetails); | ||||||||||||||||||||||||||||||||||
| const queryClient = useQueryClient(); | ||||||||||||||||||||||||||||||||||
| const { showBanner } = useBanner(); | ||||||||||||||||||||||||||||||||||
| const { showBannerWithDelay } = useBannerWithDelay(); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const { mutate: submitRequest, isPending } = useMutation({ | ||||||||||||||||||||||||||||||||||
| mutationFn: async (data: NetworkRequestValues) => { | ||||||||||||||||||||||||||||||||||
|
|
@@ -37,15 +40,12 @@ export function NetworkRequestDialog({ open, onOpenChange }: NetworkRequestDialo | |||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| return response.json(); | ||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||
| onSuccess: (resp) => { | ||||||||||||||||||||||||||||||||||
| ReusableToast({ | ||||||||||||||||||||||||||||||||||
| message: resp.message || "Your request for a new Sensor Manufacturer has been submitted successfully!", | ||||||||||||||||||||||||||||||||||
| type: "SUCCESS", | ||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||
| onSuccess: (resp) => { | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| queryClient.invalidateQueries({ queryKey: ["network-requests"] }); | ||||||||||||||||||||||||||||||||||
| showBannerWithDelay({ severity: 'success', message: resp.message || "Your request for a new Sensor Manufacturer has been submitted successfully!", scoped: true }); | ||||||||||||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was already explained |
||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||
| onError: (error) => { | ||||||||||||||||||||||||||||||||||
| ReusableToast({ message: getApiErrorMessage(error), type: "ERROR" }); | ||||||||||||||||||||||||||||||||||
| onError: (error) => { | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| showBanner({ severity: 'error', message: getApiErrorMessage(error), scoped: true }); | ||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
49
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both banners are currently unreachable as wired. Two separate problems here, mirroring (and partly contradicting)
🛠️ Suggested fix- const {showBanner}=useBanner();
+ const { showBanner, BannerSlot } = useBanner();
@@
- onSuccess: (resp) => {
- queryClient.invalidateQueries({ queryKey: ["network-requests"] });
- showBannerWithDelay({severity:'success',message:resp.message || "Your request for a new Sensor Manufacturer has been submitted successfully!",scoped:true});
- },
- onError: (error) => {
- showBanner({severity:'error',message:getApiErrorMessage(error),scoped:true})
- },
+ onSuccess: (resp) => {
+ queryClient.invalidateQueries({ queryKey: ["network-requests"] });
+ showBannerWithDelay({ severity: 'success', message: resp.message || "Your request for a new Sensor Manufacturer has been submitted successfully!", scoped: false });
+ },
+ onError: (error) => {
+ showBanner({ severity: 'error', message: getApiErrorMessage(error), scoped: true });
+ },And mount the slot inside the form for the scoped error: <Form {...form}>
+ <BannerSlot />
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The success banner has to be scoped
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The PR description images show three scenarios: (1) net1 — "Create A New Sensor Manufacturer" modal with a scoped error banner rendered inside it; (2) net2 — "Request New Sensor Manufacturer" modal with a scoped error banner ("Network request timed out") visible inside the modal; (3) net3 — "Import External Device" modal displaying a green success banner ("sensor manufacturer creation request submitted successfully") after the Request dialog has already closed.
Similarly, the error banner in net2 appearing inside the dialog makes sense for the same reason — the parent modal's My original concern was based on a single-modal assumption; the stacked-modal context makes (◕‿◕)🐇 ✏️ Learnings added
🧠 Learnings used
Comment on lines
+47
to
49
|
||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.