feat: please, work.

This commit is contained in:
Raito Bezarius 2022-03-05 20:22:30 +01:00
parent 478dbf2102
commit ee7fb9b70a
7 changed files with 222 additions and 29 deletions

111
package-lock.json generated
View file

@ -34,7 +34,8 @@
"rollup-plugin-svelte": "^7.0.0", "rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0", "rollup-plugin-terser": "^7.0.0",
"svelte": "^3.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": { "node_modules/@babel/code-frame": {
@ -325,6 +326,18 @@
"integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==",
"dev": true "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": { "node_modules/ajv": {
"version": "6.12.6", "version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@ -1610,6 +1623,12 @@
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true "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": { "node_modules/json5": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
@ -1673,6 +1692,12 @@
"node": ">=10" "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": { "node_modules/livereload": {
"version": "0.9.3", "version": "0.9.3",
"resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz",
@ -1967,6 +1992,16 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true "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": { "node_modules/picocolors": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@ -3404,6 +3439,31 @@
"@fullcalendar/interaction": "^5.0.0" "@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": { "node_modules/svelte-simple-modal": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/svelte-simple-modal/-/svelte-simple-modal-1.3.1.tgz", "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==", "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==",
"dev": true "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": { "ajv": {
"version": "6.12.6", "version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@ -4904,6 +4970,12 @@
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true "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": { "json5": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
@ -4956,6 +5028,12 @@
"integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==",
"dev": true "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": { "livereload": {
"version": "0.9.3", "version": "0.9.3",
"resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz",
@ -5178,6 +5256,16 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true "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": { "picocolors": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@ -6208,6 +6296,27 @@
"@fullcalendar/interaction": "^5.0.0" "@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": { "svelte-simple-modal": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/svelte-simple-modal/-/svelte-simple-modal-1.3.1.tgz", "resolved": "https://registry.npmjs.org/svelte-simple-modal/-/svelte-simple-modal-1.3.1.tgz",

View file

@ -24,7 +24,8 @@
"rollup-plugin-svelte": "^7.0.0", "rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0", "rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0", "svelte": "^3.0.0",
"svelte-fullcalendar": "^1.1.1" "svelte-fullcalendar": "^1.1.1",
"svelte-reactive-preprocessor": "^0.8.0"
}, },
"dependencies": { "dependencies": {
"@fullcalendar/adaptive": "^5.10.1", "@fullcalendar/adaptive": "^5.10.1",

View file

@ -49,10 +49,10 @@
}); });
$: { $: {
reloadEvents(selectedCalendars, options).then(events => { /*reloadEvents(selectedCalendars, options).then(events => {
options.events = events; options.events = events;
options = { ...options }; options = { ...options };
}); });*/
} }
</script> </script>
@ -60,7 +60,7 @@
<h1 class="title">Calendrier de la vie étudiante à l'ENS</h1> <h1 class="title">Calendrier de la vie étudiante à l'ENS</h1>
<div style="height: 100%; display: flex;"> <div style="height: 100%; display: flex;">
<Modal show={$modal}> <Modal show={$modal}>
<FilterBar {calendarTree} bind:selectedCalendars={selectedCalendars} /> <FilterBar {calendarTree} />
<div style="flex: 1;"> <div style="flex: 1;">
<FullCalendar bind:this={calendar} {options} /> <FullCalendar bind:this={calendar} {options} />
</div> </div>

View file

@ -9,6 +9,6 @@
<ul> <ul>
{#each Object.entries(calendarTree) as [toplevel, subtrees], i} {#each Object.entries(calendarTree) as [toplevel, subtrees], i}
<FilterItem item={toplevel} children={subtrees} bind:selected={subSelections[i]} /> <FilterItem item={toplevel} children={subtrees} />
{/each} {/each}
</ul> </ul>

View file

@ -1,42 +1,74 @@
<script> <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 item = null;
export let children = []; export let children = [];
export let filtering = true;
export let selected = []; 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 isVal(val) {
function setAllSubFilters(value) { return function (other) {
subfiltering = Object.entries(children).map(([k, v]) => value); return other === val;
}
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;
} }
} }
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> </script>
{#if item != null} {#if item != null}
<li> <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> <ul>
{#each Object.entries(children) as [toplevel, subchildren], i} {#each Object.entries(children) as [toplevel, subchildren], i}
{#if subchildren} {#if subchildren}
<svelte:self item={toplevel} children={subchildren} bind:filtering={subfiltering[i]} /> <svelte:self item={toplevel} children={subchildren} bind:filtering={subfiltering[i]} />
{:else} {:else}
<svelte:self item={toplevel} /> <svelte:self item={toplevel} bind:filtering={subfiltering[i]} />
{/if} {/if}
{/each} {/each}
</ul> </ul>

View 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
View 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
}
}