@byline/ui 2.4.0 → 2.4.2

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.
Files changed (95) hide show
  1. package/dist/react.d.ts +10 -18
  2. package/dist/react.js +2 -15
  3. package/dist/{admin/components/collections → widgets/diff-viewer}/diff-modal.d.ts +8 -1
  4. package/dist/{admin/components/collections → widgets/diff-viewer}/diff-modal.js +4 -6
  5. package/dist/widgets/diff-viewer/diff-modal.module.js +14 -0
  6. package/dist/{admin/components/collections → widgets/diff-viewer}/diff-modal_module.css +9 -9
  7. package/dist/{admin/components/collections → widgets/status-badge}/status-badge.js +1 -1
  8. package/dist/{admin/components/collections → widgets/status-badge}/status-badge.module.js +3 -3
  9. package/dist/{admin/components/collections → widgets/status-badge}/status-badge_module.css +3 -3
  10. package/package.json +2 -4
  11. package/src/react.ts +12 -34
  12. package/src/{admin/components/collections → widgets/diff-viewer}/diff-modal.tsx +16 -5
  13. package/src/{admin/components/collections → widgets/status-badge}/status-badge.tsx +1 -1
  14. package/dist/admin/components/admin-account/change-password.d.ts +0 -8
  15. package/dist/admin/components/admin-account/change-password.js +0 -192
  16. package/dist/admin/components/admin-account/change-password.module.js +0 -8
  17. package/dist/admin/components/admin-account/change-password_module.css +0 -27
  18. package/dist/admin/components/admin-account/container.d.ts +0 -29
  19. package/dist/admin/components/admin-account/container.js +0 -299
  20. package/dist/admin/components/admin-account/container.module.js +0 -28
  21. package/dist/admin/components/admin-account/container_module.css +0 -106
  22. package/dist/admin/components/admin-account/update.d.ts +0 -8
  23. package/dist/admin/components/admin-account/update.js +0 -207
  24. package/dist/admin/components/admin-account/update.module.js +0 -8
  25. package/dist/admin/components/admin-account/update_module.css +0 -27
  26. package/dist/admin/components/admin-permissions/inspector.d.ts +0 -4
  27. package/dist/admin/components/admin-permissions/inspector.js +0 -284
  28. package/dist/admin/components/admin-permissions/inspector.module.js +0 -56
  29. package/dist/admin/components/admin-permissions/inspector_module.css +0 -238
  30. package/dist/admin/components/admin-roles/create.d.ts +0 -7
  31. package/dist/admin/components/admin-roles/create.js +0 -177
  32. package/dist/admin/components/admin-roles/create.module.js +0 -8
  33. package/dist/admin/components/admin-roles/create_module.css +0 -27
  34. package/dist/admin/components/admin-roles/permissions.d.ts +0 -10
  35. package/dist/admin/components/admin-roles/permissions.js +0 -303
  36. package/dist/admin/components/admin-roles/permissions.module.js +0 -44
  37. package/dist/admin/components/admin-roles/permissions_module.css +0 -192
  38. package/dist/admin/components/admin-roles/update.d.ts +0 -8
  39. package/dist/admin/components/admin-roles/update.js +0 -166
  40. package/dist/admin/components/admin-roles/update.module.js +0 -8
  41. package/dist/admin/components/admin-roles/update_module.css +0 -27
  42. package/dist/admin/components/admin-users/create.d.ts +0 -8
  43. package/dist/admin/components/admin-users/create.js +0 -268
  44. package/dist/admin/components/admin-users/create.module.js +0 -10
  45. package/dist/admin/components/admin-users/create_module.css +0 -45
  46. package/dist/admin/components/admin-users/roles.d.ts +0 -11
  47. package/dist/admin/components/admin-users/roles.js +0 -148
  48. package/dist/admin/components/admin-users/roles.module.js +0 -18
  49. package/dist/admin/components/admin-users/roles_module.css +0 -75
  50. package/dist/admin/components/admin-users/set-password.d.ts +0 -8
  51. package/dist/admin/components/admin-users/set-password.js +0 -170
  52. package/dist/admin/components/admin-users/set-password.module.js +0 -9
  53. package/dist/admin/components/admin-users/set-password_module.css +0 -31
  54. package/dist/admin/components/admin-users/update.d.ts +0 -8
  55. package/dist/admin/components/admin-users/update.js +0 -254
  56. package/dist/admin/components/admin-users/update.module.js +0 -9
  57. package/dist/admin/components/admin-users/update_module.css +0 -34
  58. package/dist/admin/components/auth/sign-in-form.d.ts +0 -12
  59. package/dist/admin/components/auth/sign-in-form.js +0 -115
  60. package/dist/admin/components/auth/sign-in-form.module.js +0 -12
  61. package/dist/admin/components/auth/sign-in-form_module.css +0 -41
  62. package/dist/admin/components/collections/diff-modal.module.js +0 -14
  63. package/dist/services/admin-services-context.d.ts +0 -16
  64. package/dist/services/admin-services-context.js +0 -13
  65. package/dist/services/admin-services-types.d.ts +0 -129
  66. package/dist/services/admin-services-types.js +0 -1
  67. package/src/admin/components/admin-account/change-password.module.css +0 -40
  68. package/src/admin/components/admin-account/change-password.tsx +0 -232
  69. package/src/admin/components/admin-account/container.module.css +0 -158
  70. package/src/admin/components/admin-account/container.tsx +0 -230
  71. package/src/admin/components/admin-account/update.module.css +0 -40
  72. package/src/admin/components/admin-account/update.tsx +0 -263
  73. package/src/admin/components/admin-permissions/inspector.module.css +0 -326
  74. package/src/admin/components/admin-permissions/inspector.tsx +0 -298
  75. package/src/admin/components/admin-roles/create.module.css +0 -40
  76. package/src/admin/components/admin-roles/create.tsx +0 -218
  77. package/src/admin/components/admin-roles/permissions.module.css +0 -279
  78. package/src/admin/components/admin-roles/permissions.tsx +0 -396
  79. package/src/admin/components/admin-roles/update.module.css +0 -40
  80. package/src/admin/components/admin-roles/update.tsx +0 -218
  81. package/src/admin/components/admin-users/create.module.css +0 -63
  82. package/src/admin/components/admin-users/create.tsx +0 -323
  83. package/src/admin/components/admin-users/roles.module.css +0 -119
  84. package/src/admin/components/admin-users/roles.tsx +0 -172
  85. package/src/admin/components/admin-users/set-password.module.css +0 -46
  86. package/src/admin/components/admin-users/set-password.tsx +0 -199
  87. package/src/admin/components/admin-users/update.module.css +0 -49
  88. package/src/admin/components/admin-users/update.tsx +0 -328
  89. package/src/admin/components/auth/sign-in-form.module.css +0 -62
  90. package/src/admin/components/auth/sign-in-form.tsx +0 -132
  91. package/src/services/admin-services-context.tsx +0 -35
  92. package/src/services/admin-services-types.ts +0 -177
  93. /package/dist/{admin/components/collections → widgets/status-badge}/status-badge.d.ts +0 -0
  94. /package/src/{admin/components/collections → widgets/diff-viewer}/diff-modal.module.css +0 -0
  95. /package/src/{admin/components/collections → widgets/status-badge}/status-badge.module.css +0 -0
