@isoftdata/svelte-user-configuration 1.3.2 → 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.
- package/README.md +9 -2
- package/dist/DeactivateUserModal.svelte +32 -20
- package/dist/DeactivateUserModal.svelte.d.ts +10 -22
- package/dist/PasswordRecoveryModal.svelte +44 -22
- package/dist/PasswordRecoveryModal.svelte.d.ts +8 -20
- package/dist/PasswordSetModal.svelte +76 -43
- package/dist/PasswordSetModal.svelte.d.ts +12 -24
- package/dist/PermissionList.svelte +229 -136
- package/dist/PermissionList.svelte.d.ts +21 -34
- package/dist/UserAccountInfo.svelte +189 -96
- package/dist/UserAccountInfo.svelte.d.ts +35 -47
- package/dist/UserConfiguration.svelte +116 -41
- package/dist/UserConfiguration.svelte.d.ts +38 -51
- package/dist/UserGroupMembership.svelte +38 -14
- package/dist/UserGroupMembership.svelte.d.ts +14 -30
- package/dist/UserSiteAccess.svelte +40 -13
- package/dist/UserSiteAccess.svelte.d.ts +17 -33
- package/dist/util.d.ts +23 -24
- package/package.json +74 -73
|
@@ -1,99 +1,182 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
{
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
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
|
-
|
|
257
|
+
onchange={e => {
|
|
169
258
|
updatePermissionValues(e, selectedPermissionIds)
|
|
170
|
-
selectedPermissionIds
|
|
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
|
-
|
|
272
|
+
onclick={selectAndDeselectAllPermissions}
|
|
184
273
|
>
|
|
185
|
-
<span class:d-none={selectedPermissionIds.size !== computedPermissions.length}
|
|
186
|
-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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;
|