Public Access
feat(settings): remove the platform mails switch
Broadcasts go to every active user, so the settings switch and its API call are gone. Admin broadcast texts no longer mention an opt-out.
This commit is contained in:
1 parent
6dda186bdf
commit
80259cb0e9
8 files changed
+19
-60
No files matched your search
@@ -115,7 +115,6 @@ To Be Played is split into three repositories:
|
|||||||
(menu) lists all entries and marks them seen. Admins publish, preview, edit and delete entries on `/admin/news`.
|
(menu) lists all entries and marks them seen. Admins publish, preview, edit and delete entries on `/admin/news`.
|
||||||
- **Broadcast mail**: admins write a mail in both languages on `/admin/broadcasts`, send it to all active users or to
|
- **Broadcast mail**: admins write a mail in both languages on `/admin/broadcasts`, send it to all active users or to
|
||||||
picked ones, send a test to themselves, confirm with the real recipient count, and see the history with the counts.
|
picked ones, send a test to themselves, confirm with the real recipient count, and see the history with the counts.
|
||||||
Users turn platform mails off in the settings; account mails always come.
|
|
||||||
- **Welcome page**: `/welcome` opens once after the first login (Auth `settings.welcomeSeenAt` is null; only the
|
- **Welcome page**: `/welcome` opens once after the first login (Auth `settings.welcomeSeenAt` is null; only the
|
||||||
dashboard redirects, deep links stay). Feature cards with links, two next steps (Steam, import) with checks from
|
dashboard redirects, deep links stay). Feature cards with links, two next steps (Steam, import) with checks from
|
||||||
`/me` and the library summary. "Let's go" and "Skip" stamp it in Auth and open the dashboard. The settings page
|
`/me` and the library summary. "Let's go" and "Skip" stamp it in Auth and open the dashboard. The settings page
|
||||||
|
|||||||
+3
-5
@@ -143,9 +143,7 @@
|
|||||||
"PROFILE_TILES_HINT": "Wähle, was dein Profil zeigt und wo: öffne dein Profil und klicke auf \"Anpassen\".",
|
"PROFILE_TILES_HINT": "Wähle, was dein Profil zeigt und wo: öffne dein Profil und klicke auf \"Anpassen\".",
|
||||||
"FAVORITE_PLATFORM": "Lieblingsplattform",
|
"FAVORITE_PLATFORM": "Lieblingsplattform",
|
||||||
"FAVORITE_PLATFORM_HINT": "Wird zuerst gewählt, wenn du ein Spiel für mehrere Plattformen hinzufügst.",
|
"FAVORITE_PLATFORM_HINT": "Wird zuerst gewählt, wenn du ein Spiel für mehrere Plattformen hinzufügst.",
|
||||||
"FAVORITE_PLATFORM_NONE": "Keine",
|
"FAVORITE_PLATFORM_NONE": "Keine"
|
||||||
"PLATFORM_MAILS": "Mails von der Plattform",
|
|
||||||
"PLATFORM_MAILS_HINT": "Neuigkeiten und Ankündigungen per Mail. Mails zu deinem Konto kommen immer."
|
|
||||||
},
|
},
|
||||||
"VALIDATION": {
|
"VALIDATION": {
|
||||||
"EMAIL_REQUIRED": "Email ist erforderlich.",
|
"EMAIL_REQUIRED": "Email ist erforderlich.",
|
||||||
@@ -718,7 +716,7 @@
|
|||||||
"SUBJECT_DE": "Betreff (Deutsch)",
|
"SUBJECT_DE": "Betreff (Deutsch)",
|
||||||
"BODY_EN": "Text (Englisch)",
|
"BODY_EN": "Text (Englisch)",
|
||||||
"BODY_DE": "Text (Deutsch)",
|
"BODY_DE": "Text (Deutsch)",
|
||||||
"TEXT_HELP": "Nur Text, in beiden Sprachen. Betreff höchstens 150, Text höchstens 5000 Zeichen. Eine Fußzeile mit dem Link zum Abschalten wird angehängt.",
|
"TEXT_HELP": "Nur Text, in beiden Sprachen. Betreff höchstens 150, Text höchstens 5000 Zeichen. Eine Fußzeile wird angehängt.",
|
||||||
"RECIPIENTS": "Empfänger",
|
"RECIPIENTS": "Empfänger",
|
||||||
"ALL": "Alle aktiven Nutzer",
|
"ALL": "Alle aktiven Nutzer",
|
||||||
"PICKED": "Ausgewählte Nutzer",
|
"PICKED": "Ausgewählte Nutzer",
|
||||||
@@ -732,7 +730,7 @@
|
|||||||
"CONFIRM_TEXT": "An {{count}} Nutzer senden? Das kann nicht rückgängig gemacht werden.",
|
"CONFIRM_TEXT": "An {{count}} Nutzer senden? Das kann nicht rückgängig gemacht werden.",
|
||||||
"CONFIRM": "Senden",
|
"CONFIRM": "Senden",
|
||||||
"CANCEL": "Abbrechen",
|
"CANCEL": "Abbrechen",
|
||||||
"NO_RECIPIENTS": "Kein Empfänger: niemand ist aktiv und hat Mails an.",
|
"NO_RECIPIENTS": "Kein Empfänger: niemand davon ist aktiv.",
|
||||||
"SENT": "Mail für {{count}} Nutzer eingereiht.",
|
"SENT": "Mail für {{count}} Nutzer eingereiht.",
|
||||||
"ERROR": "Die Aktion ist fehlgeschlagen.",
|
"ERROR": "Die Aktion ist fehlgeschlagen.",
|
||||||
"LIST": "Gesendete Mails",
|
"LIST": "Gesendete Mails",
|
||||||
|
|||||||
+3
-5
@@ -143,9 +143,7 @@
|
|||||||
"PROFILE_TILES_HINT": "Choose what your profile shows, and where: open your profile and click \"Customize\".",
|
"PROFILE_TILES_HINT": "Choose what your profile shows, and where: open your profile and click \"Customize\".",
|
||||||
"FAVORITE_PLATFORM": "Favorite platform",
|
"FAVORITE_PLATFORM": "Favorite platform",
|
||||||
"FAVORITE_PLATFORM_HINT": "Selected first when you add a game on more than one platform.",
|
"FAVORITE_PLATFORM_HINT": "Selected first when you add a game on more than one platform.",
|
||||||
"FAVORITE_PLATFORM_NONE": "None",
|
"FAVORITE_PLATFORM_NONE": "None"
|
||||||
"PLATFORM_MAILS": "Mails from the platform",
|
|
||||||
"PLATFORM_MAILS_HINT": "News and announcements by mail. Mails about your account always come."
|
|
||||||
},
|
},
|
||||||
"VALIDATION": {
|
"VALIDATION": {
|
||||||
"EMAIL_REQUIRED": "Email is required.",
|
"EMAIL_REQUIRED": "Email is required.",
|
||||||
@@ -718,7 +716,7 @@
|
|||||||
"SUBJECT_DE": "Subject (German)",
|
"SUBJECT_DE": "Subject (German)",
|
||||||
"BODY_EN": "Text (English)",
|
"BODY_EN": "Text (English)",
|
||||||
"BODY_DE": "Text (German)",
|
"BODY_DE": "Text (German)",
|
||||||
"TEXT_HELP": "Plain text, both languages. Subject max 150, text max 5000 characters. A footer with the opt-out link is added.",
|
"TEXT_HELP": "Plain text, both languages. Subject max 150, text max 5000 characters. A footer is added.",
|
||||||
"RECIPIENTS": "Recipients",
|
"RECIPIENTS": "Recipients",
|
||||||
"ALL": "All active users",
|
"ALL": "All active users",
|
||||||
"PICKED": "Picked users",
|
"PICKED": "Picked users",
|
||||||
@@ -732,7 +730,7 @@
|
|||||||
"CONFIRM_TEXT": "Send to {{count}} users? This cannot be undone.",
|
"CONFIRM_TEXT": "Send to {{count}} users? This cannot be undone.",
|
||||||
"CONFIRM": "Send",
|
"CONFIRM": "Send",
|
||||||
"CANCEL": "Cancel",
|
"CANCEL": "Cancel",
|
||||||
"NO_RECIPIENTS": "No recipient: nobody active with mails on.",
|
"NO_RECIPIENTS": "No recipient: nobody active among them.",
|
||||||
"SENT": "Mail queued for {{count}} users.",
|
"SENT": "Mail queued for {{count}} users.",
|
||||||
"ERROR": "The action failed.",
|
"ERROR": "The action failed.",
|
||||||
"LIST": "Sent mails",
|
"LIST": "Sent mails",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {usePreferences} from '../context/PreferencesContext.jsx';
|
|||||||
import usePersistSettings from '../hooks/usePersistSettings.js';
|
import usePersistSettings from '../hooks/usePersistSettings.js';
|
||||||
import useSaveResponse from '../hooks/useSaveResponse.js';
|
import useSaveResponse from '../hooks/useSaveResponse.js';
|
||||||
import {FAVORITE_PLATFORMS, saveFavoritePlatform} from '../utils/platforms.js';
|
import {FAVORITE_PLATFORMS, saveFavoritePlatform} from '../utils/platforms.js';
|
||||||
import {LANGUAGES, savePlatformMails, saveSettings} from '../utils/settings.js';
|
import {LANGUAGES, saveSettings} from '../utils/settings.js';
|
||||||
|
|
||||||
// Radix Select has no empty value.
|
// Radix Select has no empty value.
|
||||||
const NO_FAVORITE = 'NONE';
|
const NO_FAVORITE = 'NONE';
|
||||||
@@ -41,13 +41,6 @@ export default function PreferencesCard() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePlatformMailsChange = async (next) => {
|
|
||||||
if (await runSave(() => savePlatformMails(next))) {
|
|
||||||
updateProfile((p) => ({...p, settings: {...p.settings, platformMails: next}}));
|
|
||||||
toast.success(t('SETTINGS.SAVED'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
@@ -90,14 +83,6 @@ export default function PreferencesCard() {
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between gap-4">
|
|
||||||
<div className="space-y-1">
|
|
||||||
<Label htmlFor="platformMails">{t('SETTINGS.PLATFORM_MAILS')}</Label>
|
|
||||||
<p className="text-xs text-muted-foreground">{t('SETTINGS.PLATFORM_MAILS_HINT')}</p>
|
|
||||||
</div>
|
|
||||||
<Switch id="platformMails" checked={profile?.settings?.platformMails ?? true}
|
|
||||||
onCheckedChange={handlePlatformMailsChange}/>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,3 +20,14 @@ describe('translation files', () => {
|
|||||||
expect(loadPath).toBe(`/i18n/{{lng}}.json?v=${hash.digest('hex').slice(0, 12)}`);
|
expect(loadPath).toBe(`/i18n/{{lng}}.json?v=${hash.digest('hex').slice(0, 12)}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('admin broadcast texts', () => {
|
||||||
|
it('adminBroadcastTexts_DoNotMentionAnOptOut', () => {
|
||||||
|
const dir = path.resolve(import.meta.dirname, '../public/i18n');
|
||||||
|
for (const file of ['en.json', 'de.json']) {
|
||||||
|
const texts = JSON.parse(readFileSync(path.join(dir, file), 'utf8')).ADMIN_BROADCAST;
|
||||||
|
expect(texts.TEXT_HELP, file).not.toMatch(/opt-out|Abschalten/i);
|
||||||
|
expect(texts.NO_RECIPIENTS, file).not.toMatch(/mails on|Mails an/i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -31,7 +31,6 @@ const authRoutes = (me) => ({
|
|||||||
'PUT /api/users/settings/appearance': noBody,
|
'PUT /api/users/settings/appearance': noBody,
|
||||||
'PUT /api/users/settings/profile-style': noBody,
|
'PUT /api/users/settings/profile-style': noBody,
|
||||||
'PUT /api/users/settings/favorite-platform': noBody,
|
'PUT /api/users/settings/favorite-platform': noBody,
|
||||||
'PUT /api/users/settings/platform-mails': noBody,
|
|
||||||
'GET /api/version': json(404, {}),
|
'GET /api/version': json(404, {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -257,29 +256,6 @@ describe('SettingsPage favorite platform', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('SettingsPage platform mails', () => {
|
|
||||||
beforeEach(() => localStorage.setItem('tbp_session', '1'));
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
cleanup();
|
|
||||||
localStorage.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('is on by default and saves the opt-out', async () => {
|
|
||||||
toast.success.mockClear();
|
|
||||||
renderPage(profile());
|
|
||||||
|
|
||||||
const mails = await screen.findByRole('switch', {name: 'SETTINGS.PLATFORM_MAILS'});
|
|
||||||
expect(mails.getAttribute('aria-checked')).toBe('true');
|
|
||||||
fireEvent.click(mails);
|
|
||||||
|
|
||||||
await waitFor(() => expect(puts()).toEqual([{enabled: false}]));
|
|
||||||
expect(fetch.mock.calls.find(([, init]) => init?.method === 'PUT')[0]).toContain('/api/users/settings/platform-mails');
|
|
||||||
await waitFor(() => expect(toast.success).toHaveBeenCalledWith('SETTINGS.SAVED'));
|
|
||||||
expect(mails.getAttribute('aria-checked')).toBe('false');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('SettingsPage session', () => {
|
describe('SettingsPage session', () => {
|
||||||
beforeEach(() => localStorage.setItem('tbp_session', '1'));
|
beforeEach(() => localStorage.setItem('tbp_session', '1'));
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const JSON_HEADERS = {'Content-Type': 'application/json'};
|
|||||||
export const fetchBroadcasts = () => apiFetch(`${AUTH()}/api/admin/broadcasts`);
|
export const fetchBroadcasts = () => apiFetch(`${AUTH()}/api/admin/broadcasts`);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {count}: the active users with platform mails on, among `userIds`; all of them when `userIds` is null.
|
* {count}: the active users among `userIds`; all of them when `userIds` is null.
|
||||||
*/
|
*/
|
||||||
export const fetchRecipientCount = (userIds) =>
|
export const fetchRecipientCount = (userIds) =>
|
||||||
apiFetch(`${AUTH()}/api/admin/broadcasts/recipient-count${userIds ? `?userIds=${userIds.join(',')}` : ''}`);
|
apiFetch(`${AUTH()}/api/admin/broadcasts/recipient-count${userIds ? `?userIds=${userIds.join(',')}` : ''}`);
|
||||||
|
|||||||
@@ -58,11 +58,3 @@ export const markWelcomeSeen = () =>
|
|||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
||||||
});
|
});
|
||||||
|
|
||||||
/** PUT on Auth, 204: turns the broadcast mails on or off. The caller handles the response status. */
|
|
||||||
export const savePlatformMails = (enabled) =>
|
|
||||||
apiFetch(`${import.meta.env.VITE_API_URL}/api/users/settings/platform-mails`, {
|
|
||||||
method: 'PUT',
|
|
||||||
headers: {'Content-Type': 'application/json'},
|
|
||||||
body: JSON.stringify({enabled}),
|
|
||||||
});
|
|
||||||
Reference in new issue
Block a user