@isoftdata/svelte-user-configuration 1.3.3 → 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 CHANGED
@@ -1,151 +1,161 @@
1
- # Svelte UserConfiguration
2
-
3
- This Svelte component provides a user configuration interface, including user account details, site access, group membership, and permissions.
4
-
5
- ## Install
6
-
7
- ```sh
8
- npm i @isoftdata/svelte-user-configuration
9
- ```
10
-
11
- ## Props
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
- > Additionally, the `validationRules` & `passwordIsValid` props from the [PasswordFields](<https://github.com/ISoft-Data-Systems/svelte-component-password-fields>) component can be passed and will be used during password setting when `hasPermissionToChangePassword` or `myAccountMode` are `true` .
25
-
26
- ### Site Access Properties
27
-
28
- | Prop | Type | Required | Default | Description |
29
- |------|------|----------|---------|-------------|
30
- | `userSites` | `UserSites` | | - | List of sites the user has access to. |
31
- | `canEditSiteAccess` | boolean | ❌ | `true` | Whether site access can be edited. |
32
-
33
- ### Group Membership Properties
34
-
35
- | Prop | Type | Required | Default | Description |
36
- |------|------|----------|---------|-------------|
37
- | `groupMembership` | `GroupMembership` | ✅ | - | The user's group membership information. |
38
- | `canEditGroupMembership` | boolean | | `true` | Whether group memberships can be edited. |
39
-
40
- ### Permission List Properties
41
-
42
- | Prop | Type | Required | Default | Description |
43
- |------|------|----------|---------|-------------|
44
- | `permissions` | `Permissions` | ✅ | - | The list of permissions for the user. |
45
- | `permissionValueMap` | `PermissionValueMap` | | `new Map()` | A mapping of permissions to their values. |
46
- | `groupPermissionValueMap` | `GroupPermissionValueMap` | ❌ | `undefined` | A mapping of group-based permissions. |
47
-
48
- ### Other Properties
49
-
50
- | Prop | Type | Required | Default | Description |
51
- |------|------|----------|---------|-------------|
52
- | `siteLabel` | `SiteLabel` | | `"Site"` | Label for the site. |
53
- | `userAccountInfoIcon` | `IconName` | ❌ | `"user"` | Icon for the user account section. |
54
- | `groupMembershipIcon` | `IconName` | | `"users"` | Icon for the group membership section. |
55
- | `permissionListIcon` | `IconName` | | `"user-lock"` | Icon for the permission list section. |
56
- | `userSiteAccessIcon` | `IconName` | ❌ | `"industry-windows"` | Icon for the site access section. |
57
- | `permissionListCardHeaderTitle` | `PermissionListCardHeaderTitle` | ❌ | `"Permissions"` | Title for the permission list card header. |
58
- | `usernameInput` | `HTMLInputElement \| undefined` | ❌ | `undefined` | Reference to the username input element. |
59
-
60
- ### Callbacks
61
-
62
- | Prop | Type | Description |
63
- |------|------|-------------|
64
- | `error` | `ErrorFn` | Callback for handling errors. |
65
- | `success` | `SuccessFn` | Callback for handling success messages. |
66
- | `deactivateUser` | `DeactivateUserFn` | Function to deactivate a user. |
67
- | `confirmPasswordSet` | `ConfirmPasswordSetFn` | Function called when a password is set. |
68
- | `accountInfoChanged` | `AccountInfoChangedFn` | Function called when account info changes. |
69
- | `sendPasswordRecoveryToken` | `SendPasswordRecoveryTokenFn` | Function to send password recovery token. |
70
- | `generateNewActivationPIN` | `GenerateNewActivationPINFn` | Function to generate a new activation PIN. |
71
- | `permissionValueChange` | `PermissionValueChangeFn` | Function called when permissions change. |
72
- | `siteAccessChange` | `SiteAccessChangeFn` | Function called when site access is changed. |
73
- | `groupMembershipChange` | `GroupMembershipChangeFn` | Function called when group membership changes. |
74
-
75
- ## Slots
76
- This component provides named slots for injecting additional content.
77
-
78
- | Slot Name | Description |
79
- |-----------|-------------|
80
- | `userAccountInfo` | Slot at the end of the `userAccountInfo` component's card body |
81
- | `siteAccess` | Slot at the end of the `siteAccess` component's card body |
82
- | `userGroupMembership` | Slot at the end of the `userGroupMembership` component's card body |
83
- | `permissionList` | Slot at the end of the `permissionList` component's card body |
84
-
85
- ## Usage Example in Svelte 5 w/ Runes
86
-
87
- ```svelte
88
- <script lang="ts">
89
- import { UserConfiguration, getGroupHighestPermissionValueMap } from '@isoftdata/svelte-user-configuration'
90
-
91
- interface Props {
92
- plants: PlantsForDropdown$result['plants']['data']
93
- groups: Array<Group>
94
- permissions: UserConfigurationData$result['permissions']['data']
95
- userAccount: UserAccount
96
- permissionValueMap?: PermissionValueMap
97
- groupPermissionMap?: GroupPermissionMap
98
- authorizedSitesSet?: any
99
- groupMembershipSet?: any
100
- }
101
-
102
- let {
103
- plants,
104
- groups,
105
- permissions,
106
- userAccount = $bindable(),
107
- permissionValueMap = $bindable(new SvelteMap()),
108
- groupPermissionMap = new SvelteMap(),
109
- authorizedSitesSet = $bindable(new SvelteSet<number>()),
110
- groupMembershipSet = $bindable(new SvelteSet<number>()),
111
- }: Props = $props()
112
-
113
- let userSites = $derived(
114
- plants.map(({ id, code, name }) => {
115
- return { id, code, name, isAuthorized: authorizedSitesSet.has(id) }
116
- }),
117
- )
118
- let groupMembership = $derived(
119
- groups.map(({ id, name }) => {
120
- return { id, name, isMember: groupMembershipSet.has(id) }
121
- }),
122
- )
123
- let groupPermissionValueMap = $derived(getGroupHighestPermissionValueMap(groupMembershipSet, groupPermissionMap))
124
- </script>
125
-
126
- <UserConfiguration
127
- siteLabel="Plant"
128
- bind:userAccount
129
- bind:usernameInput
130
- bind:doSendPasswordRecoveryToken={sendPasswordRecoveryToken}
131
- {userSites}
132
- {groupMembership}
133
- {permissions}
134
- {permissionValueMap}
135
- {groupPermissionValueMap}
136
- siteAccessChange={async site => {
137
- site.isAuthorized ? authorizedSitesSet.add(site.id) : authorizedSitesSet.delete(site.id)
138
- authorizedSitesSet = new Set(authorizedSitesSet)
139
- }}
140
- groupMembershipChange={async ({ id, isMember }) => {
141
- isMember ? groupMembershipSet.add(id) : groupMembershipSet.delete(id)
142
- groupMembershipSet = new Set(groupMembershipSet)
143
- }}
144
- permissionValueChange={async ({ permissionIds, value }) => {
145
- for (const id of permissionIds) {
146
- permissionValueMap.set(id, value)
147
- }
148
- permissionValueMap = new Map(permissionValueMap)
149
- }}
150
- />
151
- ```
1
+ # Svelte UserConfiguration
2
+
3
+ This Svelte component provides a user configuration interface, including user account details, site access, group membership, and permissions.
4
+
5
+ ![Screenshot of the attachment component](screenshot.png?raw=true "Screenshot")
6
+ ![Screenshot of the attachment component](pre.png?raw=true "Screenshot")
7
+ ## Install
8
+
9
+ ```sh
10
+ pnpm i @isoftdata/svelte-user-configuration
11
+ ```
12
+
13
+ ## Breaking changes
14
+
15
+ ### 2.0.0
16
+ - Require Svelte 5
17
+ - Slots -> Snippets
18
+ - Events -> Callbacks
19
+
20
+ ## Props
21
+
22
+ ### User Account Properties
23
+
24
+ | Prop | Type | Required | Default | Description |
25
+ |------|------|----------|---------|-------------|
26
+ | `userAccount` | `UserAccount` | ✅ | - | The user account information. |
27
+ | `canToggleActive` | boolean | ❌ | `true` | Whether the user can be activated/deactivated. |
28
+ | `canEditAccountInfo` | boolean | | `true` | Whether account details can be edited. |
29
+ | `doSendPasswordRecoveryToken` | boolean | ❌ | `false` | Whether to allow sending password recovery tokens. |
30
+ | `hasPermissionToChangePassword` | boolean | | `false` | Whether the user has permission to change passwords. |
31
+ | `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. |
32
+ | `passwordValidationRules` | `validationRules` of the [PasswordFields](<https://github.com/ISoft-Data-Systems/svelte-component-password-fields>) component | ❌ | `undefined` | Passwords rules to be enforced during password change. |
33
+
34
+ > The `passwordValidationRules` prop will be used during password setting when `hasPermissionToChangePassword` or `myAccountMode` are `true` .
35
+
36
+ ### Site Access Properties
37
+
38
+ | Prop | Type | Required | Default | Description |
39
+ |------|------|----------|---------|-------------|
40
+ | `userSites` | `UserSites` | ✅ | - | List of sites the user has access to. |
41
+ | `canEditSiteAccess` | boolean | ❌ | `true` | Whether site access can be edited. |
42
+
43
+ ### Group Membership Properties
44
+
45
+ | Prop | Type | Required | Default | Description |
46
+ |------|------|----------|---------|-------------|
47
+ | `groupMembership` | `GroupMembership` | ✅ | - | The user's group membership information. |
48
+ | `canEditGroupMembership` | boolean | ❌ | `true` | Whether group memberships can be edited. |
49
+
50
+ ### Permission List Properties
51
+
52
+ | Prop | Type | Required | Default | Description |
53
+ |------|------|----------|---------|-------------|
54
+ | `permissions` | `Permissions` | | - | The list of permissions for the user. |
55
+ | `permissionValueMap` | `PermissionValueMap` | | `new SvelteMap()` | A mapping of permissions to their values. **Note this *must* be a `SvelteMap`** or reactivity will not work. |
56
+ | `groupPermissionValueMap` | `GroupPermissionValueMap` | ❌ | `undefined` | A mapping of group-based permissions. |
57
+
58
+ ### Other Properties
59
+
60
+ | Prop | Type | Required | Default | Description |
61
+ |------|------|----------|---------|-------------|
62
+ | `siteLabel` | `SiteLabel` | | `"Site"` | Label for the site. |
63
+ | `userAccountInfoIcon` | `IconName` | ❌ | `"user"` | Icon for the user account section. |
64
+ | `groupMembershipIcon` | `IconName` | | `"users"` | Icon for the group membership section. |
65
+ | `permissionListIcon` | `IconName` | | `"user-lock"` | Icon for the permission list section. |
66
+ | `userSiteAccessIcon` | `IconName` | | `"industry-windows"` | Icon for the site access section. |
67
+ | `permissionListCardHeaderTitle` | `PermissionListCardHeaderTitle` | | `"Permissions"` | Title for the permission list card header. |
68
+ | `usernameInput` | `HTMLInputElement \| undefined` | | `undefined` | Reference to the username input element. |
69
+
70
+ ### Callbacks
71
+
72
+ | Prop | Type | Description |
73
+ |------|------|-------------|
74
+ | `error` | `ErrorFn` | Callback for handling errors. |
75
+ | `success` | `SuccessFn` | Callback for handling success messages. |
76
+ | `deactivateUser` | `DeactivateUserFn` | Function to deactivate a user. |
77
+ | `confirmPasswordSet` | `ConfirmPasswordSetFn` | Function called when a password is set. |
78
+ | `accountInfoChanged` | `AccountInfoChangedFn` | Function called when account info changes. |
79
+ | `sendPasswordRecoveryToken` | `SendPasswordRecoveryTokenFn` | Function to send password recovery token. |
80
+ | `generateNewActivationPIN` | `GenerateNewActivationPINFn` | Function to generate a new activation PIN. |
81
+ | `permissionValueChange` | `PermissionValueChangeFn` | Function called when permissions change. |
82
+ | `siteAccessChange` | `SiteAccessChangeFn` | Function called when site access is changed. |
83
+ | `groupMembershipChange` | `GroupMembershipChangeFn` | Function called when group membership changes. |
84
+
85
+ ## Snippets
86
+ This component provides snippets for injecting additional content.
87
+
88
+ | Snippet Name | Description |
89
+ |-----------|-------------|
90
+ | `userAccountInfo` | Slot at the end of the `userAccountInfo` component's card body |
91
+ | `siteAccess` | Slot at the end of the `siteAccess` component's card body |
92
+ | `userGroupMembership` | Slot at the end of the `userGroupMembership` component's card body |
93
+ | `permissionList` | Slot at the end of the `permissionList` component's card body |
94
+
95
+ ## Usage Example in Svelte 5 w/ Runes
96
+
97
+ ```svelte
98
+ <script lang="ts">
99
+ import { UserConfiguration, getGroupHighestPermissionValueMap } from '@isoftdata/svelte-user-configuration'
100
+
101
+ interface Props {
102
+ plants: PlantsForDropdown$result['plants']['data']
103
+ groups: Array<Group>
104
+ permissions: UserConfigurationData$result['permissions']['data']
105
+ userAccount: UserAccount
106
+ permissionValueMap?: PermissionValueMap
107
+ groupPermissionMap?: GroupPermissionMap
108
+ authorizedSitesSet?: any
109
+ groupMembershipSet?: any
110
+ }
111
+
112
+ let {
113
+ plants,
114
+ groups,
115
+ permissions,
116
+ userAccount = $bindable(),
117
+ permissionValueMap = $bindable(new SvelteMap()),
118
+ groupPermissionMap = new SvelteMap(),
119
+ authorizedSitesSet = $bindable(new SvelteSet<number>()),
120
+ groupMembershipSet = $bindable(new SvelteSet<number>()),
121
+ }: Props = $props()
122
+
123
+ let userSites = $derived(
124
+ plants.map(({ id, code, name }) => {
125
+ return { id, code, name, isAuthorized: authorizedSitesSet.has(id) }
126
+ }),
127
+ )
128
+ let groupMembership = $derived(
129
+ groups.map(({ id, name }) => {
130
+ return { id, name, isMember: groupMembershipSet.has(id) }
131
+ }),
132
+ )
133
+ let groupPermissionValueMap = $derived(getGroupHighestPermissionValueMap(groupMembershipSet, groupPermissionMap))
134
+ </script>
135
+
136
+ <UserConfiguration
137
+ siteLabel="Plant"
138
+ bind:userAccount
139
+ bind:usernameInput
140
+ bind:doSendPasswordRecoveryToken={sendPasswordRecoveryToken}
141
+ {userSites}
142
+ {groupMembership}
143
+ {permissions}
144
+ {permissionValueMap}
145
+ {groupPermissionValueMap}
146
+ siteAccessChange={async site => {
147
+ site.isAuthorized ? authorizedSitesSet.add(site.id) : authorizedSitesSet.delete(site.id)
148
+ authorizedSitesSet = new Set(authorizedSitesSet)
149
+ }}
150
+ groupMembershipChange={async ({ id, isMember }) => {
151
+ isMember ? groupMembershipSet.add(id) : groupMembershipSet.delete(id)
152
+ groupMembershipSet = new Set(groupMembershipSet)
153
+ }}
154
+ permissionValueChange={async ({ permissionIds, value }) => {
155
+ for (const id of permissionIds) {
156
+ permissionValueMap.set(id, value)
157
+ }
158
+ permissionValueMap = new SvelteMap(permissionValueMap)
159
+ }}
160
+ />
161
+ ```
@@ -1,47 +1,59 @@
1
- <script>import { getContext, tick } from "svelte";
2
- import { klona } from "klona";
3
- import { translate as defaultTranslate } from "@isoftdata/utility-string";
4
- import Modal from "@isoftdata/svelte-modal";
5
- import TextArea from "@isoftdata/svelte-textarea";
6
- let show = false;
7
- let userAccount;
8
- let lockNotes;
9
- let textarea;
10
- export let deactivateUser = void 0;
11
- export async function open(userAccountCtx) {
12
- userAccount = klona(userAccountCtx);
13
- lockNotes = userAccount.lockNotes;
14
- show = true;
15
- await tick();
16
- textarea?.select();
17
- }
18
- const { t: translate } = getContext("i18next") || { t: defaultTranslate };
19
- </script>
20
-
21
- <Modal
22
- title={translate('common:deactivate', 'Deactivate {{- userName}}', { userName: userAccount?.name ?? '' })}
23
- confirmButtonText={translate('common:deactivate', 'Deactivate')}
24
- confirmButtonColor="danger"
25
- cancelButtonText={translate('common:close', 'Close')}
26
- confirmButtonType="submit"
27
- confirmButtonFormId="deactivateUserModalForm"
28
- on:close={() => (show = false)}
29
- bind:show
30
- >
31
- <form
32
- id="deactivateUserModalForm"
33
- on:submit={async e => {
34
- e.preventDefault()
35
- userAccount ? await deactivateUser?.({ id: userAccount.id, lockNotes }) : undefined
36
- show = false
37
- }}
38
- >
39
- <TextArea
40
- bind:textarea
41
- label={translate('configuration.user.accountInfo.lockNote', 'Lock Notes')}
42
- labelClass="py-0 mb-2"
43
- style="min-height:83px;"
44
- bind:value={lockNotes}
45
- />
46
- </form>
47
- </Modal>
1
+ <script lang="ts">
2
+ import type { UserAccount } from './'
3
+ import type { i18n } from 'i18next'
4
+
5
+ import { getContext, tick } from 'svelte'
6
+ import { klona } from 'klona'
7
+ import { translate as defaultTranslate } from '@isoftdata/utility-string'
8
+
9
+ import Modal from '@isoftdata/svelte-modal'
10
+ import TextArea from '@isoftdata/svelte-textarea'
11
+
12
+ let show: boolean = $state(false)
13
+ let userAccount: UserAccount | undefined = $state()
14
+ let lockNotes: UserAccount['lockNotes'] = $state(null)
15
+ let textarea: HTMLTextAreaElement | undefined = $state()
16
+
17
+ interface Props {
18
+ deactivateUser?: ((user: { id: UserAccount['id']; lockNotes: UserAccount['lockNotes'] }) => void | Promise<void>) | undefined;
19
+ }
20
+
21
+ let { deactivateUser = undefined }: Props = $props();
22
+ export async function open(userAccountCtx: UserAccount) {
23
+ userAccount = klona(userAccountCtx)
24
+ lockNotes = userAccount.lockNotes
25
+ show = true
26
+ await tick()
27
+ textarea?.select()
28
+ }
29
+
30
+ const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
31
+ </script>
32
+
33
+ <Modal
34
+ title={translate('common:deactivate', 'Deactivate {{- userName}}', { userName: userAccount?.name ?? '' })}
35
+ confirmButtonText={translate('common:deactivate', 'Deactivate')}
36
+ confirmButtonColor="danger"
37
+ cancelButtonText={translate('common:close', 'Close')}
38
+ confirmButtonType="submit"
39
+ confirmButtonFormId="deactivateUserModalForm"
40
+ close={() => (show = false)}
41
+ bind:show
42
+ >
43
+ <form
44
+ id="deactivateUserModalForm"
45
+ onsubmit={async e => {
46
+ e.preventDefault()
47
+ userAccount ? await deactivateUser?.({ id: userAccount.id, lockNotes }) : undefined
48
+ show = false
49
+ }}
50
+ >
51
+ <TextArea
52
+ bind:textarea
53
+ label={translate('configuration.user.accountInfo.lockNote', 'Lock Notes')}
54
+ labelClass="py-0 mb-2"
55
+ style="min-height:83px;"
56
+ bind:value={lockNotes}
57
+ />
58
+ </form>
59
+ </Modal>
@@ -1,24 +1,12 @@
1
- import { SvelteComponent } from "svelte";
2
1
  import type { UserAccount } from './';
3
- declare const __propDef: {
4
- props: {
5
- deactivateUser?: ((user: {
6
- id: UserAccount["id"];
7
- lockNotes: UserAccount["lockNotes"];
8
- }) => void | Promise<void>) | undefined;
9
- open?: (userAccountCtx: UserAccount) => Promise<void>;
10
- };
11
- events: {
12
- [evt: string]: CustomEvent<any>;
13
- };
14
- slots: {};
15
- exports?: {} | undefined;
16
- bindings?: string | undefined;
17
- };
18
- export type DeactivateUserModalProps = typeof __propDef.props;
19
- export type DeactivateUserModalEvents = typeof __propDef.events;
20
- export type DeactivateUserModalSlots = typeof __propDef.slots;
21
- export default class DeactivateUserModal extends SvelteComponent<DeactivateUserModalProps, DeactivateUserModalEvents, DeactivateUserModalSlots> {
22
- get open(): (userAccountCtx: UserAccount) => Promise<void>;
2
+ interface Props {
3
+ deactivateUser?: ((user: {
4
+ id: UserAccount['id'];
5
+ lockNotes: UserAccount['lockNotes'];
6
+ }) => void | Promise<void>) | undefined;
23
7
  }
24
- export {};
8
+ declare const DeactivateUserModal: import("svelte").Component<Props, {
9
+ open: (userAccountCtx: UserAccount) => Promise<void>;
10
+ }, "">;
11
+ type DeactivateUserModal = ReturnType<typeof DeactivateUserModal>;
12
+ export default DeactivateUserModal;
@@ -1,61 +1,83 @@
1
- <script>import { getContext } from "svelte";
2
- import Modal from "@isoftdata/svelte-modal";
3
- import Input from "@isoftdata/svelte-input";
4
- import { translate as defaultTranslate } from "@isoftdata/utility-string";
5
- const { t: translate } = getContext("i18next") || { t: defaultTranslate };
6
- export let sendPasswordRecoveryToken = void 0;
7
- export let doSendPasswordRecoveryToken;
8
- let resetDate = void 0;
9
- let email = null;
10
- let show = false;
11
- export function open(passwordRecoveryEmail, lastResetDate) {
12
- email = passwordRecoveryEmail;
13
- resetDate = lastResetDate;
14
- show = true;
15
- }
16
- </script>
17
-
18
- <Modal
19
- bind:show
20
- title={translate('configuration.user.accountInfo.passwordRecovery.header', 'Password Recovery')}
21
- confirmButtonText={translate('configuration.user.accountInfo.passwordManagementModal.requestResetToken', 'Request Reset Token')}
22
- confirmButtonIcon="check"
23
- confirmButtonDisabled={!email}
24
- on:close={() => (show = false)}
25
- confirmButtonType="submit"
26
- confirmButtonFormId="passwordRecoveryForm"
27
- >
28
- <form
29
- id="passwordRecoveryForm"
30
- on:submit={async event => {
31
- event.preventDefault()
32
- try {
33
- doSendPasswordRecoveryToken = true
34
- await sendPasswordRecoveryToken?.(email)
35
- show = false
36
- } catch (err) {
37
- console.error(err)
38
- }
39
- }}
40
- >
41
- <div class="form-row">
42
- <Input
43
- label={translate('configuration.user.accountInfo.passwordManagementModal.lastPasswordSetDate', 'Last Password Set Date')}
44
- value={resetDate?.toLocaleString() ?? ''}
45
- labelParentClass="col-12 col-md-6 form-group mb-0"
46
- readonly
47
- />
48
- <Input
49
- label={translate('configuration.user.accountInfo.passwordRecoveryModal.passwordRecoveryEmail', 'Password Recovery Email')}
50
- value={email ?? ''}
51
- labelParentClass="col-12 col-md-6 form-group mb-0"
52
- readonly
53
- />
54
- {#if !email}
55
- <div class="alert alert-danger mt-3 mb-0">
56
- {translate('configuration.user.accountInfo.passwordRecovery.noRecoveryEmail', 'No recovery email has been set for this user.')}
57
- </div>
58
- {/if}
59
- </div>
60
- </form>
61
- </Modal>
1
+ <script lang="ts">
2
+ import type { i18n } from 'i18next'
3
+
4
+ import { getContext } from 'svelte'
5
+ import Modal from '@isoftdata/svelte-modal'
6
+ import Input from '@isoftdata/svelte-input'
7
+ import { translate as defaultTranslate } from '@isoftdata/utility-string'
8
+
9
+ const { t: translate } = getContext<i18n>('i18next') || { t: defaultTranslate }
10
+
11
+ interface Props {
12
+ sendPasswordRecoveryToken?: ((email: string | null) => void | Promise<void>) | undefined
13
+ doSendPasswordRecoveryToken: boolean
14
+ }
15
+
16
+ let { sendPasswordRecoveryToken = undefined, doSendPasswordRecoveryToken = $bindable() }: Props = $props()
17
+ let resetDate: Date | null | undefined = $state(undefined)
18
+ let email: string | null = $state(null)
19
+ let show: boolean = $state(false)
20
+
21
+ export function open(passwordRecoveryEmail: typeof email, lastResetDate: Date | null | undefined) {
22
+ email = passwordRecoveryEmail
23
+ resetDate = lastResetDate
24
+ show = true
25
+ }
26
+ </script>
27
+
28
+ <Modal
29
+ bind:show
30
+ title={translate('configuration.user.accountInfo.passwordRecovery.header', 'Password Recovery')}
31
+ confirmButtonText={translate(
32
+ 'configuration.user.accountInfo.passwordManagementModal.requestResetToken',
33
+ 'Request Reset Token',
34
+ )}
35
+ confirmButtonIcon="check"
36
+ confirmButtonDisabled={!email}
37
+ close={() => (show = false)}
38
+ confirmButtonType="submit"
39
+ confirmButtonFormId="passwordRecoveryForm"
40
+ >
41
+ <form
42
+ id="passwordRecoveryForm"
43
+ onsubmit={async event => {
44
+ event.preventDefault()
45
+ try {
46
+ doSendPasswordRecoveryToken = true
47
+ await sendPasswordRecoveryToken?.(email)
48
+ show = false
49
+ } catch (err) {
50
+ console.error(err)
51
+ }
52
+ }}
53
+ >
54
+ <div class="row">
55
+ <Input
56
+ label={translate(
57
+ 'configuration.user.accountInfo.passwordManagementModal.lastPasswordSetDate',
58
+ 'Last Password Set Date',
59
+ )}
60
+ value={resetDate?.toLocaleString() ?? ''}
61
+ labelParentClass="col-12 col-md-6 form-group mb-0"
62
+ readonly
63
+ />
64
+ <Input
65
+ label={translate(
66
+ 'configuration.user.accountInfo.passwordRecoveryModal.passwordRecoveryEmail',
67
+ 'Password Recovery Email',
68
+ )}
69
+ value={email ?? ''}
70
+ labelParentClass="col-12 col-md-6 form-group mb-0"
71
+ readonly
72
+ />
73
+ {#if !email}
74
+ <div class="alert alert-danger mt-3 mb-0">
75
+ {translate(
76
+ 'configuration.user.accountInfo.passwordRecovery.noRecoveryEmail',
77
+ 'No recovery email has been set for this user.',
78
+ )}
79
+ </div>
80
+ {/if}
81
+ </div>
82
+ </form>
83
+ </Modal>
@@ -1,21 +1,9 @@
1
- import { SvelteComponent } from "svelte";
2
- declare const __propDef: {
3
- props: {
4
- sendPasswordRecoveryToken?: ((email: string | null) => void | Promise<void>) | undefined;
5
- doSendPasswordRecoveryToken: boolean;
6
- open?: (passwordRecoveryEmail: string | null, lastResetDate: Date | null | undefined) => void;
7
- };
8
- events: {
9
- [evt: string]: CustomEvent<any>;
10
- };
11
- slots: {};
12
- exports?: {} | undefined;
13
- bindings?: string | undefined;
14
- };
15
- export type PasswordRecoveryModalProps = typeof __propDef.props;
16
- export type PasswordRecoveryModalEvents = typeof __propDef.events;
17
- export type PasswordRecoveryModalSlots = typeof __propDef.slots;
18
- export default class PasswordRecoveryModal extends SvelteComponent<PasswordRecoveryModalProps, PasswordRecoveryModalEvents, PasswordRecoveryModalSlots> {
19
- get open(): (passwordRecoveryEmail: string | null, lastResetDate: Date | null | undefined) => void;
1
+ interface Props {
2
+ sendPasswordRecoveryToken?: ((email: string | null) => void | Promise<void>) | undefined;
3
+ doSendPasswordRecoveryToken: boolean;
20
4
  }
21
- export {};
5
+ declare const PasswordRecoveryModal: import("svelte").Component<Props, {
6
+ open: (passwordRecoveryEmail: string | null, lastResetDate: Date | null | undefined) => void;
7
+ }, "doSendPasswordRecoveryToken">;
8
+ type PasswordRecoveryModal = ReturnType<typeof PasswordRecoveryModal>;
9
+ export default PasswordRecoveryModal;