mountain-ui 1.0.110 → 1.0.112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/index.d.ts +29 -0
  2. package/index.js +29 -0
  3. package/package.json +1 -1
  4. package/src/lib/registry/navigationRegistry/components/NavigationGroupRow.svelte +30 -32
  5. package/src/lib/registry/navigationRegistry/components/NewNavbarGroupDialog.svelte +43 -39
  6. package/src/lib/registry/projectRegistry/createProject.js +2 -0
  7. package/src/lib/registry/widgetGroupRegistry/components/EmptySlot.svelte +47 -0
  8. package/src/lib/registry/widgetGroupRegistry/components/GroupPreview.svelte +142 -0
  9. package/src/lib/registry/widgetGroupRegistry/components/NewWidgetGroup.svelte +122 -0
  10. package/src/lib/registry/widgetGroupRegistry/components/WidgetGroup.svelte +39 -0
  11. package/src/lib/registry/widgetGroupRegistry/createWidget.js +17 -0
  12. package/src/lib/registry/widgetGroupRegistry/createWidgetGroup.js +19 -0
  13. package/src/lib/registry/widgetGroupRegistry/registerWidgetGroups.js +37 -0
  14. package/src/lib/registry/widgetGroupRegistry/registry.svelte.js +47 -0
  15. package/src/lib/registry/widgetTypeRegistry/components/CreateWidgetDialog.svelte +25 -0
  16. package/src/lib/registry/widgetTypeRegistry/components/Widget.svelte +18 -0
  17. package/src/lib/registry/widgetTypeRegistry/components/WidgetConfig.svelte +16 -0
  18. package/src/lib/registry/widgetTypeRegistry/components/WidgetPreview.svelte +59 -0
  19. package/src/lib/registry/widgetTypeRegistry/components/WidgetTypeButton.svelte +20 -0
  20. package/src/lib/registry/widgetTypeRegistry/components/WidgetTypeSelector.svelte +32 -0
  21. package/src/lib/registry/widgetTypeRegistry/createWidgetType.js +20 -0
  22. package/src/lib/registry/widgetTypeRegistry/registerWidgetTypes.js +14 -0
  23. package/src/lib/registry/widgetTypeRegistry/registry.svelte.js +43 -0
  24. package/src/lib/registry/widgetTypeRegistry/widgetTypes/Bar/Bar.svelte +79 -0
  25. package/src/lib/registry/widgetTypeRegistry/widgetTypes/Bar/ConfigBar.svelte +176 -0
  26. package/src/lib/registry/widgetTypeRegistry/widgetTypes/Bar/index.js +13 -0
  27. package/src/lib/registry/widgetTypeRegistry/widgetTypes/Bar/text.js +21 -0
  28. package/src/lib/registry/widgetTypeRegistry/widgetTypes/Evolution/ConfigEvolution.svelte +180 -0
  29. package/src/lib/registry/widgetTypeRegistry/widgetTypes/Evolution/Evolution.svelte +81 -0
  30. package/src/lib/registry/widgetTypeRegistry/widgetTypes/Evolution/index.js +13 -0
  31. package/src/lib/registry/widgetTypeRegistry/widgetTypes/Evolution/text.js +21 -0
  32. package/src/lib/registry/widgetTypeRegistry/widgetTypes/KPI/ConfigKPI.svelte +201 -0
  33. package/src/lib/registry/widgetTypeRegistry/widgetTypes/KPI/KPI.svelte +118 -0
  34. package/src/lib/registry/widgetTypeRegistry/widgetTypes/KPI/index.js +12 -0
  35. package/src/lib/registry/widgetTypeRegistry/widgetTypes/KPI/text.js +22 -0
  36. package/src/lib/registry/widgetTypeRegistry/widgetTypes/List/ConfigList.svelte +199 -0
  37. package/src/lib/registry/widgetTypeRegistry/widgetTypes/List/List.svelte +97 -0
  38. package/src/lib/registry/widgetTypeRegistry/widgetTypes/List/index.js +12 -0
  39. package/src/lib/registry/widgetTypeRegistry/widgetTypes/List/text.js +21 -0
  40. package/src/routes/exemple/[project_normalized_name]/+layout.svelte +1 -1
  41. package/src/routes/exemple/[project_normalized_name]/home/+page.svelte +61 -1
  42. package/src/routes/exemple/[project_normalized_name]/navigation/+page.svelte +28 -0
  43. package/src/routes/exemple/[project_normalized_name]/widgets/+page.svelte +92 -0
