diff --git a/.env b/.env index ccac282a..56e79aee 100644 --- a/.env +++ b/.env @@ -33,9 +33,12 @@ HTTPS_PROXY= # id du processus d'intégration en base API_ENTREPOT_PROC_INT_VECT_FILES_DB= -# id du processus de génération de pyramide +# id du processus de génération de pyramide vecteur API_ENTREPOT_PROC_CREATE_VECT_PYR= +# id du processus de génération de pyramide raster +API_ENTREPOT_PROC_CREATE_RAST_PYR= + # Id de la community liee au datastore bac a sable SANDBOX_COMMUNITY_ID= @@ -46,8 +49,11 @@ SANDBOX_SERVICE_ACCOUNT_CLIENT_SECRET= # id du processus d'intégration en base pour le Bac a sable SANDBOX_PROC_INT_VECT_FILES_DB= -# id du processus de génération de pyramide pour le Bac a sable +# id du processus de génération de pyramide vecteur pour le Bac a sable SANDBOX_PROC_CREATE_VECT_PYR= +# id du processus de génération de pyramide raster pour le Bac à sable +SANDBOX_PROC_CREATE_RAST_PYR= + # URL de l'API espace collaboratif API_ESPACE_COLLABORATIF_URL= diff --git a/assets/components/Utils/MenuList.tsx b/assets/components/Utils/MenuList.tsx index 5ff943ed..dd788a25 100644 --- a/assets/components/Utils/MenuList.tsx +++ b/assets/components/Utils/MenuList.tsx @@ -29,7 +29,7 @@ type MenuListItem = MenuListItemCommon & type MenuListProps = { menuOpenButtonProps?: Omit; - items: MenuListItem[]; + items: (MenuListItem | undefined | false)[]; disabled?: boolean; }; @@ -48,6 +48,8 @@ const MenuList: FC = ({ menuOpenButtonProps, items = [], disabled setAnchorEl(null); }; + const _items: MenuListItem[] = useMemo(() => items.filter((item) => item !== undefined && item !== false), [items]); + // props du bouton ouvrir menu const _menuOpenBtnProps = useMemo(() => { const _props: ButtonProps = menuOpenButtonProps ? { ...(menuOpenButtonProps as ButtonProps) } : ({} as ButtonProps); @@ -66,7 +68,7 @@ const MenuList: FC = ({ menuOpenButtonProps, items = [], disabled return _props; }, [menuOpenButtonProps, disabled, isMenuOpen, otherActionsBtnId, otherActionsMenuId]); - const atLeastOneIcon = useMemo(() => items.filter((item) => item.iconId !== undefined).length > 0, [items]); + const atLeastOneIcon = useMemo(() => _items.filter((item) => item.iconId !== undefined).length > 0, [_items]); return ( <> @@ -91,7 +93,7 @@ const MenuList: FC = ({ menuOpenButtonProps, items = [], disabled }} > {disabled === false && - items.map((item, i) => { + _items.map((item, i) => { const itemContent = ( = ({ service, datasheetName, d } }, }, - { + [OfferingTypeEnum.WFS, OfferingTypeEnum.WMTSTMS].includes(service.type) && { text: "Gérer les styles", iconId: "ri-flashlight-line", linkProps: routes.datastore_service_view({ datastoreId, datasheetName, offeringId: service._id, activeTab: "styles" }) .link, - disabled: ![OfferingTypeEnum.WFS, OfferingTypeEnum.WMTSTMS].includes(service.type), }, // { // text: "Mettre à jour la légende", @@ -123,7 +122,7 @@ const ServicesListItem: FC = ({ service, datasheetName, d linkProps: routes.datastore_manage_permissions({ datastoreId }).link, disabled: service.open === true, }, - { + [OfferingTypeEnum.WMSVECTOR, OfferingTypeEnum.WFS, OfferingTypeEnum.WMTSTMS].includes(service.type) && { text: "Modifier les informations de publication", iconId: "ri-edit-box-line", linkProps: (() => { @@ -158,7 +157,11 @@ const ServicesListItem: FC = ({ service, datasheetName, d }; } })(), - disabled: ![OfferingTypeEnum.WMSVECTOR, OfferingTypeEnum.WFS, OfferingTypeEnum.WMTSTMS].includes(service.type), + }, + service.type === OfferingTypeEnum.WMSVECTOR && { + text: "Créer un service raster WMS/WMTS", + iconId: "ri-add-box-line", + linkProps: routes.datastore_pyramid_raster_generate({ datastoreId, offeringId: service._id, datasheetName }).link, }, // NOTE : reporté cf. issue #249 // { diff --git a/assets/entrepot/pages/service/wms-raster-wmts/PyramidRasterGenerateForm.tsx b/assets/entrepot/pages/service/wms-raster-wmts/PyramidRasterGenerateForm.tsx new file mode 100644 index 00000000..09b0966e --- /dev/null +++ b/assets/entrepot/pages/service/wms-raster-wmts/PyramidRasterGenerateForm.tsx @@ -0,0 +1,176 @@ +import { fr } from "@codegouvfr/react-dsfr"; +import Alert from "@codegouvfr/react-dsfr/Alert"; +import Button from "@codegouvfr/react-dsfr/Button"; +import ButtonsGroup from "@codegouvfr/react-dsfr/ButtonsGroup"; +import Input from "@codegouvfr/react-dsfr/Input"; +import Stepper from "@codegouvfr/react-dsfr/Stepper"; +import { useQuery } from "@tanstack/react-query"; +import { declareComponentKeys } from "i18nifty"; +import { FC, useCallback, useState } from "react"; + +import { Service } from "../../../../@types/app"; +import DatastoreLayout from "../../../../components/Layout/DatastoreLayout"; +import LoadingText from "../../../../components/Utils/LoadingText"; +import useScrollToTopEffect from "../../../../hooks/useScrollToTopEffect"; +import { Translations, useTranslation } from "../../../../i18n/i18n"; +import RQKeys from "../../../../modules/entrepot/RQKeys"; +import { CartesApiException } from "../../../../modules/jsonFetch"; +import { routes } from "../../../../router/router"; +import api from "../../../api"; +import { DatasheetViewActiveTabEnum } from "../../datasheet/DatasheetView/DatasheetView"; + +const STEPS = { + TECHNICAL_NAME: 1, + TOP_ZOOM_LEVEL: 2, +}; + +type PyramidRasterGenerateFormProps = { + datastoreId: string; + offeringId: string; + datasheetName: string; +}; +const PyramidRasterGenerateForm: FC = ({ datastoreId, offeringId, datasheetName }) => { + const { t } = useTranslation("PyramidRasterGenerateForm"); + const { t: tCommon } = useTranslation("Common"); + + const [currentStep, setCurrentStep] = useState(STEPS.TECHNICAL_NAME); + + const serviceQuery = useQuery({ + queryKey: RQKeys.datastore_offering(datastoreId, offeringId), + queryFn: () => api.service.getService(datastoreId, offeringId), + staleTime: 60000, + }); + + useScrollToTopEffect(currentStep); + + const previousStep = useCallback(() => setCurrentStep((currentStep) => currentStep - 1), []); + + const nextStep = useCallback(async () => { + // const isStepValid = await trigger(undefined, { shouldFocus: true }); // demande de valider le formulaire + // if (!isStepValid) return; // ne fait rien si formulaire invalide + // formulaire est valide + if (currentStep < Object.values(STEPS).length) { + // on passe à la prochaine étape du formulaire + setCurrentStep((currentStep) => currentStep + 1); + } else { + // on est à la dernière étape du formulaire donc on envoie la sauce + // if (editMode) { + // editServiceMutation.mutate(); + // } else { + // createServiceMutation.mutate(); + // } + } + }, [ + currentStep, + /*createServiceMutation, editServiceMutation, trigger, editMode*/ + ]); + + return ( + +

