feat: please, work.
This commit is contained in:
parent
478dbf2102
commit
ee7fb9b70a
7 changed files with 222 additions and 29 deletions
111
package-lock.json
generated
111
package-lock.json
generated
|
@ -34,7 +34,8 @@
|
|||
"rollup-plugin-svelte": "^7.0.0",
|
||||
"rollup-plugin-terser": "^7.0.0",
|
||||
"svelte": "^3.0.0",
|
||||
"svelte-fullcalendar": "^1.1.1"
|
||||
"svelte-fullcalendar": "^1.1.1",
|
||||
"svelte-reactive-preprocessor": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
|
@ -325,6 +326,18 @@
|
|||
"integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.7.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
|
@ -1610,6 +1623,12 @@
|
|||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||
|
@ -1673,6 +1692,12 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/linenumber": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/linenumber/-/linenumber-1.0.1.tgz",
|
||||
"integrity": "sha512-g7x+bxzGaJ7yUk1chFXmY4NT1oIiSQREUs33M29cjDPFUP1W/dlM3YGD1cR7qeSehp5TEpxAFP0L+Rpk3nUKzw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/livereload": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz",
|
||||
|
@ -1967,6 +1992,16 @@
|
|||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/periscopic": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-2.0.3.tgz",
|
||||
"integrity": "sha512-FuCZe61mWxQOJAQFEfmt9FjzebRlcpFz8sFPbyaCKtdusPkMEbA9ey0eARnRav5zAhmXznhaQkKGFAPn7X9NUw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"estree-walker": "^2.0.2",
|
||||
"is-reference": "^1.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
|
@ -3404,6 +3439,31 @@
|
|||
"@fullcalendar/interaction": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-reactive-preprocessor": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-reactive-preprocessor/-/svelte-reactive-preprocessor-0.8.0.tgz",
|
||||
"integrity": "sha512-gh24HA44avC+WcEUHdd8P76HtkeXW2YdF6iE72r+yowr6OMXOo509zKjydEcpwIFjzilcN4zIlRiy8/k9ba0BA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.0.4",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"json-stringify-safe": "^5.0.1",
|
||||
"linenumber": "^1.0.1",
|
||||
"periscopic": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-reactive-preprocessor/node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-simple-modal": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte-simple-modal/-/svelte-simple-modal-1.3.1.tgz",
|
||||
|
@ -3897,6 +3957,12 @@
|
|||
"integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn": {
|
||||
"version": "8.7.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
|
@ -4904,6 +4970,12 @@
|
|||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
|
||||
"dev": true
|
||||
},
|
||||
"json5": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||
|
@ -4956,6 +5028,12 @@
|
|||
"integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==",
|
||||
"dev": true
|
||||
},
|
||||
"linenumber": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/linenumber/-/linenumber-1.0.1.tgz",
|
||||
"integrity": "sha512-g7x+bxzGaJ7yUk1chFXmY4NT1oIiSQREUs33M29cjDPFUP1W/dlM3YGD1cR7qeSehp5TEpxAFP0L+Rpk3nUKzw==",
|
||||
"dev": true
|
||||
},
|
||||
"livereload": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz",
|
||||
|
@ -5178,6 +5256,16 @@
|
|||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"periscopic": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-2.0.3.tgz",
|
||||
"integrity": "sha512-FuCZe61mWxQOJAQFEfmt9FjzebRlcpFz8sFPbyaCKtdusPkMEbA9ey0eARnRav5zAhmXznhaQkKGFAPn7X9NUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"estree-walker": "^2.0.2",
|
||||
"is-reference": "^1.1.4"
|
||||
}
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
|
@ -6208,6 +6296,27 @@
|
|||
"@fullcalendar/interaction": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"svelte-reactive-preprocessor": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-reactive-preprocessor/-/svelte-reactive-preprocessor-0.8.0.tgz",
|
||||
"integrity": "sha512-gh24HA44avC+WcEUHdd8P76HtkeXW2YdF6iE72r+yowr6OMXOo509zKjydEcpwIFjzilcN4zIlRiy8/k9ba0BA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^8.0.4",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"json-stringify-safe": "^5.0.1",
|
||||
"linenumber": "^1.0.1",
|
||||
"periscopic": "^2.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"svelte-simple-modal": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte-simple-modal/-/svelte-simple-modal-1.3.1.tgz",
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
"rollup-plugin-svelte": "^7.0.0",
|
||||
"rollup-plugin-terser": "^7.0.0",
|
||||
"svelte": "^3.0.0",
|
||||
"svelte-fullcalendar": "^1.1.1"
|
||||
"svelte-fullcalendar": "^1.1.1",
|
||||
"svelte-reactive-preprocessor": "^0.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fullcalendar/adaptive": "^5.10.1",
|
||||
|
|
|
@ -49,10 +49,10 @@
|
|||
});
|
||||
|
||||
$: {
|
||||
reloadEvents(selectedCalendars, options).then(events => {
|
||||
/*reloadEvents(selectedCalendars, options).then(events => {
|
||||
options.events = events;
|
||||
options = { ...options };
|
||||
});
|
||||
});*/
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
|||
<h1 class="title">Calendrier de la vie étudiante à l'ENS</h1>
|
||||
<div style="height: 100%; display: flex;">
|
||||
<Modal show={$modal}>
|
||||
<FilterBar {calendarTree} bind:selectedCalendars={selectedCalendars} />
|
||||
<FilterBar {calendarTree} />
|
||||
<div style="flex: 1;">
|
||||
<FullCalendar bind:this={calendar} {options} />
|
||||
</div>
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
<ul>
|
||||
{#each Object.entries(calendarTree) as [toplevel, subtrees], i}
|
||||
<FilterItem item={toplevel} children={subtrees} bind:selected={subSelections[i]} />
|
||||
<FilterItem item={toplevel} children={subtrees} />
|
||||
{/each}
|
||||
</ul>
|
||||
|
|
|
@ -1,42 +1,74 @@
|
|||
<script>
|
||||
import { writable } from 'svelte/store';
|
||||
import { tick } from 'svelte';
|
||||
|
||||
import TriStateCheckbox from './TriStateCheckbox.svelte';
|
||||
import { createTriState, UNCHECKED, CHECKED, WEIRD } from './stores';
|
||||
|
||||
export let item = null;
|
||||
|
||||
export let children = [];
|
||||
export let filtering = true;
|
||||
export let selected = [];
|
||||
export let filtering = createTriState(CHECKED);
|
||||
let subfiltering = Array(Object.keys(children).length).fill(createTriState(CHECKED));
|
||||
|
||||
let subfiltering = Object.entries(children).map(([k, v]) => v ? true : false);
|
||||
|
||||
function setAllSubFilters(value) {
|
||||
subfiltering = Object.entries(children).map(([k, v]) => value);
|
||||
}
|
||||
|
||||
function handleClick(evt) {
|
||||
setAllSubFilters(evt.target.checked);
|
||||
}
|
||||
|
||||
$: if (subfiltering.length > 0) {
|
||||
filtering = subfiltering.every(Boolean);
|
||||
}
|
||||
|
||||
$: {
|
||||
const subselected = Object.entries(children).flatMap(([toplevel, _], index) => subfiltering[index] ? [toplevel] : []);
|
||||
if (item != null && filtering) {
|
||||
selected = [item, ...subselected];
|
||||
} else {
|
||||
selected = subselected;
|
||||
|
||||
function isVal(val) {
|
||||
return function (other) {
|
||||
return other === val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
subfiltering.forEach((subfilter, j) => {
|
||||
subfilter.subscribe(subvalue => {
|
||||
console.log('subfiltering', Object.entries(children)[j][0], 'newValue=', subvalue, 'prevValue=', subfiltering[j], '$filtering=', $filtering);
|
||||
const others = subfiltering.filter((_, i) => i !== j);
|
||||
const areAllOthers = others.every(isVal(CHECKED));
|
||||
const isThereAny = !others.some(isVal(UNCHECKED));
|
||||
|
||||
tick().then(() => {
|
||||
if (subvalue === CHECKED && areAllOthers && $filtering !== CHECKED) {
|
||||
console.log('check $filtering');
|
||||
filtering.setChecked();
|
||||
} else if (subvalue === UNCHECKED && isThereAny && $filtering !== UNCHECKED) {
|
||||
console.log('uncheck $filtering');
|
||||
filtering.setUnchecked();
|
||||
} else if (!areAllOthers && !isThereAny && $filtering !== WEIRD) {
|
||||
console.log(Object.entries(children)[j][0], 'partial checking');
|
||||
filtering.setWeird();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
filtering.subscribe(value => {
|
||||
console.log('filtering', item, 'newValue=', value, 'prevValue=', $filtering);
|
||||
if (value !== $filtering) {
|
||||
switch (value) {
|
||||
case CHECKED:
|
||||
subfiltering.forEach(subfilter => subfilter.setChecked());
|
||||
break;
|
||||
case UNCHECKED:
|
||||
subfiltering.forEach(subfilter => subfilter.setUnchecked());
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{#if item != null}
|
||||
<li>
|
||||
<input type="checkbox" bind:checked={filtering} on:click={handleClick} value={item}><span>{item}</span>
|
||||
<TriStateCheckbox bind:state={filtering} value={item} initialValue={true} />
|
||||
<span>{item}</span>
|
||||
<ul>
|
||||
{#each Object.entries(children) as [toplevel, subchildren], i}
|
||||
{#if subchildren}
|
||||
<svelte:self item={toplevel} children={subchildren} bind:filtering={subfiltering[i]} />
|
||||
{:else}
|
||||
<svelte:self item={toplevel} />
|
||||
<svelte:self item={toplevel} bind:filtering={subfiltering[i]} />
|
||||
{/if}
|
||||
{/each}
|
||||
</ul>
|
||||
|
|
33
src/TriStateCheckbox.svelte
Normal file
33
src/TriStateCheckbox.svelte
Normal file
|
@ -0,0 +1,33 @@
|
|||
<script>
|
||||
export let initialValue;
|
||||
export let state;
|
||||
export let value;
|
||||
|
||||
import { createTriState, UNCHECKED, CHECKED, WEIRD } from './stores';
|
||||
|
||||
let node;
|
||||
|
||||
state.subscribe(val => {
|
||||
if (!node) return;
|
||||
|
||||
if (val === CHECKED) {
|
||||
checkedValue = true;
|
||||
} else if (val === UNCHECKED) {
|
||||
checkedValue = false;
|
||||
}
|
||||
|
||||
node.indeterminate = val === WEIRD;
|
||||
});
|
||||
|
||||
function handleClick(evt) {
|
||||
if (evt.target.checked) {
|
||||
state.setChecked();
|
||||
} else if (!evt.target.checked) {
|
||||
state.setUnchecked();
|
||||
}
|
||||
}
|
||||
|
||||
let checkedValue = false;
|
||||
</script>
|
||||
|
||||
<input type="checkbox" checked={checkedValue} on:click={handleClick} bind:this={node} value={value} />
|
18
src/stores.js
Normal file
18
src/stores.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { writable } from 'svelte/store';
|
||||
|
||||
export const UNCHECKED = 0;
|
||||
export const CHECKED = 1;
|
||||
export const WEIRD = 2;
|
||||
|
||||
export function createTriState(initialValue) {
|
||||
const { subscribe, set } = writable(initialValue);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
setUnchecked: () => set(UNCHECKED),
|
||||
setWeird: () => set(WEIRD),
|
||||
setChecked: () => set(CHECKED),
|
||||
set
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue