Skip to content

Commit

Permalink
downlad all media ok, refacto modalFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaume-pages committed Jun 12, 2024
1 parent c3c1615 commit 251bc0b
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 74 deletions.
4 changes: 2 additions & 2 deletions server/controllers/mediatheque.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Brackets } from 'typeorm';

import type { Filter } from '../../types/mediatheque.type';
import { Activity } from '../entities/activity';
import { User } from '../entities/user';
import { AppDataSource } from '../utils/data-source';
import { Controller } from './controller';

Expand Down Expand Up @@ -40,7 +39,8 @@ mediathequeController.post({ path: '' }, async (req: Request, res: Response) =>
}),
);
});
const activities = await subQueryBuilder.andWhere('activity.status = :status', { status: 0 }).getMany();
const activitiesToFilter = await subQueryBuilder.getMany();
const activities = activitiesToFilter.filter((status) => status.status === 0);
res.send(activities);
} catch (error) {
console.error('Error fetching media data:', error);
Expand Down
9 changes: 7 additions & 2 deletions src/components/admin/mediatheque/CheckboxAdmin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ import Checkbox from '@mui/material/Checkbox';
import MediathequeContext from 'src/contexts/mediathequeContext';
import PelicoNeutre from 'src/svg/pelico/pelico_neutre.svg';

const CheckboxAdmin = ({ isChecked, onCheckboxChange }) => {
interface CheckboxAdminProps {
isChecked: boolean;
onCheckboxChange: (checked: boolean) => void;
}

const CheckboxAdmin = ({ isChecked, onCheckboxChange }: CheckboxAdminProps) => {
const label = { inputProps: { 'aria-label': 'Pelico' } };
const { setFilters, setUseAdminData } = useContext(MediathequeContext);

const handleCheckboxChange = (event: { target: { checked: unknown } }) => {
onCheckboxChange(event.target.checked);
onCheckboxChange(event.target.checked as boolean);
if (!event.target.checked) {
setFilters([[]]);
setUseAdminData(false);
Expand Down
40 changes: 36 additions & 4 deletions src/components/admin/mediatheque/DownloadButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import type { Activity } from 'types/activity.type';
export default function DownloadButton() {
const { enqueueSnackbar } = useSnackbar();
const [loading, setLoading] = useState(false);
const { allFiltered } = useContext(MediathequeContext);

const onDownload = async (videoUrl: string) => {
const onDownloadVideo = async (videoUrl: string) => {
try {
const response = await axiosRequest({
method: 'GET',
Expand All @@ -44,7 +45,24 @@ export default function DownloadButton() {
}
};

const { allFiltered } = useContext(MediathequeContext);
const onDownloadSound = async (soundUrl: string) => {
try {
const adjustedUrl = soundUrl.startsWith('/api') ? soundUrl.replace(/^\/api/, '') : soundUrl;

const response = await axiosRequest({
method: 'GET',
url: adjustedUrl,
responseType: 'blob',
});
return response.data;
} catch (error) {
console.error(error);
enqueueSnackbar("Une erreur est survenue lors du téléchargement de l'audio...", {
variant: 'error',
});
throw error;
}
};

const getActivityLabel = (type: number) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -70,6 +88,7 @@ export default function DownloadButton() {
const zip = new JSZip();
const imagePromises: Promise<void>[] = [];
const videoPromises: Promise<void>[] = [];
const soundPromises: Promise<void>[] = [];

data.forEach((item: Activity) => {
const activityLabel = getActivityLabel(item.type);
Expand Down Expand Up @@ -100,11 +119,24 @@ export default function DownloadButton() {
});

imagePromises.push(imagePromise);
} else if (contentItem.type === 'sound') {
const soundUrl = contentItem.value;
const soundFileName = `${activityLabel} ${subThemeLabel} son activité id n°${item.id} ${contentIndex + 1}.mp3`;

const soundPromise = onDownloadSound(soundUrl)
.then((blob) => {
zip.file(soundFileName, blob);
})
.catch((err) => {
console.error(`Failed to fetch sound from ${soundUrl}:`, err);
});

soundPromises.push(soundPromise);
} else if (contentItem.type === 'video') {
const videoUrl = contentItem.value;
const videoFileName = `${activityLabel} ${subThemeLabel} video activité id n°${item.id} ${contentIndex + 1}.mp4`;

const videoPromise = onDownload(videoUrl)
const videoPromise = onDownloadVideo(videoUrl)
.then((downloadLink) => fetch(downloadLink))
.then((response) => response.blob())
.then((blob) => {
Expand All @@ -119,7 +151,7 @@ export default function DownloadButton() {
});
});

await Promise.all([...imagePromises, ...videoPromises]);
await Promise.all([...imagePromises, ...videoPromises, ...soundPromises]);

const content = await zip.generateAsync({ type: 'blob' });

Expand Down
14 changes: 9 additions & 5 deletions src/components/admin/mediatheque/ModalFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext } from 'react';
import React, { useContext, useState } from 'react';

import RefreshIcon from '@mui/icons-material/Refresh';
import Box from '@mui/material/Box';
Expand Down Expand Up @@ -29,12 +29,16 @@ const ModalFilter = () => {
const [open, setOpen] = React.useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const [updateFiltersKey, setUpdateFiltersKey] = useState(0);
const [isChecked, setIsChecked] = useState(false);

const { setFilters, setOffset } = useContext(MediathequeContext);
const { setFilters, setUseAdminData } = useContext(MediathequeContext);

const handleResetFilters = () => {
setUseAdminData(false);
setFilters([[]]);
setOffset(0);
setUpdateFiltersKey((prevKey) => prevKey + 1);
setIsChecked(false);
};

return (
Expand All @@ -61,12 +65,12 @@ const ModalFilter = () => {
>
X
</button>
<FiltersActivities />
<FiltersActivities key={updateFiltersKey} />
<Filters labels={activitiesLabel} placeholder="VM" />
<Filters labels={activitiesLabel} placeholder="Pays" />
<Filters labels={activitiesLabel} placeholder="Classes" />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<CheckboxAdmin />
<CheckboxAdmin isChecked={isChecked} onCheckboxChange={setIsChecked} />
<IconButton aria-label="delete" color="primary" onClick={handleResetFilters}>
<RefreshIcon />
</IconButton>
Expand Down
129 changes: 69 additions & 60 deletions src/contexts/mediathequeContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,34 @@ type MediathequeProviderProps = {
type MediathequeContextType = {
filters: Array<Filter[]>;
setFilters: React.Dispatch<React.SetStateAction<Array<Filter[]>>>;
allFiltered: any[];
allFiltered: [];
useAdminData: boolean;
setUseAdminData: React.Dispatch<React.SetStateAction<boolean>>;
};

interface UserData {
id: number;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
content: any;
subType: number;
type: number;
villageId: number;
userId: number;
user: { type: number; school: string };
village: { name: string };
data: {
mascotteImage?: string;
verseFinalMixUrl?: string;
verseMixUrl?: string;
verseMixWithIntroUrl?: string;
verseMixWithVocalsUrl?: string;
odd?: { imageStory?: string; imageUrl?: string };
object?: { imageStory?: string; imageUrl?: string };
place?: { imageStory?: string; imageUrl?: string };
tale?: { imageStory?: string; imageUrl?: string };
};
}

const MediathequeContext = createContext<MediathequeContextType>({
filters: [],
setFilters: () => {},
Expand All @@ -28,80 +51,68 @@ export const MediathequeProvider: React.FC<MediathequeProviderProps> = ({ childr
const [useAdminData, setUseAdminData] = useState(false);

const { data: usersData } = useGetMediatheque(filters);
const [dataToUse, setDataToUse] = useState<any[]>([]);
const [dataToUse, setDataToUse] = useState<[]>([]);

useEffect(() => {
const activitiesMediaFinder = usersData
?.filter(({ type }: { type: number }) => ![3, 5, 11].includes(type))
.map(
({
id,
content,
subType,
type,
villageId,
userId,
user,
village,
data,
}: {
.map(({ id, content, subType, type, villageId, userId, user, village, data }: UserData) => {
const result: {
id: number;
content: object;
subType: number;
type: number;
villageId: number;
userId: number;
user: object;
village: object;
data: object;
}) => {
const result = { id, subType, type, villageId, userId, content: [], user, village };
if (type === 8 || type === 12 || type === 13 || type === 14) {
if (type === 8) {
result.content.push({ type: 'image', value: data.mascotteImage });
}
if (type === 12) {
result.content.push({ type: 'sound', value: data.verseFinalMixUrl });
result.content.push({ type: 'sound', value: data.verseMixUrl });
result.content.push({ type: 'sound', value: data.verseMixWithIntroUrl });
result.content.push({ type: 'sound', value: data.verseMixWithVocalsUrl });
}
if (type === 13 || type === 14) {
const properties = ['odd', 'object', 'place', 'tale'];
content: Array<{ type: string; value: string | undefined }>;
user: { type: number; school: string };
village: { name: string };
} = { id, subType, type, villageId, userId, content: [], user, village };
if (type === 8 || type === 12 || type === 13 || type === 14) {
if (type === 8) {
result.content.push({ type: 'image', value: data.mascotteImage });
}
if (type === 12) {
result.content.push({ type: 'sound', value: data.verseFinalMixUrl });
// result.content.push({ type: 'sound', value: data.verseMixUrl });
// result.content.push({ type: 'sound', value: data.verseMixWithIntroUrl });
// result.content.push({ type: 'sound', value: data.verseMixWithVocalsUrl });
}
if (type === 13 || type === 14) {
const properties = ['odd', 'object', 'place', 'tale'];

properties.forEach((prop) => {
properties.forEach((prop: string) => {
const propData = data[prop as keyof typeof data];
if (typeof propData === 'object' && propData !== null) {
if (prop === 'tale') {
result.content.push({ type: 'image', value: data[prop].imageStory });
result.content.push({ type: 'image', value: propData.imageStory });
} else {
result.content.push({ type: 'image', value: data[prop].imageUrl });
}
});
}
}
if (content.game) {
content.game.map(({ inputs }) =>
inputs.map((input: { type: number; selectedValue: string }) => {
if (input.type === 3 || input.type === 4) {
result.content.push({ type: input.type === 3 ? 'image' : 'video', value: input.selectedValue });
result.content.push({ type: 'image', value: propData.imageUrl });
}
}),
);
} else {
content.map(({ type, value }: { type: string; value: string }) => {
const wantedTypes = ['image', 'video', 'sound'];
if (wantedTypes.includes(type)) {
result.content.push({ type, value });
}
});
}
return result;
},
);

console.log('activitiesMediaFinder', activitiesMediaFinder);
}
if (content.game) {
content.game.map(({ inputs }: { inputs: Array<{ type: number; selectedValue: string }> }) =>
inputs.map((input) => {
if (input.type === 3 || input.type === 4) {
result.content.push({ type: input.type === 3 ? 'image' : 'video', value: input.selectedValue });
}
}),
);
} else {
content.map(({ type, value }: { type: string; value: string }) => {
const wantedTypes = ['image', 'video', 'sound'];
if (wantedTypes.includes(type)) {
result.content.push({ type, value });
}
});
}
return result;
});

const activitiesWithMediaOnly = activitiesMediaFinder?.filter((a) => a.content.length > 0);
const activitiesFromPelico = activitiesWithMediaOnly?.filter((a) => [0, 1, 2].includes(a.user.type));
const activitiesWithMediaOnly = activitiesMediaFinder?.filter((a: UserData) => a.content.length > 0);
const activitiesFromPelico = activitiesWithMediaOnly?.filter((a: UserData) => [0, 1, 2].includes(a.user.type));

if (useAdminData) {
setDataToUse(activitiesFromPelico || []);
Expand All @@ -121,8 +132,6 @@ export const MediathequeProvider: React.FC<MediathequeProviderProps> = ({ childr
[filters, dataToUse, useAdminData],
);

console.log('data to use = ', dataToUse);

return <MediathequeContext.Provider value={value}>{children}</MediathequeContext.Provider>;
};

Expand Down
2 changes: 1 addition & 1 deletion src/pages/admin/newportal/medialibrary/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useRef, useState } from 'react';
import React, { useContext, useState } from 'react';

// Tout doit être responsive

Expand Down

0 comments on commit 251bc0b

Please sign in to comment.