{t("title")}

+ + {serviceQuery.isLoading ? ( + + ) : serviceQuery.error !== null ? ( + +

{serviceQuery.error?.message}

+ + + } + /> + ) : ( + <> + + +

{tCommon("mandatory_fields")}

+ +
+

Choisissez le nom technique de la pyramide de tuiles raster

+ +
+ +
+

{"Choisissez le niveau de zoom top de vos tables"}

+

+ {`Les niveaux de zoom de la pyramide de tuiles raster sont prédéfinis. Choisissez la borne minimum de votre pyramide de tuiles en vous aidant + de la carte de gauche. Le zoom maximum sur l’image de droite est fixe et ne peut être modifié. Tous les niveaux intermédiaires seront + générés.`} +

+
+ + + + )} +
+ ); +}; + +export default PyramidRasterGenerateForm; + +export const { i18n } = declareComponentKeys< + "title" | { K: "step.title"; P: { stepNumber: number }; R: string } | "wmsv-service.loading" | "wmsv-service.fetch_failed" | "back_to_datasheet" +>()({ + PyramidRasterGenerateForm, +}); + +export const PyramidRasterGenerateFormFrTranslations: Translations<"fr">["PyramidRasterGenerateForm"] = { + // title: "Créer un service raster WMS/WMTS", + title: "Générer une pyramide de tuiles raster", + "step.title": ({ stepNumber }) => { + switch (stepNumber) { + case 1: + return "Nom de la pyramide de tuiles raster"; + case 2: + return "Niveau de zoom top"; + default: + return ""; + } + }, + "wmsv-service.loading": "Chargement du service WMS-Vecteur...", + "wmsv-service.fetch_failed": "Récupération des informations sur le service WMS-Vecteur a échoué", + back_to_datasheet: "Retour à la fiche de données", +}; + +export const PyramidRasterGenerateFormEnTranslations: Translations<"en">["PyramidRasterGenerateForm"] = { + title: undefined, + "step.title": undefined, + "wmsv-service.loading": undefined, + "wmsv-service.fetch_failed": undefined, + back_to_datasheet: undefined, +}; diff --git a/assets/i18n/Breadcrumb.tsx b/assets/i18n/Breadcrumb.tsx index e9f133a4..7b3feedb 100644 --- a/assets/i18n/Breadcrumb.tsx +++ b/assets/i18n/Breadcrumb.tsx @@ -39,6 +39,7 @@ export const { i18n } = declareComponentKeys< | "datastore_pyramid_vector_generate" | "datastore_pyramid_vector_tms_service_new" | "datastore_pyramid_vector_tms_service_edit" + | "datastore_pyramid_raster_generate" | "datastore_service_view" >()("Breadcrumb"); @@ -81,6 +82,7 @@ export const BreadcrumbFrTranslations: Translations<"fr">["Breadcrumb"] = { datastore_pyramid_vector_generate: "Génération d'une pyramide vecteur", datastore_pyramid_vector_tms_service_new: "Création d'un service TMS", datastore_pyramid_vector_tms_service_edit: "Modification d'un service TMS", + datastore_pyramid_raster_generate: "Génération d'une pyramide raster", datastore_service_view: "Prévisualisation d'un service", }; @@ -123,5 +125,6 @@ export const BreadcrumbEnTranslations: Translations<"en">["Breadcrumb"] = { datastore_pyramid_vector_generate: "Generate a vector pyramid", datastore_pyramid_vector_tms_service_new: "Create a TMS service", datastore_pyramid_vector_tms_service_edit: "Modify a TMS service", + datastore_pyramid_raster_generate: "Generate raster pyramid", datastore_service_view: "Preview a service", }; diff --git a/assets/i18n/i18n.ts b/assets/i18n/i18n.ts index 0080f21b..ca4ae034 100644 --- a/assets/i18n/i18n.ts +++ b/assets/i18n/i18n.ts @@ -47,6 +47,7 @@ export type ComponentKey = | typeof import("../entrepot/pages/service/wms-vector/WmsVectorServiceForm").i18n | typeof import("../entrepot/pages/service/wfs/WfsServiceForm").i18n | typeof import("../entrepot/pages/service/tms/PyramidVectorTmsServiceForm").i18n + | typeof import("../entrepot/pages/service/wms-raster-wmts/PyramidRasterGenerateForm").i18n | typeof import("../entrepot/pages/service/TableSelection").i18n | typeof import("../entrepot/pages/service/AccessRestrictions").i18n | typeof import("../entrepot/pages/service/wms-vector/UploadStyleFile").i18n diff --git a/assets/i18n/languages/en.tsx b/assets/i18n/languages/en.tsx index 4a29afc0..9567ca4c 100644 --- a/assets/i18n/languages/en.tsx +++ b/assets/i18n/languages/en.tsx @@ -34,6 +34,7 @@ import { RightsEnTranslations } from "../Rights"; import { StyleEnTranslations } from "../Style"; import type { Translations } from "../i18n"; import { DatasheetUploadFormEnTranslations } from "../../entrepot/pages/datasheet/DatasheetNew/DatasheetUploadForm"; +import { PyramidRasterGenerateFormEnTranslations } from "../../entrepot/pages/service/wms-raster-wmts/PyramidRasterGenerateForm"; export const translations: Translations<"en"> = { Common: commonEnTranslations, @@ -67,6 +68,7 @@ export const translations: Translations<"en"> = { TableSelection: TableSelectionEnTranslations, UploadStyleFile: UploadStyleFileEnTranslations, PyramidVectorTmsServiceForm: PyramidVectorTmsServiceFormEnTranslations, + PyramidRasterGenerateForm: PyramidRasterGenerateFormEnTranslations, EspaceCoCommunities: EspaceCoCommunitiesEnTranslations, DatasheetUploadForm: DatasheetUploadFormEnTranslations, DatasheetList: DatasheetListEnTranslations, diff --git a/assets/i18n/languages/fr.tsx b/assets/i18n/languages/fr.tsx index 055b17f7..9dcf83d0 100644 --- a/assets/i18n/languages/fr.tsx +++ b/assets/i18n/languages/fr.tsx @@ -34,6 +34,7 @@ import { BreadcrumbFrTranslations } from "../Breadcrumb"; import { RightsFrTranslations } from "../Rights"; import { StyleFrTranslations } from "../Style"; import type { Translations } from "../i18n"; +import { PyramidRasterGenerateFormFrTranslations } from "../../entrepot/pages/service/wms-raster-wmts/PyramidRasterGenerateForm"; export const translations: Translations<"fr"> = { Common: commonFrTranslations, @@ -67,6 +68,7 @@ export const translations: Translations<"fr"> = { TableSelection: TableSelectionFrTranslations, UploadStyleFile: UploadStyleFileFrTranslations, PyramidVectorTmsServiceForm: PyramidVectorTmsServiceFormFrTranslations, + PyramidRasterGenerateForm: PyramidRasterGenerateFormFrTranslations, EspaceCoCommunities: EspaceCoCommunitiesFrTranslations, DatasheetUploadForm: DatasheetUploadFormFrTranslations, DatasheetList: DatasheetListFrTranslations, diff --git a/assets/modules/entrepot/breadcrumbs.ts b/assets/modules/entrepot/breadcrumbs.ts index 951fb1c7..d465c064 100644 --- a/assets/modules/entrepot/breadcrumbs.ts +++ b/assets/modules/entrepot/breadcrumbs.ts @@ -163,6 +163,7 @@ const getBreadcrumb = (route: Route, datastore?: Datastore): Brea case "datastore_pyramid_vector_generate": case "datastore_pyramid_vector_tms_service_new": case "datastore_pyramid_vector_tms_service_edit": + case "datastore_pyramid_raster_generate": case "datastore_service_view": defaultProps.segments = [ ...defaultProps.segments, diff --git a/assets/router/RouterRenderer.tsx b/assets/router/RouterRenderer.tsx index 0bf578fa..622768b8 100644 --- a/assets/router/RouterRenderer.tsx +++ b/assets/router/RouterRenderer.tsx @@ -53,6 +53,7 @@ const WfsServiceForm = lazy(() => import("../entrepot/pages/service/wfs/WfsServi const WmsVectorServiceForm = lazy(() => import("../entrepot/pages/service/wms-vector/WmsVectorServiceForm")); const PyramidVectorGenerateForm = lazy(() => import("../entrepot/pages/service/tms/PyramidVectorGenerateForm")); const PyramidVectorTmsServiceForm = lazy(() => import("../entrepot/pages/service/tms/PyramidVectorTmsServiceForm")); +const PyramidRasterGenerateForm = lazy(() => import("../entrepot/pages/service/wms-raster-wmts/PyramidRasterGenerateForm")); const ServiceView = lazy(() => import("../entrepot/pages/service/view/ServiceView")); @@ -176,6 +177,14 @@ const RouterRenderer: FC = () => { offeringId={route.params.offeringId} /> ); + case "datastore_pyramid_raster_generate": + return ( + + ); case "datastore_service_view": return ; case "espaceco_community_list": diff --git a/assets/router/router.ts b/assets/router/router.ts index b659afff..982f1aca 100644 --- a/assets/router/router.ts +++ b/assets/router/router.ts @@ -211,6 +211,16 @@ const routeDefs = { (p) => `${appRoot}/entrepot/${p.datastoreId}/service/tms/${p.offeringId}/modification` ), + // Création/génération d'une pyramide raster + datastore_pyramid_raster_generate: defineRoute( + { + datastoreId: param.path.string, + offeringId: param.query.string, + datasheetName: param.query.string, + }, + (p) => `${appRoot}/entrepot/${p.datastoreId}/pyramide-raster/ajout` + ), + datastore_service_view: defineRoute( { datastoreId: param.path.string, diff --git a/config/parameters.yaml b/config/parameters.yaml index beb57504..3eaef198 100644 --- a/config/parameters.yaml +++ b/config/parameters.yaml @@ -19,6 +19,7 @@ parameters: processings: int_vect_files_db: "%env(resolve:SANDBOX_PROC_INT_VECT_FILES_DB)%" create_vect_pyr: "%env(resolve:SANDBOX_PROC_CREATE_VECT_PYR)%" + create_rast_pyr: "%env(resolve:SANDBOX_PROC_CREATE_RAST_PYR)%" api_entrepot_url: "%env(resolve:API_ENTREPOT_URL)%" annexes_url: "%env(resolve:ANNEXES_URL)%" @@ -39,6 +40,7 @@ parameters: processings: int_vect_files_db: "%env(resolve:API_ENTREPOT_PROC_INT_VECT_FILES_DB)%" create_vect_pyr: "%env(resolve:API_ENTREPOT_PROC_CREATE_VECT_PYR)%" + create_rast_pyr: "%env(resolve:API_ENTREPOT_PROC_CREATE_RAST_PYR)%" api_espaceco_url: "%env(resolve:API_ESPACE_COLLABORATIF_URL)%" catalogue_url: "%env(resolve:CATALOGUE_URL)%" diff --git a/src/Controller/Entrepot/PyramidRasterController.php b/src/Controller/Entrepot/PyramidRasterController.php new file mode 100644 index 00000000..41341a43 --- /dev/null +++ b/src/Controller/Entrepot/PyramidRasterController.php @@ -0,0 +1,16 @@ + true], + condition: 'request.isXmlHttpRequest()' +)] +class PyramidRasterController extends ServiceController implements ApiControllerInterface +{ +} diff --git a/src/Services/SandboxService.php b/src/Services/SandboxService.php index b09a29a1..4474d667 100644 --- a/src/Services/SandboxService.php +++ b/src/Services/SandboxService.php @@ -54,6 +54,14 @@ public function getProcGeneratePyramidVector(string $datastoreId): string return $processings['create_vect_pyr']; } + public function getProcGeneratePyramidRaster(string $datastoreId): string + { + $apiEntrepot = $this->isSandboxDatastore($datastoreId) ? 'sandbox' : 'api_entrepot'; + $processings = $this->parameterBag->get($apiEntrepot)['processings']; + + return $processings['create_rast_pyr']; + } + public function getSandboxCommunityId(): ?string { return $this->sandboxCommunityId;