Source Export
Source Export
Cette page est générée automatiquement à partir du dépôt local au moment de la génération de la documentation.
Fichiers inclus
packages/common/src/lib/widgets/export/export/export.declaration.tspackages/common/src/lib/widgets/export/export/export.config.tspackages/common/src/lib/widgets/export/export/Export.svelte
packages/common/src/lib/widgets/export/export/export.declaration.ts
import { widgetFactorySvelte, type WidgetProps } from '$lib/api/managers/widget';import { type ExportConfig, exportConfigSchema } from './export.config';import type { WidgetDeclaration } from '$lib/api/managers/widget/widget-declaration';
export const declaration = { factory: () => import('./Export.svelte').then((Export) => widgetFactorySvelte(Export)), schema: () => exportConfigSchema,} satisfies WidgetDeclaration;
export type ExportProps = WidgetProps<ExportConfig>;packages/common/src/lib/widgets/export/export/export.config.ts
import { defineWidgetConfig, inToolbarSchemaFrom } from '$lib/api/managers/configuration';import { type I18nRegistry, i18nSchemaFrom } from '$lib/api/managers/i18n';import { z } from 'zod';import { ExportFormat } from '$lib/api/tools';
export const exportTranslations = { orientation: { fr: 'Orientation du fichier', nl: 'NL - Orientation du fichier', }, vertical: { fr: 'Portrait', nl: 'NL - Portrait', }, horizontal: { fr: 'Paysage', nl: 'NL - Paysage', }, format: { fr: 'Format', nl: 'NL - Format', }, title: { fr: 'Titre', nl: 'NL - Titre', }, description: { fr: 'Description', nl: 'NL - Description', }, name: { fr: 'Nom', nl: 'NL - Nom', }, legend: { fr: 'Légende', nl: 'NL - Légende', }, 'show-legend': { fr: 'Afficher la légende', nl: 'NL - Afficher la légende', }, 'generate-the-format': { fr: 'Générer le {{format}}', nl: 'NL - Générer le {{format}}', },} satisfies I18nRegistry;
export const exportConfigSchema = defineWidgetConfig({ i18n: i18nSchemaFrom(exportTranslations), title: { fr: 'Exporter la carte', nl: 'NL - Exporter la carte', }, icon: { lucide: 'Printer', }, inToolbar: inToolbarSchemaFrom({ type: 'button', }), onActivate: { deactivate: { classes: ['Report', 'Identify', 'AddData', 'Draw', 'MeasureDistance', 'MeasureSurface', 'AdvancedSearch'], }, }, config: z .object({ allowedExtensions: z.array(z.enum(ExportFormat)).default([ExportFormat.PDF, ExportFormat.PNG]), templateApiUrl: z.string().default('https://geoservices.test.wallonie.be/geoviewer-services/api/template'), }) .optional() .prefault({}),});
export type ExportConfig = z.infer<typeof exportConfigSchema>;packages/common/src/lib/widgets/export/export/Export.svelte
<script lang="ts"> import { Switch } from '$lib/components/shadcn/ui/switch'; import { File } from 'lucide-svelte'; import { Item, RadioGroup } from '$lib/components/shadcn/ui/radio-group'; import { Label } from '$lib/components/shadcn/ui/label'; import { Input } from '$lib/components/shadcn/ui/input'; import { Textarea } from '$lib/components/shadcn/ui/textarea'; import { Checkbox } from '$lib/components/shadcn/ui/checkbox'; import { Button } from '$lib/components/shadcn/ui/button'; import { GeoviewerError } from '$lib/api/managers/error/geoviewer-error.model'; import { getMapManager } from '$lib/api/map'; import { downloadBlob, reverse } from '$lib/api/utils'; import { ExportFormat, ExportOrientation, TemplateParams } from '$lib/api/tools'; import { getI18n } from '$lib/api/managers/i18n'; import BlockingLoader from '$lib/components/blocking-loader/BlockingLoader.svelte'; import { LegendNode } from '$lib/api/utils/legend/legend.model.svelte'; import { getTitle, loadLegend } from '$lib/api/tools/report/report.utils'; import { cn } from '$lib/components/shadcn/utils'; import type { ExportProps } from './export.declaration';
let { fullConfig }: ExportProps = $props();
const mapManager = getMapManager(); const { config } = fullConfig; const report = mapManager.tools.report; const i18n = getI18n(fullConfig.i18n);
const legendNodes = $derived.by(() => reverse(mapManager.layerList.list) .filter((x) => x.toc.visible && x.visible) .map((service) => new LegendNode(service)), );
let templateParams = new TemplateParams(config.templateApiUrl);
let vertical = $state(false); let loading = $state(false);
$effect(() => { templateParams.orientation = vertical ? ExportOrientation.VERTICAL : ExportOrientation.HORIZONTAL; });
async function exportClicked() { try { loading = true; await mapManager.waitForAllMapServicesToBeLoaded(); const pictureBlob = await report.downloadAdvancedScreenshot(templateParams.orientation); templateParams.fileName = getTitle(); if (templateParams.format === ExportFormat.PNG) { downloadBlob(pictureBlob, `${templateParams.fileName}.png`); } else { templateParams.base64Map = await blobToBase64(pictureBlob); await generateReport(); } } catch (error) { console.error(error); throw new GeoviewerError(i18n('common.export-error'), { cause: error }); } finally { loading = false; } }
function blobToBase64(blob: Blob): Promise<string> { return new Promise<string>((resolve) => { const reader = new FileReader(); reader.onloadend = async () => { resolve(reader.result as string); }; reader.readAsDataURL(blob); }); }
async function generateReport() { if (templateParams.showLegend) { templateParams.legendList = await loadLegend(legendNodes); } templateParams.templateName = `EXPORT_${templateParams.orientation.toString()}_${templateParams.format.toString()}`; await report.downloadTemplate(templateParams); }</script>
<div class="gv-p-4"> <!--ORIENTATION--> <div class="gv-font-extrabold gv-mb-2">{i18n('orientation')}</div> <div class="gv-flex gv-align-middle gv-mb-2"> <button onclick={() => (vertical = false)} class={cn('gv-flex gv-align-middle', vertical && 'gv-opacity-60')}> <File class="gv-ml-1 gv-h-6 gv-rotate-90" /> {i18n('horizontal')} </button> <Switch data-test-id="Export-orientation-switch" bind:checked={vertical} class="gv-mx-2" /> <button onclick={() => (vertical = true)} class={cn('gv-flex gv-align-middle', !vertical && 'gv-opacity-60')}> {i18n('vertical')} <File class="gv-h-5" /> </button> </div>
<!--FORMAT--> <div class="gv-font-extrabold gv-mb-2">{i18n('format')}</div> <div class="gv-flex gv-mb-2"> <RadioGroup bind:value={templateParams.format} class="gv-flex gv-w-full gv-space-x-1"> {#each config.allowedExtensions as extension (extension)} <div class="gv-flex gv-items-center gv-space-x-2"> <Item data-test-id="Export-extension-{extension}" value={extension} id={extension} /> <Label class="gv-cursor-pointer" for={extension}>{extension}</Label> </div> {/each} </RadioGroup> </div>
{#if templateParams.format !== ExportFormat.PNG} <!--TITLE--> <Label class="gv-block gv-font-extrabold gv-mb-2">{i18n('title')}</Label> <Input maxlength={100} type="text" data-test-id="Export-title-input" bind:value={templateParams.title} class="gv-mb-2" />
<!--DESCRIPTION--> <Label class="gv-block gv-font-extrabold gv-mb-2">{i18n('description')}</Label> <Textarea maxlength={500} data-test-id="Export-description-input" bind:value={templateParams.description} rows={3} class="gv-mb-2" />
<!--LEGEND--> <div class="gv-font-extrabold gv-mb-2">{i18n('legend')}</div> <div class="gv-flex gv-items-center gv-space-x-2 gv-mb-2"> <Checkbox data-test-id="Export-legend-checkbox" bind:checked={templateParams.showLegend} id="legend" /> <Label for="legend">{i18n('show-legend')}</Label> </div> {/if}
<Button class="gv-mt-3" data-test-id="Export-export-button" onclick={exportClicked} size="sm"> {i18n('generate-the-format', { format: templateParams.format })} </Button></div>
<BlockingLoader open={loading} />