diff --git a/geneit_app/src/App.tsx b/geneit_app/src/App.tsx index 1bb55f3..a07dcd1 100644 --- a/geneit_app/src/App.tsx +++ b/geneit_app/src/App.tsx @@ -38,6 +38,7 @@ import { FamilyTreeRoute } from "./routes/family/genealogy/FamilyTreeRoute"; import { FamilyMemberTreeRoute } from "./routes/family/genealogy/FamilyMemberTreeRoute"; import { GenealogyHomeRoute } from "./routes/family/genealogy/GenealogyHomeRoute"; import { BaseGenealogyRoute } from "./widgets/genealogy/BaseGenealogyRoute"; +import { GenalogySettingsRoute } from "./routes/family/genealogy/GenalogySettingsRoute"; interface AuthContext { signedIn: boolean; @@ -105,6 +106,7 @@ export function App(): React.ReactElement { path="tree/:memberId" element={} /> + } /> } /> diff --git a/geneit_app/src/api/FamilyApi.ts b/geneit_app/src/api/FamilyApi.ts index 763dc7e..31d97b6 100644 --- a/geneit_app/src/api/FamilyApi.ts +++ b/geneit_app/src/api/FamilyApi.ts @@ -233,9 +233,9 @@ export class FamilyApi { */ static async UpdateFamily(settings: { id: number; - name: string; - enable_genealogy: boolean; - disable_couple_photos: boolean; + name?: string; + enable_genealogy?: boolean; + disable_couple_photos?: boolean; }): Promise { await APIClient.exec({ method: "PATCH", diff --git a/geneit_app/src/routes/family/FamilySettingsRoute.tsx b/geneit_app/src/routes/family/FamilySettingsRoute.tsx index bfc4186..7c0d720 100644 --- a/geneit_app/src/routes/family/FamilySettingsRoute.tsx +++ b/geneit_app/src/routes/family/FamilySettingsRoute.tsx @@ -1,26 +1,19 @@ -import DownloadIcon from "@mui/icons-material/Download"; -import UploadIcon from "@mui/icons-material/Upload"; import { - Alert, Box, Button, CardActions, CardContent, - Checkbox, FormControlLabel, + Switch, TextField, - Tooltip, Typography, } from "@mui/material"; import React from "react"; import { useNavigate } from "react-router-dom"; import { FamilyApi } from "../../api/FamilyApi"; import { ServerApi } from "../../api/ServerApi"; -import { DataApi } from "../../api/genealogy/DataApi"; import { useAlert } from "../../hooks/context_providers/AlertDialogProvider"; import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider"; -import { useLoadingMessage } from "../../hooks/context_providers/LoadingMessageProvider"; -import { downloadBlob, selectFileToUpload } from "../../utils/files_utils"; import { useFamily } from "../../widgets/BaseFamilyRoute"; import { FamilyCard } from "../../widgets/FamilyCard"; import { formatDate } from "../../widgets/TimeWidget"; @@ -55,7 +48,6 @@ export function FamilySettingsRoute(): React.ReactElement { return ( <> - {family.family.enable_genealogy && }
- - - - - ); -} diff --git a/geneit_app/src/routes/family/genealogy/GenalogySettingsRoute.tsx b/geneit_app/src/routes/family/genealogy/GenalogySettingsRoute.tsx new file mode 100644 index 0000000..086ffca --- /dev/null +++ b/geneit_app/src/routes/family/genealogy/GenalogySettingsRoute.tsx @@ -0,0 +1,221 @@ +import DownloadIcon from "@mui/icons-material/Download"; +import UploadIcon from "@mui/icons-material/Upload"; +import { + Alert, + Box, + Button, + CardActions, + CardContent, + FormControlLabel, + Switch, + Tooltip, + Typography, +} from "@mui/material"; +import React from "react"; +import { FamilyApi } from "../../../api/FamilyApi"; +import { DataApi } from "../../../api/genealogy/DataApi"; +import { useAlert } from "../../../hooks/context_providers/AlertDialogProvider"; +import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider"; +import { useLoadingMessage } from "../../../hooks/context_providers/LoadingMessageProvider"; +import { downloadBlob, selectFileToUpload } from "../../../utils/files_utils"; +import { useFamily } from "../../../widgets/BaseFamilyRoute"; +import { FamilyCard } from "../../../widgets/FamilyCard"; + +export function GenalogySettingsRoute(): React.ReactElement { + return ( + <> + + + + ); +} + +function GenealogySettingsCard(): React.ReactElement { + const alert = useAlert(); + + const family = useFamily(); + + const [disableCouplePhotos, setDisableCouplePhotos] = React.useState( + family.family.disable_couple_photos + ); + + const canEdit = family.family.is_admin; + + const [error, setError] = React.useState(); + const [success, setSuccess] = React.useState(); + + const updateFamily = async () => { + try { + setError(undefined); + setSuccess(undefined); + + await FamilyApi.UpdateFamily({ + id: family.family.family_id, + disable_couple_photos: disableCouplePhotos, + }); + + family.reloadFamilyInfo(); + + alert("Les paramètres de la famille ont été mis à jour avec succès !"); + } catch (e) { + console.error(e); + setError("Echec de la mise à jour des paramètres de la famille !"); + } + }; + + return ( + + + + Paramètres du module de généalogie + + + + + setDisableCouplePhotos(c)} + /> + } + label="Désactiver les photos de couple" + /> + + + + + + + + ); +} + +function GenealogyExportCard(): React.ReactElement { + const loading = useLoadingMessage(); + const confirm = useConfirm(); + const alert = useAlert(); + + const family = useFamily(); + + const [error, setError] = React.useState(); + const [success, setSuccess] = React.useState(); + + const exportData = async () => { + loading.show("Export des données"); + try { + setError(undefined); + setSuccess(undefined); + + const blob = await DataApi.ExportData(family.familyId); + downloadBlob(blob, `Export-${new Date().getTime()}.zip`); + + setSuccess("Export des données effectué avec succès !"); + } catch (e) { + console.error(e); + setError("Echec de l'export des données de la famille !"); + } + loading.hide(); + }; + + const importData = async () => { + try { + if ( + !(await confirm( + "Attention ! Cette opération a pour effet d'effacer toutes les données existantes en base ! Voulez-vous vraiment poursuivre l'opération ?" + )) + ) + return; + + const file = await selectFileToUpload({ + allowedTypes: ["application/zip"], + }); + if (file === null) return; + + setError(undefined); + setSuccess(undefined); + + loading.show( + "Restauration des données de généalogie de la famille en cours..." + ); + + await DataApi.ImportData(family.familyId, file); + + family.reloadFamilyInfo(); + + alert( + "Import des données de généalogie de la famille effectué avec succès !" + ); + } catch (e) { + console.error(e); + setError( + `Echec de l'import des données de généalogie de la famille ! (${e})` + ); + } + + loading.hide(); + }; + + return ( + + + + Export / import des données de généalogie + +

+ Vous pouvez, à des fins de sauvegardes ou de transfert, exporter et + importer l'ensemble des données des membres et des couples de cette + famille, sous format ZIP. +

+ + + Attention ! La restauration des données de généalogie de la famille + provoque préalablement l'effacement de toutes les données enregistrées + dans la famille ! Par ailleurs, la restauration n'est pas réversible ! + + +

 

+ + + + +
+
+ ); +} diff --git a/geneit_app/src/widgets/BaseFamilyRoute.tsx b/geneit_app/src/widgets/BaseFamilyRoute.tsx index d6f10c0..2df2f58 100644 --- a/geneit_app/src/widgets/BaseFamilyRoute.tsx +++ b/geneit_app/src/widgets/BaseFamilyRoute.tsx @@ -4,6 +4,7 @@ import { mdiContentCopy, mdiCrowd, mdiFamilyTree, + mdiFileTree, mdiHumanMaleFemale, mdiLockCheck, mdiPlus, @@ -190,6 +191,14 @@ export function BaseFamilyRoute(): React.ReactElement { uri="settings" /> + {family?.enable_genealogy && ( + } + label="Généalogie" + uri="genealogy/settings" + /> + )} + {/* Invitation code */} HttpResult { #[derive(serde::Deserialize)] pub struct UpdateFamilyBody { - name: String, - enable_genealogy: bool, - disable_couple_photos: bool, + name: Option, + enable_genealogy: Option, + disable_couple_photos: Option, } /// Update a family @@ -113,17 +113,24 @@ pub async fn update( f: FamilyInPathWithAdminMembership, req: web::Json, ) -> HttpResult { - if !StaticConstraints::default() - .family_name_len - .validate(&req.name) - { - return Ok(HttpResponse::BadRequest().body("Invalid family name!")); + let mut family = families_service::get_by_id(f.family_id()).await?; + + if let Some(name) = &req.name { + if !StaticConstraints::default().family_name_len.validate(name) { + return Ok(HttpResponse::BadRequest().body("Invalid family name!")); + } + + family.name = name.to_string(); + } + + if let Some(enable_genealogy) = req.enable_genealogy { + family.enable_genealogy = enable_genealogy; + } + + if let Some(disable_couple_photos) = req.disable_couple_photos { + family.disable_couple_photos = disable_couple_photos; } - let mut family = families_service::get_by_id(f.family_id()).await?; - family.name = req.0.name; - family.enable_genealogy = req.0.enable_genealogy; - family.disable_couple_photos = req.0.disable_couple_photos; families_service::update_family(&family).await?; log::info!("User {:?} updated family {:?}", f.user_id(), f.family_id());