@meith/web 0.31.0 → 0.33.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/app/(board)/[slug]/feed.xml/route.ts +5 -3
- package/app/(board)/[slug]/new/page.tsx +5 -0
- package/app/(board)/[slug]/page.tsx +7 -1
- package/app/(board)/discover/[view]/page.tsx +6 -1
- package/app/(board)/member/[id]/page.tsx +3 -5
- package/app/(board)/member/[id]/reputation/page.tsx +8 -15
- package/app/(board)/members/page.tsx +3 -8
- package/app/(board)/messages/[id]/page.tsx +3 -7
- package/app/(board)/messages/page.tsx +3 -5
- package/app/(board)/modcp/ip/page.tsx +3 -5
- package/app/(board)/modcp/plugins/[key]/[[...path]]/page.tsx +84 -0
- package/app/(board)/moderation/reports/page.tsx +53 -15
- package/app/(board)/moderation/warn/page.tsx +3 -6
- package/app/(board)/notifications/page.tsx +5 -10
- package/app/(board)/notifications/preferences/page.tsx +8 -0
- package/app/(board)/online/page.tsx +12 -6
- package/app/(board)/staff/page.tsx +4 -5
- package/app/(board)/stats/page.tsx +10 -3
- package/app/(board)/subscriptions/page.tsx +5 -10
- package/app/(board)/thread/[slug]/edit/page.tsx +21 -0
- package/app/(board)/thread/[slug]/feed.xml/route.ts +6 -3
- package/app/(board)/thread/[slug]/page.tsx +49 -11
- package/app/(board)/thread/[slug]/reply/page.tsx +5 -0
- package/app/(board)/unsubscribe/page.tsx +8 -11
- package/app/(board)/usercp/contacts/page.tsx +3 -5
- package/app/(board)/usercp/drafts/page.tsx +70 -0
- package/app/(board)/usercp/options/page.tsx +8 -1
- package/app/(board)/usercp/security/page.tsx +16 -0
- package/app/admin/antispam/page.tsx +4 -12
- package/app/admin/content/attachments/page.tsx +3 -6
- package/app/admin/content/page.tsx +3 -13
- package/app/admin/forums/[id]/permissions/page.tsx +9 -12
- package/app/admin/groups/page.tsx +7 -9
- package/app/admin/layout.tsx +23 -8
- package/app/admin/page.tsx +12 -6
- package/app/admin/plugins/[key]/[[...path]]/page.tsx +6 -7
- package/app/admin/plugins/page.tsx +3 -6
- package/app/admin/users/[id]/page.tsx +5 -11
- package/app/admin/users/prune/page.tsx +4 -12
- package/app/admin/webhooks/page.tsx +144 -0
- package/app/api/subscribe/thread/[id]/route.ts +53 -0
- package/app/api/unsubscribe/thread/[id]/route.ts +42 -0
- package/app/atom.xml/route.ts +2 -2
- package/app/auth/sso/[provider]/callback/route.ts +10 -0
- package/app/feed.xml/route.ts +2 -2
- package/app/offline/route.ts +98 -0
- package/next.config.mjs +1 -0
- package/package.json +49 -48
- package/public/sw.js +42 -2
- package/src/components/account/draft-forms.tsx +39 -0
- package/src/components/account/feed-token.tsx +95 -0
- package/src/components/account/notification-forms.tsx +37 -2
- package/src/components/account/relation-forms.tsx +3 -2
- package/src/components/account/subscription-forms.tsx +20 -6
- package/src/components/account/usercp-forms.tsx +44 -0
- package/src/components/admin/admin-forms.tsx +57 -9
- package/src/components/admin/api-token-forms.tsx +11 -7
- package/src/components/admin/ban-filter-forms.tsx +15 -11
- package/src/components/admin/content-forms.tsx +31 -14
- package/src/components/admin/forum-forms.tsx +241 -129
- package/src/components/admin/forum-tree.tsx +5 -7
- package/src/components/admin/navigation-forms.tsx +43 -26
- package/src/components/admin/navigation-tree.tsx +8 -13
- package/src/components/admin/oklch-picker.tsx +2 -1
- package/src/components/admin/theme-changes.tsx +3 -2
- package/src/components/admin/theme-forms.tsx +3 -2
- package/src/components/admin/webhook-forms.tsx +137 -0
- package/src/components/auth/register-form.tsx +4 -7
- package/src/components/board/live-region.tsx +3 -1
- package/src/components/content/attachment-field.tsx +93 -22
- package/src/components/content/combobox-keys.ts +38 -0
- package/src/components/content/edit-post-form.tsx +75 -1
- package/src/components/content/markdown-editor.tsx +29 -86
- package/src/components/content/mention-combobox.tsx +137 -0
- package/src/components/content/multiquote-button.tsx +15 -12
- package/src/components/content/new-thread-form.tsx +95 -17
- package/src/components/content/poll-edit-form.tsx +61 -39
- package/src/components/content/poll-vote-form.tsx +91 -0
- package/src/components/content/poll.tsx +12 -48
- package/src/components/content/progressive-marker.tsx +13 -0
- package/src/components/content/recipient-segment.ts +39 -0
- package/src/components/content/reply-form.tsx +9 -1
- package/src/components/content/thanks-button.tsx +12 -7
- package/src/components/messages/message-forms.tsx +53 -43
- package/src/components/messages/recipient-field.tsx +88 -0
- package/src/components/moderation/inline-moderation-form.tsx +2 -0
- package/src/components/moderation/modcp-shell.tsx +17 -3
- package/src/components/moderation/queue-form.tsx +3 -6
- package/src/components/moderation/report-forms.tsx +24 -5
- package/src/components/moderation/thread-tools-form.tsx +2 -0
- package/src/components/shell/board-notice.tsx +22 -1
- package/src/components/shell/confirm-dialog.tsx +93 -0
- package/src/components/shell/nav-disclosure-enhancer.tsx +36 -0
- package/src/components/shell/notice-toast.tsx +40 -0
- package/src/components/shell/notification-menu.tsx +5 -3
- package/src/components/shell/page-shell.tsx +3 -0
- package/src/components/shell/scheme-toggle.tsx +72 -0
- package/src/components/shell/theme-switcher.tsx +16 -36
- package/src/components/shell/view-tabs.tsx +1 -1
- package/src/server/admin-actions.ts +118 -49
- package/src/server/admin-settings-actions.ts +5 -0
- package/src/server/admin.ts +70 -2
- package/src/server/api/search.ts +8 -2
- package/src/server/api-token-actions.ts +4 -0
- package/src/server/appearance-actions.ts +21 -0
- package/src/server/attachments.ts +35 -0
- package/src/server/auth-actions.ts +2 -0
- package/src/server/auth-form-state.ts +28 -0
- package/src/server/auto-watch.ts +31 -0
- package/src/server/ban-filter-admin-actions.ts +5 -0
- package/src/server/confirm.ts +19 -0
- package/src/server/content-actions.ts +129 -19
- package/src/server/content-admin-actions.ts +31 -0
- package/src/server/cookies.ts +18 -0
- package/src/server/discovery.ts +11 -1
- package/src/server/feed-routes.ts +13 -4
- package/src/server/feed-token-actions.ts +61 -0
- package/src/server/feed-token.ts +78 -0
- package/src/server/fixture-post-repo.ts +18 -0
- package/src/server/forum-admin-actions.ts +23 -16
- package/src/server/forum-admin.ts +10 -1
- package/src/server/inline-moderation-actions.ts +6 -0
- package/src/server/message-actions.ts +9 -0
- package/src/server/navigation-admin-actions.ts +6 -0
- package/src/server/plugin-admin.ts +7 -2
- package/src/server/plugin-pages.ts +50 -0
- package/src/server/plugin-panel.ts +34 -1
- package/src/server/plugin-routes.ts +8 -0
- package/src/server/plugin-view.tsx +46 -7
- package/src/server/poll-actions.ts +13 -1
- package/src/server/presence.ts +23 -0
- package/src/server/push-actions.ts +9 -0
- package/src/server/reply-core.ts +8 -1
- package/src/server/report-actions.ts +13 -2
- package/src/server/reputation-actions.ts +12 -1
- package/src/server/search-page.ts +8 -2
- package/src/server/search.ts +18 -5
- package/src/server/session-cookies.ts +18 -0
- package/src/server/subscription-actions.ts +9 -0
- package/src/server/thread-core.ts +10 -2
- package/src/server/thread-tool-actions.ts +6 -0
- package/src/server/unread-goto.ts +28 -0
- package/src/server/upgrade-notice.ts +1 -1
- package/src/server/usercp-actions.ts +31 -1
- package/src/server/viewer-preferences.ts +5 -0
- package/src/server/webhook-actions.ts +98 -0
- package/src/server/webhooks-admin.ts +122 -0
- package/src/styles/globals.css +1 -1
- package/src/theme/contract.fixture.ts +36 -5
- package/src/view/account-copy.ts +39 -0
- package/src/view/admin-copy.ts +4 -9
- package/src/view/admin-nav.ts +6 -0
- package/src/view/admin-panel-copy.ts +29 -1
- package/src/view/attachments.ts +33 -1
- package/src/view/board-index.ts +31 -2
- package/src/view/board-title.ts +1 -0
- package/src/view/content-copy.ts +22 -12
- package/src/view/copy.ts +17 -0
- package/src/view/discovery-view.ts +2 -1
- package/src/view/drafts.ts +45 -0
- package/src/view/editor-toolbar.ts +14 -0
- package/src/view/forum-display.ts +39 -7
- package/src/view/modcp-nav.ts +32 -0
- package/src/view/moderation-copy.ts +20 -0
- package/src/view/notifications.ts +1 -0
- package/src/view/plugin-panel.ts +13 -0
- package/src/view/poll-vote.ts +46 -0
- package/src/view/post-link.ts +8 -1
- package/src/view/progressive-enhancement.ts +5 -0
- package/src/view/shell.ts +2 -1
- package/src/view/subscriptions.ts +1 -0
- package/src/view/thread-view.ts +41 -2
- package/src/view/usercp-nav.ts +6 -0
- package/src/view/usercp.ts +14 -0
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import { useActionState } from 'react'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
adminAbandonSecondFactorAction,
|
|
7
|
+
adminSignInAction,
|
|
8
|
+
adminSignOutAction,
|
|
9
|
+
adminVerifySecondFactorAction,
|
|
10
|
+
} from '@/server/admin-actions'
|
|
6
11
|
import { EMPTY_STATE } from '@/server/auth-form-state'
|
|
7
12
|
|
|
8
13
|
import { FormError, PendingButton } from '../auth/form-controls'
|
|
@@ -51,14 +56,6 @@ export function AdminSignInForm({
|
|
|
51
56
|
/>
|
|
52
57
|
</label>
|
|
53
58
|
|
|
54
|
-
<OtpField
|
|
55
|
-
label={fromCopy(copy, 'adminPanel.twoFactorCode')}
|
|
56
|
-
name="code"
|
|
57
|
-
required={false}
|
|
58
|
-
hint={fromCopy(copy, 'adminPanel.twoFactorCodeHint')}
|
|
59
|
-
recovery={otpRecoveryFromCopy(copy)}
|
|
60
|
-
/>
|
|
61
|
-
|
|
62
59
|
<PendingButton
|
|
63
60
|
showWorking
|
|
64
61
|
className="inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
|
|
@@ -73,6 +70,57 @@ export function AdminSignInForm({
|
|
|
73
70
|
)
|
|
74
71
|
}
|
|
75
72
|
|
|
73
|
+
export function AdminSecondFactorForm({
|
|
74
|
+
recoveryCodesLeft,
|
|
75
|
+
copy,
|
|
76
|
+
}: {
|
|
77
|
+
recoveryCodesLeft: number
|
|
78
|
+
copy: Copy
|
|
79
|
+
}) {
|
|
80
|
+
const [state, action] = useActionState(adminVerifySecondFactorAction, EMPTY_STATE)
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div className="flex w-full max-w-sm flex-col gap-4 rounded-lg border border-border bg-card p-6">
|
|
84
|
+
<h1 className="text-xl font-semibold tracking-tight">
|
|
85
|
+
{fromCopy(copy, 'adminPanel.twoFactor.title')}
|
|
86
|
+
</h1>
|
|
87
|
+
|
|
88
|
+
<p className="text-sm text-muted-foreground">{fromCopy(copy, 'adminPanel.twoFactor.lede')}</p>
|
|
89
|
+
|
|
90
|
+
<form action={action} className="flex flex-col gap-4" noValidate>
|
|
91
|
+
<FormError message={state.error} />
|
|
92
|
+
|
|
93
|
+
<OtpField
|
|
94
|
+
label={fromCopy(copy, 'adminPanel.twoFactorCode')}
|
|
95
|
+
name="code"
|
|
96
|
+
hint={
|
|
97
|
+
recoveryCodesLeft > 0
|
|
98
|
+
? fromCopy(copy, 'adminPanel.twoFactor.recoveryHint')
|
|
99
|
+
: fromCopy(copy, 'adminPanel.twoFactor.recoveryHintExhausted')
|
|
100
|
+
}
|
|
101
|
+
recovery={otpRecoveryFromCopy(copy)}
|
|
102
|
+
/>
|
|
103
|
+
|
|
104
|
+
<PendingButton
|
|
105
|
+
showWorking
|
|
106
|
+
className="inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
|
|
107
|
+
>
|
|
108
|
+
{fromCopy(copy, 'adminPanel.twoFactor.submit')}
|
|
109
|
+
</PendingButton>
|
|
110
|
+
</form>
|
|
111
|
+
|
|
112
|
+
<form action={adminAbandonSecondFactorAction}>
|
|
113
|
+
<PendingButton
|
|
114
|
+
showWorking
|
|
115
|
+
className="text-sm text-muted-foreground hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
|
|
116
|
+
>
|
|
117
|
+
{fromCopy(copy, 'adminPanel.twoFactor.cancel')}
|
|
118
|
+
</PendingButton>
|
|
119
|
+
</form>
|
|
120
|
+
</div>
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
76
124
|
export function AdminSignOutForm({ copy }: { copy: Copy }) {
|
|
77
125
|
return (
|
|
78
126
|
<form action={adminSignOutAction}>
|
|
@@ -6,6 +6,7 @@ import { issueApiTokenAction, revokeApiTokenAction } from '@/server/api-token-ac
|
|
|
6
6
|
import { EMPTY_STATE } from '@/server/auth-form-state'
|
|
7
7
|
|
|
8
8
|
import { FormError, SubmitButton } from '../auth/form-controls'
|
|
9
|
+
import { ConfirmDialog } from '../shell/confirm-dialog'
|
|
9
10
|
import { type Copy, fromCopy } from '../shell/copy'
|
|
10
11
|
|
|
11
12
|
export function IssueTokenForm({ scopes, copy }: { scopes: readonly string[]; copy: Copy }) {
|
|
@@ -78,12 +79,15 @@ export function RevokeTokenForm({ tokenId, copy }: { tokenId: number; copy: Copy
|
|
|
78
79
|
const [state, action] = useActionState(revokeApiTokenAction, EMPTY_STATE)
|
|
79
80
|
|
|
80
81
|
return (
|
|
81
|
-
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
<>
|
|
83
|
+
<form action={action}>
|
|
84
|
+
<input type="hidden" name="tokenId" value={tokenId} />
|
|
85
|
+
<SubmitButton>{fromCopy(copy, 'adminPanel.token.revoke')}</SubmitButton>
|
|
86
|
+
{state.error !== undefined && (
|
|
87
|
+
<span className="ml-2 text-xs text-destructive">{state.error}</span>
|
|
88
|
+
)}
|
|
89
|
+
</form>
|
|
90
|
+
<ConfirmDialog confirm={state.confirm} action={action} />
|
|
91
|
+
</>
|
|
88
92
|
)
|
|
89
93
|
}
|
|
@@ -6,6 +6,7 @@ import { EMPTY_STATE } from '@/server/auth-form-state'
|
|
|
6
6
|
import { addBanFilterAction, removeBanFilterAction } from '@/server/ban-filter-admin-actions'
|
|
7
7
|
|
|
8
8
|
import { FormError, PendingButton, SubmitButton } from '../auth/form-controls'
|
|
9
|
+
import { ConfirmDialog } from '../shell/confirm-dialog'
|
|
9
10
|
import { type Copy, formatFromCopy, fromCopy } from '../shell/copy'
|
|
10
11
|
import { INPUT, Saved } from './form-bits'
|
|
11
12
|
|
|
@@ -89,16 +90,19 @@ export function RemoveBanFilterForm({
|
|
|
89
90
|
const [state, action] = useActionState(removeBanFilterAction, EMPTY_STATE)
|
|
90
91
|
|
|
91
92
|
return (
|
|
92
|
-
<
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
<div className="flex flex-col items-end gap-1">
|
|
94
|
+
<form action={action} className="flex flex-col items-end gap-1">
|
|
95
|
+
<FormError message={state.error} />
|
|
96
|
+
<input type="hidden" name="id" value={id} />
|
|
97
|
+
<PendingButton
|
|
98
|
+
showWorking
|
|
99
|
+
className="text-xs text-destructive hover:underline"
|
|
100
|
+
aria-label={formatFromCopy(copy, 'adminBanFilter.removeFilter', { pattern })}
|
|
101
|
+
>
|
|
102
|
+
{fromCopy(copy, 'admin.remove')}
|
|
103
|
+
</PendingButton>
|
|
104
|
+
</form>
|
|
105
|
+
<ConfirmDialog confirm={state.confirm} action={action} />
|
|
106
|
+
</div>
|
|
103
107
|
)
|
|
104
108
|
}
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from '@/server/content-admin-actions'
|
|
26
26
|
|
|
27
27
|
import { FormError, PendingButton, SubmitButton } from '../auth/form-controls'
|
|
28
|
+
import { ConfirmDialog } from '../shell/confirm-dialog'
|
|
28
29
|
import { type Copy, fromCopy } from '../shell/copy'
|
|
29
30
|
import { INPUT, Saved } from './form-bits'
|
|
30
31
|
|
|
@@ -91,6 +92,8 @@ export function WordFilterRowForm({ filter, copy }: { filter: WordFilterValues;
|
|
|
91
92
|
{fromCopy(copy, 'adminContent.filter.removeThis')}
|
|
92
93
|
</PendingButton>
|
|
93
94
|
</form>
|
|
95
|
+
|
|
96
|
+
<ConfirmDialog confirm={removeState.confirm} action={removeAction} />
|
|
94
97
|
</div>
|
|
95
98
|
)
|
|
96
99
|
}
|
|
@@ -140,13 +143,16 @@ export function DeletePrefixForm({ prefix, copy }: { prefix: PrefixValues; copy:
|
|
|
140
143
|
const [state, action] = useActionState(deletePrefixAction, EMPTY_STATE)
|
|
141
144
|
|
|
142
145
|
return (
|
|
143
|
-
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
<>
|
|
147
|
+
<form action={action} className="flex items-center gap-2">
|
|
148
|
+
<FormError message={state.error} />
|
|
149
|
+
<input type="hidden" name="id" value={prefix.id} />
|
|
150
|
+
<PendingButton showWorking className="text-xs text-muted-foreground hover:underline">
|
|
151
|
+
{fromCopy(copy, 'admin.remove')}
|
|
152
|
+
</PendingButton>
|
|
153
|
+
</form>
|
|
154
|
+
<ConfirmDialog confirm={state.confirm} action={action} />
|
|
155
|
+
</>
|
|
150
156
|
)
|
|
151
157
|
}
|
|
152
158
|
|
|
@@ -256,6 +262,8 @@ export function SmileyRowForm({ smiley, copy }: { smiley: SmileyValues; copy: Co
|
|
|
256
262
|
{fromCopy(copy, 'admin.remove')}
|
|
257
263
|
</PendingButton>
|
|
258
264
|
</form>
|
|
265
|
+
|
|
266
|
+
<ConfirmDialog confirm={removeState.confirm} action={removeAction} />
|
|
259
267
|
</div>
|
|
260
268
|
)
|
|
261
269
|
}
|
|
@@ -366,6 +374,8 @@ export function DirectiveRowForm({ directive, copy }: { directive: DirectiveValu
|
|
|
366
374
|
{fromCopy(copy, 'admin.remove')}
|
|
367
375
|
</PendingButton>
|
|
368
376
|
</form>
|
|
377
|
+
|
|
378
|
+
<ConfirmDialog confirm={removeState.confirm} action={removeAction} />
|
|
369
379
|
</div>
|
|
370
380
|
)
|
|
371
381
|
}
|
|
@@ -419,13 +429,16 @@ export function DeleteAttachmentForm({ attachmentId, copy }: { attachmentId: num
|
|
|
419
429
|
const [state, action] = useActionState(deleteAttachmentAction, EMPTY_STATE)
|
|
420
430
|
|
|
421
431
|
return (
|
|
422
|
-
<
|
|
423
|
-
<
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
432
|
+
<div className="shrink-0">
|
|
433
|
+
<form action={action}>
|
|
434
|
+
<FormError message={state.error} />
|
|
435
|
+
<input type="hidden" name="id" value={attachmentId} />
|
|
436
|
+
<PendingButton showWorking className="text-xs text-destructive hover:underline">
|
|
437
|
+
{fromCopy(copy, 'adminContent.attachment.delete')}
|
|
438
|
+
</PendingButton>
|
|
439
|
+
</form>
|
|
440
|
+
<ConfirmDialog confirm={state.confirm} action={action} />
|
|
441
|
+
</div>
|
|
429
442
|
)
|
|
430
443
|
}
|
|
431
444
|
|
|
@@ -572,6 +585,8 @@ export function AnnouncementRowForm({
|
|
|
572
585
|
{fromCopy(copy, 'admin.remove')}
|
|
573
586
|
</PendingButton>
|
|
574
587
|
</form>
|
|
588
|
+
|
|
589
|
+
<ConfirmDialog confirm={removeState.confirm} action={removeAction} />
|
|
575
590
|
</div>
|
|
576
591
|
)
|
|
577
592
|
}
|
|
@@ -674,6 +689,8 @@ export function CaptchaQuestionRowForm({
|
|
|
674
689
|
{fromCopy(copy, 'admin.remove')}
|
|
675
690
|
</PendingButton>
|
|
676
691
|
</form>
|
|
692
|
+
|
|
693
|
+
<ConfirmDialog confirm={removeState.confirm} action={removeAction} />
|
|
677
694
|
</div>
|
|
678
695
|
)
|
|
679
696
|
}
|