@isoftdata/svelte-user-configuration 2.0.0 → 2.0.1
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 +161 -158
- package/dist/DeactivateUserModal.svelte +59 -59
- package/dist/PasswordRecoveryModal.svelte +83 -83
- package/dist/PasswordSetModal.svelte +127 -127
- package/dist/PermissionList.svelte +289 -289
- package/dist/UserAccountInfo.svelte +11 -14
- package/dist/UserGroupMembership.svelte +64 -64
- package/dist/UserSiteAccess.svelte +65 -65
- package/package.json +4 -1
|
@@ -1,289 +1,289 @@
|
|
|
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)
|
|
169
|
-
</script>
|
|
170
|
-
|
|
171
|
-
<div
|
|
172
|
-
class="card"
|
|
173
|
-
{...rest}
|
|
174
|
-
>
|
|
175
|
-
<div class="card-header">
|
|
176
|
-
<h5 class="mb-0">
|
|
177
|
-
<Icon
|
|
178
|
-
{icon}
|
|
179
|
-
class="mr-1 me-1"
|
|
180
|
-
/>
|
|
181
|
-
{cardHeaderTitle}
|
|
182
|
-
</h5>
|
|
183
|
-
</div>
|
|
184
|
-
<div class="card-body">
|
|
185
|
-
<Table
|
|
186
|
-
class="mb-0"
|
|
187
|
-
parentClass="mh-60vh overflow-y-auto"
|
|
188
|
-
filterPlaceholder={translate('common:filterPermissions', 'Filter Permissions')}
|
|
189
|
-
filterColumnClass="col-6 col-lg-4 align-self-end"
|
|
190
|
-
rows={computedPermissions}
|
|
191
|
-
columns={permissionColumns}
|
|
192
|
-
responsive
|
|
193
|
-
filterEnabled
|
|
194
|
-
>
|
|
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>
|
|
220
|
-
</Td>
|
|
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}
|
|
243
|
-
</Table>
|
|
244
|
-
{@render children?.()}
|
|
245
|
-
</div>
|
|
246
|
-
<div class="card-footer">
|
|
247
|
-
<div class="d-flex justify-content-between align-items-end">
|
|
248
|
-
<Select
|
|
249
|
-
label="{translate('common:setSelectedTo', 'Set Selected To')}:"
|
|
250
|
-
bind:value={selectedPermissionValue}
|
|
251
|
-
showEmptyOption={selectedPermissionValue === null}
|
|
252
|
-
emptyValue={null}
|
|
253
|
-
emptyText={translate('common:selectValue', 'Select a Value')}
|
|
254
|
-
labelParentClass="form-inline mr-2 me-2"
|
|
255
|
-
labelClass="mr-2 me-2 p-0"
|
|
256
|
-
disabled={selectedPermissionIds.size === 0}
|
|
257
|
-
onchange={e => {
|
|
258
|
-
updatePermissionValues(e, selectedPermissionIds)
|
|
259
|
-
selectedPermissionIds.clear()
|
|
260
|
-
selectedPermissionValue = null
|
|
261
|
-
}}
|
|
262
|
-
>
|
|
263
|
-
{#each Object.values(permissionValueList) as permission}
|
|
264
|
-
<option value={permission.value}>{permission.label}</option>
|
|
265
|
-
{/each}
|
|
266
|
-
</Select>
|
|
267
|
-
<Button
|
|
268
|
-
class="mb-1"
|
|
269
|
-
outline
|
|
270
|
-
size="sm"
|
|
271
|
-
iconClass="check-double"
|
|
272
|
-
onclick={selectAndDeselectAllPermissions}
|
|
273
|
-
>
|
|
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
|
-
>
|
|
280
|
-
</Button>
|
|
281
|
-
</div>
|
|
282
|
-
</div>
|
|
283
|
-
</div>
|
|
284
|
-
|
|
285
|
-
<style>
|
|
286
|
-
.cursor-pointer {
|
|
287
|
-
cursor: pointer;
|
|
288
|
-
}
|
|
289
|
-
</style>
|
|
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)
|
|
169
|
+
</script>
|
|
170
|
+
|
|
171
|
+
<div
|
|
172
|
+
class="card"
|
|
173
|
+
{...rest}
|
|
174
|
+
>
|
|
175
|
+
<div class="card-header">
|
|
176
|
+
<h5 class="mb-0">
|
|
177
|
+
<Icon
|
|
178
|
+
{icon}
|
|
179
|
+
class="mr-1 me-1"
|
|
180
|
+
/>
|
|
181
|
+
{cardHeaderTitle}
|
|
182
|
+
</h5>
|
|
183
|
+
</div>
|
|
184
|
+
<div class="card-body">
|
|
185
|
+
<Table
|
|
186
|
+
class="mb-0"
|
|
187
|
+
parentClass="mh-60vh overflow-y-auto"
|
|
188
|
+
filterPlaceholder={translate('common:filterPermissions', 'Filter Permissions')}
|
|
189
|
+
filterColumnClass="col-6 col-lg-4 align-self-end"
|
|
190
|
+
rows={computedPermissions}
|
|
191
|
+
columns={permissionColumns}
|
|
192
|
+
responsive
|
|
193
|
+
filterEnabled
|
|
194
|
+
>
|
|
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>
|
|
220
|
+
</Td>
|
|
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}
|
|
243
|
+
</Table>
|
|
244
|
+
{@render children?.()}
|
|
245
|
+
</div>
|
|
246
|
+
<div class="card-footer">
|
|
247
|
+
<div class="d-flex justify-content-between align-items-end">
|
|
248
|
+
<Select
|
|
249
|
+
label="{translate('common:setSelectedTo', 'Set Selected To')}:"
|
|
250
|
+
bind:value={selectedPermissionValue}
|
|
251
|
+
showEmptyOption={selectedPermissionValue === null}
|
|
252
|
+
emptyValue={null}
|
|
253
|
+
emptyText={translate('common:selectValue', 'Select a Value')}
|
|
254
|
+
labelParentClass="form-inline mr-2 me-2"
|
|
255
|
+
labelClass="mr-2 me-2 p-0"
|
|
256
|
+
disabled={selectedPermissionIds.size === 0}
|
|
257
|
+
onchange={e => {
|
|
258
|
+
updatePermissionValues(e, selectedPermissionIds)
|
|
259
|
+
selectedPermissionIds.clear()
|
|
260
|
+
selectedPermissionValue = null
|
|
261
|
+
}}
|
|
262
|
+
>
|
|
263
|
+
{#each Object.values(permissionValueList) as permission}
|
|
264
|
+
<option value={permission.value}>{permission.label}</option>
|
|
265
|
+
{/each}
|
|
266
|
+
</Select>
|
|
267
|
+
<Button
|
|
268
|
+
class="mb-1"
|
|
269
|
+
outline
|
|
270
|
+
size="sm"
|
|
271
|
+
iconClass="check-double"
|
|
272
|
+
onclick={selectAndDeselectAllPermissions}
|
|
273
|
+
>
|
|
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
|
+
>
|
|
280
|
+
</Button>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
|
|
285
|
+
<style>
|
|
286
|
+
.cursor-pointer {
|
|
287
|
+
cursor: pointer;
|
|
288
|
+
}
|
|
289
|
+
</style>
|
|
@@ -104,13 +104,12 @@
|
|
|
104
104
|
isLoading = false
|
|
105
105
|
await accountInfoChanged?.()
|
|
106
106
|
} catch (err) {
|
|
107
|
-
console.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
message:
|
|
112
|
-
|
|
113
|
-
}
|
|
107
|
+
console.error(err)
|
|
108
|
+
await error?.({
|
|
109
|
+
heading: translate('configuration.messageHeading.failedToGenerateNewPIN', 'Failed To Generate New PIN'),
|
|
110
|
+
message:
|
|
111
|
+
err instanceof Error ? err.message : translate('workOrder.unknownError', 'An unknown error occurred'),
|
|
112
|
+
})
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
}
|
|
@@ -400,12 +399,10 @@
|
|
|
400
399
|
await accountInfoChanged?.()
|
|
401
400
|
} catch (err) {
|
|
402
401
|
console.error(err)
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
})
|
|
408
|
-
}
|
|
402
|
+
await error?.({
|
|
403
|
+
heading: translate('configuration.user.messageHeading.failedToDeactivateUser', 'Failed To Deactivate User'),
|
|
404
|
+
message: err instanceof Error ? err.message : translate('workOrder.unknownError', 'An unknown error occurred'),
|
|
405
|
+
})
|
|
409
406
|
}
|
|
410
407
|
}}
|
|
411
408
|
/>
|
|
@@ -423,12 +420,12 @@
|
|
|
423
420
|
message: translate('configuration.user.passwordChangeSuccessMessage', 'Password changed successfully'),
|
|
424
421
|
})
|
|
425
422
|
} catch (err) {
|
|
423
|
+
console.error(err)
|
|
426
424
|
await error?.({
|
|
427
425
|
heading: translate('configuration.user.passwordChangeErrorHeading', 'Failed To Change Password'),
|
|
428
426
|
message:
|
|
429
427
|
err instanceof Error ? err.message : translate('workOrder.unknownError', 'An unknown error occurred'),
|
|
430
428
|
})
|
|
431
|
-
console.error(err)
|
|
432
429
|
throw err
|
|
433
430
|
}
|
|
434
431
|
} else {
|