@@ -0,0 +1,39 @@
1
+ <script>
2
+ import { handlers } from 'svelte/legacy';
3
+ import EmptySlot from './EmptySlot.svelte';
4
+ import CreateWidgetDialog from '../../widgetTypeRegistry/components/CreateWidgetDialog.svelte';
5
+ import { sendRequest, toast } from 'hamzus-ui';
6
+ import { registerWidgetGroups } from '../registerWidgetGroups';
7
+ import { widgetGroupRegistry } from '../registry.svelte';
8
+ import Widget from '../../widgetTypeRegistry/components/Widget.svelte';
9
+
10
+ let { id = null, numberOfColumn = 1, children = [] } = $props();
11
+
12
+ const group = $derived(widgetGroupRegistry.get(id))
13
+ </script>
14
+
15
+ {#if group && group.children && group.children.length > 0}
16
+ <div class="group-container" style="grid-template-columns:repeat({numberOfColumn}, minmax(0, 1fr));">
17
+ {#each Array.from({ length: numberOfColumn }) as column, index}
18
+ {const child = group.getChild(index + 1)}
19
+ {#if child}
20
+ <Widget type={child.type} {...child.props}></Widget>
21
+ {:else}
22
+ <div class="empty">
23
+
24
+ </div>
25
+ {/if}
26
+ {/each}
27
+ </div>
28
+ {/if}
29
+
30
+ <style>
31
+ .group-container {
32
+ width: 100%;
33
+ display: grid;
34
+ padding: var(--pad-xl);
35
+ column-gap: var(--pad-m);
36
+ min-height: 150px;
37
+ transition: border 0.2s ease-out;
38
+ }
39
+ </style>
@@ -0,0 +1,17 @@
1
+
2
+
3
+ export function createWidget(config = {}) {
4
+ const widget = {
5
+ id: null,
6
+ group_id:null,
7
+ position:1,
8
+ type:null,
9
+ title:"",
10
+ props:{},
11
+ };
12
+
13
+ Object.assign(widget, config);
14
+
15
+
16
+ return widget;
17
+ }
@@ -0,0 +1,19 @@
1
+ import { sendRequest } from "hamzus-ui";
2
+ import { widgetGroupRegistry } from "./registry.svelte";
3
+
4
+ export function createWidgetGroup(config = {}) {
5
+ const widgetGroup = {
6
+ id: null,
7
+ column_number:1,
8
+ position:1,
9
+ children:[],
10
+ };
11
+
12
+ Object.assign(widgetGroup, config);
13
+
14
+ widgetGroup.getChild = (position) =>{
15
+ return widgetGroup.children.find(c=>c.position === position)
16
+ }
17
+
18
+ return widgetGroup;
19
+ }
@@ -0,0 +1,37 @@
1
+ import { sendRequest } from "hamzus-ui";
2
+ import { widgetGroupRegistry } from "./registry.svelte";
3
+ import { createWidgetGroup } from "./createWidgetGroup";
4
+ import { createWidget } from "./createWidget";
5
+
6
+
7
+ export async function registerWidgetGroups() {
8
+
9
+ widgetGroupRegistry.unregisterAll()
10
+
11
+ const request = await sendRequest({
12
+ path:"/get-all-widget-groups",
13
+ })
14
+
15
+ for (const group of request.data) {
16
+ let config = {
17
+ id: group.id,
18
+ column_number:group.column_number,
19
+ position:group.position,
20
+ children:[]
21
+ }
22
+
23
+ for (const child of group.children) {
24
+ config.children.push(createWidget({
25
+ id:child.id,
26
+ group_id:child.group_id,
27
+ position:child.position,
28
+ type:child.type,
29
+ title:child.title,
30
+ props:child.props,
31
+ }))
32
+
33
+ }
34
+ widgetGroupRegistry.register(createWidgetGroup(config))
35
+
36
+ }
37
+ }
@@ -0,0 +1,47 @@
1
+ import { writable, derived, get } from 'svelte/store';
2
+
3
+ function createWidgetGroupRegistry() {
4
+ const store = writable({});
5
+
6
+ const all = derived(store, ($widgetGroups) => Object.values($widgetGroups));
7
+
8
+ return {
9
+ subscribe: store.subscribe,
10
+
11
+ register(widgetGroup) {
12
+ store.update((widgetGroups) => ({
13
+ ...widgetGroups,
14
+ [widgetGroup.id]: widgetGroup
15
+ }));
16
+ },
17
+
18
+ unregisterAll() {
19
+ store.update((widgetGroups) => {
20
+ return {};
21
+ });
22
+ },
23
+ unregister(id) {
24
+ store.update((widgetGroups) => {
25
+ const copy = { ...widgetGroups };
26
+
27
+ delete copy[id];
28
+
29
+ return copy;
30
+ });
31
+ },
32
+
33
+ get(id) {
34
+ return get(store)[id];
35
+ },
36
+
37
+ select(id) {
38
+ return derived(store, ($widgetGroups) => $widgetGroups[id]);
39
+ },
40
+
41
+ getAll() {
42
+ return all;
43
+ },
44
+ };
45
+ }
46
+
47
+ export const widgetGroupRegistry = createWidgetGroupRegistry();
@@ -0,0 +1,25 @@
1
+ <script>
2
+ import { AlertCard, Button, Dialog } from "hamzus-ui";
3
+ import WidgetTypeSelector from "./WidgetTypeSelector.svelte";
4
+ import WidgetConfig from "./WidgetConfig.svelte";
5
+
6
+ let {isOpen = $bindable(false), save = ()=>{}, ...props} = $props()
7
+
8
+ let type = $state(null)
9
+
10
+ async function handleSave(data) {
11
+ await save(data)
12
+
13
+ isOpen = false
14
+ }
15
+ </script>
16
+
17
+ <Dialog bind:isOpen>
18
+ <div style="display:flex;row-gap:var(--pad-m);flex-direction:column;">
19
+ <h3>Créer un nouveau widget</h3>
20
+ <WidgetTypeSelector onChange={(newType)=>{type = newType}}></WidgetTypeSelector>
21
+ {#if type}
22
+ <WidgetConfig save={handleSave} {type}></WidgetConfig>
23
+ {/if}
24
+ </div>
25
+ </Dialog>
@@ -0,0 +1,18 @@
1
+ <script>
2
+ import { widgetTypeRegistry } from "../registry.svelte";
3
+
4
+ let {type, ...props} = $props()
5
+
6
+ const widgetType = $derived(widgetTypeRegistry.get(type))
7
+ </script>
8
+
9
+ <div class="widget-case">
10
+ <svelte:component this={widgetType.components.component} {...props}></svelte:component>
11
+ </div>
12
+
13
+ <style>
14
+ .widget-case {
15
+ width: 100%;
16
+ height: 100%;
17
+ }
18
+ </style>
@@ -0,0 +1,16 @@
1
+ <script>
2
+ import { widgetTypeRegistry } from "../registry.svelte";
3
+
4
+ let {type, save = (data)=>{}, ...props} = $props()
5
+
6
+ const widgetType = $derived(widgetTypeRegistry.get(type))
7
+
8
+ function handleSave(data) {
9
+ save({
10
+ ...data,
11
+ type:widgetType.type
12
+ })
13
+ }
14
+ </script>
15
+
16
+ <svelte:component this={widgetType.components.config} save={handleSave} {...props}></svelte:component>
@@ -0,0 +1,59 @@
1
+ <script>
2
+ import { IconButton } from 'hamzus-ui';
3
+ import { widgetTypeRegistry } from '../registry.svelte';
4
+
5
+ let { type, onDelete = () => {}, ...props } = $props();
6
+
7
+ const widgetType = $derived(widgetTypeRegistry.get(type));
8
+ </script>
9
+
10
+ <div class="widget-case">
11
+ <svelte:component this={widgetType.components.component} {...props}></svelte:component>
12
+ <div class="btn">
13
+ <IconButton variant="secondary" onClick={onDelete}>
14
+ <svg
15
+ width="24"
16
+ height="24"
17
+ viewBox="0 0 24 24"
18
+ fill="none"
19
+ xmlns="http://www.w3.org/2000/svg"
20
+ >
21
+ <path
22
+ d="M20.9997 6.72998C20.9797 6.72998 20.9497 6.72998 20.9197 6.72998C15.6297 6.19998 10.3497 5.99998 5.11967 6.52998L3.07967 6.72998C2.65967 6.76998 2.28967 6.46998 2.24967 6.04998C2.20967 5.62998 2.50967 5.26998 2.91967 5.22998L4.95967 5.02998C10.2797 4.48998 15.6697 4.69998 21.0697 5.22998C21.4797 5.26998 21.7797 5.63998 21.7397 6.04998C21.7097 6.43998 21.3797 6.72998 20.9997 6.72998Z"
23
+ fill="#292D32"
24
+ />
25
+ <path
26
+ d="M8.50074 5.72C8.46074 5.72 8.42074 5.72 8.37074 5.71C7.97074 5.64 7.69074 5.25 7.76074 4.85L7.98074 3.54C8.14074 2.58 8.36074 1.25 10.6907 1.25H13.3107C15.6507 1.25 15.8707 2.63 16.0207 3.55L16.2407 4.85C16.3107 5.26 16.0307 5.65 15.6307 5.71C15.2207 5.78 14.8307 5.5 14.7707 5.1L14.5507 3.8C14.4107 2.93 14.3807 2.76 13.3207 2.76H10.7007C9.64074 2.76 9.62074 2.9 9.47074 3.79L9.24074 5.09C9.18074 5.46 8.86074 5.72 8.50074 5.72Z"
27
+ fill="#292D32"
28
+ />
29
+ <path
30
+ d="M15.2104 22.7501H8.79039C5.30039 22.7501 5.16039 20.8201 5.05039 19.2601L4.40039 9.19007C4.37039 8.78007 4.69039 8.42008 5.10039 8.39008C5.52039 8.37008 5.87039 8.68008 5.90039 9.09008L6.55039 19.1601C6.66039 20.6801 6.70039 21.2501 8.79039 21.2501H15.2104C17.3104 21.2501 17.3504 20.6801 17.4504 19.1601L18.1004 9.09008C18.1304 8.68008 18.4904 8.37008 18.9004 8.39008C19.3104 8.42008 19.6304 8.77007 19.6004 9.19007L18.9504 19.2601C18.8404 20.8201 18.7004 22.7501 15.2104 22.7501Z"
31
+ fill="#292D32"
32
+ />
33
+ <path
34
+ d="M13.6601 17.25H10.3301C9.92008 17.25 9.58008 16.91 9.58008 16.5C9.58008 16.09 9.92008 15.75 10.3301 15.75H13.6601C14.0701 15.75 14.4101 16.09 14.4101 16.5C14.4101 16.91 14.0701 17.25 13.6601 17.25Z"
35
+ fill="#292D32"
36
+ />
37
+ <path
38
+ d="M14.5 13.25H9.5C9.09 13.25 8.75 12.91 8.75 12.5C8.75 12.09 9.09 11.75 9.5 11.75H14.5C14.91 11.75 15.25 12.09 15.25 12.5C15.25 12.91 14.91 13.25 14.5 13.25Z"
39
+ fill="#292D32"
40
+ />
41
+ </svg>
42
+ </IconButton>
43
+ </div>
44
+ </div>
45
+
46
+ <style>
47
+ .widget-case {
48
+ width: 100%;
49
+ height: 100%;
50
+ position: relative;
51
+ }
52
+
53
+ .btn {
54
+ position: absolute;
55
+ top: var(--pad-s);
56
+ right: var(--pad-s);
57
+ z-index: 3;
58
+ }
59
+ </style>
@@ -0,0 +1,20 @@
1
+ <script>
2
+ import { Button } from "hamzus-ui";
3
+ import { widgetTypeRegistry } from "../registry.svelte";
4
+
5
+ let {
6
+ type="",
7
+ style="",
8
+ variant="ghost",
9
+ ...props
10
+ } = $props()
11
+
12
+ const widgetType = $derived(widgetTypeRegistry.get(type))
13
+ </script>
14
+
15
+
16
+ <Button {variant} style="width:100%;{style}" {...props}>
17
+ <h5>{widgetType.name}</h5>
18
+ </Button>
19
+
20
+
@@ -0,0 +1,32 @@
1
+ <script>
2
+ import { Button, DropdownMenu } from 'hamzus-ui';
3
+ import { widgetTypeRegistry } from '../registry.svelte';
4
+ import WidgetTypeButton from './WidgetTypeButton.svelte';
5
+
6
+ let { value = $bindable(null), onChange = (type) => {} } = $props();
7
+
8
+ const widgetTypes = widgetTypeRegistry.getAll();
9
+
10
+ function handleClick(type) {
11
+ value = type;
12
+ onChange(type);
13
+ }
14
+ </script>
15
+
16
+ <DropdownMenu.Root direction="bottom">
17
+ <DropdownMenu.Trigger slot="trigger">
18
+ <Button variant="secondary">
19
+ {#if value}
20
+ {@const widgetType = widgetTypeRegistry.get(value)}
21
+ <h5>{widgetType.name}</h5>
22
+ {:else}
23
+ <h5>séléctionner</h5>
24
+ {/if}
25
+ </Button>
26
+ </DropdownMenu.Trigger>
27
+ <DropdownMenu.Content slot="content" width="250px">
28
+ {#each $widgetTypes as widgetType}
29
+ <WidgetTypeButton type={widgetType.type} onClick={() => {handleClick(widgetType.type)}}></WidgetTypeButton>
30
+ {/each}
31
+ </DropdownMenu.Content>
32
+ </DropdownMenu.Root>
@@ -0,0 +1,20 @@
1
+ import { sendRequest } from "hamzus-ui";
2
+ import { widgetTypeRegistry } from "./registry.svelte";
3
+
4
+ export function createWidgetType(config = {}) {
5
+ const widgetType = {
6
+ type: null,
7
+ name: null,
8
+ default_props:{},
9
+ components:{
10
+ config:null,
11
+ preview:null,
12
+ component:null,
13
+ }
14
+ };
15
+
16
+ Object.assign(widgetType, config);
17
+
18
+
19
+ return widgetType;
20
+ }
@@ -0,0 +1,14 @@
1
+ import { sendRequest } from "hamzus-ui";
2
+ import { widgetTypeRegistry } from "./registry.svelte";
3
+ import Bar from "./widgetTypes/Bar";
4
+ import Evolution from "./widgetTypes/Evolution";
5
+ import KPI from "./widgetTypes/KPI";
6
+ import List from "./widgetTypes/List";
7
+
8
+
9
+ export async function registerWidgetTypes() {
10
+ widgetTypeRegistry.register(Bar)
11
+ widgetTypeRegistry.register(Evolution)
12
+ widgetTypeRegistry.register(KPI)
13
+ widgetTypeRegistry.register(List)
14
+ }
@@ -0,0 +1,43 @@
1
+ import { writable, derived, get } from 'svelte/store';
2
+
3
+ function createWidgetTypeRegistry() {
4
+ const store = writable({});
5
+
6
+ const all = derived(store, ($widgetTypes) => Object.values($widgetTypes));
7
+
8
+ return {
9
+ subscribe: store.subscribe,
10
+
11
+ register(widgetGroup) {
12
+ store.update((widgetTypes) => ({
13
+ ...widgetTypes,
14
+ [widgetGroup.type]: widgetGroup
15
+ }));
16
+ },
17
+
18
+ unregister(type) {
19
+ store.update((widgetTypes) => {
20
+ const copy = { ...widgetTypes };
21
+
22
+ delete copy[type];
23
+
24
+ return copy;
25
+ });
26
+ },
27
+
28
+ get(type) {
29
+ return get(store)[type];
30
+ },
31
+
32
+ select(type) {
33
+ return derived(store, ($widgetTypes) => $widgetTypes[type]);
34
+ },
35
+
36
+ getAll() {
37
+ return all;
38
+ },
39
+
40
+ };
41
+ }
42
+
43
+ export const widgetTypeRegistry = createWidgetTypeRegistry();
@@ -0,0 +1,79 @@
1
+ <script>
2
+ import { ChartBar, ChartLine, sendRequest, Skeleton } from 'hamzus-ui';
3
+ import { frequencyText, operationText } from './text';
4
+ import { onMount } from 'svelte';
5
+
6
+ let {id = '', title = '', entityId = '', frequency = '', valueFieldId = '', dateFieldId = '', operation = ''} = $props()
7
+
8
+ let data = $state(null);
9
+ let previousTotal = $state(null);
10
+
11
+ onMount(async () => {
12
+ const request = await sendRequest({
13
+ path: '/get-widget-data',
14
+ data: {
15
+ widgetLinkId: id
16
+ }
17
+ });
18
+
19
+
20
+ data = request.data
21
+ });
22
+
23
+ function getRandomSizes() {
24
+ const sizes = [60, 120, 80];
25
+
26
+ return sizes[Math.floor(Math.random() * sizes.length)];
27
+ }
28
+
29
+ function getPercent() {
30
+ if (previousTotal === 0) {
31
+ if (total === 0) return 0;
32
+ return null; // augmentation non calculable
33
+ }
34
+ return ((total - previousTotal) / previousTotal) * 100;
35
+ }
36
+ </script>
37
+
38
+ <div class="kpi-container">
39
+ <div class="kpi">
40
+ <h4>{title}</h4>
41
+ {#if data === null}
42
+ <Skeleton style="width:{getRandomSizes()}px;height:32px;"></Skeleton>
43
+ {:else}
44
+ <ChartBar {data}
45
+ ></ChartBar>
46
+ {/if}
47
+ </div>
48
+ </div>
49
+
50
+ <style>
51
+ .kpi-container {
52
+ width: 100%;
53
+ height: 100%;
54
+ padding: var(--pad-m);
55
+ }
56
+
57
+ .kpi {
58
+ display: flex;
59
+ flex-direction: column;
60
+ row-gap: var(--pad-m);
61
+ padding: var(--pad-xxl);
62
+ width: 100%;
63
+ height: 100%;
64
+ background-color: var(--bg-blur);
65
+ border-radius: var(--radius-m);
66
+ }
67
+
68
+ .bottom {
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: space-between;
72
+ }
73
+
74
+ .right {
75
+ display: flex;
76
+ align-items: center;
77
+ column-gap: var(--pad-m);
78
+ }
79
+ </style>
@@ -0,0 +1,176 @@
1
+ <script>
2
+ import { Button, DropdownMenu, Input, sendRequest } from 'hamzus-ui';
3
+ import { frequencyText, frequencyTextForConfig } from './text';
4
+ import { entityRegistry } from '../../entityRegistry/registry.svelte';
5
+
6
+ let {id = null, save = () => {}} = $props()
7
+
8
+ let title = $state('');
9
+
10
+ const entities = entityRegistry.getAll()
11
+
12
+ let entityId = $state(null);
13
+ const entity = $derived(entityRegistry.get(entityId));
14
+
15
+ let frequency = $state('month'); // day | month | year
16
+ const frequencies = ['day', 'month', 'year'];
17
+
18
+ let valueFieldId = $state(null);
19
+ const valueField = $derived(entityRegistry.getField(valueFieldId));
20
+
21
+ let dateFieldId = $state(null);
22
+ const dateField = $derived(entityRegistry.getField(dateFieldId));
23
+ const dateFieldTypes = ['time-created_at', 'time-datetime', 'time-updated_at'];
24
+
25
+ let operation = 'count'; // count | sum | avg | min | max
26
+ const operations = ['count', 'sum', 'avg', 'min', 'max'];
27
+
28
+ function handleSelectEntity(entity) {
29
+ entityId = entity.id;
30
+
31
+ // parcourir les fields pour set auto le field de value et de date
32
+ for (const field of entity.fields) {
33
+ if (field.type.startsWith('number-') || field.type.startsWith('calculation-')) {
34
+ valueFieldId = field.id;
35
+ }
36
+ if (dateFieldTypes.includes(field.type)) {
37
+ dateFieldId = field.id;
38
+ }
39
+ }
40
+ }
41
+
42
+ async function handleSave() {
43
+ save({
44
+ id,
45
+ title,
46
+ entityId,
47
+ frequency,
48
+ valueFieldId,
49
+ dateFieldId,
50
+ operation
51
+ });
52
+ }
53
+ </script>
54
+
55
+ <div class="config">
56
+ <Input label="titre" bind:value={title} placeholder="exemple"></Input>
57
+ <h5>Entité</h5>
58
+ <DropdownMenu.Root direction="bottom">
59
+ <DropdownMenu.Trigger slot="trigger">
60
+ <Button variant="secondary">
61
+ <h5>{entity?.plural_name ?? 'choisissez une entité'}</h5>
62
+ </Button>
63
+ </DropdownMenu.Trigger>
64
+ <DropdownMenu.Content slot="content" width="250px">
65
+ {#each $entities as entity}
66
+ <Button
67
+ onClick={() => {
68
+ handleSelectEntity(entity);
69
+ }}
70
+ variant="ghost"
71
+ style="width:100%;"><h5>{entity.plural_name}</h5></Button
72
+ >
73
+ {/each}
74
+ </DropdownMenu.Content>
75
+ </DropdownMenu.Root>
76
+ {#if entity}
77
+ {@const availedValueFields = entity.fields.filter(
78
+ (field) => field.type.startsWith('number-') || field.type.startsWith('calculation-')
79
+ )}
80
+ {@const availedDateFields = entity.fields.filter((field) =>
81
+ dateFieldTypes.includes(field.type)
82
+ )}
83
+ <h5>Champs pour valeurs</h5>
84
+ <DropdownMenu.Root direction="bottom">
85
+ <DropdownMenu.Trigger slot="trigger">
86
+ <Button variant="secondary">
87
+ <h5>{valueField?.name ?? 'choisissez un champ pour valeur'}</h5>
88
+ </Button>
89
+ </DropdownMenu.Trigger>
90
+ <DropdownMenu.Content slot="content" width="250px">
91
+ {#if availedValueFields.length > 0}
92
+ {#each availedValueFields as field}
93
+ <Button
94
+ onClick={() => {
95
+ valueFieldId = field.id;
96
+ }}
97
+ variant="ghost"
98
+ style="width:100%;"><h5>{field.name}</h5></Button
99
+ >
100
+ {/each}
101
+ {:else}
102
+ <div class="nothing">
103
+ <h3>Aucun champs de valeur disponible</h3>
104
+ <p>
105
+ L'entité {entity?.plural_name} ne contient pas de champs nombre, permettant les calculs.
106
+ </p>
107
+ </div>
108
+ {/if}
109
+ </DropdownMenu.Content>
110
+ </DropdownMenu.Root>
111
+ <h5>Champs pour date</h5>
112
+ <DropdownMenu.Root direction="bottom">
113
+ <DropdownMenu.Trigger slot="trigger">
114
+ <Button variant="secondary">
115
+ <h5>{dateField?.name ?? 'choisissez un champ pour date'}</h5>
116
+ </Button>
117
+ </DropdownMenu.Trigger>
118
+ <DropdownMenu.Content slot="content" width="250px">
119
+ {#if availedDateFields.length > 0}
120
+ {#each availedDateFields as field}
121
+ <Button
122
+ onClick={() => {
123
+ dateFieldId = field.id;
124
+ }}
125
+ variant="ghost"
126
+ style="width:100%;"><h5>{field.name}</h5></Button
127
+ >
128
+ {/each}
129
+ {:else}
130
+ <div class="nothing">
131
+ <h3>Aucun champs de date disponible</h3>
132
+ <p>L'entité {entity?.plural_name} ne contient pas de champs de date.</p>
133
+ </div>
134
+ {/if}
135
+ </DropdownMenu.Content>
136
+ </DropdownMenu.Root>
137
+ <h5>fréquence</h5>
138
+ <DropdownMenu.Root direction="bottom">
139
+ <DropdownMenu.Trigger slot="trigger">
140
+ <Button variant="secondary">
141
+ <h5>{frequency ? frequencyTextForConfig[frequency] : 'choisissez une fréquence'}</h5>
142
+ </Button>
143
+ </DropdownMenu.Trigger>
144
+ <DropdownMenu.Content slot="content" width="250px">
145
+ {#each frequencies as frequencyEl}
146
+ <Button
147
+ onClick={() => {
148
+ frequency = frequencyEl;
149
+ }}
150
+ variant="ghost"
151
+ style="width:100%;"><h5>{frequencyTextForConfig[frequencyEl]}</h5></Button
152
+ >
153
+ {/each}
154
+ </DropdownMenu.Content>
155
+ </DropdownMenu.Root>
156
+ {/if}
157
+
158
+ <Button onClick={handleSave}>
159
+ <h5>enregistrer</h5>
160
+ </Button>
161
+ </div>
162
+
163
+ <style>
164
+ .config {
165
+ display: flex;
166
+ flex-direction: column;
167
+ row-gap: var(--pad-m);
168
+ }
169
+
170
+ .nothing {
171
+ display: flex;
172
+ flex-direction: column;
173
+ row-gap: var(--pad-m);
174
+ padding: var(--pad-m);
175
+ }
176
+ </style>
@@ -0,0 +1,13 @@
1
+ import ConfigBar from "./ConfigBar.svelte";
2
+ import Bar from "./Bar.svelte";
3
+ import { createWidgetType } from "../../createWidgetType";
4
+
5
+
6
+ export default createWidgetType({
7
+ type:"Bar",
8
+ name:"Graphique en bar",
9
+ components:{
10
+ config:ConfigBar,
11
+ component:Bar,
12
+ }
13
+ })