просмотр сезона в краткой форме (начал делать)
This commit is contained in:
parent
3b56a160fc
commit
0d0d3fd96d
@ -61,10 +61,10 @@ function App() {
|
||||
</>
|
||||
}>
|
||||
<Route path='library/dictionaries' element={<Dictionaries />} />
|
||||
<Route path='library/anime/title' element={<AnimeTitleCreate />} />
|
||||
<Route path='library/anime/title/:id/edit' element={<AnimeTitleEdit />} />
|
||||
<Route path='library/anime/title/:id/season/' element={<AnimeSeasonCreate />} />
|
||||
<Route path='library/anime/title/:titleId/episode/' element={<AnimeEpisodeCreate />} />
|
||||
<Route path='library/anime' element={<AnimeTitleCreate />} />
|
||||
<Route path='library/anime/:id/edit' element={<AnimeTitleEdit />} />
|
||||
<Route path='library/anime/:titleId/season/' element={<AnimeSeasonCreate />} />
|
||||
<Route path='library/anime/:titleId/episode/' element={<AnimeEpisodeCreate />} />
|
||||
{/* <Route path="about" element={<About />} /> */}
|
||||
{/* <Route path="contact" element={<Contact />} /> */}
|
||||
</Route>
|
||||
|
||||
@ -10,7 +10,7 @@ const controllerUrl = 'http://localhost:5198/MediaContent/Anime/Title/';
|
||||
function FillMediaInfoUrl(mediaInfo: MediaInfo | null | undefined){
|
||||
if (mediaInfo != null){
|
||||
mediaInfo.url = `${controllerUrl}GetMedia?objectId=${mediaInfo.objectId}`;
|
||||
// console.log(`mediaInfo.url: ${mediaInfo.url}`);
|
||||
// console.log(`mediaInfo.objectId${mediaInfo.objectId}\r\nmediaInfo.url: ${mediaInfo.url}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,12 +60,17 @@ export async function GetAnimeTitleDetail(id: string, client?: AxiosInstance | n
|
||||
},
|
||||
);
|
||||
|
||||
//console.log(JSON.stringify(data, null, 4));
|
||||
|
||||
// 👇️ "response status is: 200"
|
||||
// console.log('response status is: ', status);
|
||||
FillMediaInfoUrl(data.commonProperties.preview);
|
||||
// console.log('items count: ', data.items.length);
|
||||
data.items.forEach(item => FillMediaInfoUrl(item.commonProperties.preview));
|
||||
// data.items.forEach(item => { console.log('aa'); FillMediaInfoUrl(item.commonProperties.preview);});
|
||||
data.commonProperties.relatedContent.forEach(relatedContent => FillMediaInfoUrl(relatedContent));
|
||||
|
||||
// console.log('data');
|
||||
// console.log(JSON.stringify(data, null, 4));
|
||||
|
||||
return data;
|
||||
}
|
||||
catch (error)
|
||||
@ -91,6 +96,7 @@ export async function GetAnimeTitle(id: string, client?: AxiosInstance | null) {
|
||||
// 👇️ "response status is: 200"
|
||||
// console.log('response status is: ', status);
|
||||
FillMediaInfoUrl(data.commonProperties.preview);
|
||||
data.items.forEach(item => FillMediaInfoUrl(item.commonProperties.preview));
|
||||
data.commonProperties.relatedContent.forEach(relatedContent => FillMediaInfoUrl(relatedContent));
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -0,0 +1,91 @@
|
||||
import {NameItem, NameType} from "./models/Types.tsx";
|
||||
|
||||
export type CommonPropertiesName = {
|
||||
nameInUserLanguage: string | null,
|
||||
languageCodeIso3: string | null,
|
||||
nameOriginal: string | null,
|
||||
namesUsed: Array<NameItem>,
|
||||
}
|
||||
|
||||
export function GetName(names: Array<NameItem> | null | undefined, primaryLanguageId?: string | null | undefined) : CommonPropertiesName | null {
|
||||
if (names != null) {
|
||||
const nameOriginal = names!.find(q => q.type == NameType.Original)
|
||||
if ((primaryLanguageId == null || primaryLanguageId == '') || nameOriginal?.language.id == primaryLanguageId) {
|
||||
if (nameOriginal != null) {
|
||||
// namesUsed.push(nameOriginal);
|
||||
// titleNames.titleString = `${nameOriginal.value} [${nameOriginal.language.codeIso3}]`;
|
||||
return GetCommonPropertiesName(null, nameOriginal);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let result = null as CommonPropertiesName | null;
|
||||
const namesUsed = new Array<NameItem>();
|
||||
|
||||
if (nameOriginal != null) {
|
||||
namesUsed.push(nameOriginal);
|
||||
// titleNames.titleString = `${nameOriginal.value} [${nameOriginal.language.codeIso3}]`;
|
||||
result = GetCommonPropertiesName(null, nameOriginal);
|
||||
}
|
||||
|
||||
const originalNameInAnotherLanguage = names!.find(q => q.type == NameType.OriginalInAnotherLanguage && q.language.id == primaryLanguageId);
|
||||
if (originalNameInAnotherLanguage != null) {
|
||||
namesUsed.push(originalNameInAnotherLanguage);
|
||||
// titleNames.titleString = `${originalNameInAnotherLanguage.value}${nameOriginal != null ? ` / ${titleNames.titleString}` : ''}`;
|
||||
result = GetCommonPropertiesName(originalNameInAnotherLanguage, nameOriginal ?? null);
|
||||
}
|
||||
else {
|
||||
const translatedName = names!.find(q => q.type == NameType.Translation && q.language.id == primaryLanguageId);
|
||||
if (translatedName != null) {
|
||||
namesUsed.push(translatedName);
|
||||
result = GetCommonPropertiesName(translatedName, nameOriginal ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null){
|
||||
result.namesUsed = namesUsed;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function GetCommonPropertiesName(nameInUserLanguage?: NameItem | null, nameOriginal?: NameItem | null) : CommonPropertiesName | null {
|
||||
if (nameInUserLanguage != null){
|
||||
if (nameOriginal != null){
|
||||
return {
|
||||
nameInUserLanguage: nameInUserLanguage.value,
|
||||
nameOriginal: nameOriginal.value,
|
||||
languageCodeIso3: nameOriginal!.language.codeIso3,
|
||||
} as CommonPropertiesName;
|
||||
// return `${nameInUserLanguage.value} / ${nameOriginal.value} [${nameOriginal!.language.codeIso3}]`;
|
||||
}
|
||||
else{
|
||||
return {
|
||||
nameInUserLanguage: nameInUserLanguage.value,
|
||||
nameOriginal: null,
|
||||
languageCodeIso3: null,
|
||||
} as CommonPropertiesName;
|
||||
}
|
||||
}
|
||||
else if (nameOriginal != null){
|
||||
return {
|
||||
nameInUserLanguage: null,
|
||||
nameOriginal: nameOriginal.value,
|
||||
languageCodeIso3: nameOriginal!.language.codeIso3,
|
||||
} as CommonPropertiesName;
|
||||
// return (
|
||||
// <>
|
||||
// <span className="user-select-all">{nameOriginal.value}</span> [{nameOriginal!.language.codeIso3}]
|
||||
// </>
|
||||
// )
|
||||
}
|
||||
else{
|
||||
return null;
|
||||
// return (
|
||||
// <span>NO NAME</span>
|
||||
// )
|
||||
}
|
||||
}
|
||||
@ -91,14 +91,6 @@ export function DateToString(date: Date | undefined | null): string {
|
||||
}
|
||||
}
|
||||
|
||||
export function GetDuration(durationString: string | null | undefined) : Date | null{
|
||||
|
||||
}
|
||||
|
||||
export function DurationToString(){
|
||||
|
||||
}
|
||||
|
||||
export function GetNumericValue(percentage: number | null | undefined, valueMax: number) : number | undefined{
|
||||
// if (!(percentage != undefined && percentage != null && percentage > 0)) return undefined;
|
||||
if (!IsNumericValueDefined(percentage)) return undefined;
|
||||
|
||||
@ -96,12 +96,6 @@ export default function AddAnimeSeasonOrEpisodeModalWindowComponent(props: IAddA
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{/*{addItemType == ItemType.Season &&*/}
|
||||
{/* <>*/}
|
||||
{/* Добавить сезон */}
|
||||
{/* </>*/}
|
||||
{/*}*/}
|
||||
|
||||
{addItemType == ItemType.Episode &&
|
||||
<>
|
||||
<div className='input-group mb-2'>
|
||||
|
||||
@ -99,7 +99,7 @@ export default function AnimeItemAddComponent(props : IAnimeItemAddComponentProp
|
||||
>
|
||||
<li>
|
||||
{/*<Link to='/' className='dropdown-item'>*/}
|
||||
<Link to={`/admin/library/anime/title/${props.titleId}/season/`}
|
||||
<Link to={`/admin/library/anime/${props.titleId}/season/`}
|
||||
className='dropdown-item-text link-light link-offset-2 link-body-emphasis link-underline-opacity-25 link-underline-opacity-75-hover'>
|
||||
<div className='row justify-content-between'>
|
||||
<div className='col-auto pe-0'>Добавить сезон</div>
|
||||
@ -109,7 +109,7 @@ export default function AnimeItemAddComponent(props : IAnimeItemAddComponentProp
|
||||
</li>
|
||||
<li>
|
||||
{/*<Link to='/' className='dropdown-item'>*/}
|
||||
<Link to={`/admin/library/anime/title/${props.titleId}/episode/`}
|
||||
<Link to={`/admin/library/anime/${props.titleId}/episode/`}
|
||||
className='dropdown-item-text link-light link-offset-2 link-body-emphasis link-underline-opacity-25 link-underline-opacity-75-hover'>
|
||||
<div className='row justify-content-between'>
|
||||
<div className='col-auto pe-0'>Добавить эпизод</div>
|
||||
|
||||
@ -30,6 +30,7 @@ export default function AnimeItemShortComponent(props: IAnimeSeasonsShortCompone
|
||||
{props.animeItem.number} ({props.animeItem.order}).
|
||||
</div>
|
||||
<div className='col-1'>
|
||||
sdfsdf
|
||||
<MediaInfoComponent mediaInfo={props.animeItem.commonProperties.preview?.url == null ? null : {
|
||||
type: props.animeItem.commonProperties.preview.type,
|
||||
data: props.animeItem.commonProperties.preview.url,
|
||||
@ -44,7 +45,6 @@ export default function AnimeItemShortComponent(props: IAnimeSeasonsShortCompone
|
||||
<h3 className='text-primary' role='button'>
|
||||
{Name(props.animeItem.commonProperties.names, props.user?.languageId)}
|
||||
</h3>
|
||||
id: [{props.animeItem.id}] df
|
||||
</div>
|
||||
<div className='col-auto'>
|
||||
<span className='me-2'>season.hasViews: {props.animeItem.completed ? 'TRUE' : 'FALSE'}</span>
|
||||
@ -89,6 +89,7 @@ function AnimeItemShort(animeItem: Season | Episode, goToDetailPage: () => void,
|
||||
<div className='row mb-2 border rounded py-2 bg-body-secondary'>
|
||||
{animeItem.commonProperties.preview != null &&
|
||||
<div className='col-1'>
|
||||
animeItem.commonProperties.preview?.url: {animeItem.commonProperties.preview?.url}
|
||||
<MediaInfoComponent mediaInfo={animeItem.commonProperties.preview?.url == null ? null : {
|
||||
type: animeItem.commonProperties.preview.type,
|
||||
data: animeItem.commonProperties.preview.url,
|
||||
|
||||
@ -3,8 +3,8 @@ import MediaInfoComponent, { MediaInfoModel } from '../../common/view/MediaInfoC
|
||||
import NamesViewComponent from '../../common/view/NamesViewComponent';
|
||||
import DescriptionViewComponent from '../../common/view/DescriptionViewComponent';
|
||||
import GenreListView from '../../library/view/GenreListView';
|
||||
import { AnimeTitle } from '../../../api/models/Types';
|
||||
import RateComponent from '../../common/view/RateComponent';
|
||||
import { AnimeTitleDetail} from '../../../api/models/Types';
|
||||
import RatingComponent from '../../common/view/RatingComponent.tsx';
|
||||
import { TfiPencil } from 'react-icons/tfi';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import useUser from '../../../api/hooks/useUser';
|
||||
@ -14,7 +14,7 @@ import { UserInfo } from '../../../api/models/AccountTypes';
|
||||
|
||||
export interface IAnimeTitleDetailComponentProps{
|
||||
user?: UserInfo | null | undefined,
|
||||
animeTitle: AnimeTitle,
|
||||
animeTitle: AnimeTitleDetail,
|
||||
setRate: (value: number | null) => Promise<string | undefined>,
|
||||
deleteRate: () => Promise<string | undefined>,
|
||||
forceRefresh?: () => void,
|
||||
@ -25,7 +25,7 @@ export default function AnimeTitleDetailComponent(props: IAnimeTitleDetailCompon
|
||||
const { data: user } = useQuery(userQueryKey, getUser);
|
||||
const titleNames = GetTitleNames(props.animeTitle.commonProperties.names, props.user?.languageId);
|
||||
const navigate = useNavigate();
|
||||
const goToEditPage = () => navigate(`/admin/library/anime/title/${props.animeTitle.id}/edit`);
|
||||
const goToEditPage = () => navigate(`/admin/library/anime/${props.animeTitle.id}/edit`);
|
||||
const canUserEdit = user != null;
|
||||
// const canUserEdit = true;
|
||||
return (
|
||||
@ -102,7 +102,7 @@ export default function AnimeTitleDetailComponent(props: IAnimeTitleDetailCompon
|
||||
{/* <div className='card-header'>
|
||||
<h3 className='card-heading'>Оценка</h3>
|
||||
</div> */}
|
||||
<RateComponent
|
||||
<RatingComponent
|
||||
user={props.user}
|
||||
rateObjectId={props.animeTitle.id}
|
||||
ratePercentage={props.animeTitle.rate}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { AnimeTitleShort } from '../../../api/models/Types'
|
||||
import MediaInfoComponent, { MediaInfoModel } from '../../common/view/MediaInfoComponent'
|
||||
import RateComponent from '../../common/view/RateComponent';
|
||||
import RatingComponent from '../../common/view/RatingComponent.tsx';
|
||||
|
||||
// import { atom, useAtom } from 'jotai';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
@ -63,7 +63,7 @@ export default function AnimeTitleShortComponent(props: IAnimeTitleShortComponen
|
||||
</div> */}
|
||||
<div className='row'>
|
||||
<div className='col-12 p-0'>
|
||||
<RateComponent
|
||||
<RatingComponent
|
||||
user={props.user}
|
||||
rateObjectId={props.item.id}
|
||||
ratePercentage={props.item.rate}
|
||||
|
||||
@ -5,15 +5,9 @@ import {GetName} from "../../../api/CommonPropertiesHelper.tsx";
|
||||
import {Link} from "react-router-dom";
|
||||
import {MdVideoLibrary} from "react-icons/md";
|
||||
|
||||
export type TitleNames = {
|
||||
titleElement: ReactNode | null
|
||||
// titleString: string
|
||||
namesUsed: Array<NameItem>,
|
||||
};
|
||||
|
||||
export interface IGetTitleNamesProps {
|
||||
titleNames: Array<NameItem>,
|
||||
titleId: string,
|
||||
titleId: string | null | undefined,
|
||||
titleNames: Array<NameItem> | null | undefined,
|
||||
seasonNames?: Array<NameItem> | null | undefined,
|
||||
seasonId?: string | null | undefined,
|
||||
episodeNames?: Array<NameItem> | null | undefined,
|
||||
@ -22,11 +16,13 @@ export interface IGetTitleNamesProps {
|
||||
returnToEdit?: boolean | null | undefined,
|
||||
}
|
||||
|
||||
export function NameBreadcrumpsComponent(props: IGetTitleNamesProps){
|
||||
export function NameBreadcrumbsComponent(props: IGetTitleNamesProps){
|
||||
const [titleExists, setTitleExists] = useState<boolean>(false);
|
||||
const [seasonExists, setSeasonExists] = useState<boolean>(false);
|
||||
const [episodeExists, setEpisodeExists] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
setTitleExists(props.titleNames != null && props.titleId != null && props.titleId != '');
|
||||
setSeasonExists(props.seasonNames != null && props.seasonId != null && props.seasonId != '');
|
||||
setEpisodeExists(props.episodeNames != null && props.episodeId != null && props.episodeId != '');
|
||||
}, [props])
|
||||
@ -40,15 +36,21 @@ export function NameBreadcrumpsComponent(props: IGetTitleNamesProps){
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="breadcrumb-item active" aria-current="page">
|
||||
<Link to={`/library/anime/${props.titleId}`} className=''>
|
||||
{GetItemName(props.titleNames, props.userLanguageId)}
|
||||
</Link>
|
||||
</li>
|
||||
{titleExists &&
|
||||
<li className="breadcrumb-item active" aria-current="page">
|
||||
<Link
|
||||
to={`${props.returnToEdit == true ? '/admin' : ''}/library/anime/${props.titleId}${props.returnToEdit == true ? '/edit' : ''}`}
|
||||
className=''>
|
||||
{GetItemName(props.titleNames ?? [], props.userLanguageId)}
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
|
||||
{seasonExists &&
|
||||
<li className="breadcrumb-item active" aria-current="page">
|
||||
<Link to={`${(props.returnToEdit == true) ? '/admin' : ''}/library/anime/${props.titleId}/season/${props.seasonId}`} className=''>
|
||||
<Link
|
||||
to={`${props.returnToEdit == true ? '/admin' : ''}/library/anime/${props.titleId}/season/${props.seasonId}${props.returnToEdit == true ? '/edit' : ''}`}
|
||||
className=''>
|
||||
{GetItemName(props.seasonNames ?? [], props.userLanguageId)}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { ReactNode } from "react";
|
||||
import { NameItem, NameType } from "../../../api/models/Types";
|
||||
// import { NameItem, NameType } from "../../../api/models/Types";
|
||||
import { NameItem } from "../../../api/models/Types";
|
||||
import {GetName} from "../../../api/CommonPropertiesHelper.tsx";
|
||||
|
||||
export type TitleNames = {
|
||||
titleElement: ReactNode | null
|
||||
@ -8,7 +10,54 @@ export type TitleNames = {
|
||||
};
|
||||
|
||||
export function GetTitleNames(names: Array<NameItem> | null | undefined, primaryLanguageId?: string | null | undefined){
|
||||
const titleNames = names == undefined || names == null
|
||||
const titleNames = GetName(names, primaryLanguageId);
|
||||
|
||||
if (titleNames != null){
|
||||
if (titleNames.nameInUserLanguage != null){
|
||||
if (titleNames.nameOriginal != null){
|
||||
return {
|
||||
titleElement: (
|
||||
<>
|
||||
<span className="user-select-all">{titleNames.nameInUserLanguage}</span> / <span className="user-select-all">{titleNames.nameOriginal}</span> [{titleNames.languageCodeIso3}]
|
||||
</>
|
||||
),
|
||||
namesUsed: titleNames.namesUsed,
|
||||
} as TitleNames;
|
||||
}
|
||||
else{
|
||||
return {
|
||||
titleElement: (
|
||||
<>
|
||||
<span className="user-select-all">{titleNames.nameInUserLanguage}</span>
|
||||
</>
|
||||
),
|
||||
namesUsed: titleNames.namesUsed,
|
||||
} as TitleNames
|
||||
}
|
||||
}
|
||||
else if (titleNames.nameOriginal != null){
|
||||
return {
|
||||
titleElement: (
|
||||
<>
|
||||
<span className="user-select-all">{titleNames.nameOriginal}</span> [{titleNames.languageCodeIso3}]
|
||||
</>
|
||||
),
|
||||
namesUsed: titleNames.namesUsed,
|
||||
} as TitleNames
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
titleElement: (
|
||||
<span>NO NAME</span>
|
||||
),
|
||||
namesUsed: [],
|
||||
} as TitleNames
|
||||
}
|
||||
|
||||
/*
|
||||
export function GetTitleNames(names: Array<NameItem> | null | undefined, primaryLanguageId?: string | null | undefined){
|
||||
const titleNames = names == null
|
||||
? null
|
||||
: {
|
||||
titleElement: NameComponent(null, null),
|
||||
@ -16,7 +65,7 @@ export function GetTitleNames(names: Array<NameItem> | null | undefined, primary
|
||||
} as TitleNames;
|
||||
if (titleNames != null){
|
||||
const nameOriginal = names!.find(q => q.type == NameType.Original)
|
||||
if ((primaryLanguageId == undefined || primaryLanguageId == null) || nameOriginal?.language.id == primaryLanguageId){
|
||||
if ((primaryLanguageId == null || primaryLanguageId == '') || nameOriginal?.language.id == primaryLanguageId){
|
||||
if (nameOriginal != null){
|
||||
titleNames.namesUsed.push(nameOriginal);
|
||||
// titleNames.titleString = `${nameOriginal.value} [${nameOriginal.language.codeIso3}]`;
|
||||
@ -43,7 +92,7 @@ export function GetTitleNames(names: Array<NameItem> | null | undefined, primary
|
||||
titleNames.titleElement = NameComponent(translatedName, nameOriginal ?? null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return titleNames == null
|
||||
@ -83,4 +132,5 @@ function NameComponent(nameInUserLanguage?: NameItem | null, nameOriginal?: Name
|
||||
<span>NO NAME</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
@ -23,7 +23,7 @@ export interface IRateComponentProps{
|
||||
forceRefresh?: () => void | null | undefined,
|
||||
}
|
||||
|
||||
export default function RateComponent(props: IRateComponentProps) {
|
||||
export default function RatingComponent(props: IRateComponentProps) {
|
||||
const [ratePercentage, setRatePercentage] = useState<number | null>(null);
|
||||
const [userRatePercentage, setUserRatePercentage] = useState<number | null>(null);
|
||||
const [rateEditId, setRateEditId] = useAtom(expandedRatingAtom);
|
||||
|
||||
@ -2,7 +2,7 @@ import { useParams } from 'react-router-dom'
|
||||
import { GetAnimeTitleDetail, VoteAnimeTitle, UnvoteAnimeTitle } from '../../../api/AnimeTitleApi';
|
||||
import { QueryClient, useQuery, useQueryClient } from 'react-query';
|
||||
import AnimeTitleDetailComponent from '../../../components/MediaContent/view/AnimeTitleDetailComponent';
|
||||
import { VoteDeleteModel, VoteEditModel } from '../../../api/models/Types';
|
||||
import { VoteDeleteModel, VoteEditModel} from '../../../api/models/Types';
|
||||
import { libraryClient } from '../../../api/axios';
|
||||
import useUser from '../../../api/hooks/useUser';
|
||||
import { userQueryKey } from '../../../components/common/UserShortComponent';
|
||||
@ -64,4 +64,6 @@ export default function AnimeTitleDetail() {
|
||||
}
|
||||
|
||||
|
||||
function InvalidateGenres(queryClient: QueryClient) { queryClient.invalidateQueries({ queryKey: [queryKey] }); }
|
||||
function InvalidateGenres(queryClient: QueryClient) {
|
||||
return queryClient.invalidateQueries({ queryKey: [queryKey] });
|
||||
}
|
||||
@ -1,11 +1,489 @@
|
||||
import {useParams} from "react-router-dom";
|
||||
import {useNavigate, useParams} from "react-router-dom";
|
||||
import {useEffect, useState} from "react";
|
||||
import {
|
||||
AnimeSeasonCreateModel,
|
||||
AnimeTitleCreateModel,
|
||||
CreateDescriptionModel, CreateGenreProportionModel,
|
||||
CreateMediaInfoModel,
|
||||
CreateNameModel,
|
||||
Description,
|
||||
GenreProportion,
|
||||
Language, MediaInfoType,
|
||||
NameItem
|
||||
} from "../../../api/models/Types.tsx";
|
||||
import {MediaInfoEditModel} from "../../../components/common/edit/MediaInfoTypes.tsx";
|
||||
import {AddSeason, CreateAnimeTitle, GetAnimeTitle} from "../../../api/AnimeTitleApi.tsx";
|
||||
import MediaInfoEditComponent from "../../../components/common/edit/MediaInfoEditComponent.tsx";
|
||||
import DateEditComponent from "../../../components/common/edit/DateEditComponent.tsx";
|
||||
import {GetDate} from "../../../common/Helper.tsx";
|
||||
import NamesEditComponent from "../../../components/MediaContent/edit/Names/NamesEditComponent.tsx";
|
||||
import DescriptionsEditComponent
|
||||
from "../../../components/MediaContent/edit/Descriptions/DescriptionsEditComponent.tsx";
|
||||
import GenreProportionEditComponent
|
||||
from "../../../components/MediaContent/edit/Genres/GenreProportionEditComponent.tsx";
|
||||
import {TfiSave} from "react-icons/tfi";
|
||||
import useUser from "../../../api/hooks/useUser.tsx";
|
||||
import {useQuery} from "react-query";
|
||||
import {userQueryKey} from "../../../components/common/UserShortComponent.tsx";
|
||||
import {NameBreadcrumbsComponent} from "../../../components/common/view/NameBreadcrumbsComponent.tsx";
|
||||
|
||||
export default function AnimeSeasonCreate(){
|
||||
const { id } = useParams();
|
||||
const client = null;
|
||||
const navigate = useNavigate();
|
||||
const { getUser } = useUser();
|
||||
const { data: user } = useQuery(userQueryKey, getUser);
|
||||
|
||||
const { titleId } = useParams();
|
||||
const [ titleNames, setTitleNames ] = useState<Array<NameItem> | null>(null);
|
||||
|
||||
const [ names, setNames ] = useState<Array<NameItem>>([]);
|
||||
const [ preview, setPreview ] = useState<MediaInfoEditModel | null>(null);
|
||||
const [ descriptions, setDescriptions ] = useState<Array<Description>>([]);
|
||||
const [ genres, setGenres ] = useState<Array<GenreProportion>>([]);
|
||||
// const [ relatedContent, setRelatedContent ] = useState<Array<MediaInfo>>([]);
|
||||
const [ announcementDate, setAnnouncementDate ] = useState<string | null>(null);
|
||||
const [ estimatedReleaseDate, setEstimatedReleaseDate ] = useState<string | null>(null);
|
||||
const [ releaseDate, setReleaseDate ] = useState<string | null>(null);
|
||||
|
||||
// const [duration, setDuration] = useState<number | null>(null);
|
||||
|
||||
const AddName = (nameItem: NameItem) => {
|
||||
if (names.find(q => q.language.id == nameItem.language.id && q.type == nameItem.type && q.value == nameItem.value)){
|
||||
return 'Name already exists';
|
||||
}
|
||||
else {
|
||||
const obj = names;
|
||||
names.push(nameItem);
|
||||
setNames(obj);
|
||||
return '';
|
||||
}
|
||||
};
|
||||
const EditName = (nameItem: NameItem, newValue: string | null, newLanguage: Language | null) => {
|
||||
const obj = names;
|
||||
const name = obj.find(q => q.language == nameItem.language && q.type == nameItem.type && q.value == nameItem.value);
|
||||
if (name != null){
|
||||
if (newValue != null) name.value = newValue;
|
||||
if (newLanguage != null) name.language = newLanguage;
|
||||
setNames(obj);
|
||||
}
|
||||
};
|
||||
const DeleteName = (nameItem: NameItem) => {
|
||||
const obj = names;
|
||||
setNames(obj.filter(q => !(q.language == nameItem.language && q.type == nameItem.type && q.value == nameItem.value)));
|
||||
};
|
||||
|
||||
const AddDescription = (description: Description) => {
|
||||
if (descriptions.find(q => q.language.id == description.language.id && q.isOriginal == description.isOriginal && q.value == description.value)){
|
||||
return 'Description already exists';
|
||||
}
|
||||
else {
|
||||
const obj = descriptions
|
||||
obj.push(description);
|
||||
setDescriptions(obj);
|
||||
return '';
|
||||
}
|
||||
};
|
||||
const EditDescription = (descriptionItem: Description, newValue: string | null, newLanguage: Language | null) => {
|
||||
const obj = descriptions;
|
||||
const description = obj.find(q => q.language == descriptionItem.language && q.isOriginal == descriptionItem.isOriginal && q.value == descriptionItem.value);
|
||||
if (description != null){
|
||||
if (newValue != null) description.value = newValue;
|
||||
if (newLanguage != null) description.language = newLanguage;
|
||||
setDescriptions(obj);
|
||||
}
|
||||
};
|
||||
const DeleteDescription = (description: Description) => {
|
||||
const obj = descriptions;
|
||||
setDescriptions(obj.filter(q => !(q.language == description.language && q.isOriginal == description.isOriginal && q.value == description.value)));
|
||||
};
|
||||
|
||||
const AddGenre = (genreProportionItem: GenreProportion) => {
|
||||
if (genres.find(q => q.genre.id == genreProportionItem.genre.id && q.proportion == genreProportionItem.proportion)){
|
||||
return 'Genre already exists';
|
||||
}
|
||||
else {
|
||||
const obj = genres;
|
||||
obj.push(genreProportionItem);
|
||||
setGenres(obj);
|
||||
return '';
|
||||
}
|
||||
};
|
||||
const EditGenre = (genreProportionItem: GenreProportion, proportionPercentage: number | null) => {
|
||||
const obj = genres;
|
||||
const genreProportion = obj.find(q => q.genre == genreProportionItem.genre && q.proportion == genreProportionItem.proportion);
|
||||
if (genreProportion != null){
|
||||
if (proportionPercentage != null) genreProportion.proportion = proportionPercentage;
|
||||
setGenres(obj);
|
||||
}
|
||||
};
|
||||
const DeleteGenre = (genreProportionItem: GenreProportion) => {
|
||||
const obj = genres;
|
||||
setGenres(obj.filter(q => !(q.genre == genreProportionItem.genre && q.proportion == genreProportionItem.proportion)));
|
||||
};
|
||||
|
||||
const SetAnnouncementDate = (date: Date | null) => setAnnouncementDate(date == null ? null : date.toISOString());
|
||||
const SetEstimatedReleaseDate = (date: Date | null) => setEstimatedReleaseDate(date == null ? null : date.toISOString());
|
||||
const SetReleaseDate = (date: Date | null) => setReleaseDate(date == null ? null : date.toISOString());
|
||||
|
||||
// const SetPreview = (preview: MediaInfoEditModel | null) => setPreview(preview);
|
||||
|
||||
const [ isEditing, setIsEditingValue ] = useState<Array<string>>([]);
|
||||
const setEditing = (elementName: string, value: boolean) => {
|
||||
const alreadyEditing = isEditing.find(q => q == elementName) != null;
|
||||
if (value){
|
||||
if (!alreadyEditing){
|
||||
setIsEditingValue(isEditing.concat([elementName]))
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (alreadyEditing){
|
||||
setIsEditingValue(isEditing.filter(q => q != elementName))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const [ isDeleting, setIsDeletingValue ] = useState<Array<string>>([]);
|
||||
const setDeleting = (elementName: string, value: boolean) => {
|
||||
const alreadyDeleting = isDeleting.find(q => q == elementName) != null;
|
||||
if (value){
|
||||
// console.log('a');
|
||||
// console.log('alreadyDeleting');
|
||||
// console.log(alreadyDeleting ? 'TR' : 'FA');
|
||||
if (!alreadyDeleting){
|
||||
setIsDeletingValue(isDeleting.concat([elementName]))
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (alreadyDeleting){
|
||||
setIsDeletingValue(isDeleting.filter(q => q != elementName))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const Save = () =>{
|
||||
const model = {
|
||||
animeTitleId: titleId,
|
||||
preview: preview == null ? null : {
|
||||
newType: preview.type,
|
||||
// newUrl: preview.objectId,
|
||||
newUrl: preview.url,
|
||||
newFile: preview.data
|
||||
} as CreateMediaInfoModel,
|
||||
names: names.map(q => {
|
||||
return {
|
||||
languageId: q.language.id,
|
||||
value: q.value,
|
||||
type: q.type,
|
||||
} as CreateNameModel
|
||||
}),
|
||||
descriptions: descriptions.map(q => {
|
||||
return {
|
||||
languageId: q.language.id,
|
||||
isOriginal: q.isOriginal,
|
||||
value: q.value,
|
||||
} as CreateDescriptionModel
|
||||
}),
|
||||
// relatedContent: relatedContent.map(q => {
|
||||
// return {
|
||||
// type: q.type,
|
||||
// contentType: q.contentType,
|
||||
// url: q.url,
|
||||
// } as CreateMediaInfoModel
|
||||
// }),
|
||||
relatedContent: [],
|
||||
genres: genres.map(q => {
|
||||
return {
|
||||
genreId: q.genre.id,
|
||||
proportion: q.proportion,
|
||||
} as CreateGenreProportionModel
|
||||
}),
|
||||
announcementDate: announcementDate,
|
||||
estimatedReleaseDate: estimatedReleaseDate,
|
||||
releaseDate: releaseDate,
|
||||
} as AnimeSeasonCreateModel;
|
||||
|
||||
AddSeason(model)
|
||||
.then(() => navigate(`/admin/library/anime/${titleId}/edit`))
|
||||
// .then(() => navigate(`/admin/library/anime/${titleId}/season/${seasonId}/edit`))
|
||||
.catch((err) => { console.error(err);});
|
||||
};
|
||||
|
||||
useEffect(() =>{
|
||||
if (titleId == null || titleId == ''){
|
||||
setTitleNames(null);
|
||||
}
|
||||
else{
|
||||
GetAnimeTitle(titleId ?? '', client)
|
||||
.then((data) =>{
|
||||
if (data == null){
|
||||
setTitleNames(null);
|
||||
}
|
||||
else{
|
||||
// const name = GetTitleNames(names, user?.languageId)?.titleElement;
|
||||
setTitleNames(data.commonProperties.names);
|
||||
}
|
||||
// setDataLoadingError(null);
|
||||
})
|
||||
.catch((error) => {
|
||||
setTitleNames(null);
|
||||
console.log(error);
|
||||
// setDataLoadingError(error);
|
||||
});
|
||||
}
|
||||
}, [ titleId ]);
|
||||
|
||||
return (
|
||||
<>
|
||||
title id: { id }
|
||||
</>
|
||||
<NameBreadcrumbsComponent titleId={titleId} titleNames={titleNames} returnToEdit={true}
|
||||
userLanguageId={user?.languageId} />
|
||||
|
||||
номер сезона
|
||||
вариант сезона
|
||||
|
||||
<div className='row overflow-x-hidden overflow-y-visible'>
|
||||
<div className='col-4'>
|
||||
<MediaInfoEditComponent
|
||||
mediaInfo={preview}
|
||||
classes={'card-img-top rounded-3 border border-5 border-secondary'}
|
||||
|
||||
isEditing={isEditing.find(q => q == 'preview') != null}
|
||||
setEditing={(_, value) => setEditing('preview', value)}
|
||||
// editMediaInfo={(mediaInfo, newUrl, newFile) =>{
|
||||
editMediaInfo={(_, newUrl, newFile) => {
|
||||
// console.log(`new url: ${newUrl}`)
|
||||
// SetPreview(mediaInfo == null ? null :
|
||||
setPreview((newUrl == null && newFile == null) ? null :
|
||||
{
|
||||
// type: mediaInfo?.type ?? MediaInfoType.Image,
|
||||
type: MediaInfoType.Image,
|
||||
url: newUrl,
|
||||
data: newFile,
|
||||
objectId: null,
|
||||
// isNew: false,
|
||||
} as MediaInfoEditModel);
|
||||
return Promise.resolve('');
|
||||
}}
|
||||
|
||||
isDeleting={isDeleting.find(q => q == 'preview') != null}
|
||||
setDeleting={(_, value) => setDeleting('preview', value)}
|
||||
|
||||
deleteMediaInfo={() => {
|
||||
setPreview(null);
|
||||
return Promise.resolve('');
|
||||
}}
|
||||
dataLoadingError={null}
|
||||
forceRefresh={Plug}
|
||||
/>
|
||||
|
||||
<div className='card p-0 mt-2'>
|
||||
<div className='card-body p-0'>
|
||||
<div className='table-responsive'>
|
||||
{/* <table className="table m-0 table-bordered"> */}
|
||||
<table className="table m-0">
|
||||
{/* <thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">First</th>
|
||||
<th scope="col">Last</th>
|
||||
<th scope="col">Handle</th>
|
||||
</tr>
|
||||
</thead> */}
|
||||
<tbody>
|
||||
<tr>
|
||||
{/* <th className='text-nowrap'>Дата анонса</th>
|
||||
<td className='w-100 text-center'>{data.commonProperties.announcementDate?.toString() ?? '—//—'}</td> */}
|
||||
<th>Дата анонса</th>
|
||||
<td className='text-end'>
|
||||
<DateEditComponent
|
||||
placeholder={'Дата анонса'}
|
||||
required={true}
|
||||
isEditing={isEditing.find(q => q == 'announcementDate') != null}
|
||||
enabled={true}
|
||||
date={GetDate(announcementDate)}
|
||||
editDate={(value: Date | null) => {
|
||||
SetAnnouncementDate(value);
|
||||
return Promise.resolve();
|
||||
}}
|
||||
setEditing={(value: boolean) => setEditing('announcementDate', value)}
|
||||
// setDeleting: (genreId: string, value: boolean) => void,
|
||||
dataLoadingError={null}
|
||||
forceRefresh={Plug}
|
||||
/>
|
||||
{/* {props.animeTitle.commonProperties.announcementDate?.toString() ?? '—//—'} */}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
{/* <th className='text-nowrap'>Предполагаемая дата выхода</th>
|
||||
<td className='w-100 text-center'>{data.commonProperties.estimatedReleaseDate?.toString() ?? '—//—'}</td> */}
|
||||
<th>Предполагаемая дата выхода</th>
|
||||
<td className='text-end'>
|
||||
<DateEditComponent
|
||||
placeholder={'Предполагаемая дата выхода'}
|
||||
required={true}
|
||||
isEditing={isEditing.find(q => q == 'estimatedReleaseDate') != null}
|
||||
enabled={true}
|
||||
|
||||
date={estimatedReleaseDate != null ? new Date(estimatedReleaseDate) : null}
|
||||
editDate={(value: Date | null) => {
|
||||
SetEstimatedReleaseDate(value);
|
||||
return Promise.resolve();
|
||||
}}
|
||||
setEditing={(value: boolean) => setEditing('estimatedReleaseDate', value)}
|
||||
// setDeleting: (genreId: string, value: boolean) => void,
|
||||
dataLoadingError={null}
|
||||
forceRefresh={Plug}
|
||||
/>
|
||||
{/* {props.animeTitle.commonProperties.estimatedReleaseDate?.toString() ?? '—//—'} */}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
{/* <th className='text-nowrap'>Предполагаемая дата выхода</th>
|
||||
<td className='w-100 text-center'>{data.commonProperties.estimatedReleaseDate?.toString() ?? '—//—'}</td> */}
|
||||
<th>Дата выхода</th>
|
||||
<td className='text-end'>
|
||||
<DateEditComponent
|
||||
placeholder={'Дата выхода'}
|
||||
required={true}
|
||||
isEditing={isEditing.find(q => q == 'releaseDate') != null}
|
||||
enabled={true}
|
||||
date={releaseDate != null ? new Date(releaseDate) : null}
|
||||
editDate={(value: Date | null) => {
|
||||
SetReleaseDate(value);
|
||||
return Promise.resolve();
|
||||
}}
|
||||
setEditing={(value: boolean) => setEditing('releaseDate', value)}
|
||||
// setDeleting: (genreId: string, value: boolean) => void,
|
||||
dataLoadingError={null}
|
||||
forceRefresh={Plug}
|
||||
/>
|
||||
{/* {props.animeTitle.commonProperties.estimatedReleaseDate?.toString() ?? '—//—'} */}
|
||||
</td>
|
||||
</tr>
|
||||
{/*<tr>*/}
|
||||
{/* <th>Продолжительность</th>*/}
|
||||
{/* <td className='text-end'>*/}
|
||||
{/* <TimespanComponent*/}
|
||||
{/* title="Продолжительность"*/}
|
||||
{/* value={TimespanFromTicks(addEpisodeDuration)}*/}
|
||||
{/* onChange={(ts) => setAddEpisodeDuration(TimespanToTicks(ts))}*/}
|
||||
{/* />*/}
|
||||
{/* </td>*/}
|
||||
{/*</tr>*/}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className='col p-0 pe-2'>
|
||||
<NamesEditComponent
|
||||
names={names}
|
||||
createName={(name) => {
|
||||
const error = AddName({
|
||||
language: name.language,
|
||||
value: name.value,
|
||||
type: name.type
|
||||
} as NameItem);
|
||||
return error.length == 0 ? Promise.resolve('') : Promise.reject({message: error} as Error);
|
||||
}}
|
||||
|
||||
editName={(name, newValue, newLanguage) => {
|
||||
EditName({
|
||||
language: name.language,
|
||||
value: name.value,
|
||||
type: name.type
|
||||
} as NameItem, newValue, newLanguage);
|
||||
return Promise.resolve('');
|
||||
}}
|
||||
|
||||
deleteName={(name) => {
|
||||
DeleteName({
|
||||
language: name.language,
|
||||
value: name.value,
|
||||
type: name.type
|
||||
} as NameItem);
|
||||
return Promise.resolve('');
|
||||
}}
|
||||
dataLoadingError={null}
|
||||
forceRefresh={Plug}
|
||||
/>
|
||||
{/* <DescriptionViewComponent descriptions={props.animeTitle.commonProperties.descriptions} userLanguageId={props.userLanguageId} /> */}
|
||||
<DescriptionsEditComponent
|
||||
descriptions={descriptions}
|
||||
createDescription={(description) => {
|
||||
const error = AddDescription({
|
||||
language: description.language,
|
||||
value: description.value,
|
||||
isOriginal: description.isOriginal
|
||||
} as Description);
|
||||
return error.length == 0 ? Promise.resolve('') : Promise.reject({message: error} as Error);
|
||||
}}
|
||||
|
||||
editDescription={(description, newValue, newLanguage) => {
|
||||
EditDescription({
|
||||
language: description.language,
|
||||
value: description.value,
|
||||
isOriginal: description.isOriginal
|
||||
} as Description, newValue, newLanguage);
|
||||
return Promise.resolve('');
|
||||
}}
|
||||
|
||||
deleteDescription={(description) => {
|
||||
DeleteDescription({
|
||||
language: description.language,
|
||||
value: description.value,
|
||||
isOriginal: description.isOriginal
|
||||
} as Description);
|
||||
return Promise.resolve('');
|
||||
}}
|
||||
dataLoadingError={null}
|
||||
forceRefresh={Plug}
|
||||
/>
|
||||
|
||||
<div className='card p-0'>
|
||||
<div className='card-header'>
|
||||
<h3 className='card-heading'>Жанры</h3>
|
||||
</div>
|
||||
<div className='card-body'>
|
||||
<GenreProportionEditComponent
|
||||
genresProportions={genres}
|
||||
createGenreProportionPercentage={(genreProportionItem) => {
|
||||
const error = AddGenre(genreProportionItem);
|
||||
return error.length == 0 ? Promise.resolve('') : Promise.reject({message: error} as Error);
|
||||
}}
|
||||
editGenreProportionPercentage={(genreProportionItem, proportionPercentage) => {
|
||||
EditGenre(genreProportionItem, proportionPercentage);
|
||||
return Promise.resolve('');
|
||||
}}
|
||||
deleteGenreProportionPercentage={(genreProportionItem) => {
|
||||
DeleteGenre(genreProportionItem);
|
||||
return Promise.resolve('');
|
||||
}}
|
||||
dataLoadingError={null}
|
||||
forceRefresh={Plug}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className='bg-success'>
|
||||
<div>Содержимое</div>
|
||||
<div>сезоны</div>
|
||||
<div>эпизоды</div>
|
||||
</div> */}
|
||||
<hr/>
|
||||
<div className='row g-2 justify-content-end'>
|
||||
<div className="col">
|
||||
<div className='btn btn-primary w-100' onClick={Save}>Save <TfiSave/></div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Plug() {
|
||||
|
||||
}
|
||||
@ -57,8 +57,6 @@ export default function AnimeTitleEdit() {
|
||||
const fetchData = () => {
|
||||
GetAnimeTitle(id ?? '', client)
|
||||
.then((data) =>{
|
||||
console.log('data');
|
||||
console.log(data);
|
||||
setData(data ?? null);
|
||||
setDataLoadingError(null);
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user