mountain-ui 1.0.55 → 1.0.56
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.
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/package.json +1 -1
- package/src/lib/components/Nothing.svelte +26 -0
- package/src/lib/registry/entityRegistry/components/EntitiesSelector.svelte +41 -0
- package/src/lib/registry/entityRegistry/components/EntityCard.svelte +2 -2
- package/src/lib/registry/entityRegistry/components/EntityFieldContainer.svelte +13 -0
- package/src/lib/registry/entityRegistry/components/EntityForm.svelte +141 -75
- package/src/lib/registry/entityRegistry/components/EntityPage.svelte +5 -147
- package/src/lib/registry/entityRegistry/components/EntryForm.svelte +102 -0
- package/src/lib/registry/entityRegistry/components/EntryPage.svelte +155 -0
- package/src/lib/registry/entityRegistry/components/FieldBinding.svelte +90 -0
- package/src/lib/registry/entityRegistry/components/FieldRow.svelte +71 -0
- package/src/lib/registry/entityRegistry/createEntity.js +6 -0
- package/src/lib/registry/entityRegistry/utils.js +15 -0
- package/src/lib/registry/entryActionRegistry/components/EntryActionButton.svelte +21 -0
- package/src/lib/registry/entryActionRegistry/components/EntryActionsButtons.svelte +18 -0
- package/src/lib/registry/entryActionRegistry/createEntryActionType.js +17 -0
- package/src/lib/registry/entryActionRegistry/registry.svelte.js +48 -0
- package/src/lib/registry/entryActionTypeRegistry/components/EntryActionProperties.svelte +42 -0
- package/src/lib/registry/entryActionTypeRegistry/components/EntryActionTypeCard.svelte +11 -0
- package/src/lib/registry/entryActionTypeRegistry/createEntryActionType.js +24 -0
- package/src/lib/registry/entryActionTypeRegistry/entryActionTypes/PrefillNewEntry/Card.svelte +20 -0
- package/src/lib/registry/entryActionTypeRegistry/entryActionTypes/PrefillNewEntry/Properties.svelte +147 -0
- package/src/lib/registry/entryActionTypeRegistry/entryActionTypes/PrefillNewEntry/component/Binding.svelte +103 -0
- package/src/lib/registry/entryActionTypeRegistry/entryActionTypes/PrefillNewEntry/component/BindingClone.svelte +103 -0
- package/src/lib/registry/entryActionTypeRegistry/entryActionTypes/PrefillNewEntry/index.js +77 -0
- package/src/lib/registry/entryActionTypeRegistry/registerDefaultEntryActionTypes.js +7 -0
- package/src/lib/registry/entryActionTypeRegistry/registry.svelte.js +48 -0
- package/src/lib/registry/fieldTypeRegistry/createFieldType.js +8 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/Lines/index.js +52 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/Link/index.js +3 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/Primary/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/calculation/CalculationColumn/index.js +2 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/calculation/CalculationLine/index.js +2 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/list/ListRadio/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/localisation/LocalisationLand/index.js +2 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/money/MoneyCurrency/index.js +2 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/number/NumberInt/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/number/float/NumberFloatDefault/index.js +2 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/number/float/NumberFloatPercent/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/number/float/NumberFloatPrice/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/text/TextTextarea/index.js +2 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/text/varchar/TextVarcharDefault/index.js +2 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/text/varchar/TextVarcharEmail/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/text/varchar/TextVarcharPassword/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/text/varchar/TextVarcharPhone/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/text/varchar/TextVarcharUrl/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeCreatedAt/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeDate/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeDatetime/index.js +2 -1
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeDay/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeHour/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeMonth/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeMonthOfYear/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeUpdatedAt/index.js +1 -0
- package/src/lib/registry/fieldTypeRegistry/fieldTypes/time/TimeYear/index.js +1 -0
- package/src/lib/registry/viewEntriesProfilRegistery/components/ViewEntriesProfilButton.svelte +1 -1
- package/src/lib/registry/viewEntriesProfilRegistery/components/ViewEntriesProfilComponent.svelte +1 -1
- package/src/routes/exemple/[project_normalized_name]/+layout.svelte +16 -2
- package/src/routes/exemple/[project_normalized_name]/[entity_slug]/[entry_id]/+page.svelte +70 -16
- package/src/routes/exemple/[project_normalized_name]/[entity_slug]/create/+page.svelte +19 -3
- package/src/routes/exemple/[project_normalized_name]/actions/+page.svelte +62 -0
- package/src/routes/exemple/[project_normalized_name]/entities/+layout.svelte +5 -0
- package/src/routes/exemple/[project_normalized_name]/entities/+page.svelte +70 -0
- package/src/routes/exemple/[project_normalized_name]/entities/[entity_id]/+page.svelte +8 -0
- package/src/routes/exemple/[project_normalized_name]/entities/create/+page.svelte +6 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { entityRegistry } from '../registry.svelte';
|
|
4
|
+
import FieldView from './FieldView.svelte';
|
|
5
|
+
import { sendRequest, toast } from 'hamzus-ui';
|
|
6
|
+
|
|
7
|
+
let { entityId, entryId, children, ctx = $bindable(null) } = $props();
|
|
8
|
+
|
|
9
|
+
let mounted = false;
|
|
10
|
+
|
|
11
|
+
const entity = $derived(entityRegistry.select(entityId));
|
|
12
|
+
|
|
13
|
+
$effect(() => {
|
|
14
|
+
getData(entityId, entryId);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
onMount(() => {
|
|
18
|
+
getData(entityId, entryId, true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
async function getData(entityId, entryId, isMounting = false) {
|
|
22
|
+
if (!isMounting && !mounted) return;
|
|
23
|
+
|
|
24
|
+
const request = await sendRequest({
|
|
25
|
+
path: '/get-entry',
|
|
26
|
+
data: {
|
|
27
|
+
entityId: entityId,
|
|
28
|
+
entryId: entryId,
|
|
29
|
+
idMode: true
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (request.statusType === 'error') {
|
|
34
|
+
if (request.statusCode === 403) {
|
|
35
|
+
ctx = 403;
|
|
36
|
+
} else {
|
|
37
|
+
ctx = 'error';
|
|
38
|
+
}
|
|
39
|
+
toast.error({
|
|
40
|
+
title: 'Erreur !',
|
|
41
|
+
description: request.message
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ctx = request.data;
|
|
47
|
+
|
|
48
|
+
mounted = true;
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
{#if ctx !== null}
|
|
53
|
+
{#if ctx === 403}
|
|
54
|
+
<div class="error">
|
|
55
|
+
<svg
|
|
56
|
+
width="24"
|
|
57
|
+
height="24"
|
|
58
|
+
viewBox="0 0 24 24"
|
|
59
|
+
fill="none"
|
|
60
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
61
|
+
>
|
|
62
|
+
<path
|
|
63
|
+
opacity="0.4"
|
|
64
|
+
d="M10.9608 2.10989L5.46078 4.16989C4.41078 4.56989 3.55078 5.80989 3.55078 6.93989V15.0399C3.55078 15.8499 4.08078 16.9199 4.73078 17.3999L10.2308 21.5099C11.2008 22.2399 12.7908 22.2399 13.7608 21.5099L19.2608 17.3999C19.9108 16.9099 20.4408 15.8499 20.4408 15.0399V6.93989C20.4408 5.81989 19.5808 4.56988 18.5308 4.17988L13.0308 2.11989C12.4708 1.89989 11.5308 1.89989 10.9608 2.10989Z"
|
|
65
|
+
fill="#292D32"
|
|
66
|
+
/>
|
|
67
|
+
<path
|
|
68
|
+
d="M14.5 10.5C14.5 9.12 13.38 8 12 8C10.62 8 9.5 9.12 9.5 10.5C9.5 11.62 10.24 12.55 11.25 12.87V15.5C11.25 15.91 11.59 16.25 12 16.25C12.41 16.25 12.75 15.91 12.75 15.5V12.87C13.76 12.55 14.5 11.62 14.5 10.5Z"
|
|
69
|
+
fill="#292D32"
|
|
70
|
+
/>
|
|
71
|
+
</svg>
|
|
72
|
+
|
|
73
|
+
<h3>Vous n'avez pas accès a cet ressource</h3>
|
|
74
|
+
<p>Vous ne pouvez pas consulté les element lié a cette entité !</p>
|
|
75
|
+
</div>
|
|
76
|
+
{:else if ctx === 'error'}
|
|
77
|
+
<div class="error">
|
|
78
|
+
<svg
|
|
79
|
+
width="24"
|
|
80
|
+
height="24"
|
|
81
|
+
viewBox="0 0 24 24"
|
|
82
|
+
fill="none"
|
|
83
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
84
|
+
>
|
|
85
|
+
<path
|
|
86
|
+
opacity="0.4"
|
|
87
|
+
d="M21.7605 15.92L15.3605 4.4C14.5005 2.85 13.3105 2 12.0005 2C10.6905 2 9.50047 2.85 8.64047 4.4L2.24047 15.92C1.43047 17.39 1.34047 18.8 1.99047 19.91C2.64047 21.02 3.92047 21.63 5.60047 21.63H18.4005C20.0805 21.63 21.3605 21.02 22.0105 19.91C22.6605 18.8 22.5705 17.38 21.7605 15.92Z"
|
|
88
|
+
fill="#292D32"
|
|
89
|
+
/>
|
|
90
|
+
<path
|
|
91
|
+
d="M12 14.75C11.59 14.75 11.25 14.41 11.25 14V9C11.25 8.59 11.59 8.25 12 8.25C12.41 8.25 12.75 8.59 12.75 9V14C12.75 14.41 12.41 14.75 12 14.75Z"
|
|
92
|
+
fill="#292D32"
|
|
93
|
+
/>
|
|
94
|
+
<path
|
|
95
|
+
d="M12 18.0001C11.94 18.0001 11.87 17.9901 11.8 17.9801C11.74 17.9701 11.68 17.9501 11.62 17.9201C11.56 17.9001 11.5 17.8701 11.44 17.8301C11.39 17.7901 11.34 17.7501 11.29 17.7101C11.11 17.5201 11 17.2601 11 17.0001C11 16.7401 11.11 16.4801 11.29 16.2901C11.34 16.2501 11.39 16.2101 11.44 16.1701C11.5 16.1301 11.56 16.1001 11.62 16.0801C11.68 16.0501 11.74 16.0301 11.8 16.0201C11.93 15.9901 12.07 15.9901 12.19 16.0201C12.26 16.0301 12.32 16.0501 12.38 16.0801C12.44 16.1001 12.5 16.1301 12.56 16.1701C12.61 16.2101 12.66 16.2501 12.71 16.2901C12.89 16.4801 13 16.7401 13 17.0001C13 17.2601 12.89 17.5201 12.71 17.7101C12.66 17.7501 12.61 17.7901 12.56 17.8301C12.5 17.8701 12.44 17.9001 12.38 17.9201C12.32 17.9501 12.26 17.9701 12.19 17.9801C12.13 17.9901 12.06 18.0001 12 18.0001Z"
|
|
96
|
+
fill="#292D32"
|
|
97
|
+
/>
|
|
98
|
+
</svg>
|
|
99
|
+
|
|
100
|
+
<h3>Une erreur est survenue !</h3>
|
|
101
|
+
<p>Impossible de récuperer l'entrée !</p>
|
|
102
|
+
</div>
|
|
103
|
+
{:else if $entity}
|
|
104
|
+
{@const primaryField = $entity.getPrimaryField()}
|
|
105
|
+
<div class="form">
|
|
106
|
+
<div class="title">
|
|
107
|
+
<h1>{$entity.symbol}{ctx?.[primaryField.id].flat}</h1>
|
|
108
|
+
{#if children}
|
|
109
|
+
{@render children()}
|
|
110
|
+
{/if}
|
|
111
|
+
</div>
|
|
112
|
+
{#each $entity.fields as field}
|
|
113
|
+
<FieldView id={field.id} entityId={$entity.id} value={ctx?.[field.id] ?? null}></FieldView>
|
|
114
|
+
{/each}
|
|
115
|
+
</div>
|
|
116
|
+
{/if}
|
|
117
|
+
{/if}
|
|
118
|
+
|
|
119
|
+
<style>
|
|
120
|
+
.loader {
|
|
121
|
+
display: flex;
|
|
122
|
+
align-items: center;
|
|
123
|
+
justify-content: center;
|
|
124
|
+
padding: 60px var(--pad-m);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.error {
|
|
128
|
+
padding: 60px var(--pad-m);
|
|
129
|
+
display: flex;
|
|
130
|
+
flex-direction: column;
|
|
131
|
+
align-items: center;
|
|
132
|
+
row-gap: var(--pad-m);
|
|
133
|
+
}
|
|
134
|
+
.error > svg {
|
|
135
|
+
width: 60px;
|
|
136
|
+
height: auto;
|
|
137
|
+
}
|
|
138
|
+
.error > svg path {
|
|
139
|
+
fill: var(--red);
|
|
140
|
+
}
|
|
141
|
+
.title {
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
justify-content: space-between;
|
|
145
|
+
width: min(100%, 900px);
|
|
146
|
+
margin-bottom: 20px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.form {
|
|
150
|
+
display: flex;
|
|
151
|
+
flex-direction: column;
|
|
152
|
+
align-items: center;
|
|
153
|
+
width: 100%;
|
|
154
|
+
}
|
|
155
|
+
</style>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { get } from 'svelte/store';
|
|
3
|
+
import { entityRegistry } from '../registry.svelte';
|
|
4
|
+
import FieldButton from './FieldButton.svelte';
|
|
5
|
+
import { Button, DropdownMenu } from 'hamzus-ui';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
allowedType = (field) => {
|
|
9
|
+
return true;
|
|
10
|
+
},
|
|
11
|
+
onChange = (fieldId)=>{},
|
|
12
|
+
// allowRecursive = false,
|
|
13
|
+
// allowConstant = false,
|
|
14
|
+
restrictedEntityId = null,
|
|
15
|
+
fieldId = $bindable(null),
|
|
16
|
+
// fieldPath = null,
|
|
17
|
+
// constantId = null
|
|
18
|
+
} = $props();
|
|
19
|
+
|
|
20
|
+
const activeField = $derived.by(() => {
|
|
21
|
+
if (fieldId !== null) {
|
|
22
|
+
return entityRegistry.getField(fieldId);
|
|
23
|
+
}
|
|
24
|
+
// if (fieldPath !== null) {
|
|
25
|
+
// return entityRegistry.getField(fieldPath.at(-1));
|
|
26
|
+
// }
|
|
27
|
+
return null;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const availedFields = $derived.by(() => {
|
|
31
|
+
let allowedFieldIds = [];
|
|
32
|
+
if (restrictedEntityId) {
|
|
33
|
+
const entity = entityRegistry.get(restrictedEntityId);
|
|
34
|
+
for (const field of entity.fields) {
|
|
35
|
+
if (!allowedType(field)) continue;
|
|
36
|
+
allowedFieldIds.push(field.id);
|
|
37
|
+
}
|
|
38
|
+
return allowedFieldIds;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const allEntities = entityRegistry.getAll();
|
|
42
|
+
for (const entity of get(allEntities)) {
|
|
43
|
+
for (const field of entity.fields) {
|
|
44
|
+
if (!allowedType(field)) continue;
|
|
45
|
+
allowedFieldIds.push(field.id);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return allowedFieldIds;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
function handleChange(newFieldId) {
|
|
53
|
+
fieldId = newFieldId
|
|
54
|
+
|
|
55
|
+
onChange(fieldId)
|
|
56
|
+
}
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<DropdownMenu.Root direction="bottom">
|
|
60
|
+
<DropdownMenu.Trigger slot="trigger">
|
|
61
|
+
{#if activeField}
|
|
62
|
+
<FieldButton variant="secondary" id={activeField.id}></FieldButton>
|
|
63
|
+
{:else}
|
|
64
|
+
<Button variant="secondary">
|
|
65
|
+
<h5>selectionner un champs</h5>
|
|
66
|
+
</Button>
|
|
67
|
+
{/if}
|
|
68
|
+
</DropdownMenu.Trigger>
|
|
69
|
+
<DropdownMenu.Content slot="content" width="250px">
|
|
70
|
+
{#if !availedFields || availedFields.length <= 0}
|
|
71
|
+
<div class="nothing">
|
|
72
|
+
<h4>Aucun champs disponible !</h4>
|
|
73
|
+
<p>Aucun champs ne peut être attaché !</p>
|
|
74
|
+
</div>
|
|
75
|
+
{:else}
|
|
76
|
+
{#each availedFields as availedField}
|
|
77
|
+
<FieldButton onClick={()=>{handleChange(availedField)}} style="width:100%;" id={availedField}></FieldButton>
|
|
78
|
+
{/each}
|
|
79
|
+
{/if}
|
|
80
|
+
</DropdownMenu.Content>
|
|
81
|
+
</DropdownMenu.Root>
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
<style>
|
|
85
|
+
.nothing {
|
|
86
|
+
display: flex;
|
|
87
|
+
flex-direction: column;
|
|
88
|
+
row-gap: var(--pad-m);
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import FieldTypeIcon from '../../fieldTypeRegistry/components/FieldTypeIcon.svelte';
|
|
3
|
+
import { fieldTypeRegistry } from '../../fieldTypeRegistry/registry.svelte';
|
|
4
|
+
import { Button } from 'hamzus-ui';
|
|
5
|
+
import { entityRegistry } from '../registry.svelte';
|
|
6
|
+
import FieldIsSecretIcon from './FieldIsSecretIcon.svelte';
|
|
7
|
+
import FieldIsUniqueIcon from './FieldIsUniqueIcon.svelte';
|
|
8
|
+
import FieldIsRequiredIcon from './FieldIsRequiredIcon.svelte';
|
|
9
|
+
|
|
10
|
+
let { id, entityId = null, ...props } = $props();
|
|
11
|
+
|
|
12
|
+
const field = $derived(entityRegistry.selectField(id, entityId));
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
{#if $field}
|
|
16
|
+
<div class="row">
|
|
17
|
+
<div class="top">
|
|
18
|
+
<div class="left">
|
|
19
|
+
<FieldTypeIcon type={$field.type}></FieldTypeIcon>
|
|
20
|
+
<h4>{$field.name}</h4>
|
|
21
|
+
<div class="icons">
|
|
22
|
+
{#if $field.is_secret}
|
|
23
|
+
<FieldIsSecretIcon></FieldIsSecretIcon>
|
|
24
|
+
{/if}
|
|
25
|
+
{#if $field.is_unique}
|
|
26
|
+
<FieldIsUniqueIcon></FieldIsUniqueIcon>
|
|
27
|
+
{/if}
|
|
28
|
+
{#if $field.is_required}
|
|
29
|
+
<FieldIsRequiredIcon></FieldIsRequiredIcon>
|
|
30
|
+
{/if}
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="right">
|
|
34
|
+
<slot name="right" />
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="bottom">
|
|
38
|
+
<slot name="bottom"/>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
{/if}
|
|
42
|
+
|
|
43
|
+
<style>
|
|
44
|
+
.row {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
row-gap: var(--pad-xs);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.row:not(:last-child) {
|
|
51
|
+
border-bottom: 1px solid var(--stroke);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.top {
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: space-between;
|
|
58
|
+
padding: var(--pad-m);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.icons,
|
|
62
|
+
.left {
|
|
63
|
+
display: flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
column-gap: var(--pad-m);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.bottom:has( :global(:first-child)) {
|
|
69
|
+
background-color: var(--bg-blur);
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { sanitizePluralNameToNormalizedName, sanitizePluralNameToSlug } from "./utils";
|
|
2
|
+
|
|
1
3
|
export function createEntity(config = {}) {
|
|
2
4
|
const entity = {
|
|
3
5
|
id: null,
|
|
@@ -36,5 +38,9 @@ export function createEntity(config = {}) {
|
|
|
36
38
|
|
|
37
39
|
entity.getPrimaryField = () => entity.fields.find((field) => field.type === "primary");
|
|
38
40
|
|
|
41
|
+
entity.sanitizePluralNameToSlug = sanitizePluralNameToSlug;
|
|
42
|
+
entity.sanitizePluralNameToNormalizedName = sanitizePluralNameToNormalizedName;
|
|
43
|
+
|
|
39
44
|
return entity;
|
|
40
45
|
}
|
|
46
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
function sanitizeString(str, separator) {
|
|
3
|
+
return str
|
|
4
|
+
.toLowerCase() // mettre tout en minuscule
|
|
5
|
+
.normalize("NFD") // décompose les lettres accentuées
|
|
6
|
+
.replace(/[^a-z\s]/g, '') // garde seulement les lettres minuscules et les espaces
|
|
7
|
+
.replace(/\s+/g, separator); // remplace les espaces par des tirets du bas
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function sanitizePluralNameToNormalizedName(pluralName) {
|
|
11
|
+
return sanitizeString(pluralName, "_")
|
|
12
|
+
}
|
|
13
|
+
export function sanitizePluralNameToSlug(pluralName) {
|
|
14
|
+
return sanitizeString(pluralName, "-")
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Button } from "hamzus-ui";
|
|
3
|
+
import { entryActionRegistry } from "../registry.svelte";
|
|
4
|
+
import { entryActionTypeRegistry } from "../../entryActionTypeRegistry/registry.svelte";
|
|
5
|
+
import { entityRegistry } from "../../entityRegistry/registry.svelte";
|
|
6
|
+
|
|
7
|
+
let {id, variant="ghost", entityId, entry, ...props} = $props()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const entity = $derived(entityRegistry.get(entityId))
|
|
12
|
+
const entryAction = $derived(entryActionRegistry.select(id))
|
|
13
|
+
const entryActionType = $derived($entryAction.type ? entryActionTypeRegistry.select($entryAction.type) : null)
|
|
14
|
+
console.log($entryActionType);
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#if entity && $entryAction && $entryActionType && $entryActionType.canPerformAction(entity, entry, $entryAction.props)}
|
|
18
|
+
<Button {variant} onClick={()=>{$entryActionType.action(entity, entry, $entryAction.props)}} {...props}>
|
|
19
|
+
<h5>{$entryAction.name}</h5>
|
|
20
|
+
</Button>
|
|
21
|
+
{/if}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Button, DropdownMenu } from 'hamzus-ui';
|
|
3
|
+
import { entryActionRegistry } from '../registry.svelte';
|
|
4
|
+
import EntryActionButton from './EntryActionButton.svelte';
|
|
5
|
+
import { entityRegistry } from '../../entityRegistry/registry.svelte';
|
|
6
|
+
|
|
7
|
+
let { entityId, entry, ...props } = $props();
|
|
8
|
+
|
|
9
|
+
const entity = $derived(entityRegistry.get(entityId));
|
|
10
|
+
|
|
11
|
+
const allActions = entryActionRegistry.getAll();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{#if $allActions && entity}
|
|
15
|
+
{#each $allActions as action}
|
|
16
|
+
<EntryActionButton id={action.id} entityId={entity.id} {entry}></EntryActionButton>
|
|
17
|
+
{/each}
|
|
18
|
+
{/if}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { writable, derived, get } from 'svelte/store';
|
|
2
|
+
|
|
3
|
+
function createEntryActionRegistry() {
|
|
4
|
+
const store = writable({});
|
|
5
|
+
|
|
6
|
+
const all = derived(store, ($entryActions) => Object.values($entryActions));
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
subscribe: store.subscribe,
|
|
10
|
+
|
|
11
|
+
register(entryAction) {
|
|
12
|
+
store.update((entryActions) => ({
|
|
13
|
+
...entryActions,
|
|
14
|
+
[entryAction.id]: entryAction
|
|
15
|
+
}));
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
unregister(id) {
|
|
19
|
+
store.update((entryActions) => {
|
|
20
|
+
const copy = { ...entryActions };
|
|
21
|
+
|
|
22
|
+
delete copy[id];
|
|
23
|
+
|
|
24
|
+
return copy;
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
unregisterAll() {
|
|
29
|
+
store.update((entryActions) => {
|
|
30
|
+
return {};
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
get(id) {
|
|
35
|
+
return get(store)[id];
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
select(id) {
|
|
39
|
+
return derived(store, ($entryActions) => $entryActions[id]);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
getAll() {
|
|
43
|
+
return all;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const entryActionRegistry = createEntryActionRegistry();
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Input } from 'hamzus-ui';
|
|
3
|
+
import { entryActionTypeRegistry } from '../registry.svelte';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
entryActionType,
|
|
7
|
+
name = $bindable(''),
|
|
8
|
+
props = $bindable(undefined),
|
|
9
|
+
entityId = $bindable(null),
|
|
10
|
+
...restProps
|
|
11
|
+
} = $props();
|
|
12
|
+
|
|
13
|
+
const entryActionTypeData = $derived(entryActionTypeRegistry.select(entryActionType));
|
|
14
|
+
|
|
15
|
+
$effect(()=>{
|
|
16
|
+
entityId = $entryActionTypeData?.getEntityIdFromProps(props) ?? null
|
|
17
|
+
});
|
|
18
|
+
$effect(() => {
|
|
19
|
+
if (!$entryActionTypeData) return;
|
|
20
|
+
props = {
|
|
21
|
+
...$entryActionTypeData.defaultProps
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
{#if $entryActionTypeData && props !== null}
|
|
27
|
+
<div class="props">
|
|
28
|
+
<Input label="nom" bind:value={name} placeholder="nom de l'action" />
|
|
29
|
+
<svelte:component this={$entryActionTypeData.components.properties} bind:props {...restProps}
|
|
30
|
+
></svelte:component>
|
|
31
|
+
</div>
|
|
32
|
+
{/if}
|
|
33
|
+
|
|
34
|
+
<style>
|
|
35
|
+
.props {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
padding: var(--pad-m);
|
|
39
|
+
row-gap: var(--pad-m);
|
|
40
|
+
width: 100%;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { entryActionTypeRegistry } from '../registry.svelte';
|
|
3
|
+
|
|
4
|
+
let { type, ...props } = $props();
|
|
5
|
+
|
|
6
|
+
const entryActionType = $derived(entryActionTypeRegistry.select(type));
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
{#if $entryActionType}
|
|
10
|
+
<svelte:component this={$entryActionType.components.card} name={$entryActionType.name} description={$entryActionType.description} {...props}></svelte:component>
|
|
11
|
+
{/if}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export function createEntryActionType(config = {}) {
|
|
4
|
+
const element = {
|
|
5
|
+
type: null,
|
|
6
|
+
name: "",
|
|
7
|
+
description: "",
|
|
8
|
+
defaultProps:{},
|
|
9
|
+
getEntityIdFromProps:(props)=>{},
|
|
10
|
+
canPerformAction:(entity, entry, props)=>{},
|
|
11
|
+
action:(entity, entry, props)=>{},
|
|
12
|
+
components: {
|
|
13
|
+
button:null,
|
|
14
|
+
properties:null,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
Object.assign(element, config);
|
|
19
|
+
|
|
20
|
+
// element.test = () => {};
|
|
21
|
+
|
|
22
|
+
return element;
|
|
23
|
+
}
|
|
24
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Button } from "hamzus-ui";
|
|
3
|
+
|
|
4
|
+
let {variant="outline", name, description,style, ...props} = $props()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<Button {variant} style="border-radius:var(--radius-xl);padding:var(--pad-xl) var(--pad-xxl);{style}" {...props}>
|
|
8
|
+
<div class="btn">
|
|
9
|
+
<h4>{name}</h4>
|
|
10
|
+
<p>{description}</p>
|
|
11
|
+
</div>
|
|
12
|
+
</Button>
|
|
13
|
+
|
|
14
|
+
<style>
|
|
15
|
+
.btn {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
align-items: baseline;
|
|
19
|
+
}
|
|
20
|
+
</style>
|