Compare commits

...

2 Commits

Author SHA1 Message Date
6df71e3341 [FIX] correct fullsceen hide of menu 2025-02-26 00:20:21 +01:00
263a4ae4c0 [FEAT] update upload of data 2025-02-26 00:09:58 +01:00
19 changed files with 256 additions and 197 deletions

View File

@ -78,6 +78,9 @@ public class MediaResource {
if (data.contentEquals("null")) { if (data.contentEquals("null")) {
return null; return null;
} }
if (data.contentEquals("undefined")) {
return null;
}
return data; return data;
} }
@ -86,34 +89,43 @@ public class MediaResource {
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Create a new Media", tags = "GLOBAL") @Operation(description = "Create a new Media", tags = "GLOBAL")
@TypeScriptProgress @TypeScriptProgress
public Media uploadFile( // public Media uploadMedia( //
@FormDataParam("fileName") String fileName, // // @AsyncType(Long.class) @FormDataParam("universeId") String universeId, //
@FormDataParam("universe") String universe, // // @AsyncType(Long.class) @FormDataParam("typeId") String typeId, //
@FormDataParam("series") String series, // // @AsyncType(Long.class) @FormDataParam("seriesId") String seriesId, //
// @FormDataParam("seriesId") String seriesId, // Not used ... // @AsyncType(Long.class) @FormDataParam("season") String season, // value of the season ==> local add if needed
@FormDataParam("season") String season, // // @AsyncType(Long.class) @FormDataParam("episode") String episode, // value of the season ==> local add if needed
@FormDataParam("episode") String episode, // @FormDataParam("universeId") String universeId, //
@FormDataParam("title") String title, //
@FormDataParam("typeId") String typeId, // @FormDataParam("typeId") String typeId, //
@FormDataParam("seriesId") String seriesId, //
@FormDataParam("season") String season, // value of the season ==> local add if needed
@FormDataParam("episode") String episode, // value of the season ==> local add if needed
@FormDataParam("title") String title, //
@FormDataParam("file") final InputStream fileInputStream, // @FormDataParam("file") final InputStream fileInputStream, //
@FormDataParam("file") final FormDataContentDisposition fileMetaData // @FormDataParam("file") final FormDataContentDisposition fileMetaData //
) throws FailException { ) throws FailException {
try (DBAccess db = DBAccess.createInterface()) { try (DBAccess db = DBAccess.createInterface()) {
// correct input string stream : // correct input string stream :
fileName = multipartCorrection(fileName); final String fileName = multipartCorrection(fileMetaData.getFileName());
universe = multipartCorrection(universe); universeId = multipartCorrection(universeId);
series = multipartCorrection(series); final Long universeIdLong = universeId != null ? Long.parseLong(universeId) : null;
typeId = multipartCorrection(typeId);
final Long typeIdLong = typeId != null ? Long.parseLong(typeId) : null;
seriesId = multipartCorrection(seriesId);
final Long seriesIdLong = seriesId != null ? Long.parseLong(seriesId) : null;
season = multipartCorrection(season); season = multipartCorrection(season);
final Long seasonLong = season != null ? Long.parseLong(season) : null;
episode = multipartCorrection(episode); episode = multipartCorrection(episode);
title = multipartCorrection(title); title = multipartCorrection(title);
typeId = multipartCorrection(typeId);
// todo: check if all remotes Id exist ...
// public NodeSmall uploadFile(final FormDataMultiPart form) { // public NodeSmall uploadFile(final FormDataMultiPart form) {
LOGGER.info("Upload media file: {}", fileMetaData); LOGGER.info("Upload media file: {}", fileMetaData);
LOGGER.info(" - fileName: {}", fileName); LOGGER.info(" - fileName: {}", fileName);
LOGGER.info(" - universe: {}", universe); LOGGER.info(" - universe: {}", universeIdLong);
LOGGER.info(" - series: {}", series); LOGGER.info(" - series: {}", seriesIdLong);
LOGGER.info(" - season: {}", season); LOGGER.info(" - season: {}", seasonLong);
LOGGER.info(" - episode: {}", episode); LOGGER.info(" - episode: {}", episode);
LOGGER.info(" - title: {}", title); LOGGER.info(" - title: {}", title);
LOGGER.info(" - type: {}", typeId); LOGGER.info(" - type: {}", typeId);
@ -149,26 +161,32 @@ public class MediaResource {
// Fist step: retieve all the Id of each parents:... // Fist step: retieve all the Id of each parents:...
LOGGER.info("Find typeNode"); LOGGER.info("Find typeNode");
// check if id of type exist: // check if id of type exist:
final Type typeNode = TypeResource.getId(Long.parseLong(typeId)); final Type typeNode = TypeResource.getId(typeIdLong);
if (typeNode == null) { if (typeNode == null) {
DataResource.removeTemporaryFile(tmpUID); DataResource.removeTemporaryFile(tmpUID);
throw new InputException("typeId", "TypeId does not exist ..."); throw new InputException("typeId", "TypeId does not exist ...");
} }
LOGGER.info(" ==> {}", typeNode); // check if id of type exist:
LOGGER.info("Find seriesNode");
// get uid of group:
Series seriesNode = null; Series seriesNode = null;
if (series != null) { if (seriesIdLong != null) {
seriesNode = SeriesResource.getOrCreate(series, typeNode.id); seriesNode = SeriesResource.getId(seriesIdLong);
if (seriesNode == null) {
DataResource.removeTemporaryFile(tmpUID);
throw new InputException("seriesId", "seriesId does not exist ...");
}
if (seriesNode.parentId != typeNode.id) {
DataResource.removeTemporaryFile(tmpUID);
throw new InputException("seriesId", "seriesId object have not the correct parent...");
}
} }
LOGGER.info(" ==> {}", seriesNode); LOGGER.info(" ==> {}", seriesNode);
LOGGER.info("Find seasonNode"); LOGGER.info("Find seasonNode");
// get uid of season: // get uid of season:
Season seasonNode = null; Season seasonNode = null;
if (seriesNode == null && season != null) { if (seriesNode == null && seasonLong != null) {
DataResource.removeTemporaryFile(tmpUID); DataResource.removeTemporaryFile(tmpUID);
throw new InputException("season", "Season is set but no seraies is set !!"); throw new InputException("season", "Season is set but no series is set !!");
} }
if (season != null) { if (season != null) {
seasonNode = SeasonResource.getOrCreate(season, seriesNode.id); seasonNode = SeasonResource.getOrCreate(season, seriesNode.id);

View File

@ -52,6 +52,9 @@ public class SeriesResource {
return DataAccess.get(Series.class, id); return DataAccess.get(Series.class, id);
} }
public static Series getId(final Long id) throws Exception {
return DataAccess.get(Series.class, id);
}
/* ============================================================================= ADMIN SECTION: ============================================================================= */ /* ============================================================================= ADMIN SECTION: ============================================================================= */
@POST @POST

View File

@ -34,6 +34,7 @@ public class Media extends GenericDataSoftDelete {
public ObjectId dataId; public ObjectId dataId;
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Data.class)
@Column(nullable = false) @Column(nullable = false)
@Nullable
public UUID dataIdOld; public UUID dataIdOld;
@Schema(description = "Type of the media") @Schema(description = "Type of the media")
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class) @ManyToOne(fetch = FetchType.LAZY, targetEntity = Type.class)

View File

@ -181,21 +181,20 @@ export namespace MediaResource {
/** /**
* Create a new Media * Create a new Media
*/ */
export function uploadFile({ export function uploadMedia({
restConfig, restConfig,
data, data,
callbacks, callbacks,
}: { }: {
restConfig: RESTConfig, restConfig: RESTConfig,
data: { data: {
fileName: string,
file: File, file: File,
series: string, universeId: string,
universe: string,
season: string, season: string,
episode: string,
typeId: string, typeId: string,
episode: string,
title: string, title: string,
seriesId: string,
}, },
callbacks?: RESTCallbacks, callbacks?: RESTCallbacks,
}): Promise<Media> { }): Promise<Media> {

View File

@ -22,7 +22,7 @@ export const ZodMedia = ZodGenericDataSoftDelete.extend({
* Foreign Key Id of the data * Foreign Key Id of the data
*/ */
dataId: ZodObjectId, dataId: ZodObjectId,
dataIdOld: ZodUUID, dataIdOld: ZodUUID.optional(),
/** /**
* Type of the media * Type of the media
*/ */
@ -79,7 +79,7 @@ export const ZodMediaWrite = ZodGenericDataSoftDeleteWrite.extend({
* Foreign Key Id of the data * Foreign Key Id of the data
*/ */
dataId: ZodObjectId.optional(), dataId: ZodObjectId.optional(),
dataIdOld: ZodUUID.optional(), dataIdOld: ZodUUID.nullable().optional(),
/** /**
* Type of the media * Type of the media
*/ */

View File

@ -69,7 +69,8 @@ export const Covers = ({
loading="lazy" loading="lazy"
src={url} src={url}
maxWidth={size} maxWidth={size}
boxSize={size} /*{...rest}*/ maxHeight={size}
boxSize={size}
onClick={onClick} onClick={onClick}
/> />
); );

View File

@ -5,6 +5,7 @@ import {
MdFastForward, MdFastForward,
MdFastRewind, MdFastRewind,
MdFullscreen, MdFullscreen,
MdFullscreenExit,
MdLooksOne, MdLooksOne,
MdNavigateBefore, MdNavigateBefore,
MdNavigateNext, MdNavigateNext,
@ -63,6 +64,8 @@ const formatTime = (time) => {
}; };
export const VideoPlayer = ({}: AudioPlayerProps) => { export const VideoPlayer = ({}: AudioPlayerProps) => {
const { playMediaList, MediaOffset, previous, next, first, clear } =
useActivePlaylistService();
const [time, setTime] = useState(10); const [time, setTime] = useState(10);
const [isRunning, setIsRunning] = useState(true); const [isRunning, setIsRunning] = useState(true);
useEffect(() => { useEffect(() => {
@ -82,22 +85,24 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
}, [time, isRunning]); }, [time, isRunning]);
const resetTimer = () => { const resetTimer = () => {
setTime(10); if (playMediaList.length !== 0 && !!document.fullscreenElement) {
setIsRunning(true);
};
useEffect(() => {
const resetTimer = () => {
setTime(10); setTime(10);
setIsRunning(true); setIsRunning(true);
}
};
useEffect(() => {
const resetTimerLocal = () => {
if (playMediaList.length !== 0 && !!document.fullscreenElement) {
setTime(10);
setIsRunning(true);
}
}; };
window.addEventListener("mousemove", resetTimer); window.addEventListener("mousemove", resetTimerLocal);
return () => { return () => {
window.removeEventListener("mousemove", resetTimer); window.removeEventListener("mousemove", resetTimerLocal);
}; };
}, []); }, [playMediaList, setTime, setIsRunning]);
const { playMediaList, MediaOffset, previous, next, first, clear } =
useActivePlaylistService();
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const videoRef = useRef<HTMLVideoElement>(null); const videoRef = useRef<HTMLVideoElement>(null);
const [isPlaying, setIsPlaying] = useState<boolean>(false); const [isPlaying, setIsPlaying] = useState<boolean>(false);
@ -111,7 +116,7 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
const { dataType } = useSpecificType(dataMedia?.typeId); const { dataType } = useSpecificType(dataMedia?.typeId);
const { dataSeries } = useSpecificSeries(dataMedia?.seriesId); const { dataSeries } = useSpecificSeries(dataMedia?.seriesId);
const isMobile = useBreakpointValue({ base: false, sm: true }); const isMobile = useBreakpointValue({ base: true, md: false });
const [mediaSource, setMediaSource] = useState<string>(''); const [mediaSource, setMediaSource] = useState<string>('');
useEffect(() => { useEffect(() => {
setMediaSource( setMediaSource(
@ -471,7 +476,9 @@ export const VideoPlayer = ({}: AudioPlayerProps) => {
onClick={onFullScreen} onClick={onFullScreen}
variant="ghost" variant="ghost"
> >
<MdFullscreen style={{ width: '100%', height: '100%' }} /> {!!document.fullscreenElement ?
<MdFullscreenExit style={{ width: '100%', height: '100%' }} />:
<MdFullscreen style={{ width: '100%', height: '100%' }} />}
</IconButton> </IconButton>
{isPiPSupported && !isMobile && {isPiPSupported && !isMobile &&
<IconButton <IconButton

View File

@ -16,6 +16,8 @@ export type FormSelectProps = {
placeholder?: string; placeholder?: string;
// Form: Specify if the element is required or not // Form: Specify if the element is required or not
isRequired?: boolean; isRequired?: boolean;
// is locked for edition
disabled?: boolean;
// List of object options // List of object options
options: object[]; options: object[];
// in the option specify the value Key // in the option specify the value Key
@ -35,6 +37,7 @@ export const FormSelect = ({
options, options,
keyInputKey = 'id', keyInputKey = 'id',
keyInputValue = 'name', keyInputValue = 'name',
disabled = false,
suggestion, suggestion,
addNewItem, addNewItem,
...rest ...rest
@ -60,6 +63,7 @@ export const FormSelect = ({
keyValue={keyInputValue} keyValue={keyInputValue}
onCreate={onCreate} onCreate={onCreate}
suggestion={suggestion} suggestion={suggestion}
disabled={disabled}
/> />
</FormGroup> </FormGroup>
); );

View File

@ -73,7 +73,13 @@ export const PopUpUploadProgress = ({
animated animated
max={totalSize} max={totalSize}
height="24px" height="24px"
/> width="full"
colorPalette="blue"
>
<Progress.Track>
<Progress.Range />
</Progress.Track>
</Progress.Root>
<Flex> <Flex>
<Text>{currentSize.toLocaleString('fr-FR')} Bytes</Text> <Text>{currentSize.toLocaleString('fr-FR')} Bytes</Text>
<Text marginLeft="auto"> <Text marginLeft="auto">
@ -81,7 +87,7 @@ export const PopUpUploadProgress = ({
</Text> </Text>
</Flex> </Flex>
{error && ( {error && (
<Text fontWeight="bold" color="darkred"> <Text fontWeight="bold" color="darkred" whiteSpace="pre-wrap">
{error} {error}
</Text> </Text>
)} )}

View File

@ -17,6 +17,8 @@ export type SelectSingleProps = {
onChange?: (value: number | string | undefined) => void; onChange?: (value: number | string | undefined) => void;
keyKey?: string; keyKey?: string;
keyValue?: string; keyValue?: string;
// is locked for edition
disabled?: boolean;
ref?: RefObject<any>; ref?: RefObject<any>;
// if set add capability to add the search item // if set add capability to add the search item
onCreate?: (data: string) => void; onCreate?: (data: string) => void;
@ -31,6 +33,7 @@ export const SelectSingle = ({
ref, ref,
keyKey = 'id', keyKey = 'id',
keyValue = keyKey, keyValue = keyKey,
disabled = false,
suggestion, suggestion,
onCreate, onCreate,
}: SelectSingleProps) => { }: SelectSingleProps) => {
@ -107,6 +110,7 @@ export const SelectSingle = ({
<Flex> <Flex>
<Input <Input
ref={refFocus} ref={refFocus}
disabled={disabled}
width="full" width="full"
onChange={(e) => onChangeInput(e.target.value)} onChange={(e) => onChangeInput(e.target.value)}
onFocus={() => setShowList(true)} onFocus={() => setShowList(true)}
@ -124,6 +128,7 @@ export const SelectSingle = ({
/> />
<Button <Button
onClick={onRemoveItem} onClick={onRemoveItem}
disabled={disabled}
variant="outline" variant="outline"
borderRadius="0 5px 5px 0" borderRadius="0 5px 5px 0"
borderWidth="1px 1px 1px 0" borderWidth="1px 1px 1px 0"

View File

@ -17,7 +17,7 @@ import { SettingsPage } from './home/SettingsPage';
import { MediaRoutes } from './media/MediaRoutes'; import { MediaRoutes } from './media/MediaRoutes';
import { OnAirPage } from './onAir/OnAirPage'; import { OnAirPage } from './onAir/OnAirPage';
import { SeasonRoutes } from './season/SeasonRoutes'; import { SeasonRoutes } from './season/SeasonRoutes';
import { SeriesRoutes } from './series/SeriesRoutes'; import { SeriesRoutes } from './sso/series/SeriesRoutes';
import { TypeRoutes } from './type/TypesRoutes'; import { TypeRoutes } from './type/TypesRoutes';
export const AppRoutes = () => { export const AppRoutes = () => {

View File

@ -5,8 +5,10 @@ import { LuTrash } from 'react-icons/lu';
import { MdCloudUpload } from 'react-icons/md'; import { MdCloudUpload } from 'react-icons/md';
import { import {
Media,
MediaResource,
RestErrorResponse,
Season, Season,
SeasonResource,
Series, Series,
SeriesResource, SeriesResource,
Type, Type,
@ -22,8 +24,7 @@ import {
NumberInputRoot, NumberInputRoot,
} from '@/components/ui/number-input'; } from '@/components/ui/number-input';
import { useMediaService } from '@/service/Media'; import { useMediaService } from '@/service/Media';
import { useOrderedSeasons, useSeasonService } from '@/service/Season'; import { useOrderedSeries, useOrderedSeriesWithType, useSeriesService } from '@/service/Series';
import { useOrderedSeries, useSeriesService } from '@/service/Series';
import { useServiceContext } from '@/service/ServiceContext'; import { useServiceContext } from '@/service/ServiceContext';
import { useOrderedTypes, useTypeService } from '@/service/Type'; import { useOrderedTypes, useTypeService } from '@/service/Type';
import { isNullOrUndefined } from '@/utils/validator'; import { isNullOrUndefined } from '@/utils/validator';
@ -39,14 +40,17 @@ export class ElementList {
export class FileParsedElement { export class FileParsedElement {
public isSended: boolean = false; public isSended: boolean = false;
public nameDetected: boolean = false; public nameDetected: boolean = false;
public MediaIdDetected: boolean = false; public mediaIdDetected: boolean = false;
public seasonId?: Season['id'] = undefined;
public seriesId?: Series['id'] = undefined;
constructor( constructor(
public uniqueId: number, public uniqueId: number,
public file: File, public file: File,
public title: string, public title: string,
public Series?: string, public universe?: string,
public Season?: string, public series?: string,
public MediaId?: number public season?: number,
public mediaId?: number
) { ) {
console.log(`Unique element: ${uniqueId}`); console.log(`Unique element: ${uniqueId}`);
// nothing to do. // nothing to do.
@ -64,8 +68,8 @@ export class FileFailParsedElement {
} }
type FormInsertData = { type FormInsertData = {
TypeId?: number; typeId?: number;
SeriesId?: number; seriesId?: number;
titleSeason?: string; titleSeason?: string;
}; };
@ -83,11 +87,9 @@ export const AddPage = () => {
); );
const { dataTypes } = useOrderedTypes(); const { dataTypes } = useOrderedTypes();
const { dataSeries } = useOrderedSeries(); const { dataSeries: dataSeriesFull } = useOrderedSeries();
const { dataSeasons } = useOrderedSeasons();
const { store: storeType } = useTypeService(); const { store: storeType } = useTypeService();
const { store: storeSeries } = useSeriesService(); const { store: storeSeries } = useSeriesService();
const { store: storeSeason } = useSeasonService();
const { store: storeMedia } = useMediaService(); const { store: storeMedia } = useMediaService();
const { session } = useServiceContext(); const { session } = useServiceContext();
@ -97,6 +99,8 @@ export const AddPage = () => {
enableReset: false, enableReset: false,
}, },
}); });
// I think this does not work ...
const { dataSeries } = useOrderedSeriesWithType(form.values["typeId"]);
const updateNeedSend = () => { const updateNeedSend = () => {
if (parsedElement.length === 0) { if (parsedElement.length === 0) {
@ -142,7 +146,12 @@ export const AddPage = () => {
}; };
const onMediaId = (data: FileParsedElement, value: any): void => { const onMediaId = (data: FileParsedElement, value: any): void => {
data.MediaId = value; data.mediaId = value;
setParsedElement([...parsedElement]);
updateNeedSend();
};
const onSeasonId = (data: FileParsedElement, value: any): void => {
data.season = value;
setParsedElement([...parsedElement]); setParsedElement([...parsedElement]);
updateNeedSend(); updateNeedSend();
}; };
@ -151,68 +160,64 @@ export const AddPage = () => {
setParsedElement([]); setParsedElement([]);
setParsedFailedElement(undefined); setParsedFailedElement(undefined);
setListFileInBdd(undefined); setListFileInBdd(undefined);
setSuggestedSeries(undefined); setSuggestedSeries(undefined);
setSuggestedSeason(undefined); //setSuggestedSeason(undefined);
}; };
const regex = /^(?:(?<universe>[\w. -]+):)?((?<series>[\w. -]+?)((-s| S)(?<season>\d{1,5}))?(?:(-e|E)(?<episode>\d{1,5}))[- ])?\s*(?<title>.+?)\.(webm|WEBM|Webm|mkv|MKV|Mkv)$/;
const addFileWithMetaData = (file: File, id: number) => { const addFileWithMetaData = (file: File, id: number) => {
// parsedElement: FileParsedElement[] = []; // parsedElement: FileParsedElement[] = [];
let Series: string | undefined = undefined; let universe: string | undefined = undefined;
let Season: string | undefined = undefined; let series: string | undefined = undefined;
let MediaIdNumber: number | undefined = undefined; let season: number | undefined = undefined;
let mediaIdNumber: number | undefined = undefined;
let title: string = ''; let title: string = '';
form.restoreValues(); form.restoreValues();
console.log(`select file ${file.name}`); console.log(`select file ${file.name}`);
let tmpName = file.name.replace(/[ \t]*-[ \t]*/g, '-');
//tmpName = tmpName.replace(/_/g, '-');
//tmpName = tmpName.replace(/--/g, '-');
console.log(`select file ${tmpName}`);
const splitElement = tmpName.split('~');
if (splitElement.length > 1) {
Series = splitElement[0];
tmpName = tmpName.substring(Series.length + 1);
}
const splitElement2 = tmpName.split('#');
if (splitElement2.length > 1) {
Season = splitElement2[0];
tmpName = tmpName.substring(Season.length + 1);
}
//console.log("ploppppp " + tmpName);
const splitElement3 = tmpName.split('-');
if (splitElement3.length > 1) {
MediaIdNumber = parseInt(splitElement3[0], 10);
tmpName = tmpName.substring(splitElement3[0].length + 1);
}
//console.log("KKKppppp " + tmpName);
//console.log(" ===> " + splitElement3[0]);
title = tmpName;
if (MediaIdNumber && isNaN(MediaIdNumber)) { const match = file.name.match(regex);
MediaIdNumber = undefined; if (match?.groups) {
universe = match.groups.universe || undefined;
series = match.groups.series ? match.groups.series.trim() : undefined;
season = match.groups.season? parseInt(match.groups.season, 10) : undefined;
mediaIdNumber = match.groups.episode ? parseInt(match.groups.episode, 10) : undefined;
title = match.groups.title.trim();
} else {
console.log("❌ not match :", file.name);
title = file.name.trim();
}
if (season && isNaN(season)) {
season = undefined;
}
if (mediaIdNumber && isNaN(mediaIdNumber)) {
mediaIdNumber = undefined;
} }
// remove extension // remove extension
title = title.replace(new RegExp('\\.(webm|WEBM|Webm)'), ''); title = title.replace(new RegExp('\\.(webm|WEBM|Webm|mkv|MKV|Mkv)'), '');
let tmp = new FileParsedElement( let tmp = new FileParsedElement(
id, id,
file, file,
title, title,
Series, universe,
Season, series,
MediaIdNumber season,
mediaIdNumber
); );
console.log(`==>${JSON.stringify(tmp)}`); console.log(`==>${JSON.stringify(tmp, null, 2)}`);
// add it in the list. // add it in the list.
return tmp; return tmp;
}; };
const [suggestedSeries, setSuggestedSeries] = useState<string | undefined>( const [suggestedSeries, setSuggestedSeries] = useState<string | undefined>(
undefined undefined
); );
const [suggestedSeason, setSuggestedSeason] = useState<string | undefined>( // const [suggestedSeason, setSuggestedSeason] = useState<string | undefined>(
undefined // undefined
); // );
const onChangeFile = (value: any): void => { const onChangeFile = (value: any): void => {
clearData(); clearData();
@ -232,9 +237,9 @@ export const AddPage = () => {
// clean different Series: // clean different Series:
for (let iii = 1; iii < parsedElementTmp.length; iii++) { for (let iii = 1; iii < parsedElementTmp.length; iii++) {
console.log( console.log(
`check Series [${iii + 1}/${parsedElementTmp.length}] '${parsedElementTmp[0].Series} !== ${parsedElementTmp[iii].Series}'` `check Series [${iii + 1}/${parsedElementTmp.length}] '${parsedElementTmp[0].series} !== ${parsedElementTmp[iii].series}'`
); );
if (parsedElementTmp[0].Series !== parsedElementTmp[iii].Series) { if (parsedElementTmp[0].series !== parsedElementTmp[iii].series) {
parsedFailedElementTmp.push( parsedFailedElementTmp.push(
new FileFailParsedElement( new FileFailParsedElement(
parsedFailedElementTmp.length, parsedFailedElementTmp.length,
@ -249,64 +254,29 @@ export const AddPage = () => {
iii--; iii--;
} }
} }
// clean different Season:
for (let iii = 1; iii < parsedElementTmp.length; iii++) {
console.log(
`check Season [${iii + 1}/${parsedElementTmp.length}] '${parsedElementTmp[0].Season} !== ${parsedElementTmp[iii].Season}'`
);
if (parsedElementTmp[0].Season !== parsedElementTmp[iii].Season) {
parsedFailedElementTmp.push(
new FileFailParsedElement(
parsedFailedElementTmp.length,
parsedElementTmp[iii].file,
'Remove from list due to wrong Season value'
)
);
console.log(
`Remove from list (!= Season) : [${iii + 1}/${parsedElementTmp.length}] '${parsedElementTmp[iii].file.name}'`
);
parsedElementTmp.splice(iii, 1);
iii--;
}
}
setParsedElement(parsedElementTmp); setParsedElement(parsedElementTmp);
setParsedFailedElement(parsedFailedElementTmp); setParsedFailedElement(parsedFailedElementTmp);
console.log(`check : ${JSON.stringify(parsedElementTmp[0])}`); console.log(`check : ${JSON.stringify(parsedElementTmp[0])}`);
// find SeriesId: // find seriesId:
console.log(`try find Series : ${parsedElementTmp[0].Series}`); console.log(`try find Series : ${parsedElementTmp[0].series}`);
let SeriesFound = false; let SeriesFound = false;
dataSeries.forEach((data) => { dataSeriesFull.forEach((data) => {
if ( if (
data.name?.toLowerCase() === parsedElementTmp[0].Series?.toLowerCase() data.name?.toLowerCase() === parsedElementTmp[0].series?.toLowerCase()
) { ) {
console.log(` find Series : ${data.id}`); console.log(` find Series : ${data.id}`);
form.setValues({ SeriesId: data.id }); form.setValues({ seriesId: data.id });
form.setValues({ typeId: data.parentId });
SeriesFound = true; SeriesFound = true;
} }
}); });
if (!SeriesFound) { if (!SeriesFound) {
console.log(` set Suggested Series : ${parsedElementTmp[0].Series}`); console.log(` set Suggested Series : ${parsedElementTmp[0].series}`);
setSuggestedSeries(parsedElementTmp[0].Series); setSuggestedSeries(parsedElementTmp[0].series);
} else { } else {
setSuggestedSeries(undefined); setSuggestedSeries(undefined);
} }
// try to find Season
console.log(`try find Season : ${parsedElementTmp[0].Season}`);
let SeasonFound = false;
dataSeasons.forEach((data) => {
if (
data.name?.toLowerCase() === parsedElementTmp[0].Season?.toLowerCase()
) {
console.log(` find Season : ${data.id}`);
form.setValues({ SeasonId: data.id });
SeasonFound = true;
}
});
if (!SeasonFound) {
console.log(` set Suggested Season : ${parsedElementTmp[0].Season}`);
setSuggestedSeason(parsedElementTmp[0].Season);
}
updateNeedSend(); updateNeedSend();
}; };
@ -327,6 +297,9 @@ export const AddPage = () => {
const uploadNext = useCallback( const uploadNext = useCallback(
(index: number = 0): void => { (index: number = 0): void => {
// if (indexUpload == undefined) {
// return;
// }
if (parsedElement.length <= index) { if (parsedElement.length <= index) {
console.log('end of upload'); console.log('end of upload');
setIsFinishedUpload(true); setIsFinishedUpload(true);
@ -339,33 +312,34 @@ export const AddPage = () => {
const data = { const data = {
title: parsedElement[index].title, title: parsedElement[index].title,
file: parsedElement[index].file, file: parsedElement[index].file,
SeasonId: form.values['SeasonId'] ?? undefined, universeId: `${form.values['universeId']}`,
SeriesId: form.values['SeriesId'] ?? undefined, typeId: `${form.values['typeId']}`,
TypeId: form.values['TypeId'] ?? undefined, seriesId: `${form.values['seriesId']}`,
MediaId: parsedElement[index].MediaId ?? undefined, season: `${parsedElement[index].season}`,
episode: `${parsedElement[index].mediaId}`,
}; };
console.log(`data= ${JSON.stringify(data, null, 2)}`); console.log(`data= ${JSON.stringify(data, null, 2)}`);
console.error("Not_ implemented"); console.error("Not_ implemented");
// storeMedia storeMedia
// .update( .update(
// MediaResource.uploadMedia({ MediaResource.uploadMedia({
// restConfig: session.getRestConfig(), restConfig: session.getRestConfig(),
// data, data,
// callbacks: { callbacks: {
// progressUpload: progressUpload, progressUpload: progressUpload,
// }, },
// }) })
// ) )
// .then((data: Media) => { .then((data: Media) => {
// // element sended good // element sended good
// // Send next ... // Send next ...
// uploadNext(index + 1); uploadNext(index + 1);
// }) })
// .catch((error: RestErrorResponse) => { .catch((error: RestErrorResponse) => {
// // TODO: manage error // TODO: manage error
// console.log(`element error: ${JSON.stringify(error, null, 2)}`); console.log(`element error: ${JSON.stringify(error, null, 2)}`);
// setUploadError(JSON.stringify(error, null, 2)); setUploadError(JSON.stringify(error, null, 2));
// }); });
}, },
[ [
setUploadError, setUploadError,
@ -374,6 +348,7 @@ export const AddPage = () => {
parsedElement, parsedElement,
form, form,
form.values, form.values,
indexUpload,
] ]
); );
@ -409,16 +384,7 @@ export const AddPage = () => {
restConfig: session.getRestConfig(), restConfig: session.getRestConfig(),
data: { data: {
name: data, name: data,
}, parentId: form.values["typeId"]
})
);
};
const addNewSeason = (data: string): Promise<Season> => {
return storeSeason.update(
SeasonResource.post({
restConfig: session.getRestConfig(),
data: {
name: data,
}, },
}) })
); );
@ -439,11 +405,10 @@ export const AddPage = () => {
<Flex> <Flex>
<Text flex={1}>format:</Text> <Text flex={1}>format:</Text>
<Text flex={4}> <Text flex={4}>
The format of the media permit to automatic find meta-data: The format of the media permit to automatic find meta-data:<br />
<br /> <li>Universe:Series name-s05-e22-Title.webm/mkv</li>
Series~Season#idMedia-my name of my media.webm <li>Universe:Series name S05E22 Title.webm/mkv</li>
<br /> <b>example:</b> Stargate:SG1-s05-e22-Tolans.webm
<b>example:</b> Clarika~Moi En Mieux#22-des bulles.webm
</Text> </Text>
</Flex> </Flex>
<Flex> <Flex>
@ -452,7 +417,7 @@ export const AddPage = () => {
flex={4} flex={4}
type="file" type="file"
placeholder="Select a media file" placeholder="Select a media file"
accept=".webm" accept=".webm,.mkv"
multiple multiple
onChange={onChangeFile} onChange={onChangeFile}
/> />
@ -463,24 +428,20 @@ export const AddPage = () => {
<Text fontSize="30px">Meta-data:</Text> <Text fontSize="30px">Meta-data:</Text>
<FormSelect <FormSelect
label="Type" label="Type"
name="TypeId" name="typeId"
options={dataTypes} options={dataTypes}
addNewItem={addNewType} addNewItem={addNewType}
isRequired
/> />
<FormSelect <FormSelect
label="Series" label="Series"
name="SeriesId" name="seriesId"
options={dataSeries} options={dataSeries}
addNewItem={addNewSeries} addNewItem={addNewSeries}
suggestion={suggestedSeries} suggestion={suggestedSeries}
disabled={form.values["typeId"] === undefined}
/> />
<FormSelect
label="Season"
name="SeasonId"
options={dataSeasons}
addNewItem={addNewSeason}
suggestion={suggestedSeason}
/>
<Table.Root <Table.Root
colorPalette="striped" colorPalette="striped"
colorScheme="teal" colorScheme="teal"
@ -488,6 +449,9 @@ export const AddPage = () => {
> >
<Table.Header> <Table.Header>
<Table.Row> <Table.Row>
<Table.ColumnHeader width="10%">
Season ID
</Table.ColumnHeader>
<Table.ColumnHeader width="10%"> <Table.ColumnHeader width="10%">
Media ID Media ID
</Table.ColumnHeader> </Table.ColumnHeader>
@ -499,19 +463,38 @@ export const AddPage = () => {
{parsedElement.map((data) => ( {parsedElement.map((data) => (
<Table.Row key={data.uniqueId}> <Table.Row key={data.uniqueId}>
<Table.Cell> <Table.Cell>
{form.values["seriesId"] &&
<NumberInputRoot <NumberInputRoot
value={data.MediaId ? `${data.MediaId}` : undefined} value={data.season ? `${data.season}` : undefined}
onValueChange={(e) => onMediaId(data, e.value)} onValueChange={(e) => onSeasonId(data, e.value)}
min={0} min={0}
max={5000} max={5000}
backgroundColor={ backgroundColor={
data.MediaIdDetected === true data.mediaIdDetected === true
? 'darkred' ? 'darkred'
: undefined : undefined
} }
> >
<NumberInputField /> <NumberInputField />
</NumberInputRoot> </NumberInputRoot>
}
</Table.Cell>
<Table.Cell>
{form.values["seriesId"] &&
<NumberInputRoot
value={data.mediaId ? `${data.mediaId}` : undefined}
onValueChange={(e) => onMediaId(data, e.value)}
min={0}
max={5000}
backgroundColor={
data.mediaIdDetected === true
? 'darkred'
: undefined
}
>
<NumberInputField />
</NumberInputRoot>
}
</Table.Cell> </Table.Cell>
<Table.Cell> <Table.Cell>
<Input <Input

View File

@ -45,8 +45,8 @@ export const TypesPage = () => {
{dataTypes.map((data) => ( {dataTypes.map((data) => (
<Flex <Flex
align="flex-start" align="flex-start"
width={{ base: "200px", sm: "160px" }} width={{ lg: "200px", base: "160px" }}
height={{ base: "280px", sm: "200px" }} height={{ lg: "280px", base: "200px" }}
border="1px" border="1px"
borderColor="brand.900" borderColor="brand.900"
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')} backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}

View File

@ -1,6 +1,6 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { Series, SeriesResource } from '@/back-api'; import { Series, SeriesResource, Type } from '@/back-api';
import { useServiceContext } from '@/service/ServiceContext'; import { useServiceContext } from '@/service/ServiceContext';
import { SessionServiceProps } from '@/service/session'; import { SessionServiceProps } from '@/service/session';
import { DataStoreType, useDataStore } from '@/utils/data-store'; import { DataStoreType, useDataStore } from '@/utils/data-store';
@ -60,6 +60,35 @@ export const useOrderedSeries = (nameFilter?: string) => {
}, [store.data, nameFilter]); }, [store.data, nameFilter]);
return { isLoading: store.isLoading, dataSeries }; return { isLoading: store.isLoading, dataSeries };
}; };
export const useOrderedSeriesWithType = (typeId?: Type["id"], nameFilter?: string) => {
const { store } = useSeriesService();
const dataSeries = useMemo(() => {
let tmpData = store.data;
if (!isNullOrUndefined(nameFilter)) {
tmpData = DataTools.getNameLike(tmpData, nameFilter);
}
if (typeId === undefined) {
return [];
}
return DataTools.getsWhere(
tmpData,
[
{
check: TypeCheck.NOT_EQUAL,
key: 'id',
value: [undefined, null],
},
{
check: TypeCheck.EQUAL,
key: 'parentId',
value: typeId,
},
],
['name', 'id']
);
}, [store.data, nameFilter, typeId]);
return { isLoading: store.isLoading, dataSeries };
};
export const useSpecificSeries = (id: number | undefined) => { export const useSpecificSeries = (id: number | undefined) => {
const { store } = useSeriesService(); const { store } = useSeriesService();

View File

@ -102,6 +102,9 @@ export const ServiceContext = createContext<ServiceContextType>({
first: () => { first: () => {
console.error('!!! WTF !!!'); console.error('!!! WTF !!!');
}, },
clear: () => {
console.error('!!! WTF !!!');
},
}, },
}); });