mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add notification warning alert to Tasks page (#20900)
## Problem Users may not realize that task notifications are disabled by default. To improve awareness, we show a warning alert on the Tasks page when all task notifications are disabled. **Alert visibility logic:** - Shows when **all** task notification templates (Task Working, Task Idle, Task Completed, Task Failed) are disabled - Can be dismissed by the user, which stores the dismissal in the user preferences API - If the user later enables any task notification in Account Settings, the dismissal state is cleared so the alert will show again if they disable all notifications in the future <img width="2980" height="1588" alt="Screenshot 2025-11-25 at 17 48 17" src="https://github.com/user-attachments/assets/316bf097-d9d2-4489-bc16-2987ba45f45c" /> ## Changes - Added a warning alert to the Tasks page when all task notifications are disabled - Introduced new `/users/{user}/preferences` endpoint to manage user preferences (stored in `user_configs` table) - Alert is dismissible and stores the dismissal state via the new user preferences API endpoint - Enabling any task notification in Account Settings clears the dismissal state via the preferences API - Added comprehensive Storybook stories for both TasksPage and NotificationsPage to test all alert visibility states and interactions Closes: https://github.com/coder/internal/issues/1089
This commit is contained in:
+78
-9
@@ -2192,16 +2192,16 @@ func TestUserTerminalFont(t *testing.T) {
|
||||
firstUser := coderdtest.CreateFirstUser(t, adminClient)
|
||||
client, _ := coderdtest.CreateAnotherUser(t, adminClient, firstUser.OrganizationID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||
defer cancel()
|
||||
|
||||
// given
|
||||
initial, err := client.GetUserAppearanceSettings(ctx, "me")
|
||||
initial, err := client.GetUserAppearanceSettings(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, codersdk.TerminalFontName(""), initial.TerminalFont)
|
||||
|
||||
// when
|
||||
updated, err := client.UpdateUserAppearanceSettings(ctx, "me", codersdk.UpdateUserAppearanceSettingsRequest{
|
||||
updated, err := client.UpdateUserAppearanceSettings(ctx, codersdk.Me, codersdk.UpdateUserAppearanceSettingsRequest{
|
||||
ThemePreference: "light",
|
||||
TerminalFont: "fira-code",
|
||||
})
|
||||
@@ -2218,16 +2218,16 @@ func TestUserTerminalFont(t *testing.T) {
|
||||
firstUser := coderdtest.CreateFirstUser(t, adminClient)
|
||||
client, _ := coderdtest.CreateAnotherUser(t, adminClient, firstUser.OrganizationID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||
defer cancel()
|
||||
|
||||
// given
|
||||
initial, err := client.GetUserAppearanceSettings(ctx, "me")
|
||||
initial, err := client.GetUserAppearanceSettings(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, codersdk.TerminalFontName(""), initial.TerminalFont)
|
||||
|
||||
// when
|
||||
_, err = client.UpdateUserAppearanceSettings(ctx, "me", codersdk.UpdateUserAppearanceSettingsRequest{
|
||||
_, err = client.UpdateUserAppearanceSettings(ctx, codersdk.Me, codersdk.UpdateUserAppearanceSettingsRequest{
|
||||
ThemePreference: "light",
|
||||
TerminalFont: "foobar",
|
||||
})
|
||||
@@ -2243,16 +2243,16 @@ func TestUserTerminalFont(t *testing.T) {
|
||||
firstUser := coderdtest.CreateFirstUser(t, adminClient)
|
||||
client, _ := coderdtest.CreateAnotherUser(t, adminClient, firstUser.OrganizationID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||
defer cancel()
|
||||
|
||||
// given
|
||||
initial, err := client.GetUserAppearanceSettings(ctx, "me")
|
||||
initial, err := client.GetUserAppearanceSettings(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, codersdk.TerminalFontName(""), initial.TerminalFont)
|
||||
|
||||
// when
|
||||
_, err = client.UpdateUserAppearanceSettings(ctx, "me", codersdk.UpdateUserAppearanceSettingsRequest{
|
||||
_, err = client.UpdateUserAppearanceSettings(ctx, codersdk.Me, codersdk.UpdateUserAppearanceSettingsRequest{
|
||||
ThemePreference: "light",
|
||||
TerminalFont: "",
|
||||
})
|
||||
@@ -2262,6 +2262,75 @@ func TestUserTerminalFont(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestUserTaskNotificationAlertDismissed(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("defaults to false", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
adminClient := coderdtest.New(t, nil)
|
||||
firstUser := coderdtest.CreateFirstUser(t, adminClient)
|
||||
client, _ := coderdtest.CreateAnotherUser(t, adminClient, firstUser.OrganizationID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||
defer cancel()
|
||||
|
||||
// When: getting user preference settings for a user
|
||||
settings, err := client.GetUserPreferenceSettings(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Then: the task notification alert dismissed should default to false
|
||||
require.False(t, settings.TaskNotificationAlertDismissed)
|
||||
})
|
||||
|
||||
t.Run("update to true", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
adminClient := coderdtest.New(t, nil)
|
||||
firstUser := coderdtest.CreateFirstUser(t, adminClient)
|
||||
client, _ := coderdtest.CreateAnotherUser(t, adminClient, firstUser.OrganizationID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||
defer cancel()
|
||||
|
||||
// When: user dismisses the task notification alert
|
||||
updated, err := client.UpdateUserPreferenceSettings(ctx, codersdk.Me, codersdk.UpdateUserPreferenceSettingsRequest{
|
||||
TaskNotificationAlertDismissed: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Then: the setting is updated to true
|
||||
require.True(t, updated.TaskNotificationAlertDismissed)
|
||||
})
|
||||
|
||||
t.Run("update to false", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
adminClient := coderdtest.New(t, nil)
|
||||
firstUser := coderdtest.CreateFirstUser(t, adminClient)
|
||||
client, _ := coderdtest.CreateAnotherUser(t, adminClient, firstUser.OrganizationID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||
defer cancel()
|
||||
|
||||
// Given: user has dismissed the task notification alert
|
||||
_, err := client.UpdateUserPreferenceSettings(ctx, codersdk.Me, codersdk.UpdateUserPreferenceSettingsRequest{
|
||||
TaskNotificationAlertDismissed: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// When: the task notification alert dismissal is cleared
|
||||
// (e.g., when user enables a task notification in the UI settings)
|
||||
updated, err := client.UpdateUserPreferenceSettings(ctx, codersdk.Me, codersdk.UpdateUserPreferenceSettingsRequest{
|
||||
TaskNotificationAlertDismissed: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Then: the setting is updated to false
|
||||
require.False(t, updated.TaskNotificationAlertDismissed)
|
||||
})
|
||||
}
|
||||
|
||||
func TestWorkspacesByUser(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Empty", func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user