New filterbar
This commit is contained in:
parent
d31a4bbcc4
commit
22c1b4a784
3 changed files with 81 additions and 28 deletions
|
@ -35,6 +35,7 @@
|
|||
bootstrap5Plugin
|
||||
],
|
||||
locale: frLocale,
|
||||
allDayContent: '',
|
||||
headerToolbar: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
|
@ -48,6 +49,7 @@
|
|||
openModal = true;
|
||||
event.set(info.event);
|
||||
},
|
||||
titleFormat: { year: '2-digit', month: 'numeric', day: 'numeric' },
|
||||
events: [],
|
||||
themeSystem: 'bootstrap5'
|
||||
});
|
||||
|
@ -82,13 +84,16 @@
|
|||
|
||||
<div class="app-container">
|
||||
<h1 class="title">Calendrier de la vie étudiante à l'ENS</h1>
|
||||
<div style="height: 100%; display: flex;">
|
||||
<FilterBar {calendarTree} bind:selected={selectedCalendars} />
|
||||
<div style="flex: 1;">
|
||||
|
||||
<FilterBar {calendarTree} bind:selected={selectedCalendars} />
|
||||
|
||||
<div class="h-100 d-flex">
|
||||
<div class="flex-grow-1">
|
||||
<FullCalendar bind:this={calendar} options={$options} />
|
||||
</div>
|
||||
<EventModal event={$event} open={openModal} {toggle} />
|
||||
</div>
|
||||
|
||||
<EventModal event={$event} open={openModal} {toggle} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
<script>
|
||||
import { Button, Offcanvas, Icon } from 'sveltestrap';
|
||||
import FilterItem from './FilterItem.svelte';
|
||||
export let calendarTree = [];
|
||||
export let selected = null;
|
||||
|
||||
let subSelections = Array.from({length: Object.keys(calendarTree).length}, e => []);
|
||||
let subSelections = Array.from({ length: Object.keys(calendarTree).length }, _ => []);
|
||||
$: selected = subSelections.flat();
|
||||
|
||||
let open = true;
|
||||
const toggle = () => (open = !open);
|
||||
</script>
|
||||
|
||||
<ul>
|
||||
{#each Object.entries(calendarTree) as [toplevel, subtrees], i}
|
||||
<FilterItem item={toplevel} children={subtrees} bind:selected={subSelections[i]} />
|
||||
{/each}
|
||||
</ul>
|
||||
<Button on:click={toggle} class="my-2">
|
||||
<span class="me-2">Sélection des calendriers</span>
|
||||
<Icon name="chevron-double-right" />
|
||||
</Button>
|
||||
|
||||
<Offcanvas
|
||||
isOpen={open}
|
||||
{toggle}
|
||||
scroll
|
||||
placement="start"
|
||||
header="Sélection des calendriers"
|
||||
>
|
||||
{#each Object.entries(calendarTree) as [toplevel, subtrees], i}
|
||||
<FilterItem item={toplevel} children={subtrees} bind:selected={subSelections[i]} />
|
||||
{/each}
|
||||
</Offcanvas>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import TriStateCheckbox from './TriStateCheckbox.svelte';
|
||||
import { createTriState, createTriStates, UNCHECKED, CHECKED, WEIRD } from './stores';
|
||||
import { Icon } from 'sveltestrap';
|
||||
|
||||
export let item = null;
|
||||
|
||||
|
@ -11,12 +12,12 @@
|
|||
export let selected = [];
|
||||
export let filtering = createTriState(CHECKED);
|
||||
let subfiltering = createTriStates(CHECKED, Object.entries(children).length);
|
||||
let subselected = Array.from({length: Object.entries(children).length}, e => []);
|
||||
let subselected = Array.from({ length: Object.entries(children).length }, e => []);
|
||||
|
||||
function isVal(val) {
|
||||
return function (other) {
|
||||
return other === val;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function areAllChecked(values) {
|
||||
|
@ -30,7 +31,7 @@
|
|||
function handleChildChange(i) {
|
||||
return function handler(evt) {
|
||||
subfiltering.setAt(i, evt.detail.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
subfiltering.subscribe(subvalues => {
|
||||
|
@ -38,7 +39,11 @@
|
|||
filtering.setChecked();
|
||||
} else if (areAllUnchecked(subvalues) && $filtering !== UNCHECKED) {
|
||||
filtering.setUnchecked();
|
||||
} else if (!areAllChecked(subvalues) && !areAllUnchecked(subvalues) && $filtering !== WEIRD) {
|
||||
} else if (
|
||||
!areAllChecked(subvalues) &&
|
||||
!areAllUnchecked(subvalues) &&
|
||||
$filtering !== WEIRD
|
||||
) {
|
||||
filtering.setWeird();
|
||||
}
|
||||
});
|
||||
|
@ -62,21 +67,49 @@
|
|||
dispatch('change', { value: evt.detail.value });
|
||||
}
|
||||
|
||||
$: selected = $filtering === CHECKED ? [item, ...subselected.flat()] : subselected.flat();
|
||||
$: icon = () => {
|
||||
switch ($filtering) {
|
||||
case UNCHECKED:
|
||||
return 'circle';
|
||||
case WEIRD:
|
||||
return 'circle-half';
|
||||
case CHECKED:
|
||||
return 'check-circle-fill';
|
||||
}
|
||||
};
|
||||
|
||||
$: selected =
|
||||
$filtering === CHECKED ? [item, ...subselected.flat()] : subselected.flat();
|
||||
</script>
|
||||
|
||||
{#if item != null}
|
||||
<li>
|
||||
<TriStateCheckbox state={$filtering} on:change={handleChange} value={item} initialValue={true} />
|
||||
<span>{item}</span>
|
||||
<ul>
|
||||
{#each Object.entries(children) as [toplevel, subchildren], i}
|
||||
{#if subchildren}
|
||||
<svelte:self item={toplevel} children={subchildren} on:change={handleChildChange(i)} filtering={subfiltering.storeAt(i)} bind:selected={subselected[i]} />
|
||||
{:else}
|
||||
<svelte:self item={toplevel} on:change={handleChildChange(i)} filtering={subfiltering.storeAt(i)} bind:selected={subselected[i]} />
|
||||
{/if}
|
||||
{/each}
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<TriStateCheckbox
|
||||
state={$filtering}
|
||||
on:change={handleChange}
|
||||
value={item}
|
||||
initialValue={true}
|
||||
/>
|
||||
<span><Icon name={icon()} />{item}</span>
|
||||
<ul>
|
||||
{#each Object.entries(children) as [toplevel, subchildren], i}
|
||||
{#if subchildren}
|
||||
<svelte:self
|
||||
item={toplevel}
|
||||
children={subchildren}
|
||||
on:change={handleChildChange(i)}
|
||||
filtering={subfiltering.storeAt(i)}
|
||||
bind:selected={subselected[i]}
|
||||
/>
|
||||
{:else}
|
||||
<svelte:self
|
||||
item={toplevel}
|
||||
on:change={handleChildChange(i)}
|
||||
filtering={subfiltering.storeAt(i)}
|
||||
bind:selected={subselected[i]}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
</ul>
|
||||
</li>
|
||||
{/if}
|
||||
|
|
Loading…
Reference in a new issue