forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			107 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
<script lang="ts">/**
 | 
						|
 * The FilterView shows the various options to enable/disable a single layer or to only show a subset of the data.
 | 
						|
 */
 | 
						|
import type FilteredLayer from "../../Models/FilteredLayer";
 | 
						|
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
 | 
						|
import ToSvelte from "../Base/ToSvelte.svelte";
 | 
						|
import Checkbox from "../Base/Checkbox.svelte";
 | 
						|
import FilterConfig from "../../Models/ThemeConfig/FilterConfig";
 | 
						|
import type {Writable} from "svelte/store";
 | 
						|
import If from "../Base/If.svelte";
 | 
						|
import Dropdown from "../Base/Dropdown.svelte";
 | 
						|
import {onDestroy} from "svelte";
 | 
						|
import {ImmutableStore, Store} from "../../Logic/UIEventSource";
 | 
						|
import FilterviewWithFields from "./FilterviewWithFields.svelte";
 | 
						|
import Tr from "../Base/Tr.svelte";
 | 
						|
import Translations from "../i18n/Translations";
 | 
						|
 | 
						|
export let filteredLayer: FilteredLayer;
 | 
						|
export let highlightedLayer: Store<string | undefined> = new ImmutableStore(undefined);
 | 
						|
export let zoomlevel: Store<number> = new ImmutableStore(22);
 | 
						|
let layer: LayerConfig = filteredLayer.layerDef;
 | 
						|
let isDisplayed: Store<boolean> = filteredLayer.isDisplayed;
 | 
						|
 | 
						|
/**
 | 
						|
 * Gets a UIEventSource as boolean for the given option, to be used with a checkbox
 | 
						|
 */
 | 
						|
function getBooleanStateFor(option: FilterConfig): Writable<boolean> {
 | 
						|
    const state = filteredLayer.appliedFilters.get(option.id);
 | 
						|
    return state.sync(f => f === 0, [], (b) => b ? 0 : undefined);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Gets a UIEventSource as number for the given option, to be used with a dropdown or radiobutton
 | 
						|
 */
 | 
						|
function getStateFor(option: FilterConfig): Writable<number> {
 | 
						|
    return filteredLayer.appliedFilters.get(option.id);
 | 
						|
}
 | 
						|
 | 
						|
let mainElem: HTMLElement;
 | 
						|
$:  onDestroy(
 | 
						|
    highlightedLayer.addCallbackAndRun(highlightedLayer => {
 | 
						|
        if (highlightedLayer === filteredLayer.layerDef.id) {
 | 
						|
            mainElem?.classList?.add("glowing-shadow");
 | 
						|
        } else {
 | 
						|
            mainElem?.classList?.remove("glowing-shadow");
 | 
						|
        }
 | 
						|
    })
 | 
						|
);
 | 
						|
</script>
 | 
						|
{#if filteredLayer.layerDef.name}
 | 
						|
    <div bind:this={mainElem} class="mb-1.5">
 | 
						|
        <label class="flex gap-1 no-image-background">
 | 
						|
            <Checkbox selected={isDisplayed}/>
 | 
						|
            <If condition={filteredLayer.isDisplayed}>
 | 
						|
                <ToSvelte
 | 
						|
                        construct={() => layer.defaultIcon()?.SetClass("block h-6 w-6 no-image-background")}></ToSvelte>
 | 
						|
                <ToSvelte slot="else"
 | 
						|
                          construct={() => layer.defaultIcon()?.SetClass("block h-6 w-6 no-image-background opacity-50")}></ToSvelte>
 | 
						|
            </If>
 | 
						|
 | 
						|
            {filteredLayer.layerDef.name}
 | 
						|
 | 
						|
            {#if $zoomlevel < layer.minzoom}
 | 
						|
        <span class="alert">
 | 
						|
          <Tr t={Translations.t.general.layerSelection.zoomInToSeeThisLayer}/>
 | 
						|
        </span>
 | 
						|
            {/if}
 | 
						|
 | 
						|
        </label>
 | 
						|
 | 
						|
        {#if $isDisplayed && filteredLayer.layerDef.filters?.length > 0}
 | 
						|
            <div id="subfilters" class="flex flex-col gap-y-1 ml-4">
 | 
						|
                {#each filteredLayer.layerDef.filters as filter}
 | 
						|
                    <div>
 | 
						|
 | 
						|
                        <!-- There are three (and a half) modes of filters: a single checkbox, a radio button/dropdown or with searchable fields -->
 | 
						|
                        {#if filter.options.length === 1 && filter.options[0].fields.length === 0}
 | 
						|
                            <label>
 | 
						|
                                <Checkbox selected={getBooleanStateFor(filter)}/>
 | 
						|
                                {filter.options[0].question}
 | 
						|
                            </label>
 | 
						|
                        {/if}
 | 
						|
 | 
						|
                        {#if filter.options.length === 1 && filter.options[0].fields.length > 0}
 | 
						|
                            <FilterviewWithFields id={filter.id} filteredLayer={filteredLayer}
 | 
						|
                                                  option={filter.options[0]}></FilterviewWithFields>
 | 
						|
 | 
						|
                        {/if}
 | 
						|
 | 
						|
                        {#if filter.options.length > 1}
 | 
						|
                            <Dropdown value={getStateFor(filter)}>
 | 
						|
                                {#each filter.options as option, i}
 | 
						|
                                    <option value={i}>
 | 
						|
                                        { option.question}
 | 
						|
                                    </option>
 | 
						|
                                {/each}
 | 
						|
                            </Dropdown>
 | 
						|
                        {/if}
 | 
						|
 | 
						|
 | 
						|
                    </div>
 | 
						|
                {/each}
 | 
						|
            </div>
 | 
						|
        {/if}
 | 
						|
    </div>
 | 
						|
{/if}
 | 
						|
 |