Add password reset functionality for admin users: implement ResetPassword endpoint, update AdminUserEndpoints to include password reset logic, and enhance user interface for password management. Update translations for new features and ensure proper error handling in the reset process.
This commit is contained in:
@@ -206,11 +206,18 @@ export type ChannelAdDto = {
|
||||
|
||||
export type OverrideShowDto = { showId: string; showName: string; weight: number }
|
||||
|
||||
export type OverrideRecurrence = 'OneTime' | 'Weekly'
|
||||
|
||||
export type ProgrammingOverrideDto = {
|
||||
id: string
|
||||
mode: OverrideMode
|
||||
startsAtUtc: string
|
||||
endsAtUtc: string
|
||||
recurrence: OverrideRecurrence
|
||||
startsAtUtc: string | null
|
||||
endsAtUtc: string | null
|
||||
/** Weekly: день недели 0=Вс..6=Сб; окно минут суток (UTC). */
|
||||
dayOfWeek: number | null
|
||||
startMinute: number | null
|
||||
endMinute: number | null
|
||||
shows: OverrideShowDto[]
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const resources = {
|
||||
confirm: 'Подтвердить',
|
||||
search: 'Поиск',
|
||||
actions: 'Действия',
|
||||
prevPage: 'Предыдущая страница',
|
||||
nextPage: 'Следующая страница',
|
||||
yes: 'Да',
|
||||
no: 'Нет',
|
||||
},
|
||||
@@ -105,6 +107,10 @@ const resources = {
|
||||
active: 'Активен',
|
||||
block: 'Заблокировать',
|
||||
unblock: 'Разблокировать',
|
||||
resetPassword: 'Пароль',
|
||||
resetPasswordFor: 'Сменить пароль: {{name}}',
|
||||
newPassword: 'Новый пароль',
|
||||
passwordReset: 'Пароль изменён',
|
||||
filterAll: 'Все роли',
|
||||
createTitle: 'Создать пользователя',
|
||||
password: 'Пароль',
|
||||
@@ -288,6 +294,19 @@ const resources = {
|
||||
noAds: 'Пул рекламы пуст',
|
||||
overrides: 'Марафоны / override',
|
||||
modes: { Exclusive: 'Эксклюзив', Boost: 'Буст' },
|
||||
overrideRecurrence: 'Повтор',
|
||||
recurrenceOneTime: 'Разово',
|
||||
recurrenceWeekly: 'Еженедельно',
|
||||
weekday: 'День недели',
|
||||
weekdays: {
|
||||
0: 'Вс',
|
||||
1: 'Пн',
|
||||
2: 'Вт',
|
||||
3: 'Ср',
|
||||
4: 'Чт',
|
||||
5: 'Пт',
|
||||
6: 'Сб',
|
||||
},
|
||||
from: 'С',
|
||||
to: 'По',
|
||||
noOverrides: 'Override не заданы',
|
||||
@@ -368,6 +387,8 @@ const resources = {
|
||||
confirm: 'Confirm',
|
||||
search: 'Search',
|
||||
actions: 'Actions',
|
||||
prevPage: 'Previous page',
|
||||
nextPage: 'Next page',
|
||||
yes: 'Yes',
|
||||
no: 'No',
|
||||
},
|
||||
@@ -446,6 +467,10 @@ const resources = {
|
||||
active: 'Active',
|
||||
block: 'Block',
|
||||
unblock: 'Unblock',
|
||||
resetPassword: 'Password',
|
||||
resetPasswordFor: 'Reset password: {{name}}',
|
||||
newPassword: 'New password',
|
||||
passwordReset: 'Password changed',
|
||||
filterAll: 'All roles',
|
||||
createTitle: 'Create user',
|
||||
password: 'Password',
|
||||
@@ -629,6 +654,19 @@ const resources = {
|
||||
noAds: 'Ad pool is empty',
|
||||
overrides: 'Marathons / overrides',
|
||||
modes: { Exclusive: 'Exclusive', Boost: 'Boost' },
|
||||
overrideRecurrence: 'Repeat',
|
||||
recurrenceOneTime: 'One-time',
|
||||
recurrenceWeekly: 'Weekly',
|
||||
weekday: 'Weekday',
|
||||
weekdays: {
|
||||
0: 'Sun',
|
||||
1: 'Mon',
|
||||
2: 'Tue',
|
||||
3: 'Wed',
|
||||
4: 'Thu',
|
||||
5: 'Fri',
|
||||
6: 'Sat',
|
||||
},
|
||||
from: 'From',
|
||||
to: 'To',
|
||||
noOverrides: 'No overrides set',
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Button } from './button'
|
||||
|
||||
/** Простой пейджер «‹ N / M ›». Ничего не рисует, если страница одна. */
|
||||
export function Pager({
|
||||
page,
|
||||
totalPages,
|
||||
onChange,
|
||||
}: {
|
||||
page: number
|
||||
totalPages: number
|
||||
onChange: (page: number) => void
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
if (totalPages <= 1) return null
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-2 text-sm">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={page <= 1}
|
||||
onClick={() => onChange(page - 1)}
|
||||
aria-label={t('common.prevPage')}
|
||||
>
|
||||
‹
|
||||
</Button>
|
||||
<span className="tabular-nums text-muted-foreground">
|
||||
{page} / {totalPages}
|
||||
</span>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={page >= totalPages}
|
||||
onClick={() => onChange(page + 1)}
|
||||
aria-label={t('common.nextPage')}
|
||||
>
|
||||
›
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user