@isoftdata/svelte-user-configuration 1.3.3 → 2.0.0

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.
@@ -1,99 +1,182 @@
1
- <script>import { getContext } from "svelte";
2
- import camelCase from "just-camel-case";
3
- import Icon from "@isoftdata/svelte-icon";
4
- import Button from "@isoftdata/svelte-button";
5
- import Select from "@isoftdata/svelte-select";
6
- import { getEventValue } from "@isoftdata/browser-event";
7
- import { Table, Td } from "@isoftdata/svelte-table";
8
- import { translate as defaultTranslate } from "@isoftdata/utility-string";
9
- const { t: translate } = getContext("i18next") || { t: defaultTranslate };
10
- export let permissions;
11
- export let siteLabel = "Site";
12
- export let permissionValueChange = void 0;
13
- export let icon = "user-lock";
14
- export let cardHeaderTitle = translate("common:permissions", "Permissions");
15
- export let permissionValueMap = /* @__PURE__ */ new Map();
16
- export let groupPermissionValueMap = void 0;
17
- let computedPermissions = [];
18
- let selectedPermissionIds = /* @__PURE__ */ new Set();
19
- let selectedPermissionValue = null;
20
- const permissionColumns = getColumns(groupPermissionValueMap);
21
- const permissionValueList = {
22
- NONE: { label: translate("common:permissionLevel.none", "None"), value: "NONE", color: "danger" },
23
- SITE: { label: translate(`common:permissionLevel.${siteLabel.toLowerCase()}`, siteLabel), value: "SITE", color: "primary" },
24
- GLOBAL: { label: translate("common:permissionLevel.global", "Global"), value: "GLOBAL", color: "success" }
25
- };
26
- function getColumns(groupPermissionValueMap2) {
27
- let columns = [
28
- { property: "value", name: groupPermissionValueMap2 ? translate("common:user", "User") : translate("common:permission", "Permission"), width: "1rem" },
29
- { property: "category", name: translate("common:category", "Category") },
30
- { property: "displayName", name: translate("common:name", "Name") }
31
- ];
32
- if (groupPermissionValueMap2) {
33
- columns.splice(
34
- 1,
35
- 0,
36
- { property: "groupValue", name: translate("common:group", "Group"), align: "center", width: "1rem", minWidth: "25%" },
37
- { property: "computedValue", name: translate("common:access", "Access"), align: "center", width: "1rem", minWidth: "25%" }
38
- );
39
- }
40
- return columns;
41
- }
42
- function selectPermissions(permissionId) {
43
- selectedPermissionIds.has(permissionId) ? selectedPermissionIds.delete(permissionId) : selectedPermissionIds.add(permissionId);
44
- selectedPermissionIds = selectedPermissionIds;
45
- }
46
- function selectAndDeselectAllPermissions() {
47
- if (selectedPermissionIds.size === computedPermissions.length) {
48
- selectedPermissionIds.clear();
49
- selectedPermissionValue = null;
50
- } else {
51
- selectedPermissionIds = new Set(permissions.map((permission) => permission.id));
52
- }
53
- selectedPermissionIds = selectedPermissionIds;
54
- }
55
- const getButtonColor = (optionValue, permissionValue) => optionValue === permissionValue ? permissionValueList[optionValue].color : "outline-secondary";
56
- const isValidPermissionValue = (value) => Object.keys(permissionValueList).includes(value);
57
- async function updatePermissionValues(event, permissionIds) {
58
- const newValue = getEventValue(event);
59
- if (isValidPermissionValue(newValue)) {
60
- const permissionIdsArray = Array.from(permissionIds);
61
- for (const id of permissionIdsArray) {
62
- permissionValueMap.set(id, newValue);
63
- }
64
- permissionValueMap = permissionValueMap;
65
- await permissionValueChange?.({
66
- value: newValue,
67
- permissionIds: permissionIdsArray
68
- });
69
- }
70
- }
71
- function getComputedPermissions(permissions2, permissionValueMap2, groupPermissionValueMap2) {
72
- return permissions2.map((permission) => {
73
- const value = permissionValueMap2.get(permission.id) ?? "NONE";
74
- const groupValue = groupPermissionValueMap2?.get(permission.id);
75
- return {
76
- ...permission,
77
- displayName: translate(`permissions:${camelCase(permission.codeName)}.displayName`, permission.displayName),
78
- category: translate(`permissions:categories.${camelCase(permission.category)}`, permission.category),
79
- value,
80
- groupValue,
81
- computedValue: value === "NONE" && groupValue || value === "SITE" && groupValue === "GLOBAL" ? groupValue : value
82
- };
83
- });
84
- }
85
- $: computedPermissions = getComputedPermissions(permissions, permissionValueMap, groupPermissionValueMap);
1
+ <script lang="ts">
2
+ import type { i18n } from 'i18next'
3
+ import type { Merge } from 'type-fest'
4
+ import type { IconName, SiteLabel, HTMLDivAttributes } from './'
5
+ import type { Snippet } from 'svelte'
6
+
7
+ import { getContext } from 'svelte'
8
+ import camelCase from 'just-camel-case'
9
+ import Icon from '@isoftdata/svelte-icon'
10
+ import Button from '@isoftdata/svelte-button'
11
+ import Select from '@isoftdata/svelte-select'
12
+ import { getEventValue } from '@isoftdata/browser-event'
13
+ import { Table, Td, type Column } from '@isoftdata/svelte-table'
14
+ import { translate as defaultTranslate } from '@isoftdata/utility-string'
15
+ import { SvelteSet, SvelteMap } from 'svelte/reactivity'
16
+
17
+ const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
18
+
19
+ type Permission = {
20
+ id: number
21
+ displayName: string
22
+ category: string
23
+ codeName: string
24
+ }
25
+ type ComputedPermission = Merge<
26
+ Permission,
27
+ { value: PermissionValue; groupValue?: PermissionValue | undefined; computedValue?: PermissionValue }
28
+ >
29
+ type ComputedPermissionColumns = Array<Column<ComputedPermission>>
30
+ type PermissionValue = keyof typeof permissionValueList
31
+ type PermissionValueMap = Map<number, PermissionValue>
32
+
33
+ interface Props extends HTMLDivAttributes {
34
+ permissions: Array<Permission>
35
+ siteLabel?: SiteLabel
36
+ permissionValueChange?:
37
+ | ((change: { value: PermissionValue; permissionIds: Array<number> }) => void | Promise<void>)
38
+ | undefined
39
+ icon?: IconName
40
+ cardHeaderTitle?: string
41
+ permissionValueMap: PermissionValueMap
42
+ groupPermissionValueMap?: PermissionValueMap | undefined
43
+ children?: Snippet
44
+ }
45
+
46
+ let {
47
+ permissions,
48
+ siteLabel = 'Site',
49
+ permissionValueChange = undefined,
50
+ icon = 'user-lock',
51
+ cardHeaderTitle = translate('common:permissions', 'Permissions'),
52
+ permissionValueMap = $bindable(new SvelteMap()),
53
+ groupPermissionValueMap = undefined,
54
+ children,
55
+ ...rest
56
+ }: Props = $props()
57
+
58
+ let selectedPermissionIds: SvelteSet<number> = $state(new SvelteSet())
59
+ let selectedPermissionValue: string | null = $state(null)
60
+
61
+ const permissionColumns: ComputedPermissionColumns = getColumns(groupPermissionValueMap)
62
+ const permissionValueList = {
63
+ NONE: { label: translate('common:permissionLevel.none', 'None'), value: 'NONE', color: 'danger' },
64
+ SITE: {
65
+ label: translate(`common:permissionLevel.${siteLabel.toLowerCase()}`, siteLabel),
66
+ value: 'SITE',
67
+ color: 'primary',
68
+ },
69
+ GLOBAL: { label: translate('common:permissionLevel.global', 'Global'), value: 'GLOBAL', color: 'success' },
70
+ }
71
+
72
+ function getColumns(groupPermissionValueMap: PermissionValueMap | undefined): ComputedPermissionColumns {
73
+ let columns: ComputedPermissionColumns = [
74
+ {
75
+ property: 'value',
76
+ name: groupPermissionValueMap ? translate('common:user', 'User') : translate('common:permission', 'Permission'),
77
+ width: '1rem',
78
+ },
79
+ { property: 'category', name: translate('common:category', 'Category') },
80
+ { property: 'displayName', name: translate('common:name', 'Name') },
81
+ ]
82
+
83
+ if (groupPermissionValueMap) {
84
+ columns.splice(
85
+ 1,
86
+ 0,
87
+ {
88
+ property: 'groupValue',
89
+ name: translate('common:group', 'Group'),
90
+ align: 'center',
91
+ width: '1rem',
92
+ minWidth: '25%',
93
+ },
94
+ {
95
+ property: 'computedValue',
96
+ name: translate('common:access', 'Access'),
97
+ align: 'center',
98
+ width: '1rem',
99
+ minWidth: '25%',
100
+ },
101
+ )
102
+ }
103
+
104
+ return columns
105
+ }
106
+
107
+ function selectPermissions(permissionId: number) {
108
+ selectedPermissionIds.has(permissionId)
109
+ ? selectedPermissionIds.delete(permissionId)
110
+ : selectedPermissionIds.add(permissionId)
111
+ }
112
+
113
+ function selectAndDeselectAllPermissions() {
114
+ if (selectedPermissionIds.size === computedPermissions.length) {
115
+ selectedPermissionIds.clear()
116
+ selectedPermissionValue = null
117
+ } else {
118
+ selectedPermissionIds = new SvelteSet(permissions.map(permission => permission.id))
119
+ }
120
+ }
121
+
122
+ const getButtonColor = (optionValue: string, permissionValue: PermissionValue) =>
123
+ optionValue === permissionValue ? permissionValueList[optionValue].color : 'outline-secondary'
124
+
125
+ const isValidPermissionValue = (value: string): value is PermissionValue =>
126
+ Object.keys(permissionValueList).includes(value)
127
+
128
+ async function updatePermissionValues(event: Event, permissionIds: SvelteSet<number>) {
129
+ const newValue = getEventValue(event)
130
+ if (isValidPermissionValue(newValue)) {
131
+ const permissionIdsArray = Array.from(permissionIds)
132
+ for (const id of permissionIdsArray) {
133
+ permissionValueMap.set(id, newValue)
134
+ }
135
+ permissionValueMap = permissionValueMap
136
+ await permissionValueChange?.({
137
+ value: newValue,
138
+ permissionIds: permissionIdsArray,
139
+ })
140
+ }
141
+ }
142
+
143
+ function getComputedPermissions(
144
+ permissions: Array<Permission>,
145
+ permissionValueMap: PermissionValueMap,
146
+ groupPermissionValueMap: PermissionValueMap | undefined,
147
+ ): Array<ComputedPermission> {
148
+ return permissions.map(permission => {
149
+ const value = permissionValueMap.get(permission.id) ?? 'NONE'
150
+ const groupValue = groupPermissionValueMap?.get(permission.id)
151
+
152
+ return {
153
+ ...permission,
154
+ displayName: translate(`permissions:${camelCase(permission.codeName)}.displayName`, permission.displayName),
155
+ category: translate(`permissions:categories.${camelCase(permission.category)}`, permission.category),
156
+ value,
157
+ groupValue,
158
+ computedValue:
159
+ (value === 'NONE' && groupValue) || (value === 'SITE' && groupValue === 'GLOBAL') ? groupValue : value,
160
+ }
161
+ })
162
+ }
163
+
164
+ let computedPermissions = $derived.by(() =>
165
+ getComputedPermissions(permissions, permissionValueMap, groupPermissionValueMap),
166
+ )
167
+
168
+ $inspect(computedPermissions)
86
169
  </script>
