Skip to content

Commit 8c223ae

Browse files
committed
Update how notifications are handled.
1 parent d9363f4 commit 8c223ae

File tree

5 files changed

+102
-73
lines changed

5 files changed

+102
-73
lines changed

src/budget/overview/budget-detail.component.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import { Range } from "../../core/Dates";
2-
import { ApiError, Budget } from "../../core/types";
2+
import { Budget } from "../../core/types";
33
import React, { useEffect, useState } from "react";
44
import BudgetRepository from "../../core/repositories/budget.repository";
5-
import { Buttons, Dialog, Formats, Layout, Message, Notifications, Translations } from "../../core";
5+
import { Buttons, Dialog, Formats, Layout, Notifications, Translations } from "../../core";
66
import ExpenseOverviewComponent from "./expense-overview.component";
77
import { Form, Input, SubmitButton } from "../../core/form";
88
import { mdiContentSave, mdiPlus } from "@mdi/js";
99
import { AxiosError } from "axios";
1010

1111
const AddExpenseDialog = ({ onChange }: { onChange : () => void }) => {
1212
const editControl = { close: () => undefined }
13-
const [error, setError] = useState<string | undefined>()
1413

1514
const onSubmit = (values: any) => {
1615
const patch = {
@@ -22,10 +21,7 @@ const AddExpenseDialog = ({ onChange }: { onChange : () => void }) => {
2221
.then(() => Notifications.Service.success('page.budget.group.expense.added'))
2322
.then(editControl.close)
2423
.then(onChange)
25-
.catch((error: AxiosError) => {
26-
const apiError: ApiError = error.response?.data as ApiError
27-
setError(apiError._embedded?.errors[0]?.message || apiError.message)
28-
})
24+
.catch((error: AxiosError) => Notifications.Service.exception(error))
2925
}
3026

3127
return <Form entity='Budget' onSubmit={ onSubmit }>
@@ -39,8 +35,6 @@ const AddExpenseDialog = ({ onChange }: { onChange : () => void }) => {
3935
] }
4036
openButton={ <Buttons.Button label='page.budget.group.action.addExpense' icon={ mdiPlus }/> }>
4137

42-
{ error && <Message message={ error } variant='warning' /> }
43-
4438
<Input.Text id='name'
4539
required
4640
type='text'

src/budget/overview/expense-overview-row.component.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, { useEffect, useState } from "react";
44
import BudgetRepository, { ComputedExpense } from "../../core/repositories/budget.repository";
55
import { mdiContentSave, mdiDotsVertical, mdiSquareEditOutline } from "@mdi/js";
66
import { Form, Input, SubmitButton } from "../../core/form";
7+
import { AxiosError } from "axios";
78

89
type ExpenseOverviewRowProps = {
910
expense: BudgetExpense,
@@ -40,7 +41,7 @@ const ExpenseOverviewRowComponent = ({ expense, year, month, onChanges } : Expen
4041
.then(() => Notifications.Service.success('page.budget.group.expense.updated'))
4142
.then(editControl.close)
4243
.then(onChanges)
43-
.catch(console.error)
44+
.catch((error: AxiosError) => Notifications.Service.exception(error))
4445
}
4546

4647
const dropDownActions = { close: () => undefined }
@@ -78,6 +79,7 @@ const ExpenseOverviewRowComponent = ({ expense, year, month, onChanges } : Expen
7879
variant='primary'
7980
icon={ mdiSquareEditOutline } />}
8081
>
82+
8183
<Input.Text id='name'
8284
type='text'
8385
readonly

src/core/Notification.js

Lines changed: 0 additions & 63 deletions
This file was deleted.

src/core/Notification.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React, { ReactElement, useEffect, useState } from "react";
2+
3+
import '../assets/css/NotificationCenter.scss'
4+
import { Translation } from "./localization";
5+
import { AxiosError } from "axios";
6+
import { ApiError } from "./types";
7+
import { Resolver } from "./index";
8+
9+
export type NotificationEvent = {
10+
type: 'success' | 'warning',
11+
label?: string
12+
message?: string,
13+
id?: string
14+
}
15+
16+
// @deprecated
17+
const NotificationService = (() => {
18+
19+
const push = (messageKey: string, style: 'warning' | 'success') => {
20+
notifyUser({ type: style, label: messageKey })
21+
}
22+
const handleException = (error: AxiosError) => {
23+
const apiError: ApiError = error.response?.data as ApiError
24+
if (apiError._links.help) {
25+
push(apiError._links.help[0].href, 'warning')
26+
} else {
27+
console.error('Error intercepted', error)
28+
}
29+
}
30+
31+
return {
32+
warning: (messageKey: string) => push(messageKey, 'warning'),
33+
success: (messageKey: string) => push(messageKey, 'success'),
34+
exception: (e: AxiosError) => handleException(e),
35+
push: push
36+
}
37+
})()
38+
39+
const Notification = ({ type, message, label } : NotificationEvent) => {
40+
return (
41+
<div className={`Notification ${type}`}>
42+
{ label && <Translation label={ label } /> }
43+
{ message && <span>{ message }</span> }
44+
<div className='CountDown' />
45+
</div>
46+
);
47+
}
48+
49+
const NotificationCenter = () => {
50+
const [notifications, setNotifications] = useState<NotificationEvent[]>([])
51+
52+
useEffect(() => {
53+
const onNotificationEvent = (event: Event) => {
54+
const notification = (event as CustomEvent).detail as NotificationEvent
55+
56+
setTimeout(() => {
57+
// Remove the notification after 2 seconds
58+
setNotifications((existing) => {
59+
return existing.filter(existing => existing.id !== notification.id)
60+
})
61+
}, 2000)
62+
setNotifications((existing) => {
63+
return [
64+
...existing,
65+
notification
66+
]
67+
})
68+
}
69+
70+
window.addEventListener('notification', onNotificationEvent)
71+
return () => {
72+
window.removeEventListener('notification', onNotificationEvent)
73+
}
74+
}, []);
75+
76+
return <div className='NotificationCenter'>
77+
{ notifications.map(notification =>
78+
<Notification key={ notification.id } { ...notification } />) }
79+
</div>
80+
}
81+
82+
const notifyUser = (event: NotificationEvent) => {
83+
event.id = Resolver.uuid()
84+
window.dispatchEvent(new CustomEvent('notification', { detail: event }))
85+
}
86+
87+
88+
export {
89+
NotificationService as Service,
90+
NotificationCenter
91+
}

src/core/types.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,10 @@ export type ApiError = {
178178
field?: string
179179
message: string
180180
}[]
181+
},
182+
_links: {
183+
help?: {
184+
href: string
185+
}[]
181186
}
182187
}

0 commit comments

Comments
 (0)