Source IdentifyAdvanced
Source IdentifyAdvanced
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/identify-advanced/identify-advanced.declaration.tspackages/common/src/lib/widgets/identify-advanced/identify-advanced.config.tspackages/common/src/lib/widgets/identify-advanced/identify-advanced.i18n.tspackages/common/src/lib/widgets/identify-advanced/identify-advanced.model.tspackages/common/src/lib/widgets/identify-advanced/identify-advanced.state.svelte.tspackages/common/src/lib/widgets/identify-advanced/IdentifyAdvanced.sveltepackages/common/src/lib/widgets/identify-advanced/IdentifyAdvancedLayerSelect.svelte
packages/common/src/lib/widgets/identify-advanced/identify-advanced.declaration.ts
import { widgetFactorySvelte, type WidgetProps } from '$lib/api/managers/widget';import { type IdentifyAdvancedFullConfig, identifyAdvancedFullConfigSchema } from './identify-advanced.config';import type { WidgetDeclaration } from '$lib/api/managers/widget/widget-declaration';import { IdentifyAdvancedState } from '$lib/widgets/identify-advanced/identify-advanced.state.svelte';
export const declaration = { factory: () => import('./IdentifyAdvanced.svelte').then((IdentifyAdvanced) => widgetFactorySvelte(IdentifyAdvanced)), schema: () => identifyAdvancedFullConfigSchema, state: (props) => new IdentifyAdvancedState(props),} satisfies WidgetDeclaration;
export type IdentifyAdvancedProps = WidgetProps<IdentifyAdvancedFullConfig, IdentifyAdvancedState>;packages/common/src/lib/widgets/identify-advanced/identify-advanced.config.ts
import { z } from 'zod';import { i18nSchemaFrom } from '$lib/api/managers/i18n';import { identifyAdvancedI18n } from '$lib/widgets/identify-advanced/identify-advanced.i18n';import { defineWidgetConfig, inToolbarSchemaFrom } from '$lib/api/managers/configuration';import { colorfulDrawFeatureSymbolsSchema, defaultHighlightSymbolColor } from '$lib/api/symbol';
export const identifyAdvancedFullConfigSchema = defineWidgetConfig({ i18n: i18nSchemaFrom(identifyAdvancedI18n), title: identifyAdvancedI18n.title, inToolbar: inToolbarSchemaFrom({ type: 'button', }), icon: { lucide: 'Info', }, container: { id: 'dialog', draggable: true, minWidth: '25vw', center: true, }, config: z.object({ dataTableWidgetId: z.string(), defaultSymbols: colorfulDrawFeatureSymbolsSchema(defaultHighlightSymbolColor), layerListMaxHeight: z.string().default('100vh'), }),});
export type IdentifyAdvancedFullConfig = z.infer<typeof identifyAdvancedFullConfigSchema>;export type IdentifyAdvancedI18n = IdentifyAdvancedFullConfig['i18n'];packages/common/src/lib/widgets/identify-advanced/identify-advanced.i18n.ts
import type { I18nRegistry } from '$lib/api/managers/i18n';
export const identifyAdvancedI18n = { title: { fr: 'Identification avancée', nl: 'NL - Identification avancée', }, 'identify-advanced.geometry-title': { fr: 'Dessiner une géométrie', nl: 'NL - Dessiner une géométrie', }, 'identify-advanced.buffer-title': { fr: 'Buffer', nl: 'NL - Buffer', }, 'identify-advanced.layers-title': { fr: 'Couches', nl: 'NL - Couches', }, 'identify-advanced.layer-name': { fr: "Couche d'identification avancée", nl: "NL - Couche d'identification avancée", }, 'identify-advanced.missing-draw': { fr: "Veuillez réaliser un dessin avant de lancer l'identification", nl: "NL - Veuillez réaliser un dessin avant de lancer l'identification", }, 'identify-advanced.missing-services': { fr: "Veuillez sélectionner au moins un service avant de lancer l'identification", nl: "NL - Veuillez sélectionner au moins un service avant de lancer l'identification", }, 'identify-advanced.validate-selection': { fr: 'Valider la sélection', nl: 'NL - Valider la sélection', }, 'identify-advanced.buffer': { fr: 'Largeur (m)', nl: 'NL - Largeur (m)', },} satisfies I18nRegistry;packages/common/src/lib/widgets/identify-advanced/identify-advanced.model.ts
import { type DrawCreateType } from '$lib/api/tools';import type { CommonI18nKeys } from '$lib/api/managers/i18n';import type { Icon } from '$lib/api/icons';import type { ApiSublayer } from '$lib/api/layers';import type { ApiMapService } from '$lib/api/mapservices';
export type ServiceOrLayer = ApiMapService | ApiSublayer;
export type IdentifyAdvancedDrawOption = { type: DrawCreateType; title: CommonI18nKeys; icon: Icon;};
export const identifyAdvancedDrawOptions: IdentifyAdvancedDrawOption[] = [ { type: 'point', title: 'common.geometry.point', icon: { lucide: 'Dot', }, }, { type: 'polyline', title: 'common.geometry.line', icon: { lucide: 'Waypoints', }, }, { type: 'polygon', title: 'common.geometry.polygon', icon: { geoviewer: 'geoviewer-polygon', }, }, { type: 'circle', title: 'common.geometry.circle', icon: { lucide: 'Circle', }, },];packages/common/src/lib/widgets/identify-advanced/identify-advanced.state.svelte.ts
import type { WidgetStateProps } from '$lib/api/managers/widget/widget-declaration';import type { ApiSublayer } from '$lib/api/layers';
export class IdentifyAdvancedState { public readonly servicesSelection: Map<ApiSublayer, IdentifyAdvancedItemState> = new Map();
constructor(private readonly props: WidgetStateProps) {}
public add(service: ApiSublayer) { if (this.servicesSelection.has(service)) { return this.servicesSelection.get(service)!; } const state = new IdentifyAdvancedItemState(); this.servicesSelection.set(service, state); return state; }}
export class IdentifyAdvancedItemState { checked = $state(false);}packages/common/src/lib/widgets/identify-advanced/IdentifyAdvanced.svelte
<script lang="ts"> import type { IdentifyAdvancedProps } from '$lib/widgets/identify-advanced/identify-advanced.declaration'; import { getI18n } from '$lib/api/managers/i18n'; import { initGraphicMapServiceConfiguration } from '$lib/api/managers/configuration'; import { getMapManager } from '$lib/api/map'; import { onDestroy } from 'svelte'; import type { DrawCreateType } from '$lib/api/tools'; import { identifyAdvancedDrawOptions } from '$lib/widgets/identify-advanced/identify-advanced.model'; import { Icon } from '$lib/components/icon'; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '$lib/components/shadcn/ui/accordion'; import { getLayerLeafs, hasSublayers } from '$lib/api/layers'; import IdentifyAdvancedLayerSelect from '$lib/widgets/identify-advanced/IdentifyAdvancedLayerSelect.svelte'; import { Button } from '$lib/components/shadcn/ui/button'; import type ServiceDataTableWidget from '$lib/widgets/service-data-table/ServiceDataTableWidget.svelte'; import { getWidgetManager } from '$lib/api/managers/widget'; import { isQueryable, type Queryable, recordToCssStyle, reverse } from '$lib/api/utils'; import type { ApiFeature } from '$lib/api/feature'; import { showToast } from '$lib/components/toast/toast.utils'; import { renderSnippet } from '$lib/components/magical-svelte-renderer/magical-svelte-renderer-helpers'; import { Label } from '$lib/components/shadcn/ui/label'; import { Input } from '$lib/components/shadcn/ui/input'; import type { BufferSymbol } from '$lib/api/symbol'; import type { ServiceDataTableState } from '$lib/widgets/service-data-table/service-data-table.state.svelte'; import { Tabs, TabsList, TabsTrigger } from '$lib/components/shadcn/ui/tabs';
let { fullConfig, state: widgetState }: IdentifyAdvancedProps = $props(); let { config } = fullConfig; const i18n = getI18n(fullConfig.i18n); const mapManager = getMapManager(); const widgetManager = getWidgetManager(); const layerList = mapManager.layerList; const drawFactory = mapManager.tools.draw; const geometryEngine = mapManager.tools.geometryEngine; const zoom = mapManager.tools.zoom;
const serviceIdentifier = 'IdentifyAdvancedLayerId'; const identifyAdvancedGraphicService = mapManager.addGraphicMapService( initGraphicMapServiceConfiguration({ label: i18n('identify-advanced.layer-name'), id: serviceIdentifier, toc: { visible: false, }, symbols: config.defaultSymbols, }), ); const drawTool = drawFactory.create({ layer: identifyAdvancedGraphicService, defaultSymbols: config.defaultSymbols, }); const services = $derived.by(() => layerList.list.filter((service) => { const visibleAndHasSublayers = service.toc.visible && service.visible && hasSublayers(service); const layerLeafs = getLayerLeafs(service); return visibleAndHasSublayers && layerLeafs.some((leaf) => isQueryable(leaf)); }), ); const serviceIds = $derived(services.map((service) => service.id));
let activeDraw = $state<DrawCreateType>(); let currentBuffer = $state<number>(0); let bufferSymbol: BufferSymbol = $derived({ enabled: currentBuffer > 0, distance: currentBuffer, repeat: 1, showLabel: true, });
let currentFeature: ApiFeature | undefined;
$effect(() => { drawTool.stop(); if (activeDraw) { drawTool.create({ type: activeDraw, onDrawComplete: (feature: ApiFeature) => { updateCurrentFeature(feature); activeDraw = null as unknown as undefined; }, }); } });
$effect(() => { const visibleElements = { buffer: bufferSymbol }; drawTool.defaultSymbols = { point: { ...config.defaultSymbols.point, visibleElements }, polyline: { ...config.defaultSymbols.polyline, visibleElements }, polygon: { ...config.defaultSymbols.polygon, visibleElements }, circle: { ...config.defaultSymbols.circle, visibleElements }, }; if (currentFeature) { // @ts-expect-error ts do not accept deconstructive symbol setter currentFeature.symbol = { ...currentFeature.symbol, visibleElements }; } });
async function launchIdentify() { if (!currentFeature) { showToast({ level: 'warning', message: i18n('identify-advanced.missing-draw') }); return; }
const selectedServices = Array.from(widgetState.servicesSelection.entries()) .filter(([, selection]) => selection.checked) .map(([service]) => service) .filter((service) => isQueryable(service));
if (!selectedServices.length) { showToast({ level: 'warning', message: i18n('identify-advanced.missing-services') }); return; }
const spatialFilter = currentBuffer ? geometryEngine.buffer(currentFeature, currentBuffer) : currentFeature;
const dataTableWidget = await widgetManager .getReference<ServiceDataTableWidget>(config.dataTableWidgetId) .activate(); dataTableWidget.openDataTables( selectedServices.map((service) => ({ tabName: service.label, service, defaultSpatialFilter: spatialFilter, disableAllFilters: true, allowSelection: true, additionalHeaderContent: [renderSnippet(headerContent, service)], })), ); }
function validateSelection(service: Queryable) { const dataTableRef = widgetManager.getReference<ServiceDataTableWidget, ServiceDataTableState>( config.dataTableWidgetId, ); if (!dataTableRef) { return; } const dataTableItemState = dataTableRef.state.get(service); if (!dataTableItemState) { return; } const featuresSelection = dataTableItemState.pageQuery.featuresSelection; const unionFeature = geometryEngine.union(featuresSelection); updateCurrentFeature(unionFeature); zoom.zoomToFeature(unionFeature); identifyAdvancedGraphicService.addFeature(unionFeature); }
function updateCurrentFeature(feature: ApiFeature) { if (currentFeature) { identifyAdvancedGraphicService.removeFeature(currentFeature); } currentFeature = feature; }
onDestroy(() => { drawTool.destroy(); mapManager.removeMapService(serviceIdentifier); });</script>
{#snippet headerContent(service: Queryable)} <Button variant="outline" class="gv-border-primary/70" data-test-id="Identify-Advanced-Validate-Selection" onclick={() => validateSelection(service)} > {i18n('identify-advanced.validate-selection')} </Button>{/snippet}
<div class="gv-flex gv-flex-col gv-gap-2 gv-p-2 gv-h-full"> <div class="gv-flex gv-flex-col gv-gap-2"> <p class="gv-text-lg gv-font-bold gv-pb-1 gv-border-b gv-border-muted-600"> {i18n('identify-advanced.geometry-title')} </p> <Tabs bind:value={activeDraw} class="gv-w-fit gv-m-auto"> <TabsList> {#each identifyAdvancedDrawOptions as item (item.title)} <TabsTrigger value={item.type} class="gv-gap-1.5 gv-font-bold gv-rounded-full"> <Icon icon={item.icon} class="gv-size-4" /> <span>{i18n(item.title)}</span> </TabsTrigger> {/each} </TabsList> </Tabs> </div> <div class="gv-flex gv-flex-col gv-gap-2"> <p class="gv-text-lg gv-font-bold gv-pb-1 gv-border-b gv-border-muted-600"> {i18n('identify-advanced.buffer-title')} </p> <div class="gv-w-full gv-flex gv-items-center"> <Label class="gv-w-full">{i18n('identify-advanced.buffer')}</Label> <Input type="number" class="gv-w-full gv-h-7" min={0} bind:value={currentBuffer} /> </div> </div> <div class="gv-flex gv-flex-col gv-gap-2"> <p class="gv-text-lg gv-font-bold gv-pb-1 gv-border-b gv-border-muted-600"> {i18n('identify-advanced.layers-title')} </p> <div class="gv-flex gv-flex-col gv-overflow-y-auto" style={recordToCssStyle({ 'max-height': config.layerListMaxHeight })} > <Accordion multiple={true} value={serviceIds} class="gv-px-2"> {#each reverse(services) as service (service.id)} <AccordionItem value={service.id}> <AccordionTrigger>{service.label}</AccordionTrigger> <AccordionContent> <IdentifyAdvancedLayerSelect {service} {widgetState} displayLabel={false} /> </AccordionContent> </AccordionItem> {/each} </Accordion> </div> </div> <div class="gv-flex gv-justify-end"> <Button onclick={launchIdentify} data-test-id="IdentifyAdvanced-Launch" size="sm">Lancer</Button> </div></div>packages/common/src/lib/widgets/identify-advanced/IdentifyAdvancedLayerSelect.svelte
<script lang="ts"> import { hasSublayers, isSublayer } from '$lib/api/layers'; import { reverse } from '$lib/api/utils'; import { Checkbox } from '$lib/components/shadcn/ui/checkbox'; import { Label } from '$lib/components/shadcn/ui/label'; import SvelteSelf from './IdentifyAdvancedLayerSelect.svelte'; import { cn } from '$lib/components/shadcn/utils'; import type { ServiceOrLayer } from '$lib/widgets/identify-advanced/identify-advanced.model'; import type { IdentifyAdvancedState } from '$lib/widgets/identify-advanced/identify-advanced.state.svelte';
interface Props { service: ServiceOrLayer; widgetState: IdentifyAdvancedState; displayLabel: boolean; }
let { service, widgetState, displayLabel = true }: Props = $props();
if (isSublayer(service) && !widgetState.servicesSelection.has(service)) { widgetState.add(service); }</script>
<div> {#if hasSublayers(service)} {#if displayLabel} <Label>{service.label}</Label> {/if} <div class={cn('gv-flex gv-flex-col gv-gap-2 gv-mt-2', displayLabel ? 'gv-ml-5' : '')}> {#each reverse(service.sublayers.list) as sublayer (sublayer.id)} <SvelteSelf service={sublayer} {widgetState} displayLabel={true} /> {/each} </div> {:else if isSublayer(service)} {@const serviceSelection = widgetState.servicesSelection.get(service)} {#if serviceSelection} <div class="gv-flex gv-items-center gv-space-x-2" data-test-id={`IdentifyAdvancedLayerSelect-${service.id}`} > <Checkbox bind:checked={serviceSelection.checked} data-test-id={`IdentifyAdvancedLayerSelect-${service.id}-Checkbox`} /> <Label>{service.label}</Label> </div> {/if} {/if}</div>