87
170
 
88
171
  <div
89
172
  class="card"
90
- {...$$restProps}
173
+ {...rest}
91
174
  >
92
175
  <div class="card-header">
93
176
  <h5 class="mb-0">
94
177
  <Icon
95
178
  {icon}
96
- class="mr-1"
179
+ class="mr-1 me-1"
97
180
  />
98
181
  {cardHeaderTitle}
99
182
  </h5>
@@ -108,51 +191,57 @@ $: computedPermissions = getComputedPermissions(permissions, permissionValueMap,
108
191
  columns={permissionColumns}
109
192
  responsive
110
193
  filterEnabled
111
- let:row={permission}
112
194
  >
113
- <tr
114
- on:click={() => selectPermissions(permission.id)}
115
- class:table-primary={selectedPermissionIds.has(permission.id)}
116
- class="cursor-pointer"
117
- >
118
- <Td property="value">
119
- <div
120
- class="btn-group btn-group-toggle"
121
- data-toggle="buttons"
122
- >
123
- {#each Object.values(permissionValueList) as permissionValue}
124
- <label class="btn btn-sm btn-{getButtonColor(permissionValue.value, permission.value)} cursor-pointer">
125
- <input
126
- type="radio"
127
- autocomplete="off"
128
- name={permission.value}
129
- value={permissionValue.value}
130
- on:change={e => updatePermissionValues(e, new Set([permission.id]))}
131
- />
132
- {permissionValue.label}
133
- </label>
134
- {/each}
135
- </div>
136
- </Td>
137
- {#if groupPermissionValueMap}
138
- <Td
139
- property="groupValue"
140
- class="px-4"
141
- >
142
- <span class="badge badge-pill badge-{permissionValueList[permission.groupValue ?? 'NONE'].color}">{permissionValueList[permission.groupValue ?? 'NONE'].label}</span>
143
- </Td>
144
- <Td
145
- property="computedValue"
146
- class="px-4"
147
- >
148
- <span class="badge badge-pill badge-{permissionValueList[permission.computedValue ?? 'NONE'].color}">{permissionValueList[permission.computedValue ?? 'NONE'].label}</span>
195
+ {#snippet children({ row: permission })}
196
+ <tr
197
+ onclick={() => selectPermissions(permission.id)}
198
+ class:table-primary={selectedPermissionIds.has(permission.id)}
199
+ class="cursor-pointer"
200
+ >
201
+ <Td property="value">
202
+ <div
203
+ class="btn-group btn-group-toggle"
204
+ data-toggle="buttons"
205
+ >
206
+ {#each Object.values(permissionValueList) as permissionValue}
207
+ <label class="btn btn-sm btn-{getButtonColor(permissionValue.value, permission.value)} cursor-pointer">
208
+ <input
209
+ class="btn-check"
210
+ type="radio"
211
+ autocomplete="off"
212
+ name={permission.value}
213
+ value={permissionValue.value}
214
+ onchange={e => updatePermissionValues(e, new SvelteSet([permission.id]))}
215
+ />
216
+ {permissionValue.label}
217
+ </label>
218
+ {/each}
219
+ </div>
149
220
  </Td>
150
- {/if}
151
- <Td property="category">{permission.category}</Td>
152
- <Td property="displayName">{permission.displayName}</Td>
153
- </tr>
221
+ {#if groupPermissionValueMap}
222
+ <Td
223
+ property="groupValue"
224
+ class="px-4"
225
+ >
226
+ <span class="badge badge-pill bg-{permissionValueList[permission.groupValue ?? 'NONE'].color}"
227
+ >{permissionValueList[permission.groupValue ?? 'NONE'].label}</span
228
+ >
229
+ </Td>
230
+ <Td
231
+ property="computedValue"
232
+ class="px-4"
233
+ >
234
+ <span class="badge badge-pill bg-{permissionValueList[permission.computedValue ?? 'NONE'].color}"
235
+ >{permissionValueList[permission.computedValue ?? 'NONE'].label}</span
236
+ >
237
+ </Td>
238
+ {/if}
239
+ <Td property="category">{permission.category}</Td>
240
+ <Td property="displayName">{permission.displayName}</Td>
241
+ </tr>
242
+ {/snippet}
154
243
  </Table>
155
- <slot></slot>
244
+ {@render children?.()}
156
245
  </div>
157
246
  <div class="card-footer">
158
247
  <div class="d-flex justify-content-between align-items-end">
@@ -162,12 +251,12 @@ $: computedPermissions = getComputedPermissions(permissions, permissionValueMap,
162
251
  showEmptyOption={selectedPermissionValue === null}
163
252
  emptyValue={null}
164
253
  emptyText={translate('common:selectValue', 'Select a Value')}
165
- labelParentClass="form-inline mr-2"
166
- labelClass="mr-2 p-0"
254
+ labelParentClass="form-inline mr-2 me-2"
255
+ labelClass="mr-2 me-2 p-0"
167
256
  disabled={selectedPermissionIds.size === 0}
168
- on:change={e => {
257
+ onchange={e => {
169
258
  updatePermissionValues(e, selectedPermissionIds)
170
- selectedPermissionIds = new Set() //clear the Set and trigger reactivity
259
+ selectedPermissionIds.clear()
171
260
  selectedPermissionValue = null
172
261
  }}
173
262
  >
@@ -180,10 +269,14 @@ $: computedPermissions = getComputedPermissions(permissions, permissionValueMap,
180
269
  outline
181
270
  size="sm"
182
271
  iconClass="check-double"
183
- on:click={selectAndDeselectAllPermissions}
272
+ onclick={selectAndDeselectAllPermissions}
184
273
  >
185
- <span class:d-none={selectedPermissionIds.size !== computedPermissions.length}>{translate('common:deselectAll', 'Deselect All')}</span>
186
- <span class:d-none={selectedPermissionIds.size === computedPermissions.length}>{translate('common:selectAll', 'Select All')}</span>
274
+ <span class:d-none={selectedPermissionIds.size !== computedPermissions.length}
275
+ >{translate('common:deselectAll', 'Deselect All')}</span
276
+ >
277
+ <span class:d-none={selectedPermissionIds.size === computedPermissions.length}
278
+ >{translate('common:selectAll', 'Select All')}</span
279
+ >
187
280
  </Button>
188
281
  </div>
189
282
  </div>
@@ -1,35 +1,22 @@
1
- import { SvelteComponent } from "svelte";
2
1
  import type { IconName, SiteLabel, HTMLDivAttributes } from './';
3
- declare const __propDef: {
4
- props: HTMLDivAttributes & {
5
- permissions: Array<{
6
- id: number;
7
- displayName: string;
8
- category: string;
9
- codeName: string;
10
- }>;
11
- siteLabel?: SiteLabel;
12
- permissionValueChange?: ((change: {
13
- value: "NONE" | "SITE" | "GLOBAL";
14
- permissionIds: Array<number>;
15
- }) => void | Promise<void>) | undefined;
16
- icon?: IconName;
17
- cardHeaderTitle?: string;
18
- permissionValueMap: Map<number, "NONE" | "SITE" | "GLOBAL">;
19
- groupPermissionValueMap?: Map<number, "NONE" | "SITE" | "GLOBAL"> | undefined;
20
- };
21
- events: {
22
- [evt: string]: CustomEvent<any>;
23
- };
24
- slots: {
25
- default: {};
26
- };
27
- exports?: {} | undefined;
28
- bindings?: string | undefined;
29
- };
30
- export type PermissionListProps = typeof __propDef.props;
31
- export type PermissionListEvents = typeof __propDef.events;
32
- export type PermissionListSlots = typeof __propDef.slots;
33
- export default class PermissionList extends SvelteComponent<PermissionListProps, PermissionListEvents, PermissionListSlots> {
34
- }
35
- export {};
2
+ import type { Snippet } from 'svelte';
3
+ declare const PermissionList: import("svelte").Component<HTMLDivAttributes & {
4
+ permissions: Array<{
5
+ id: number;
6
+ displayName: string;
7
+ category: string;
8
+ codeName: string;
9
+ }>;
10
+ siteLabel?: SiteLabel;
11
+ permissionValueChange?: ((change: {
12
+ value: "NONE" | "SITE" | "GLOBAL";
13
+ permissionIds: Array<number>;
14
+ }) => void | Promise<void>) | undefined;
15
+ icon?: IconName;
16
+ cardHeaderTitle?: string;
17
+ permissionValueMap: Map<number, "NONE" | "SITE" | "GLOBAL">;
18
+ groupPermissionValueMap?: Map<number, "NONE" | "SITE" | "GLOBAL"> | undefined;
19
+ children?: Snippet;
20
+ }, {}, "permissionValueMap">;
21
+ type PermissionList = ReturnType<typeof PermissionList>;
22
+ export default PermissionList;