@@ -1,40 +0,0 @@
1
- /**
2
- * ChangeAccountPassword — self-service password-change form (drawer body).
3
- *
4
- * Override handles:
5
- * .byline-account-change-password-wrap — outer container
6
- * .byline-account-change-password-form — vertical-stack form element
7
- * .byline-account-change-password-actions — Cancel/Save row
8
- * .byline-account-change-password-action — buttons in the actions row
9
- */
10
-
11
- .wrap,
12
- :global(.byline-account-change-password-wrap) {
13
- display: flex;
14
- flex-direction: column;
15
- gap: var(--spacing-8);
16
- padding: var(--spacing-4);
17
- margin-top: var(--spacing-4);
18
- }
19
-
20
- .form,
21
- :global(.byline-account-change-password-form) {
22
- display: flex;
23
- flex-direction: column;
24
- gap: var(--spacing-16);
25
- padding-top: var(--spacing-8);
26
- }
27
-
28
- .actions,
29
- :global(.byline-account-change-password-actions) {
30
- display: flex;
31
- align-items: center;
32
- justify-content: flex-end;
33
- gap: var(--spacing-8);
34
- margin-top: var(--spacing-16);
35
- }
36
-
37
- .action,
38
- :global(.byline-account-change-password-action) {
39
- min-width: 4rem;
40
- }
@@ -1,232 +0,0 @@
1
- 'use client'
2
-
3
- /**
4
- * This Source Code is subject to the terms of the Mozilla Public
5
- * License, v. 2.0. If a copy of the MPL was not distributed with this
6
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
- *
8
- * Copyright (c) Infonomic Company Limited
9
- */
10
-
11
- /**
12
- * Self-service change-password drawer form.
13
- *
14
- * Distinct from the admin-users `set-password.tsx`:
15
- *
16
- * - Requires the current password as defence against
17
- * session-hijack abuse. The server verifies it against the
18
- * stored hash before swapping in the new one — wrong current
19
- * password surfaces as `admin.account.invalidCurrentPassword`.
20
- * - Confirmation field catches typos before round-trip.
21
- *
22
- * Caveat: changing the password here does not revoke other active
23
- * sessions today. Existing access tokens stay valid until expiry
24
- * (~15 min); a "sign out everywhere on password change" follow-up
25
- * will close that gap.
26
- */
27
-
28
- import { useState } from 'react'
29
- import { revalidateLogic, useForm } from '@tanstack/react-form-start'
30
-
31
- import type { AccountResponse } from '@byline/admin/admin-account'
32
- import { passwordSchema } from '@byline/core/validation'
33
- import cx from 'classnames'
34
- import { z } from 'zod'
35
-
36
- import { useBylineAdminServices } from '../../../services/admin-services-context.js'
37
- import { Alert, Button, InputPassword, LoaderEllipsis } from '../../../uikit.js'
38
- import styles from './change-password.module.css'
39
-
40
- const changePasswordFormSchema = z
41
- .object({
42
- currentPassword: z.string().min(1, { message: 'Please enter your current password' }),
43
- newPassword: passwordSchema,
44
- confirm: z.string({ message: 'Please confirm the new password' }),
45
- })
46
- .refine((v) => v.newPassword === v.confirm, {
47
- message: 'New passwords do not match',
48
- path: ['confirm'],
49
- })
50
-
51
- type ChangePasswordValues = z.infer<typeof changePasswordFormSchema>
52
-
53
- interface ChangePasswordProps {
54
- account: AccountResponse
55
- onClose?: () => void
56
- onSuccess?: (account: AccountResponse) => void
57
- }
58
-
59
- export function ChangeAccountPassword({ account, onClose, onSuccess }: ChangePasswordProps) {
60
- const { changeAccountPassword } = useBylineAdminServices()
61
- const [formError, setFormError] = useState<string | null>(null)
62
- const [successMessage, setSuccessMessage] = useState<string | null>(null)
63
-
64
- const form = useForm({
65
- defaultValues: { currentPassword: '', newPassword: '', confirm: '' } as ChangePasswordValues,
66
- validationLogic: revalidateLogic({
67
- mode: 'blur',
68
- modeAfterSubmission: 'change',
69
- }),
70
- validators: {
71
- onDynamic: changePasswordFormSchema,
72
- },
73
- onSubmit: async ({ value }) => {
74
- setFormError(null)
75
- setSuccessMessage(null)
76
- try {
77
- const updated = await changeAccountPassword({
78
- data: {
79
- vid: account.vid,
80
- currentPassword: value.currentPassword,
81
- newPassword: value.newPassword,
82
- },
83
- })
84
- setSuccessMessage('Password updated.')
85
- form.reset({ currentPassword: '', newPassword: '', confirm: '' })
86
- onSuccess?.(updated)
87
- } catch (err) {
88
- const code = getErrorCode(err)
89
- if (code === 'admin.account.invalidCurrentPassword') {
90
- form.setFieldMeta('currentPassword', (meta) => ({
91
- ...meta,
92
- errorMap: { ...meta.errorMap, onServer: 'Current password is incorrect.' },
93
- errors: ['Current password is incorrect.'],
94
- }))
95
- return
96
- }
97
- if (code === 'admin.users.versionConflict') {
98
- setFormError(
99
- 'Your account has been modified elsewhere since you opened this form. Reload to refresh and try again.'
100
- )
101
- return
102
- }
103
- if (code === 'admin.account.notFound') {
104
- setFormError('Your admin account could not be found. Please sign in again.')
105
- return
106
- }
107
- setFormError('Could not change the password. Please try again.')
108
- }
109
- },
110
- })
111
-
112
- return (
113
- <div className={cx('byline-account-change-password-wrap', styles.wrap)}>
114
- <form
115
- noValidate
116
- onSubmit={(event) => {
117
- event.preventDefault()
118
- event.stopPropagation()
119
- void form.handleSubmit()
120
- }}
121
- className={cx('byline-account-change-password-form', styles.form)}
122
- >
123
- {formError ? <Alert intent="danger">{formError}</Alert> : null}
124
- {successMessage ? <Alert intent="success">{successMessage}</Alert> : null}
125
-
126
- <p className="muted">
127
- Other active sessions will continue to work until their tokens expire. Sign out elsewhere
128
- if you suspect another device has been compromised.
129
- </p>
130
-
131
- <form.Field name="currentPassword">
132
- {(field) => (
133
- <InputPassword
134
- label="Current password"
135
- id="currentPassword"
136
- name={field.name}
137
- value={field.state.value}
138
- onBlur={field.handleBlur}
139
- onChange={(e) => field.handleChange(e.currentTarget.value)}
140
- error={field.state.meta.errors.length > 0}
141
- errorText={firstError(field.state.meta.errors)}
142
- autoComplete="current-password"
143
- required
144
- />
145
- )}
146
- </form.Field>
147
-
148
- <form.Field name="newPassword">
149
- {(field) => (
150
- <InputPassword
151
- label="New password"
152
- id="newPassword"
153
- name={field.name}
154
- value={field.state.value}
155
- onBlur={field.handleBlur}
156
- onChange={(e) => field.handleChange(e.currentTarget.value)}
157
- error={field.state.meta.errors.length > 0}
158
- errorText={firstError(field.state.meta.errors)}
159
- autoComplete="new-password"
160
- required
161
- />
162
- )}
163
- </form.Field>
164
-
165
- <form.Field name="confirm">
166
- {(field) => (
167
- <InputPassword
168
- label="Confirm new password"
169
- id="confirm"
170
- name={field.name}
171
- value={field.state.value}
172
- onBlur={field.handleBlur}
173
- onChange={(e) => field.handleChange(e.currentTarget.value)}
174
- error={field.state.meta.errors.length > 0}
175
- errorText={firstError(field.state.meta.errors)}
176
- autoComplete="new-password"
177
- required
178
- />
179
- )}
180
- </form.Field>
181
-
182
- <div className={cx('byline-account-change-password-actions', styles.actions)}>
183
- <Button
184
- type="button"
185
- intent="secondary"
186
- size="sm"
187
- onClick={onClose}
188
- className={cx('byline-account-change-password-action', styles.action)}
189
- >
190
- {successMessage ? 'Close' : 'Cancel'}
191
- </Button>
192
- <form.Subscribe
193
- selector={(state) => ({
194
- canSubmit: state.canSubmit,
195
- isSubmitting: state.isSubmitting,
196
- isDirty: state.isDirty,
197
- })}
198
- >
199
- {({ canSubmit, isSubmitting }) => (
200
- <Button
201
- size="sm"
202
- intent="primary"
203
- type="submit"
204
- disabled={!canSubmit || isSubmitting}
205
- className={cx('byline-account-change-password-action', styles.action)}
206
- >
207
- {isSubmitting === true ? <LoaderEllipsis size={42} /> : 'Save'}
208
- </Button>
209
- )}
210
- </form.Subscribe>
211
- </div>
212
- </form>
213
- </div>
214
- )
215
- }
216
-
217
- function firstError(errors: readonly unknown[]): string | undefined {
218
- for (const err of errors) {
219
- if (typeof err === 'string') return err
220
- if (err && typeof err === 'object' && 'message' in err) {
221
- const msg = (err as { message?: unknown }).message
222
- if (typeof msg === 'string') return msg
223
- }
224
- }
225
- return undefined
226
- }
227
-
228
- function getErrorCode(err: unknown): string | null {
229
- return typeof (err as { code?: unknown })?.code === 'string'
230
- ? (err as { code: string }).code
231
- : null
232
- }
@@ -1,158 +0,0 @@
1
- /**
2
- * AccountSelfContainer — self-service account dashboard with edit drawers.
3
- *
4
- * Override handles:
5
- * .byline-account-grid — outer two-column grid
6
- * .byline-account-column — column wrapper (vertical card stack)
7
- * .byline-account-section — single bordered section card
8
- * .byline-account-section-head — section title + edit-icon row
9
- * .byline-account-line — single key/value text line
10
- * .byline-account-cta-line — paragraph above the in-card primary CTA
11
- * .byline-account-meta — small metadata block (created/updated/last login)
12
- * .byline-account-status — status colour modifier (enabled / disabled)
13
- * .byline-account-status-on
14
- * .byline-account-status-off
15
- * .byline-account-status-help — italic helper line on Account Status card
16
- * .byline-account-drawer — drawer responsive width override
17
- * .byline-account-drawer-body — drawer content container
18
- * .byline-account-drawer-scroll — drawer scrollable inner viewport
19
- * .byline-account-drawer-skip — sr-only "no action" focus shim
20
- */
21
-
22
- .grid,
23
- :global(.byline-account-grid) {
24
- display: flex;
25
- flex-direction: column;
26
- gap: var(--spacing-16);
27
- margin-bottom: var(--spacing-48);
28
- }
29
-
30
- @media (min-width: 40rem) {
31
- .grid,
32
- :global(.byline-account-grid) {
33
- display: grid;
34
- grid-template-columns: 1fr 1fr;
35
- }
36
- }
37
-
38
- .column,
39
- :global(.byline-account-column) {
40
- display: flex;
41
- flex-direction: column;
42
- gap: var(--spacing-16);
43
- margin-bottom: var(--spacing-16);
44
- }
45
-
46
- .section,
47
- :global(.byline-account-section) {
48
- padding: var(--spacing-16);
49
- border: var(--border-width-thin) var(--border-style-solid) var(--gray-100);
50
- background-color: var(--canvas-25);
51
- border-radius: var(--border-radius-sm);
52
- }
53
-
54
- .section-head,
55
- :global(.byline-account-section-head) {
56
- display: flex;
57
- align-items: center;
58
- justify-content: space-between;
59
- margin-bottom: var(--spacing-8);
60
- }
61
-
62
- .line,
63
- :global(.byline-account-line) {
64
- margin-bottom: 0;
65
- }
66
-
67
- .cta-line,
68
- :global(.byline-account-cta-line) {
69
- margin-bottom: var(--spacing-12);
70
- }
71
-
72
- .meta,
73
- :global(.byline-account-meta) {
74
- margin-top: var(--spacing-16);
75
- font-size: var(--font-size-xs);
76
- }
77
-
78
- .status-on,
79
- :global(.byline-account-status-on) {
80
- color: var(--green-600);
81
- }
82
-
83
- .status-off,
84
- :global(.byline-account-status-off) {
85
- color: var(--red-600);
86
- }
87
-
88
- .status-help,
89
- :global(.byline-account-status-help) {
90
- margin-top: var(--spacing-12);
91
- margin-bottom: 0;
92
- font-size: var(--font-size-xs);
93
- }
94
-
95
- /*
96
- * Italic helper for "Not set" placeholders. Replaces the Tailwind
97
- * `italic` utility we used pre-lift; with the component now in a
98
- * published package, Tailwind's source scanner doesn't see the class
99
- * string in the host so the rule was never generated.
100
- */
101
- .not-set,
102
- :global(.byline-account-not-set) {
103
- font-style: italic;
104
- }
105
-
106
- .drawer,
107
- :global(.byline-account-drawer) {
108
- /* Width handled by uikit Drawer prop; no additional class needed today. */
109
- }
110
-
111
- @media (min-width: 48rem) {
112
- .drawer,
113
- :global(.byline-account-drawer) {
114
- width: 500px;
115
- }
116
- }
117
-
118
- .drawer-body,
119
- :global(.byline-account-drawer-body) {
120
- padding: var(--spacing-8);
121
- }
122
-
123
- .drawer-scroll,
124
- :global(.byline-account-drawer-scroll) {
125
- max-height: calc(100vh - 160px);
126
- overflow-y: auto;
127
- }
128
-
129
- .drawer-skip,
130
- :global(.byline-account-drawer-skip) {
131
- position: absolute;
132
- width: 1px;
133
- height: 1px;
134
- padding: 0;
135
- margin: -1px;
136
- overflow: hidden;
137
- clip: rect(0, 0, 0, 0);
138
- white-space: nowrap;
139
- border: 0;
140
- }
141
-
142
- :is([data-theme="dark"], :global(.dark)) {
143
- .section,
144
- :global(.byline-account-section) {
145
- border-color: var(--gray-700);
146
- background-color: var(--canvas-800);
147
- }
148
-
149
- .status-on,
150
- :global(.byline-account-status-on) {
151
- color: var(--green-400);
152
- }
153
-
154
- .status-off,
155
- :global(.byline-account-status-off) {
156
- color: var(--red-400);
157
- }
158
- }
@@ -1,230 +0,0 @@
1
- 'use client'
2
-
3
- /**
4
- * This Source Code is subject to the terms of the Mozilla Public
5
- * License, v. 2.0. If a copy of the MPL was not distributed with this
6
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
- *
8
- * Copyright (c) Infonomic Company Limited
9
- */
10
-
11
- /**
12
- * Self-service account container.
13
- *
14
- * Same drawer pattern as `admin-users/ui/container.tsx` but
15
- * narrower: only Profile and Password sections (no Roles, no
16
- * Delete) — those are admin-only actions on someone else, not
17
- * self-service. Each card surfaces the read-only summary plus an
18
- * "Edit" affordance that opens the matching drawer.
19
- *
20
- * Forms lift the fresh `AccountResponse` back into local state on
21
- * success so the container's bumped `vid` is in hand for any
22
- * subsequent edit without a refetch.
23
- *
24
- * Stable override handles: see `container.module.css`.
25
- */
26
-
27
- import type React from 'react'
28
- import { useState } from 'react'
29
-
30
- import type { AccountResponse } from '@byline/admin/admin-account'
31
- import cx from 'classnames'
32
-
33
- import { LocalDateTime } from '../../../fields/local-date-time.js'
34
- import { Button, CloseIcon, Drawer, EditIcon, IconButton } from '../../../uikit.js'
35
- import { ChangeAccountPassword } from './change-password.js'
36
- import styles from './container.module.css'
37
- import { UpdateAccount } from './update.js'
38
-
39
- type ComponentKey = 'update' | 'change_password' | 'empty'
40
-
41
- interface PanelProps {
42
- account: AccountResponse
43
- onClose?: () => void
44
- onSuccess?: (account: AccountResponse) => void
45
- }
46
-
47
- const panels: Record<ComponentKey, { title: string; component: React.ComponentType<PanelProps> }> =
48
- {
49
- update: { title: 'Profile', component: UpdateAccount },
50
- change_password: { title: 'Change Password', component: ChangeAccountPassword },
51
- empty: { title: '', component: () => null },
52
- }
53
-
54
- function ContainerSection({
55
- title,
56
- onEdit,
57
- children,
58
- }: {
59
- title: string
60
- onEdit?: () => void
61
- children: React.ReactNode
62
- }) {
63
- return (
64
- <div className={cx('byline-account-section', styles.section)}>
65
- <div className={cx('byline-account-section-head', styles['section-head'])}>
66
- <h2>{title}</h2>
67
- {onEdit ? (
68
- <IconButton variant="text" onClick={onEdit} aria-label={`Edit ${title}`}>
69
- <EditIcon width="20px" height="20px" />
70
- </IconButton>
71
- ) : null}
72
- </div>
73
- <div>{children}</div>
74
- </div>
75
- )
76
- }
77
-
78
- interface AccountSelfContainerProps {
79
- account: AccountResponse
80
- }
81
-
82
- export function AccountSelfContainer({ account }: AccountSelfContainerProps) {
83
- const [currentAccount, setCurrentAccount] = useState<AccountResponse>(account)
84
- const [current, setCurrent] = useState<ComponentKey>('empty')
85
- const [isDrawerOpen, setIsDrawerOpen] = useState(false)
86
-
87
- const openDrawer = (key: ComponentKey) => () => {
88
- setCurrent(key)
89
- setIsDrawerOpen(true)
90
- }
91
- const closeDrawer = () => {
92
- setCurrent('empty')
93
- setIsDrawerOpen(false)
94
- }
95
- const handleSuccess = (updated: AccountResponse) => {
96
- setCurrentAccount(updated)
97
- }
98
-
99
- const Panel = panels[current].component
100
-
101
- return (
102
- <>
103
- <div className={cx('byline-account-grid', styles.grid)}>
104
- <div className={cx('byline-account-column', styles.column)}>
105
- <ContainerSection title="Profile" onEdit={openDrawer('update')}>
106
- <p className={cx('byline-account-line', styles.line)}>
107
- <span className="muted">Email:</span> {currentAccount.email}
108
- </p>
109
- <p className={cx('byline-account-line', styles.line)}>
110
- <span className="muted">Given name:</span>{' '}
111
- {currentAccount.given_name ?? (
112
- <span className={cx('muted', 'byline-account-not-set', styles['not-set'])}>
113
- Not set
114
- </span>
115
- )}
116
- </p>
117
- <p className={cx('byline-account-line', styles.line)}>
118
- <span className="muted">Family name:</span>{' '}
119
- {currentAccount.family_name ?? (
120
- <span className={cx('muted', 'byline-account-not-set', styles['not-set'])}>
121
- Not set
122
- </span>
123
- )}
124
- </p>
125
- <p className={cx('byline-account-cta-line', styles['cta-line'])}>
126
- <span className="muted">Username:</span>{' '}
127
- {currentAccount.username ?? (
128
- <span className={cx('muted', 'byline-account-not-set', styles['not-set'])}>
129
- Not set
130
- </span>
131
- )}
132
- </p>
133
- <Button size="sm" onClick={openDrawer('update')}>
134
- Edit Profile
135
- </Button>
136
- <div className={cx('muted', 'byline-account-meta', styles.meta)}>
137
- <p>
138
- <span className="font-bold">Created:&nbsp;</span>
139
- <LocalDateTime value={currentAccount.created_at} />
140
- </p>
141
- <p>
142
- <span className="font-bold">Updated:&nbsp;</span>
143
- <LocalDateTime value={currentAccount.updated_at} />
144
- </p>
145
- <p className={cx('byline-account-line', styles.line)}>
146
- <span className="font-bold">Last login:&nbsp;</span>
147
- <LocalDateTime value={currentAccount.last_login} fallback="Never" />
148
- </p>
149
- </div>
150
- </ContainerSection>
151
- </div>
152
-
153
- <div className={cx('byline-account-column', styles.column)}>
154
- <ContainerSection title="Password" onEdit={openDrawer('change_password')}>
155
- <p className={cx('byline-account-cta-line', styles['cta-line'])}>
156
- Change the password used to sign in to the admin. You'll need to enter your current
157
- password to confirm the change.
158
- </p>
159
- <Button size="sm" onClick={openDrawer('change_password')}>
160
- Change Password
161
- </Button>
162
- </ContainerSection>
163
-
164
- <ContainerSection title="Account Status">
165
- <p className={cx('byline-account-line', styles.line)}>
166
- <span className="muted">Super admin:</span>{' '}
167
- {currentAccount.is_super_admin ? 'Yes' : 'No'}
168
- </p>
169
- <p className={cx('byline-account-line', styles.line)}>
170
- <span className="muted">Email verified:</span>{' '}
171
- {currentAccount.is_email_verified ? 'Yes' : 'No'}
172
- </p>
173
- <p className={cx('byline-account-line', styles.line)}>
174
- <span className="muted">Status:</span>{' '}
175
- <span
176
- className={
177
- currentAccount.is_enabled
178
- ? cx('byline-account-status-on', styles['status-on'])
179
- : cx('byline-account-status-off', styles['status-off'])
180
- }
181
- >
182
- {currentAccount.is_enabled ? 'Enabled' : 'Disabled'}
183
- </span>
184
- </p>
185
- <p className={cx('muted', 'byline-account-status-help', styles['status-help'])}>
186
- These flags are managed by an admin with the appropriate permissions and are not
187
- self-editable.
188
- </p>
189
- </ContainerSection>
190
- </div>
191
- </div>
192
-
193
- <Drawer
194
- id="admin-account-drawer"
195
- closeOnOverlayClick={false}
196
- width="medium"
197
- topOffset="46px"
198
- isOpen={isDrawerOpen}
199
- onDismiss={closeDrawer}
200
- className={cx('byline-account-drawer', styles.drawer)}
201
- >
202
- <Drawer.Container
203
- aria-hidden={!isDrawerOpen}
204
- className={cx('byline-account-drawer-body', styles['drawer-body'])}
205
- >
206
- <Drawer.TopActions>
207
- <button
208
- type="button"
209
- tabIndex={0}
210
- className={cx('byline-account-drawer-skip', styles['drawer-skip'])}
211
- >
212
- no action
213
- </button>
214
- <IconButton aria-label="Close" size="sm" onClick={closeDrawer}>
215
- <CloseIcon width="14px" height="14px" svgClassName="white-icon stroke-white" />
216
- </IconButton>
217
- </Drawer.TopActions>
218
- <Drawer.Header>
219
- <h2>{panels[current].title}</h2>
220
- </Drawer.Header>
221
- <Drawer.Content>
222
- <div className={cx('byline-account-drawer-scroll', styles['drawer-scroll'])}>
223
- <Panel account={currentAccount} onClose={closeDrawer} onSuccess={handleSuccess} />
224
- </div>
225
- </Drawer.Content>
226
- </Drawer.Container>
227
- </Drawer>
228
- </>
229
- )
230
- }
@@ -1,40 +0,0 @@
1
- /**
2
- * UpdateAccount — self-service profile form (drawer body).
3
- *
4
- * Override handles:
5
- * .byline-account-update-wrap — outer container
6
- * .byline-account-update-form — vertical-stack form element
7
- * .byline-account-update-actions — Cancel/Save row
8
- * .byline-account-update-action — buttons in the actions row
9
- */
10
-
11
- .wrap,
12
- :global(.byline-account-update-wrap) {
13
- display: flex;
14
- flex-direction: column;
15
- gap: var(--spacing-8);
16
- padding: var(--spacing-4);
17
- margin-top: var(--spacing-4);
18
- }
19
-
20
- .form,
21
- :global(.byline-account-update-form) {
22
- display: flex;
23
- flex-direction: column;
24
- gap: var(--spacing-16);
25
- padding-top: var(--spacing-8);
26
- }
27
-
28
- .actions,
29
- :global(.byline-account-update-actions) {
30
- display: flex;
31
- align-items: center;
32
- justify-content: flex-end;
33
- gap: var(--spacing-8);
34
- margin-top: var(--spacing-16);
35
- }
36
-
37
- .action,
38
- :global(.byline-account-update-action) {
39
- min-width: 4rem;
40
- }