@isoftdata/svelte-user-configuration 1.0.27 → 1.1.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 +131 -11
- package/dist/DeactivateUserModal.svelte +2 -1
- package/dist/PasswordRecoveryModal.svelte +2 -1
- package/dist/PasswordSetModal.svelte +4 -3
- package/dist/PermissionList.svelte +2 -1
- package/dist/UserAccountInfo.svelte +75 -11
- package/dist/UserAccountInfo.svelte.d.ts +5 -2
- package/dist/UserGroupMembership.svelte +2 -1
- package/dist/UserSiteAccess.svelte +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/util.d.ts +1 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Svelte UserConfiguration
|
|
2
2
|
|
|
3
|
+
This Svelte component provides a user configuration interface, including user account details, site access, group membership, and permissions.
|
|
4
|
+
|
|
3
5
|
## Install
|
|
4
6
|
|
|
5
7
|
```sh
|
|
@@ -7,23 +9,141 @@ npm i @isoftdata/svelte-user-configuration
|
|
|
7
9
|
```
|
|
8
10
|
|
|
9
11
|
## Props
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
|
14
|
-
|
|
12
|
+
|
|
13
|
+
### User Account Properties
|
|
14
|
+
|
|
15
|
+
| Prop | Type | Required | Default | Description |
|
|
16
|
+
|------|------|----------|---------|-------------|
|
|
17
|
+
| `userAccount` | `UserAccount` | ✅ | - | The user account information. |
|
|
18
|
+
| `canToggleActive` | boolean | ❌ | `true` | Whether the user can be activated/deactivated. |
|
|
19
|
+
| `canEditAccountInfo` | boolean | ❌ | `true` | Whether account details can be edited. |
|
|
20
|
+
| `doSendPasswordRecoveryToken` | boolean | ❌ | `false` | Whether to allow sending password recovery tokens. |
|
|
21
|
+
| `hasPermissionToChangePassword` | boolean | ❌ | `false` | Whether the user has permission to change passwords. |
|
|
22
|
+
| `myAccountMode` | boolean | ❌ | `false` | When `true`, admin controls will be hidden/disabled. This is designed to be used when using the user account info component standalone so the current session user can edit their own account info, including first & last name, password recovery email, & password. |
|
|
23
|
+
|
|
24
|
+
### Site Access Properties
|
|
25
|
+
|
|
26
|
+
| Prop | Type | Required | Default | Description |
|
|
27
|
+
|------|------|----------|---------|-------------|
|
|
28
|
+
| `userSites` | `UserSites` | ✅ | - | List of sites the user has access to. |
|
|
29
|
+
| `canEditSiteAccess` | boolean | ❌ | `true` | Whether site access can be edited. |
|
|
30
|
+
|
|
31
|
+
### Group Membership Properties
|
|
32
|
+
|
|
33
|
+
| Prop | Type | Required | Default | Description |
|
|
34
|
+
|------|------|----------|---------|-------------|
|
|
35
|
+
| `groupMembership` | `GroupMembership` | ✅ | - | The user's group membership information. |
|
|
36
|
+
| `canEditGroupMembership` | boolean | ❌ | `true` | Whether group memberships can be edited. |
|
|
37
|
+
|
|
38
|
+
### Permission List Properties
|
|
39
|
+
|
|
40
|
+
| Prop | Type | Required | Default | Description |
|
|
41
|
+
|------|------|----------|---------|-------------|
|
|
42
|
+
| `permissions` | `Permissions` | ✅ | - | The list of permissions for the user. |
|
|
43
|
+
| `permissionValueMap` | `PermissionValueMap` | ✅ | `new Map()` | A mapping of permissions to their values. |
|
|
44
|
+
| `groupPermissionValueMap` | `GroupPermissionValueMap` | ❌ | `undefined` | A mapping of group-based permissions. |
|
|
45
|
+
|
|
46
|
+
### Other Properties
|
|
47
|
+
|
|
48
|
+
| Prop | Type | Required | Default | Description |
|
|
49
|
+
|------|------|----------|---------|-------------|
|
|
50
|
+
| `siteLabel` | `SiteLabel` | ❌ | `"Site"` | Label for the site. |
|
|
51
|
+
| `userAccountInfoIcon` | `IconName` | ❌ | `"user"` | Icon for the user account section. |
|
|
52
|
+
| `groupMembershipIcon` | `IconName` | ❌ | `"users"` | Icon for the group membership section. |
|
|
53
|
+
| `permissionListIcon` | `IconName` | ❌ | `"user-lock"` | Icon for the permission list section. |
|
|
54
|
+
| `userSiteAccessIcon` | `IconName` | ❌ | `"industry-windows"` | Icon for the site access section. |
|
|
55
|
+
| `permissionListCardHeaderTitle` | `PermissionListCardHeaderTitle` | ❌ | `"Permissions"` | Title for the permission list card header. |
|
|
56
|
+
| `usernameInput` | `HTMLInputElement \| undefined` | ❌ | `undefined` | Reference to the username input element. |
|
|
57
|
+
|
|
58
|
+
### Callbacks
|
|
59
|
+
|
|
60
|
+
| Prop | Type | Description |
|
|
61
|
+
|------|------|-------------|
|
|
62
|
+
| `error` | `ErrorFn` | Callback for handling errors. |
|
|
63
|
+
| `success` | `SuccessFn` | Callback for handling success messages. |
|
|
64
|
+
| `deactivateUser` | `DeactivateUserFn` | Function to deactivate a user. |
|
|
65
|
+
| `confirmPasswordSet` | `ConfirmPasswordSetFn` | Function called when a password is set. |
|
|
66
|
+
| `accountInfoChanged` | `AccountInfoChangedFn` | Function called when account info changes. |
|
|
67
|
+
| `sendPasswordRecoveryToken` | `SendPasswordRecoveryTokenFn` | Function to send password recovery token. |
|
|
68
|
+
| `generateNewActivationPIN` | `GenerateNewActivationPINFn` | Function to generate a new activation PIN. |
|
|
69
|
+
| `permissionValueChange` | `PermissionValueChangeFn` | Function called when permissions change. |
|
|
70
|
+
| `siteAccessChange` | `SiteAccessChangeFn` | Function called when site access is changed. |
|
|
71
|
+
| `groupMembershipChange` | `GroupMembershipChangeFn` | Function called when group membership changes. |
|
|
15
72
|
|
|
16
73
|
## Slots
|
|
17
|
-
|
|
74
|
+
This component provides named slots for injecting additional content.
|
|
18
75
|
|
|
19
|
-
|
|
20
|
-
|
|
76
|
+
| Slot Name | Description |
|
|
77
|
+
|-----------|-------------|
|
|
78
|
+
| `userAccountInfo` | Slot at the end of the `userAccountInfo` component's card body |
|
|
79
|
+
| `siteAccess` | Slot at the end of the `siteAccess` component's card body |
|
|
80
|
+
| `userGroupMembership` | Slot at the end of the `userGroupMembership` component's card body |
|
|
81
|
+
| `permissionList` | Slot at the end of the `permissionList` component's card body |
|
|
82
|
+
|
|
83
|
+
## Usage Example in Svelte 5 w/ Runes
|
|
21
84
|
|
|
22
|
-
## Example
|
|
23
85
|
```svelte
|
|
24
86
|
<script lang="ts">
|
|
25
|
-
import UserConfiguration from '@isoftdata/svelte-user-configuration'
|
|
87
|
+
import { UserConfiguration, getGroupHighestPermissionValueMap } from '@isoftdata/svelte-user-configuration'
|
|
88
|
+
|
|
89
|
+
interface Props {
|
|
90
|
+
plants: PlantsForDropdown$result['plants']['data']
|
|
91
|
+
groups: Array<Group>
|
|
92
|
+
permissions: UserConfigurationData$result['permissions']['data']
|
|
93
|
+
userAccount: UserAccount
|
|
94
|
+
permissionValueMap?: PermissionValueMap
|
|
95
|
+
groupPermissionMap?: GroupPermissionMap
|
|
96
|
+
authorizedSitesSet?: any
|
|
97
|
+
groupMembershipSet?: any
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let {
|
|
101
|
+
plants,
|
|
102
|
+
groups,
|
|
103
|
+
permissions,
|
|
104
|
+
userAccount = $bindable(),
|
|
105
|
+
permissionValueMap = $bindable(new SvelteMap()),
|
|
106
|
+
groupPermissionMap = new SvelteMap(),
|
|
107
|
+
authorizedSitesSet = $bindable(new SvelteSet<number>()),
|
|
108
|
+
groupMembershipSet = $bindable(new SvelteSet<number>()),
|
|
109
|
+
}: Props = $props()
|
|
110
|
+
|
|
111
|
+
let userSites = $derived(
|
|
112
|
+
plants.map(({ id, code, name }) => {
|
|
113
|
+
return { id, code, name, isAuthorized: authorizedSitesSet.has(id) }
|
|
114
|
+
}),
|
|
115
|
+
)
|
|
116
|
+
let groupMembership = $derived(
|
|
117
|
+
groups.map(({ id, name }) => {
|
|
118
|
+
return { id, name, isMember: groupMembershipSet.has(id) }
|
|
119
|
+
}),
|
|
120
|
+
)
|
|
121
|
+
let groupPermissionValueMap = $derived(getGroupHighestPermissionValueMap(groupMembershipSet, groupPermissionMap))
|
|
26
122
|
</script>
|
|
27
123
|
|
|
28
|
-
<UserConfiguration
|
|
124
|
+
<UserConfiguration
|
|
125
|
+
siteLabel="Plant"
|
|
126
|
+
bind:userAccount
|
|
127
|
+
bind:usernameInput
|
|
128
|
+
bind:doSendPasswordRecoveryToken={sendPasswordRecoveryToken}
|
|
129
|
+
{userSites}
|
|
130
|
+
{groupMembership}
|
|
131
|
+
{permissions}
|
|
132
|
+
{permissionValueMap}
|
|
133
|
+
{groupPermissionValueMap}
|
|
134
|
+
siteAccessChange={async site => {
|
|
135
|
+
site.isAuthorized ? authorizedSitesSet.add(site.id) : authorizedSitesSet.delete(site.id)
|
|
136
|
+
authorizedSitesSet = new Set(authorizedSitesSet)
|
|
137
|
+
}}
|
|
138
|
+
groupMembershipChange={async ({ id, isMember }) => {
|
|
139
|
+
isMember ? groupMembershipSet.add(id) : groupMembershipSet.delete(id)
|
|
140
|
+
groupMembershipSet = new Set(groupMembershipSet)
|
|
141
|
+
}}
|
|
142
|
+
permissionValueChange={async ({ permissionIds, value }) => {
|
|
143
|
+
for (const id of permissionIds) {
|
|
144
|
+
permissionValueMap.set(id, value)
|
|
145
|
+
}
|
|
146
|
+
permissionValueMap = new Map(permissionValueMap)
|
|
147
|
+
}}
|
|
148
|
+
/>
|
|
29
149
|
```
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script>import { getContext, tick } from "svelte";
|
|
2
2
|
import { klona } from "klona";
|
|
3
|
+
import { translate as defaultTranslate } from "@isoftdata/utility-string";
|
|
3
4
|
import Modal from "@isoftdata/svelte-modal";
|
|
4
5
|
import TextArea from "@isoftdata/svelte-textarea";
|
|
5
6
|
let show = false;
|
|
@@ -14,7 +15,7 @@ export async function open(userAccountCtx) {
|
|
|
14
15
|
await tick();
|
|
15
16
|
textarea?.select();
|
|
16
17
|
}
|
|
17
|
-
const { t: translate } = getContext("i18next") || { t:
|
|
18
|
+
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
|
|
18
19
|
</script>
|
|
19
20
|
|
|
20
21
|
<Modal
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script>import { getContext } from "svelte";
|
|
2
2
|
import Modal from "@isoftdata/svelte-modal";
|
|
3
3
|
import Input from "@isoftdata/svelte-input";
|
|
4
|
-
|
|
4
|
+
import { translate as defaultTranslate } from "@isoftdata/utility-string";
|
|
5
|
+
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
|
|
5
6
|
export let sendPasswordRecoveryToken = void 0;
|
|
6
7
|
export let doSendPasswordRecoveryToken;
|
|
7
8
|
let resetDate = void 0;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { klona } from "klona";
|
|
2
|
+
import { tick, getContext } from "svelte";
|
|
2
3
|
import Input from "@isoftdata/svelte-input";
|
|
3
4
|
import Modal from "@isoftdata/svelte-modal";
|
|
4
5
|
import PasswordFields from "@isoftdata/svelte-password-fields";
|
|
5
|
-
import {
|
|
6
|
+
import { translate as defaultTranslate } from "@isoftdata/utility-string";
|
|
6
7
|
let show = false;
|
|
7
8
|
let newPassword = "";
|
|
8
9
|
let confirmPassword = "";
|
|
@@ -22,7 +23,7 @@ export async function open(userAccount) {
|
|
|
22
23
|
await tick();
|
|
23
24
|
input?.focus();
|
|
24
25
|
}
|
|
25
|
-
const { t: translate } = getContext("i18next") || { t:
|
|
26
|
+
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
|
|
26
27
|
</script>
|
|
27
28
|
|
|
28
29
|
<Modal
|
|
@@ -5,7 +5,8 @@ import Button from "@isoftdata/svelte-button";
|
|
|
5
5
|
import Select from "@isoftdata/svelte-select";
|
|
6
6
|
import { getEventValue } from "@isoftdata/browser-event";
|
|
7
7
|
import { Table, Td } from "@isoftdata/svelte-table";
|
|
8
|
-
|
|
8
|
+
import { translate as defaultTranslate } from "@isoftdata/utility-string";
|
|
9
|
+
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
|
|
9
10
|
export let permissions;
|
|
10
11
|
export let siteLabel = "Site";
|
|
11
12
|
export let permissionValueChange = void 0;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
<script>import { getContext } from "svelte";
|
|
1
|
+
<script>import { getContext, tick } from "svelte";
|
|
2
2
|
import Icon from "@isoftdata/svelte-icon";
|
|
3
3
|
import Input from "@isoftdata/svelte-input";
|
|
4
|
-
import { translate as defaultTranslate } from "@isoftdata/utility-string";
|
|
5
4
|
import Button from "@isoftdata/svelte-button";
|
|
6
5
|
import TextArea from "@isoftdata/svelte-textarea";
|
|
7
6
|
import PasswordSetModal from "./PasswordSetModal.svelte";
|
|
7
|
+
import { getEventValue } from "@isoftdata/browser-event";
|
|
8
8
|
import PasswordFields from "@isoftdata/svelte-password-fields";
|
|
9
9
|
import DeactivateUserModal from "./DeactivateUserModal.svelte";
|
|
10
10
|
import PasswordRecoveryModal from "./PasswordRecoveryModal.svelte";
|
|
11
|
+
import { translate as defaultTranslate } from "@isoftdata/utility-string";
|
|
12
|
+
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
|
|
11
13
|
export let userAccount;
|
|
12
14
|
export let icon = "user";
|
|
13
15
|
export let canToggleActive = true;
|
|
@@ -23,12 +25,17 @@ export let doSendPasswordRecoveryToken = false;
|
|
|
23
25
|
export let generateNewActivationPIN = () => Promise.resolve();
|
|
24
26
|
export let usernameInput = void 0;
|
|
25
27
|
export let cardHeight = 0;
|
|
28
|
+
export let myAccountMode = false;
|
|
29
|
+
export let passwordValidationRules = void 0;
|
|
30
|
+
export let showPasswordChange = false;
|
|
26
31
|
let isLoading = false;
|
|
27
32
|
let passwordSetModal;
|
|
28
33
|
let deactivateUserModal;
|
|
29
34
|
let passwordRecoveryModal;
|
|
30
35
|
let activationPINInput;
|
|
31
|
-
|
|
36
|
+
let currentPasswordField;
|
|
37
|
+
let cardTitle = translate("configuration.user.accountInfoHeader", "Account");
|
|
38
|
+
let confirmPassword = "";
|
|
32
39
|
async function getNewActivationPIN(sendEmail = false) {
|
|
33
40
|
let confirmationMessage = sendEmail ? translate("configuration.user.permissions.sendNewActivationPINMessage", "Are you sure you want to send a new activation PIN? The user will receive an email with the new activation PIN.") : translate("configuration.user.permissions.generateNewActivationPINMessage", "Are you sure you want to generate a new activation PIN?");
|
|
34
41
|
if (confirm(confirmationMessage)) {
|
|
@@ -83,9 +90,9 @@ $: isCreatingNewUser = userAccount.id === null;
|
|
|
83
90
|
{icon}
|
|
84
91
|
class="mr-1"
|
|
85
92
|
/>
|
|
86
|
-
{isCreatingNewUser ? translate('configuration.user.creatingNewAccountInfoHeader', 'New Account') :
|
|
93
|
+
{isCreatingNewUser ? translate('configuration.user.creatingNewAccountInfoHeader', 'New Account') : cardTitle}
|
|
87
94
|
</h5>
|
|
88
|
-
{#if !isCreatingNewUser && status === 'ACTIVE'}
|
|
95
|
+
{#if !myAccountMode && !isCreatingNewUser && status === 'ACTIVE'}
|
|
89
96
|
<Button
|
|
90
97
|
size="xs"
|
|
91
98
|
outline
|
|
@@ -96,7 +103,7 @@ $: isCreatingNewUser = userAccount.id === null;
|
|
|
96
103
|
>
|
|
97
104
|
<span>{translate('common:deactivate', 'Deactivate')}</span>
|
|
98
105
|
</Button>
|
|
99
|
-
{:else if (!isCreatingNewUser && status === 'DEACTIVATED') || status === 'LOCKED'}
|
|
106
|
+
{:else if !myAccountMode && ((!isCreatingNewUser && status === 'DEACTIVATED') || status === 'LOCKED')}
|
|
100
107
|
<Button
|
|
101
108
|
size="xs"
|
|
102
109
|
outline
|
|
@@ -160,6 +167,34 @@ $: isCreatingNewUser = userAccount.id === null;
|
|
|
160
167
|
>
|
|
161
168
|
{/if}
|
|
162
169
|
</div>
|
|
170
|
+
{:else if myAccountMode}
|
|
171
|
+
<div class="col-12">
|
|
172
|
+
<Button
|
|
173
|
+
size="sm"
|
|
174
|
+
outline
|
|
175
|
+
iconClass="key"
|
|
176
|
+
color={showPasswordChange ? 'danger' : 'primary'}
|
|
177
|
+
disabled={!canEditAccountInfo}
|
|
178
|
+
on:click={async () => {
|
|
179
|
+
showPasswordChange = !showPasswordChange
|
|
180
|
+
await tick()
|
|
181
|
+
if (showPasswordChange) {
|
|
182
|
+
currentPasswordField?.select()
|
|
183
|
+
} else {
|
|
184
|
+
//Clear the password fields
|
|
185
|
+
userAccount.currentPassword = ''
|
|
186
|
+
userAccount.newPassword = ''
|
|
187
|
+
confirmPassword = ''
|
|
188
|
+
}
|
|
189
|
+
}}
|
|
190
|
+
>
|
|
191
|
+
{#if !showPasswordChange}
|
|
192
|
+
{translate('configuration.user.changePassword', 'Change Password')}...
|
|
193
|
+
{:else}
|
|
194
|
+
{translate('configuration.user.cancelPasswordChange', 'Cancel Password Change')}
|
|
195
|
+
{/if}
|
|
196
|
+
</Button>
|
|
197
|
+
</div>
|
|
163
198
|
{:else}
|
|
164
199
|
<div class="col-12">
|
|
165
200
|
<Button
|
|
@@ -200,29 +235,33 @@ $: isCreatingNewUser = userAccount.id === null;
|
|
|
200
235
|
},
|
|
201
236
|
}}
|
|
202
237
|
bind:input={usernameInput}
|
|
238
|
+
readonly={myAccountMode || undefined}
|
|
239
|
+
tabindex={myAccountMode ? -1 : undefined}
|
|
203
240
|
/>
|
|
204
241
|
</div>
|
|
205
|
-
<div class="col-6">
|
|
242
|
+
<div class="col-12 col-md-6">
|
|
206
243
|
<Input
|
|
207
244
|
label={translate('configuration.user.accountInfo.firstName', 'First Name')}
|
|
208
245
|
bind:value={userAccount.firstName}
|
|
209
246
|
maxlength={100}
|
|
210
247
|
/>
|
|
211
248
|
</div>
|
|
212
|
-
<div class="col-6">
|
|
249
|
+
<div class="col-12 col-md-6">
|
|
213
250
|
<Input
|
|
214
251
|
label={translate('configuration.user.accountInfo.lastName', 'Last Name')}
|
|
215
252
|
bind:value={userAccount.lastName}
|
|
216
253
|
maxlength={100}
|
|
217
254
|
/>
|
|
218
255
|
</div>
|
|
219
|
-
<div class="col-12">
|
|
256
|
+
<div class="col-12 col-lg-6">
|
|
220
257
|
<Input
|
|
221
258
|
label={translate('configuration.user.accountInfo.workEmail', 'Work Email')}
|
|
222
259
|
bind:value={userAccount.workEmail}
|
|
223
260
|
autocomplete="email"
|
|
224
261
|
type="email"
|
|
225
262
|
inputmode="email"
|
|
263
|
+
readonly={myAccountMode || undefined}
|
|
264
|
+
tabindex={myAccountMode ? -1 : undefined}
|
|
226
265
|
/>
|
|
227
266
|
{#if workEmail && !isCreatingNewUser && status === 'PENDING_ACTIVATION'}
|
|
228
267
|
<Button
|
|
@@ -235,8 +274,19 @@ $: isCreatingNewUser = userAccount.id === null;
|
|
|
235
274
|
</Button>
|
|
236
275
|
{/if}
|
|
237
276
|
</div>
|
|
277
|
+
<div class="col-12 col-lg-6">
|
|
278
|
+
<Input
|
|
279
|
+
label={translate('configuration.user.accountInfo.passwordRecoveryModal.passwordRecoveryEmail', 'Password Recovery Email')}
|
|
280
|
+
bind:value={userAccount.recoveryEmail}
|
|
281
|
+
autocomplete="email"
|
|
282
|
+
type="email"
|
|
283
|
+
inputmode="email"
|
|
284
|
+
readonly={!myAccountMode || undefined}
|
|
285
|
+
tabindex={!myAccountMode ? -1 : undefined}
|
|
286
|
+
/>
|
|
287
|
+
</div>
|
|
238
288
|
<div class="col-12">
|
|
239
|
-
{#if !isCreatingNewUser}
|
|
289
|
+
{#if !isCreatingNewUser && !myAccountMode}
|
|
240
290
|
<TextArea
|
|
241
291
|
label={translate('configuration.user.accountInfo.lockNote', 'Lock Note')}
|
|
242
292
|
labelClass="py-0 mb-2"
|
|
@@ -244,16 +294,30 @@ $: isCreatingNewUser = userAccount.id === null;
|
|
|
244
294
|
bind:value={userAccount.lockNotes}
|
|
245
295
|
readonly
|
|
246
296
|
/>
|
|
247
|
-
{:else if hasPermissionToChangePassword}
|
|
297
|
+
{:else if (hasPermissionToChangePassword && !myAccountMode) || (myAccountMode && showPasswordChange)}
|
|
298
|
+
{#if myAccountMode}
|
|
299
|
+
<Input
|
|
300
|
+
bind:input={currentPasswordField}
|
|
301
|
+
label={translate('configuration.user.accountInfo.passwordManagementModal.currentPassword', 'Current Password')}
|
|
302
|
+
type="password"
|
|
303
|
+
value={userAccount.currentPassword ?? ''}
|
|
304
|
+
autocomplete="current-password"
|
|
305
|
+
on:change={e => (userAccount.currentPassword = getEventValue(e))}
|
|
306
|
+
required
|
|
307
|
+
/>
|
|
308
|
+
{/if}
|
|
248
309
|
<!-- TODO: When we migrate to Svelte 5, switch this and the other usage of PasswordFields to use a snippet-->
|
|
249
310
|
<PasswordFields
|
|
250
311
|
bind:password={userAccount.newPassword}
|
|
312
|
+
bind:confirmPassword
|
|
251
313
|
columnClass="col-12"
|
|
252
314
|
passwordLabel={translate('configuration.user.accountInfo.passwordManagementModal.newPassword', 'New Password')}
|
|
253
315
|
confirmPasswordLabel={translate('configuration.user.accountInfo.passwordManagementModal.confirmNewPassword', 'Confirm New Password')}
|
|
316
|
+
validationRules={passwordValidationRules}
|
|
254
317
|
/>
|
|
255
318
|
{/if}
|
|
256
319
|
</div>
|
|
320
|
+
<slot name="formFields"></slot>
|
|
257
321
|
</div>
|
|
258
322
|
<slot></slot>
|
|
259
323
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { ComponentProps } from 'svelte';
|
|
3
|
-
import type { UserAccount, ConfirmPasswordSetFn, DeactivateUserFn, HTMLDivAttributes, IconName } from './';
|
|
3
|
+
import type { UserAccount, ConfirmPasswordSetFn, DeactivateUserFn, HTMLDivAttributes, IconName, PasswordValidationRules } from './';
|
|
4
4
|
import PasswordRecoveryModal from './PasswordRecoveryModal.svelte';
|
|
5
5
|
declare const __propDef: {
|
|
6
6
|
props: HTMLDivAttributes & {
|
|
@@ -21,15 +21,18 @@ declare const __propDef: {
|
|
|
21
21
|
}) => void | Promise<void>) | undefined;
|
|
22
22
|
accountInfoChanged?: (() => void | Promise<void>) | undefined;
|
|
23
23
|
sendPasswordRecoveryToken?: ComponentProps<PasswordRecoveryModal>["sendPasswordRecoveryToken"];
|
|
24
|
-
doSendPasswordRecoveryToken
|
|
24
|
+
doSendPasswordRecoveryToken?: boolean;
|
|
25
25
|
icon?: IconName;
|
|
26
26
|
usernameInput?: HTMLInputElement | undefined;
|
|
27
27
|
cardHeight?: number;
|
|
28
|
+
myAccountMode?: boolean;
|
|
29
|
+
passwordValidationRules?: PasswordValidationRules | undefined;
|
|
28
30
|
};
|
|
29
31
|
events: {
|
|
30
32
|
[evt: string]: CustomEvent<any>;
|
|
31
33
|
};
|
|
32
34
|
slots: {
|
|
35
|
+
formFields: {};
|
|
33
36
|
default: {};
|
|
34
37
|
};
|
|
35
38
|
exports?: {} | undefined;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script>import { getContext } from "svelte";
|
|
2
2
|
import Icon from "@isoftdata/svelte-icon";
|
|
3
3
|
import Checkbox from "@isoftdata/svelte-checkbox";
|
|
4
|
-
|
|
4
|
+
import { translate as defaultTranslate } from "@isoftdata/utility-string";
|
|
5
|
+
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
|
|
5
6
|
export let groupMembership;
|
|
6
7
|
export let canEditGroupMembership = true;
|
|
7
8
|
export let groupMembershipChange = void 0;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script>import { getContext } from "svelte";
|
|
2
|
-
import Checkbox from "@isoftdata/svelte-checkbox";
|
|
3
2
|
import Icon from "@isoftdata/svelte-icon";
|
|
4
|
-
|
|
3
|
+
import Checkbox from "@isoftdata/svelte-checkbox";
|
|
4
|
+
import { translate as defaultTranslate } from "@isoftdata/utility-string";
|
|
5
|
+
const { t: translate } = getContext("i18next") || { t: defaultTranslate };
|
|
5
6
|
export let userSites;
|
|
6
7
|
export let siteLabel = "Site";
|
|
7
8
|
export let canEditSiteAccess = true;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,3 +5,4 @@ export { default as PermissionList } from './PermissionList.svelte';
|
|
|
5
5
|
export { default as UserSiteAccess } from './UserSiteAccess.svelte';
|
|
6
6
|
export * from './util';
|
|
7
7
|
export type * from './util';
|
|
8
|
+
export type { ValidationRules as PasswordValidationRules } from '@isoftdata/svelte-password-fields';
|
package/dist/util.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface UserAccount {
|
|
|
17
17
|
recoveryEmail: string | null;
|
|
18
18
|
status: 'ACTIVE' | 'DEACTIVATED' | 'LOCKED' | 'PENDING_ACTIVATION';
|
|
19
19
|
newPassword?: string;
|
|
20
|
+
currentPassword?: string;
|
|
20
21
|
lastPasswordResetDate?: Date;
|
|
21
22
|
lastAccessDate?: Date;
|
|
22
23
|
userActivationData?: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isoftdata/svelte-user-configuration",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite dev",
|
|
6
6
|
"build": "vite build && npm run package",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@fortawesome/fontawesome-common-types": "^6.7.2",
|
|
34
34
|
"@isoftdata/prettier-config": "^1.0.3",
|
|
35
|
+
"@isoftdata/svelte-bootstrap-version-switcher": "^1.0.2",
|
|
35
36
|
"@sveltejs/adapter-auto": "^3.0.0",
|
|
36
37
|
"@sveltejs/kit": "^2.0.0",
|
|
37
38
|
"@sveltejs/package": "^2.0.0",
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
"@isoftdata/svelte-icon": "^1.4.0",
|
|
64
65
|
"@isoftdata/svelte-input": "^1.6.0",
|
|
65
66
|
"@isoftdata/svelte-modal": "^1.3.1",
|
|
66
|
-
"@isoftdata/svelte-password-fields": "^1.
|
|
67
|
+
"@isoftdata/svelte-password-fields": "^1.4.1",
|
|
67
68
|
"@isoftdata/svelte-select": "^1.5.0",
|
|
68
69
|
"@isoftdata/svelte-table": "^1.16.0",
|
|
69
70
|
"@isoftdata/svelte-textarea": "^1.2.0",
|