Skip to content

Commit 73f8471

Browse files
committed
Bind notifications into the user account notifications page
1 parent 997e0d3 commit 73f8471

File tree

10 files changed

+315
-91
lines changed

10 files changed

+315
-91
lines changed

coderd/database/migrations/000235_update_notification_templates.down.sql

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
UPDATE notification_templates
2+
SET
3+
"group" = 'User Events'
4+
WHERE
5+
id = '4e19c0ac-94e1-4532-9515-d1801aa283b2';

coderd/notifications.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ func convertNotificationTemplates(in []database.NotificationTemplate) (out []cod
277277
BodyTemplate: tmpl.BodyTemplate,
278278
Actions: string(tmpl.Actions),
279279
Group: tmpl.Group.String,
280-
Method: string(tmpl.Method.NotificationMethod),
280+
Method: codersdk.NotificationTemplateMethod(tmpl.Method.NotificationMethod),
281281
Kind: string(tmpl.Kind),
282282
})
283283
}

codersdk/notifications.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,23 @@ type NotificationsSettings struct {
1616
NotifierPaused bool `json:"notifier_paused"`
1717
}
1818

19+
type NotificationTemplateMethod string
20+
21+
const (
22+
NotificationTemplateEmailMethod NotificationTemplateMethod = "email"
23+
NotificationTemplateWebhookMethod NotificationTemplateMethod = "webhook"
24+
NotificationTemplateNotDefinedMethod NotificationTemplateMethod = ""
25+
)
26+
1927
type NotificationTemplate struct {
20-
ID uuid.UUID `json:"id" format:"uuid"`
21-
Name string `json:"name"`
22-
TitleTemplate string `json:"title_template"`
23-
BodyTemplate string `json:"body_template"`
24-
Actions string `json:"actions" format:""`
25-
Group string `json:"group"`
26-
Method string `json:"method"`
27-
Kind string `json:"kind"`
28+
ID uuid.UUID `json:"id" format:"uuid"`
29+
Name string `json:"name"`
30+
TitleTemplate string `json:"title_template"`
31+
BodyTemplate string `json:"body_template"`
32+
Actions string `json:"actions" format:""`
33+
Group string `json:"group"`
34+
Method NotificationTemplateMethod `json:"method" enums:"email,webhook,''"`
35+
Kind string `json:"kind"`
2836
}
2937

3038
type NotificationMethodsResponse struct {
@@ -73,7 +81,7 @@ func (c *Client) PutNotificationsSettings(ctx context.Context, settings Notifica
7381

7482
// UpdateNotificationTemplateMethod modifies a notification template to use a specific notification method, overriding
7583
// the method set in the deployment configuration.
76-
func (c *Client) UpdateNotificationTemplateMethod(ctx context.Context, notificationTemplateID uuid.UUID, method string) error {
84+
func (c *Client) UpdateNotificationTemplateMethod(ctx context.Context, notificationTemplateID uuid.UUID, method NotificationTemplateMethod) error {
7785
res, err := c.Request(ctx, http.MethodPut,
7886
fmt.Sprintf("/api/v2/notifications/templates/%s/method", notificationTemplateID),
7987
UpdateNotificationTemplateMethod{Method: method},
@@ -193,7 +201,7 @@ func (c *Client) GetNotificationDispatchMethods(ctx context.Context) (Notificati
193201
}
194202

195203
type UpdateNotificationTemplateMethod struct {
196-
Method string `json:"method,omitempty" example:"webhook"`
204+
Method NotificationTemplateMethod `json:"method,omitempty" enums:"email,webhook" example:"webhook"`
197205
}
198206

199207
type UpdateUserNotificationPreferences struct {

pnpm-lock.yaml

Lines changed: 13 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/src/api/api.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,31 @@ class ApiMethods {
19951995

19961996
return response.data;
19971997
};
1998+
1999+
getUserNotificationPreferences = async (userId: string) => {
2000+
const res = await this.axios.get<TypesGen.NotificationPreference[] | null>(
2001+
`/api/v2/users/${userId}/notifications/preferences`,
2002+
);
2003+
return res.data ?? [];
2004+
};
2005+
2006+
putUserNotificationPreferences = async (
2007+
userId: string,
2008+
req: TypesGen.UpdateUserNotificationPreferences,
2009+
) => {
2010+
const res = await this.axios.put<TypesGen.NotificationPreference[]>(
2011+
`/api/v2/users/${userId}/notifications/preferences`,
2012+
req,
2013+
);
2014+
return res.data;
2015+
};
2016+
2017+
getSystemNotificationTemplates = async () => {
2018+
const res = await this.axios.get<TypesGen.NotificationTemplate[]>(
2019+
`/api/v2/notifications/templates/system`,
2020+
);
2021+
return res.data;
2022+
};
19982023
}
19992024

20002025
// This is a hard coded CSRF token/cookie pair for local development. In prod,

site/src/api/queries/notifications.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import type { QueryClient, UseMutationOptions } from "react-query";
2+
import { API } from "api/api";
3+
import type {
4+
NotificationPreference,
5+
UpdateUserNotificationPreferences,
6+
} from "api/typesGenerated";
7+
8+
const userNotificationPreferencesKey = (userId: string) => [
9+
"users",
10+
userId,
11+
"notifications",
12+
"preferences",
13+
];
14+
15+
export const userNotificationPreferences = (userId: string) => {
16+
return {
17+
queryKey: userNotificationPreferencesKey(userId),
18+
queryFn: () => API.getUserNotificationPreferences(userId),
19+
};
20+
};
21+
22+
export const updateUserNotificationPreferences = (
23+
userId: string,
24+
queryClient: QueryClient,
25+
) => {
26+
return {
27+
mutationFn: (req) => {
28+
return API.putUserNotificationPreferences(userId, req);
29+
},
30+
onMutate: (data) => {
31+
queryClient.setQueryData(
32+
userNotificationPreferencesKey(userId),
33+
Object.entries(data.template_disabled_map).map(
34+
([id, disabled]) =>
35+
({
36+
id,
37+
disabled,
38+
updated_at: new Date().toISOString(),
39+
}) as NotificationPreference,
40+
),
41+
);
42+
},
43+
} satisfies UseMutationOptions<
44+
NotificationPreference[],
45+
unknown,
46+
UpdateUserNotificationPreferences
47+
>;
48+
};
49+
50+
export const systemNotificationTemplatesByGroup = () => {
51+
return {
52+
queryKey: ["notifications", "templates", "system"],
53+
queryFn: () => API.getSystemNotificationTemplates(),
54+
};
55+
};

site/src/api/typesGenerated.ts

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)