Refactor user and media endpoints: remove unused GetUser and GetMedia methods, streamline AdminUserEndpoints and MediaEndpoints, and enhance metadata handling in MetadataEndpoints. Update Program.cs to remove legacy image relocation logic and improve overall code clarity.
build / backend (push) Successful in 1m14s
build / frontend (push) Successful in 35s
tests / backend-tests (push) Successful in 3m16s

This commit is contained in:
Leonid Pershin
2026-07-26 02:58:17 +03:00
parent 44e954920c
commit a0533a8ed8
50 changed files with 230 additions and 849 deletions
+1 -5
View File
@@ -1,5 +1,5 @@
import { apiRequest, setAccessToken } from '@/shared/api/client'
import type { AuthResponse, CurrentUser, RegistrationStatus } from '@/shared/api/types'
import type { AuthResponse, RegistrationStatus } from '@/shared/api/types'
import { useAuthStore } from './store'
/** Публично: включена ли открытая регистрация (для страниц входа/регистрации). */
@@ -19,10 +19,6 @@ export function logout() {
return apiRequest<void>('/auth/logout', { method: 'POST' })
}
export function fetchCurrentUser() {
return apiRequest<CurrentUser>('/auth/me')
}
export function changePassword(currentPassword: string, newPassword: string) {
return apiRequest<void>('/auth/change-password', { method: 'POST', body: { currentPassword, newPassword } })
}
-5
View File
@@ -53,11 +53,8 @@ export type MediaAssetDto = {
source: MediaSource
status: MediaAssetStatus
durationSeconds: number | null
segmentCount: number | null
width: number | null
height: number | null
videoCodec: string | null
audioCodec: string | null
errorMessage: string | null
processingSeconds: number | null
createdAt: string
@@ -119,7 +116,6 @@ export type EpisodeDto = {
title: string | null
overview: string | null
stillImageId: string | null
airDate: string | null
}
export type ImageCategory = 'Library' | 'ShowPoster' | 'EpisodeStill' | 'BumperBackground'
@@ -214,7 +210,6 @@ export type ChannelShowDto = {
blockMode: BlockMode
blockValue: number
isEnabled: boolean
nextEpisodeIndex: number
/** Во сколько раз усиливать вес в предпочтительные часы (1 — без буста). */
preferredWeightMultiplier: number
preferredHours: HourWindow[]
-46
View File
@@ -6,7 +6,6 @@ const resources = {
translation: {
appName: 'TeleWave',
nav: {
home: 'Главная',
dashboard: 'Эфир',
admin: 'Админка',
settings: 'Настройки',
@@ -24,7 +23,6 @@ const resources = {
create: 'Создать',
loading: 'Загрузка…',
error: 'Что-то пошло не так',
confirm: 'Подтвердить',
search: 'Поиск',
actions: 'Действия',
prevPage: 'Предыдущая страница',
@@ -57,11 +55,6 @@ const resources = {
blocked: 'Аккаунт заблокирован администратором',
genericError: 'Не удалось выполнить вход. Попробуйте ещё раз',
},
dashboard: {
welcome: 'На связи, {{userName}}',
placeholder: 'Список каналов появится здесь позже — пока в эфире только тестовая заставка.',
role: 'Роль',
},
air: {
now: 'Сейчас',
next: 'Далее',
@@ -94,8 +87,6 @@ const resources = {
system: 'Системная',
create: 'Новая роль',
rename: 'Переименовать',
cannotModifySystem: 'Системную роль нельзя изменить или удалить',
roleInUse: 'Роль назначена пользователям',
},
users: {
title: 'Пользователи',
@@ -123,14 +114,9 @@ const resources = {
upload: 'Загрузить',
uploadToShow: 'Загрузить в шоу',
toShowTitle: 'Загрузить и добавить в шоу',
toShowSubtitle: 'Файлов выбрано: {{count}}. После загрузки они добавятся сериями в выбранное шоу.',
autoDetectLabel: 'Определять шоу по названию файла',
autoDetectHint:
'Каждый файл привяжется к шоу, чьё оригинальное (или отображаемое) название есть в имени релиза, напр. «The.Simpsons.S33E01…» → The Simpsons.',
toShowShow: 'Шоу',
toShowFallback: 'Для нераспознанных',
toShowLibrary: 'В библиотеку',
toShowPick: 'Выберите шоу',
toShowSeason: 'Сезон (вручную)',
toShowAuto: 'авто',
toShowRegex: 'Regex серии',
@@ -138,12 +124,10 @@ const resources = {
toShowHint:
'Сезон и regex — необязательны: обычно номера распознаются сами (см. ниже). Regex: 1 группа = серия, 2 группы = сезон и серия. Пример: ^(\\d+) для «01. Название.mkv».',
toShowPreview: 'Что распознаем',
toShowRecognized: 'распознано {{recognized}} из {{total}}',
toShowMatched: 'шоу распознано у {{matched}} из {{total}}',
applyToAll: 'Задать всем…',
toShowUnknown: '—',
toShowConfirm: 'Загрузить и добавить',
uploaded: 'Файл загружен, идёт обработка',
uploadedCount: 'Загружено файлов: {{count}}',
uploadingCount: 'Загрузка {{done}}/{{total}}',
cancelAll: 'Отменить все загрузки',
@@ -202,8 +186,6 @@ const resources = {
loadedSeasons: 'Загружены сезоны',
episodes: 'Серии',
episode: 'Серия',
addEpisode: 'Добавить серию',
pickAsset: 'Выберите файл',
noEpisodes: 'Серий пока нет',
filterAssets: 'Фильтр по имени, напр. Family.Guy.S16',
selectAll: 'Выбрать все',
@@ -251,7 +233,6 @@ const resources = {
bumperBg2: 'Фон (цвет 2)',
bumperAccent: 'Акцент',
bumperText: 'Текст',
bumperOnlyDifferent: 'Только на смене шоу (не внутри марафона)',
bumperTemplates: 'Блоки заставок',
bumperTemplatesHint:
'Каждый блок — свой звук и оформление. Первый блок дефолтный, его нельзя удалить. Длительность заставки — по длине звука.',
@@ -359,15 +340,12 @@ const resources = {
},
metadata: {
title: 'Метаданные',
pickFromGallery: 'Выбрать из галереи',
pickPoster: 'Из галереи',
name: 'Название',
originalName: 'Оригинальное название (eng)',
originalNamePlaceholder: 'Например: Family Guy',
originalNameHint: 'По нему ищутся метаданные; на экранах показывается обычное название.',
source: 'Источник',
sourceLabel: 'Источник',
searchPlaceholder: 'Название для поиска',
searchBtn: 'Искать',
nothingFound: 'Ничего не найдено',
apply: 'Применить',
@@ -375,7 +353,6 @@ const resources = {
overview: 'Описание',
year: 'Год',
clear: 'Очистить',
uploadPoster: 'Загрузить постер',
noPoster: 'Нет постера',
refreshEpisodes: 'Обновить серии',
refreshing: 'Обновляем…',
@@ -396,7 +373,6 @@ const resources = {
translation: {
appName: 'TeleWave',
nav: {
home: 'Home',
dashboard: 'On Air',
admin: 'Admin',
settings: 'Settings',
@@ -414,7 +390,6 @@ const resources = {
create: 'Create',
loading: 'Loading…',
error: 'Something went wrong',
confirm: 'Confirm',
search: 'Search',
actions: 'Actions',
prevPage: 'Previous page',
@@ -447,11 +422,6 @@ const resources = {
blocked: 'Account blocked by an administrator',
genericError: 'Could not sign in. Please try again',
},
dashboard: {
welcome: 'On air, {{userName}}',
placeholder: 'The channel list will show up here later — for now, enjoy the test card.',
role: 'Role',
},
air: {
now: 'Now',
next: 'Up next',
@@ -484,8 +454,6 @@ const resources = {
system: 'System',
create: 'New role',
rename: 'Rename',
cannotModifySystem: 'A system role cannot be modified or deleted',
roleInUse: 'Role is assigned to users',
},
users: {
title: 'Users',
@@ -513,14 +481,9 @@ const resources = {
upload: 'Upload',
uploadToShow: 'Upload to show',
toShowTitle: 'Upload and add to show',
toShowSubtitle: '{{count}} file(s) selected. After upload they are added as episodes to the chosen show.',
autoDetectLabel: 'Detect show from file name',
autoDetectHint:
'Each file is linked to the show whose original (or display) name appears in the release name, e.g. “The.Simpsons.S33E01…” → The Simpsons.',
toShowShow: 'Show',
toShowFallback: 'For unrecognized',
toShowLibrary: 'To library',
toShowPick: 'Pick a show',
toShowSeason: 'Season (manual)',
toShowAuto: 'auto',
toShowRegex: 'Episode regex',
@@ -528,12 +491,10 @@ const resources = {
toShowHint:
'Season and regex are optional: numbers are usually detected automatically (see below). Regex: 1 group = episode, 2 groups = season and episode. Example: ^(\\d+) for “01. Title.mkv”.',
toShowPreview: 'What we detect',
toShowRecognized: '{{recognized}} of {{total}} recognized',
toShowMatched: 'show detected for {{matched}} of {{total}}',
applyToAll: 'Set for all…',
toShowUnknown: '—',
toShowConfirm: 'Upload and add',
uploaded: 'File uploaded, processing started',
uploadedCount: 'Uploaded files: {{count}}',
uploadingCount: 'Uploading {{done}}/{{total}}',
cancelAll: 'Cancel all uploads',
@@ -592,8 +553,6 @@ const resources = {
loadedSeasons: 'Loaded seasons',
episodes: 'Episodes',
episode: 'Episode',
addEpisode: 'Add episode',
pickAsset: 'Pick a file',
noEpisodes: 'No episodes yet',
filterAssets: 'Filter by name, e.g. Family.Guy.S16',
selectAll: 'Select all',
@@ -641,7 +600,6 @@ const resources = {
bumperBg2: 'Background (color 2)',
bumperAccent: 'Accent',
bumperText: 'Text',
bumperOnlyDifferent: 'Only on show change (not within a marathon)',
bumperTemplates: 'Bumper blocks',
bumperTemplatesHint:
'Each block has its own sound and style. The first block is the default and cannot be removed. Bumper length follows the sound length.',
@@ -749,15 +707,12 @@ const resources = {
},
metadata: {
title: 'Metadata',
pickFromGallery: 'Pick from gallery',
pickPoster: 'From gallery',
name: 'Name',
originalName: 'Original name (eng)',
originalNamePlaceholder: 'e.g. Family Guy',
originalNameHint: 'Metadata is looked up by this; screens still show the regular name.',
source: 'Source',
sourceLabel: 'Source',
searchPlaceholder: 'Title to search',
searchBtn: 'Search',
nothingFound: 'Nothing found',
apply: 'Apply',
@@ -765,7 +720,6 @@ const resources = {
overview: 'Overview',
year: 'Year',
clear: 'Clear',
uploadPoster: 'Upload poster',
noPoster: 'No poster',
refreshEpisodes: 'Refresh episodes',
refreshing: 'Refreshing…',
-5
View File
@@ -27,8 +27,3 @@ export const CardContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElem
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
))
CardContent.displayName = 'CardContent'
export const CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (
<div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />
))
CardFooter.displayName = 'CardFooter'
-1
View File
@@ -5,7 +5,6 @@ import { cn } from '@/shared/lib/cn'
export const Dialog = DialogPrimitive.Root
export const DialogTrigger = DialogPrimitive.Trigger
export const DialogClose = DialogPrimitive.Close
export const DialogOverlay = forwardRef<
ElementRef<typeof DialogPrimitive.Overlay>,