@carlonicora/nextjs-jsonapi 3.3.8 → 3.4.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/dist/{BlockNoteEditor-BYMRWUVG.mjs → BlockNoteEditor-3D5D7YL7.mjs} +2 -2
- package/dist/{BlockNoteEditor-USRMFZGP.js → BlockNoteEditor-F6TGKMTW.js} +9 -9
- package/dist/{BlockNoteEditor-USRMFZGP.js.map → BlockNoteEditor-F6TGKMTW.js.map} +1 -1
- package/dist/billing/index.js +347 -347
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +27 -27
- package/dist/billing/index.mjs.map +1 -1
- package/dist/{chunk-CFZW6GU4.mjs → chunk-G5LSXG5K.mjs} +2572 -2482
- package/dist/chunk-G5LSXG5K.mjs.map +1 -0
- package/dist/{chunk-5WFYQE22.js → chunk-KT4CTWCV.js} +825 -735
- package/dist/chunk-KT4CTWCV.js.map +1 -0
- package/dist/client/index.d.mts +5 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.js +2 -2
- package/dist/client/index.mjs +1 -1
- package/dist/components/index.d.mts +12 -6
- package/dist/components/index.d.ts +12 -6
- package/dist/components/index.js +2 -2
- package/dist/components/index.mjs +1 -1
- package/dist/contexts/index.d.mts +13 -1
- package/dist/contexts/index.d.ts +13 -1
- package/dist/contexts/index.js +6 -2
- package/dist/contexts/index.js.map +1 -1
- package/dist/contexts/index.mjs +5 -1
- package/dist/features/help/index.js +35 -35
- package/dist/features/help/index.js.map +1 -1
- package/dist/features/help/index.mjs +6 -6
- package/dist/features/help/index.mjs.map +1 -1
- package/dist/features/tokenusage/index.js +135 -129
- package/dist/features/tokenusage/index.js.map +1 -1
- package/dist/features/tokenusage/index.mjs +74 -68
- package/dist/features/tokenusage/index.mjs.map +1 -1
- package/package.json +2 -2
- package/scripts/check-rtl-classes.mjs +60 -0
- package/scripts/check-rtl-classes.test.ts +25 -0
- package/src/components/TableCellAvatar.tsx +1 -1
- package/src/components/containers/PageContainer.tsx +1 -1
- package/src/components/containers/ReactMarkdownContainer.tsx +20 -4
- package/src/components/containers/RoundPageContainer.tsx +7 -7
- package/src/components/contents/AttributeElement.tsx +1 -1
- package/src/components/editors/BlockNoteDiffInlineContent.tsx +2 -2
- package/src/components/editors/BlockNoteEditorMentionHoverCard.tsx +1 -0
- package/src/components/forms/CommonDeleter.tsx +1 -1
- package/src/components/forms/CommonEditorButtons.tsx +1 -1
- package/src/components/forms/DatePickerPopover.tsx +2 -2
- package/src/components/forms/DateRangeSelector.tsx +2 -2
- package/src/components/forms/EditorSheet.tsx +18 -9
- package/src/components/forms/EntityMultiSelector.tsx +7 -7
- package/src/components/forms/EntitySelector.tsx +8 -8
- package/src/components/forms/FileUploader.tsx +1 -0
- package/src/components/forms/FormCheckbox.tsx +3 -3
- package/src/components/forms/FormDateTime.tsx +3 -3
- package/src/components/forms/FormFieldWrapper.tsx +1 -1
- package/src/components/forms/FormPlaceAutocomplete.tsx +2 -2
- package/src/components/forms/GdprConsentCheckbox.tsx +1 -1
- package/src/components/forms/MultiFileUploader.tsx +1 -1
- package/src/components/forms/PasswordInput.tsx +1 -1
- package/src/components/forms/__tests__/FormCheckbox.test.tsx +4 -4
- package/src/components/navigations/Header.tsx +2 -2
- package/src/components/navigations/PageSection.tsx +1 -1
- package/src/components/pages/PageContainerContentDetails.tsx +1 -1
- package/src/components/pages/PageContentContainer.tsx +5 -2
- package/src/components/tables/ContentListTable.tsx +4 -4
- package/src/components/tables/ContentTableSearch.tsx +5 -5
- package/src/contexts/DirectionContext.tsx +25 -0
- package/src/contexts/__tests__/DirectionContext.test.tsx +22 -0
- package/src/contexts/index.ts +1 -0
- package/src/features/ai-connection/components/lists/AiConnectionTypeCard.tsx +1 -1
- package/src/features/assistant/components/containers/AssistantPageContainer.tsx +1 -1
- package/src/features/assistant/components/parts/AssistantBlockNoteComposer.tsx +2 -2
- package/src/features/assistant/components/parts/AssistantComposer.tsx +2 -2
- package/src/features/assistant/components/parts/AssistantEmptyState.tsx +1 -1
- package/src/features/assistant/components/parts/AssistantSidebar.tsx +3 -3
- package/src/features/assistant-action/components/ApprovalActionCard.tsx +1 -1
- package/src/features/assistant-action/components/AssistantContainerWithApprovals.tsx +1 -1
- package/src/features/assistant-message/components/MessageItem.tsx +3 -3
- package/src/features/assistant-message/components/__tests__/MessageItem.spec.tsx +1 -0
- package/src/features/assistant-message/components/parts/MessageSourcesPanel.tsx +2 -2
- package/src/features/assistant-message/components/parts/RelevanceMeter.tsx +1 -1
- package/src/features/assistant-message/components/parts/tabs/SuggestedQuestionsTab.tsx +1 -1
- package/src/features/auth/components/buttons/GoogleSignInButton.tsx +1 -1
- package/src/features/auth/components/forms/Register.tsx +2 -2
- package/src/features/auth/components/two-factor/BackupCodesDialog.tsx +3 -3
- package/src/features/auth/utils/__tests__/clearClientStorage.spec.ts +4 -4
- package/src/features/billing/components/cards/BillingUsageSummaryCard.tsx +1 -1
- package/src/features/billing/components/cards/CustomerInfoCard.tsx +1 -1
- package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +1 -1
- package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +1 -1
- package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +1 -1
- package/src/features/billing/components/containers/BillingDashboardContainer.tsx +1 -1
- package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +1 -1
- package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +6 -6
- package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +2 -2
- package/src/features/billing/stripe-price/hooks/useStripePriceTableStructure.tsx +3 -3
- package/src/features/billing/stripe-product/hooks/useStripeProductTableStructure.tsx +2 -2
- package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +4 -4
- package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +2 -2
- package/src/features/billing/stripe-subscription/components/widgets/SubscriptionConfirmation.tsx +1 -1
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +2 -2
- package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +2 -2
- package/src/features/company/components/forms/CompanyDeleter.tsx +4 -4
- package/src/features/content/hooks/useContentTableStructure.tsx +1 -1
- package/src/features/feature/components/forms/FormFeatures.tsx +2 -2
- package/src/features/help/components/HelpAssistantSheet.tsx +3 -2
- package/src/features/help/components/HelpHint.tsx +2 -2
- package/src/features/help/components/HelpTOC.tsx +1 -1
- package/src/features/how-to/components/containers/HowToCommand.tsx +2 -2
- package/src/features/how-to/components/containers/HowToCommandViewer.tsx +5 -5
- package/src/features/how-to/components/forms/HowToEditor.tsx +3 -3
- package/src/features/how-to/components/forms/HowToSelector.tsx +5 -5
- package/src/features/notification/components/lists/NotificationsList.tsx +2 -2
- package/src/features/notification/components/modals/NotificationModal.tsx +1 -1
- package/src/features/oauth/components/OAuthClientCard.tsx +2 -2
- package/src/features/oauth/components/OAuthClientDetail.tsx +2 -2
- package/src/features/oauth/components/OAuthClientList.tsx +3 -3
- package/src/features/oauth/components/OAuthRedirectUriInput.tsx +1 -1
- package/src/features/oauth/components/OAuthScopeSelector.tsx +2 -2
- package/src/features/onboarding/components/OnboardingCard.tsx +1 -7
- package/src/features/rbac/components/RbacByRoleContainer.tsx +3 -3
- package/src/features/rbac/components/RbacContainer.tsx +3 -3
- package/src/features/referral/components/ReferralWidget.tsx +1 -0
- package/src/features/role/components/forms/FormRoles.tsx +1 -1
- package/src/features/role/components/forms/RemoveUserFromRole.tsx +1 -1
- package/src/features/role/components/forms/UserRoleAdd.tsx +1 -1
- package/src/features/tokenusage/components/TokenUsageBreakdownTable.tsx +9 -9
- package/src/features/tokenusage/components/TokenUsageRankedBar.tsx +8 -3
- package/src/features/tokenusage/components/TokenUsageTimelineChart.tsx +5 -1
- package/src/features/user/components/details/UserStandaloneDetails.tsx +1 -1
- package/src/features/user/components/forms/UserReactivator.tsx +2 -2
- package/src/features/user/components/forms/UserResentInvitationEmail.tsx +1 -1
- package/src/features/user/components/forms/UserSelector.tsx +7 -7
- package/src/features/user/components/lists/ContributorsList.tsx +1 -1
- package/src/features/user/components/lists/UserListInAdd.tsx +1 -1
- package/src/features/user/components/widgets/UserSearchPopover.tsx +5 -5
- package/src/features/user/hooks/useUserTableStructure.tsx +1 -1
- package/src/features/waitlist/components/forms/WaitlistQuestionnaireRenderer.tsx +1 -1
- package/src/features/waitlist/hooks/useWaitlistTableStructure.tsx +1 -1
- package/src/hooks/useCustomD3Graph.tsx +16 -0
- package/src/lib/__tests__/direction.test.ts +18 -0
- package/src/lib/direction.ts +8 -0
- package/src/shadcnui/custom/multi-select.tsx +6 -6
- package/src/shadcnui/custom/multiple-selector.tsx +6 -2
- package/src/shadcnui/ui/accordion.tsx +1 -1
- package/src/shadcnui/ui/alert-dialog.tsx +2 -1
- package/src/shadcnui/ui/alert.tsx +2 -2
- package/src/shadcnui/ui/avatar.tsx +1 -1
- package/src/shadcnui/ui/badge.tsx +1 -1
- package/src/shadcnui/ui/breadcrumb.tsx +1 -1
- package/src/shadcnui/ui/button.tsx +4 -4
- package/src/shadcnui/ui/calendar.tsx +9 -8
- package/src/shadcnui/ui/carousel.tsx +18 -11
- package/src/shadcnui/ui/combobox.tsx +3 -3
- package/src/shadcnui/ui/command.tsx +2 -2
- package/src/shadcnui/ui/context-menu.tsx +15 -11
- package/src/shadcnui/ui/dialog.tsx +2 -1
- package/src/shadcnui/ui/drawer.tsx +19 -3
- package/src/shadcnui/ui/dropdown-menu.tsx +12 -10
- package/src/shadcnui/ui/field.tsx +2 -2
- package/src/shadcnui/ui/input-group.tsx +3 -3
- package/src/shadcnui/ui/input-otp.tsx +2 -0
- package/src/shadcnui/ui/navigation-menu.tsx +2 -2
- package/src/shadcnui/ui/progress.tsx +1 -1
- package/src/shadcnui/ui/radio-group.tsx +1 -0
- package/src/shadcnui/ui/resizable.tsx +1 -0
- package/src/shadcnui/ui/scroll-area.tsx +1 -1
- package/src/shadcnui/ui/select.tsx +2 -2
- package/src/shadcnui/ui/sheet.tsx +11 -4
- package/src/shadcnui/ui/sidebar.tsx +37 -20
- package/src/shadcnui/ui/sonner.tsx +6 -1
- package/src/shadcnui/ui/switch.tsx +1 -1
- package/src/shadcnui/ui/table.tsx +2 -2
- package/src/shadcnui/ui/tabs.tsx +1 -1
- package/dist/chunk-5WFYQE22.js.map +0 -1
- package/dist/chunk-CFZW6GU4.mjs.map +0 -1
- /package/dist/{BlockNoteEditor-BYMRWUVG.mjs.map → BlockNoteEditor-3D5D7YL7.mjs.map} +0 -0
|
@@ -49,9 +49,9 @@ export const useStripePriceTableStructure: UseTableStructureHook<StripePriceInte
|
|
|
49
49
|
header: t("billing.admin.prices.fields.amount"),
|
|
50
50
|
cell: ({ row }: { row: TableContent<StripePriceInterface> }) => {
|
|
51
51
|
const price: StripePriceInterface = row.original.jsonApiData;
|
|
52
|
-
// Typography role 15 (numeric): tabular-nums,
|
|
52
|
+
// Typography role 15 (numeric): tabular-nums, end-aligned. NEVER font-mono.
|
|
53
53
|
return (
|
|
54
|
-
<span className="block text-xs tabular-nums text-
|
|
54
|
+
<span className="block text-xs tabular-nums text-end">
|
|
55
55
|
{formatCurrency(price.unitAmount, price.currency)}
|
|
56
56
|
</span>
|
|
57
57
|
);
|
|
@@ -77,7 +77,7 @@ export const useStripePriceTableStructure: UseTableStructureHook<StripePriceInte
|
|
|
77
77
|
header: t("billing.admin.prices.fields.token"),
|
|
78
78
|
cell: ({ row }: { row: TableContent<StripePriceInterface> }) => {
|
|
79
79
|
const price: StripePriceInterface = row.original.jsonApiData;
|
|
80
|
-
return <span className="block text-xs tabular-nums text-
|
|
80
|
+
return <span className="block text-xs tabular-nums text-end">{price.token ?? ""}</span>;
|
|
81
81
|
},
|
|
82
82
|
enableSorting: false,
|
|
83
83
|
enableHiding: false,
|
|
@@ -59,9 +59,9 @@ export const useStripeProductTableStructure: UseTableStructureHook<StripeProduct
|
|
|
59
59
|
header: t("billing.admin.products.fields.prices"),
|
|
60
60
|
cell: ({ row }: { row: TableContent<StripeProductInterface> }) => {
|
|
61
61
|
const product: StripeProductInterface = row.original.jsonApiData;
|
|
62
|
-
// Typography role 15 (numeric): tabular-nums,
|
|
62
|
+
// Typography role 15 (numeric): tabular-nums, end-aligned. NEVER
|
|
63
63
|
// font-mono — no monospace font is loaded in these apps.
|
|
64
|
-
return <span className="block text-xs tabular-nums text-
|
|
64
|
+
return <span className="block text-xs tabular-nums text-end">{product.stripePrices.length}</span>;
|
|
65
65
|
},
|
|
66
66
|
enableSorting: false,
|
|
67
67
|
enableHiding: false,
|
|
@@ -60,8 +60,8 @@ export function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChan
|
|
|
60
60
|
<TableHead>Status</TableHead>
|
|
61
61
|
<TableHead>Plan</TableHead>
|
|
62
62
|
<TableHead>Period</TableHead>
|
|
63
|
-
<TableHead className="text-
|
|
64
|
-
<TableHead className="text-
|
|
63
|
+
<TableHead className="text-end">Amount</TableHead>
|
|
64
|
+
<TableHead className="text-end">Actions</TableHead>
|
|
65
65
|
</TableRow>
|
|
66
66
|
</TableHeader>
|
|
67
67
|
<TableBody>
|
|
@@ -84,8 +84,8 @@ export function SubscriptionsList({ subscriptions, onSubscriptionsChange, onChan
|
|
|
84
84
|
</TableCell>
|
|
85
85
|
<TableCell className="font-medium">{formatPlanName(price)}</TableCell>
|
|
86
86
|
<TableCell className="text-muted-foreground text-sm">{period}</TableCell>
|
|
87
|
-
<TableCell className="text-
|
|
88
|
-
<TableCell className="text-
|
|
87
|
+
<TableCell className="text-end font-medium">{amount}</TableCell>
|
|
88
|
+
<TableCell className="text-end">
|
|
89
89
|
{(subscription.status === SubscriptionStatus.ACTIVE ||
|
|
90
90
|
subscription.status === SubscriptionStatus.TRIALING) &&
|
|
91
91
|
onChangePlan && (
|
|
@@ -61,7 +61,7 @@ export function PricingCard({
|
|
|
61
61
|
)}
|
|
62
62
|
>
|
|
63
63
|
{isCurrentPlan && (
|
|
64
|
-
<Badge variant="secondary" className="absolute top-2
|
|
64
|
+
<Badge variant="secondary" className="absolute top-2 end-2">
|
|
65
65
|
Current
|
|
66
66
|
</Badge>
|
|
67
67
|
)}
|
|
@@ -73,7 +73,7 @@ export function PricingCard({
|
|
|
73
73
|
<CardContent className="pb-4 grow">
|
|
74
74
|
<div className="mb-4">
|
|
75
75
|
<span className="text-3xl font-bold">{formattedPrice}</span>
|
|
76
|
-
<span className="text-muted-foreground
|
|
76
|
+
<span className="text-muted-foreground ms-1">{interval}</span>
|
|
77
77
|
</div>
|
|
78
78
|
|
|
79
79
|
{features.length > 0 && (
|
package/src/features/billing/stripe-subscription/components/widgets/SubscriptionConfirmation.tsx
CHANGED
|
@@ -54,7 +54,7 @@ export function SubscriptionConfirmation({ price, isLoading, onConfirm, onCancel
|
|
|
54
54
|
<Button onClick={onConfirm} disabled={isLoading}>
|
|
55
55
|
{isLoading ? (
|
|
56
56
|
<>
|
|
57
|
-
<Loader2 className="h-4 w-4 animate-spin
|
|
57
|
+
<Loader2 className="h-4 w-4 animate-spin me-2" />
|
|
58
58
|
Processing...
|
|
59
59
|
</>
|
|
60
60
|
) : (
|
|
@@ -127,7 +127,7 @@ export function WizardStepReview({
|
|
|
127
127
|
<p className="font-medium">{selectedPrice.product?.name}</p>
|
|
128
128
|
{selectedPrice.nickname && <p className="text-sm text-muted-foreground">{selectedPrice.nickname}</p>}
|
|
129
129
|
</div>
|
|
130
|
-
<div className="text-
|
|
130
|
+
<div className="text-end">
|
|
131
131
|
{discountedPrice !== null ? (
|
|
132
132
|
<>
|
|
133
133
|
<p className="text-sm text-muted-foreground line-through">
|
|
@@ -168,7 +168,7 @@ export function WizardStepReview({
|
|
|
168
168
|
<span className={`font-medium ${isTrialUpgrade ? "text-warning" : "text-foreground"}`}>
|
|
169
169
|
{discountedImmediateCharge !== null ? (
|
|
170
170
|
<>
|
|
171
|
-
<span className="line-through text-muted-foreground
|
|
171
|
+
<span className="line-through text-muted-foreground me-2">
|
|
172
172
|
{formatCurrency(prorationPreview.immediateCharge, prorationPreview.currency)}
|
|
173
173
|
</span>
|
|
174
174
|
<span className="text-success">
|
|
@@ -47,7 +47,7 @@ export function UsageHistoryTable({ usageRecords }: UsageHistoryTableProps) {
|
|
|
47
47
|
<TableRow>
|
|
48
48
|
<TableHead>Date & Time</TableHead>
|
|
49
49
|
<TableHead>Meter Event</TableHead>
|
|
50
|
-
<TableHead className="text-
|
|
50
|
+
<TableHead className="text-end">Quantity</TableHead>
|
|
51
51
|
<TableHead>Event ID</TableHead>
|
|
52
52
|
</TableRow>
|
|
53
53
|
</TableHeader>
|
|
@@ -60,7 +60,7 @@ export function UsageHistoryTable({ usageRecords }: UsageHistoryTableProps) {
|
|
|
60
60
|
<TableRow key={record.id}>
|
|
61
61
|
<TableCell className="font-medium">{dateTime}</TableCell>
|
|
62
62
|
<TableCell className="text-muted-foreground">{record.meterEventName}</TableCell>
|
|
63
|
-
<TableCell className="text-
|
|
63
|
+
<TableCell className="text-end font-medium">{quantity}</TableCell>
|
|
64
64
|
<TableCell className="text-muted-foreground text-sm tabular-nums">{record.stripeEventId}</TableCell>
|
|
65
65
|
</TableRow>
|
|
66
66
|
);
|
|
@@ -99,7 +99,7 @@ function CompanyDeleterInternal({ company, isAdministrator }: CompanyDeleterInte
|
|
|
99
99
|
<div className="flex w-full flex-col">
|
|
100
100
|
<Label className="flex items-center">
|
|
101
101
|
{t(`company.fields.name.label`)}
|
|
102
|
-
<span className="
|
|
102
|
+
<span className="ms-1 text-destructive">*</span>
|
|
103
103
|
</Label>
|
|
104
104
|
<Input
|
|
105
105
|
className={`w-full`}
|
|
@@ -109,7 +109,7 @@ function CompanyDeleterInternal({ company, isAdministrator }: CompanyDeleterInte
|
|
|
109
109
|
</div>
|
|
110
110
|
</div>
|
|
111
111
|
<div className="flex justify-end">
|
|
112
|
-
<Button className="
|
|
112
|
+
<Button className="me-2" variant={"outline"} type={`button`} onClick={() => setOpen(false)}>
|
|
113
113
|
{t(`ui.buttons.cancel`)}
|
|
114
114
|
</Button>
|
|
115
115
|
<Button
|
|
@@ -136,7 +136,7 @@ function CompanyDeleterInternal({ company, isAdministrator }: CompanyDeleterInte
|
|
|
136
136
|
</AlertDialogHeader>
|
|
137
137
|
<div className="bg-destructive/10 border-destructive text-destructive rounded-md border p-4 text-sm">
|
|
138
138
|
<p className="mb-3 font-semibold">{t(`common.delete.finalWarning.description`)}</p>
|
|
139
|
-
<ul className="list-disc space-y-1
|
|
139
|
+
<ul className="list-disc space-y-1 ps-5">
|
|
140
140
|
<li>{t(`common.delete.finalWarning.bullet1`)}</li>
|
|
141
141
|
<li>{t(`common.delete.finalWarning.bullet2`)}</li>
|
|
142
142
|
<li>{t(`common.delete.finalWarning.bullet3`)}</li>
|
|
@@ -145,7 +145,7 @@ function CompanyDeleterInternal({ company, isAdministrator }: CompanyDeleterInte
|
|
|
145
145
|
</ul>
|
|
146
146
|
</div>
|
|
147
147
|
<div className="flex justify-end">
|
|
148
|
-
<Button className="
|
|
148
|
+
<Button className="me-2" variant={"outline"} type={`button`} onClick={handleGoBack} disabled={isDeleting}>
|
|
149
149
|
{t(`ui.buttons.go_back`)}
|
|
150
150
|
</Button>
|
|
151
151
|
<Button
|
|
@@ -75,7 +75,7 @@ export const useContentTableStructure = <U extends string = ContentFields>(
|
|
|
75
75
|
return (
|
|
76
76
|
<div className="relative flex h-5 w-20 items-center justify-center overflow-clip rounded border text-center">
|
|
77
77
|
<div
|
|
78
|
-
className={`bg-accent absolute top-0
|
|
78
|
+
className={`bg-accent absolute top-0 start-0 h-full opacity-${Math.round(content.relevance)}`}
|
|
79
79
|
style={{ width: `${content.relevance}%` }}
|
|
80
80
|
></div>
|
|
81
81
|
<span
|
|
@@ -37,7 +37,7 @@ export function FormFeatures({ form, name, features, featureField = "featureIds"
|
|
|
37
37
|
</SectionHeader>
|
|
38
38
|
)}
|
|
39
39
|
<ScrollArea className="h-[40vh]">
|
|
40
|
-
<div className="flex flex-col gap-y-2
|
|
40
|
+
<div className="flex flex-col gap-y-2 pe-4">
|
|
41
41
|
{features
|
|
42
42
|
.filter((feature) => !feature.isCore)
|
|
43
43
|
.map((feature) => (
|
|
@@ -49,7 +49,7 @@ export function FormFeatures({ form, name, features, featureField = "featureIds"
|
|
|
49
49
|
toggleFeature(feature, val === true);
|
|
50
50
|
}}
|
|
51
51
|
/>
|
|
52
|
-
<Label htmlFor={feature.id} className="
|
|
52
|
+
<Label htmlFor={feature.id} className="ms-3 cursor-pointer font-normal">
|
|
53
53
|
{feature.name}
|
|
54
54
|
</Label>
|
|
55
55
|
</div>
|
|
@@ -10,8 +10,9 @@ export function HelpAssistantSheet({ open, onOpenChange }: { open: boolean; onOp
|
|
|
10
10
|
return (
|
|
11
11
|
<Sheet open={open} onOpenChange={onOpenChange}>
|
|
12
12
|
<SheetContent
|
|
13
|
-
side="
|
|
14
|
-
|
|
13
|
+
side="end"
|
|
14
|
+
/* rtl-ok: keyed to the resolved physical side ("right" in LTR, "left" in RTL) */
|
|
15
|
+
className="flex w-full flex-col data-[side=right]:sm:max-w-2xl data-[side=right]:lg:max-w-3xl data-[side=left]:sm:max-w-2xl data-[side=left]:lg:max-w-3xl"
|
|
15
16
|
>
|
|
16
17
|
<AssistantProvider manageUrl={false}>
|
|
17
18
|
<HelpAssistantSheetBody />
|
|
@@ -52,7 +52,7 @@ export function HelpHint({ contextKey }: { contextKey: string }) {
|
|
|
52
52
|
<SheetTrigger render={<Button variant="ghost" size="icon-sm" aria-label={t("help.hint.trigger")} />}>
|
|
53
53
|
<HelpCircleIcon className="h-4 w-4" />
|
|
54
54
|
</SheetTrigger>
|
|
55
|
-
<SheetContent side="
|
|
55
|
+
<SheetContent side="end" className="w-full max-w-md sm:max-w-lg">
|
|
56
56
|
<SheetHeader>
|
|
57
57
|
<SheetTitle>{active ? active.name : t("help.hint.pickArticle")}</SheetTitle>
|
|
58
58
|
<SheetDescription>{active?.summary ?? ""}</SheetDescription>
|
|
@@ -71,7 +71,7 @@ export function HelpHint({ contextKey }: { contextKey: string }) {
|
|
|
71
71
|
<button
|
|
72
72
|
type="button"
|
|
73
73
|
onClick={() => setPicked(a)}
|
|
74
|
-
className="hover:bg-muted block w-full rounded px-2 py-1 text-
|
|
74
|
+
className="hover:bg-muted block w-full rounded px-2 py-1 text-start text-sm"
|
|
75
75
|
>
|
|
76
76
|
<div className="font-medium">{a.name}</div>
|
|
77
77
|
<div className="text-muted-foreground text-xs">{a.summary}</div>
|
|
@@ -30,7 +30,7 @@ export function HelpTOC({ headings }: { headings: readonly HelpHeading[] }) {
|
|
|
30
30
|
<MicroLabel className="mb-2">{t("help.toc.title")}</MicroLabel>
|
|
31
31
|
<ul className="space-y-1 text-sm">
|
|
32
32
|
{headings.map((h) => (
|
|
33
|
-
<li key={h.slug} style={{
|
|
33
|
+
<li key={h.slug} style={{ paddingInlineStart: `${(h.depth - 2) * 0.75}rem` }}>
|
|
34
34
|
<a
|
|
35
35
|
href={`#${h.slug}`}
|
|
36
36
|
className={
|
|
@@ -184,7 +184,7 @@ export default function HowToCommand({ pathname, extraGroups, onStartChat }: How
|
|
|
184
184
|
<CommandGroup heading={t(`howto.command.relevant`)}>
|
|
185
185
|
{relevantHowTos.map((howTo: HowToInterface) => (
|
|
186
186
|
<CommandItem key={howTo.id} onSelect={() => setSelectedHowTo(howTo)} className="cursor-pointer">
|
|
187
|
-
<ArrowRight className="h-4 w-4" />
|
|
187
|
+
<ArrowRight className="h-4 w-4 rtl:rotate-180" />
|
|
188
188
|
<span>{howTo.name}</span>
|
|
189
189
|
</CommandItem>
|
|
190
190
|
))}
|
|
@@ -196,7 +196,7 @@ export default function HowToCommand({ pathname, extraGroups, onStartChat }: How
|
|
|
196
196
|
<CommandGroup heading={searchTerm ? undefined : t(`howto.command.all`)}>
|
|
197
197
|
{otherHowTos.map((howTo: HowToInterface) => (
|
|
198
198
|
<CommandItem key={howTo.id} onSelect={() => setSelectedHowTo(howTo)} className="cursor-pointer">
|
|
199
|
-
<ArrowRight className="h-4 w-4" />
|
|
199
|
+
<ArrowRight className="h-4 w-4 rtl:rotate-180" />
|
|
200
200
|
<span>{howTo.name}</span>
|
|
201
201
|
</CommandItem>
|
|
202
202
|
))}
|
|
@@ -27,8 +27,8 @@ export default function HowToCommandViewer({ howTo, onBack, onStartChat }: HowTo
|
|
|
27
27
|
{/* Header with back button, title, and reading time */}
|
|
28
28
|
<div className="flex items-center gap-3 border-b px-4 py-3">
|
|
29
29
|
<Button variant="ghost" size="sm" onClick={onBack} className="h-8 px-2">
|
|
30
|
-
<ArrowLeft className="h-4 w-4" />
|
|
31
|
-
<span className="
|
|
30
|
+
<ArrowLeft className="h-4 w-4 rtl:rotate-180" />
|
|
31
|
+
<span className="ms-1">{t("howto.command.back")}</span>
|
|
32
32
|
</Button>
|
|
33
33
|
<SectionHeader level={2} className="flex-1 truncate">
|
|
34
34
|
{howTo.name}
|
|
@@ -43,14 +43,14 @@ export default function HowToCommandViewer({ howTo, onBack, onStartChat }: HowTo
|
|
|
43
43
|
<div className="flex min-h-0 flex-1">
|
|
44
44
|
{/* Left sidebar - table of contents */}
|
|
45
45
|
{headings.length > 0 && (
|
|
46
|
-
<div className="w-50 shrink-0 overflow-y-auto border-
|
|
46
|
+
<div className="w-50 shrink-0 overflow-y-auto border-e p-4">
|
|
47
47
|
<nav className="space-y-1">
|
|
48
48
|
{headings.map((heading) => (
|
|
49
49
|
<a
|
|
50
50
|
key={heading.id}
|
|
51
51
|
href={`#${heading.id}`}
|
|
52
52
|
className="text-muted-foreground hover:text-foreground block truncate text-sm"
|
|
53
|
-
style={{
|
|
53
|
+
style={{ paddingInlineStart: `${(heading.level - 1) * 0.75}rem` }}
|
|
54
54
|
>
|
|
55
55
|
{heading.text}
|
|
56
56
|
</a>
|
|
@@ -69,7 +69,7 @@ export default function HowToCommandViewer({ howTo, onBack, onStartChat }: HowTo
|
|
|
69
69
|
{onStartChat && (
|
|
70
70
|
<div className="flex items-center justify-end gap-2 border-t px-4 py-3">
|
|
71
71
|
<Button onClick={onStartChat} variant="default" size="sm">
|
|
72
|
-
<MessageSquare className="
|
|
72
|
+
<MessageSquare className="me-2 h-4 w-4" />
|
|
73
73
|
{t("howto.command.chat_button")}
|
|
74
74
|
</Button>
|
|
75
75
|
</div>
|
|
@@ -77,11 +77,11 @@ function PageSelector({
|
|
|
77
77
|
<PopoverContent align="start" className="w-(--anchor-width) p-0">
|
|
78
78
|
<Command shouldFilter={false}>
|
|
79
79
|
<div className="relative w-full border-b">
|
|
80
|
-
<SearchIcon className="text-muted-foreground absolute top-2.5
|
|
80
|
+
<SearchIcon className="text-muted-foreground absolute top-2.5 start-2.5 h-4 w-4" />
|
|
81
81
|
<Input
|
|
82
82
|
placeholder={placeholder}
|
|
83
83
|
type="text"
|
|
84
|
-
className="rounded-none border-0
|
|
84
|
+
className="rounded-none border-0 ps-8 focus-visible:ring-0"
|
|
85
85
|
onChange={(e) => setSearch(e.target.value)}
|
|
86
86
|
value={search}
|
|
87
87
|
/>
|
|
@@ -339,7 +339,7 @@ function HowToEditorInternal({
|
|
|
339
339
|
/>
|
|
340
340
|
))}
|
|
341
341
|
<Button type="button" variant="outline" size="sm" onClick={addPage}>
|
|
342
|
-
<PlusIcon className="
|
|
342
|
+
<PlusIcon className="me-2 h-4 w-4" />
|
|
343
343
|
{t(`howto.fields.pages.add`)}
|
|
344
344
|
</Button>
|
|
345
345
|
</div>
|
|
@@ -111,7 +111,7 @@ export default function HowToSelector({
|
|
|
111
111
|
</PopoverTrigger>
|
|
112
112
|
{field.value && (
|
|
113
113
|
<CircleX
|
|
114
|
-
className="text-muted hover:text-destructive
|
|
114
|
+
className="text-muted hover:text-destructive ms-2 h-4 w-4 shrink-0 cursor-pointer"
|
|
115
115
|
onClick={() => setHowTo()}
|
|
116
116
|
/>
|
|
117
117
|
)}
|
|
@@ -119,19 +119,19 @@ export default function HowToSelector({
|
|
|
119
119
|
<PopoverContent align="start" className="w-(--anchor-width)">
|
|
120
120
|
<Command shouldFilter={false}>
|
|
121
121
|
<div className="relative mb-2 w-full">
|
|
122
|
-
<SearchIcon className="text-muted-foreground absolute top-2.5
|
|
122
|
+
<SearchIcon className="text-muted-foreground absolute top-2.5 start-2.5 h-4 w-4" />
|
|
123
123
|
<Input
|
|
124
124
|
placeholder={t(`generic.search.placeholder`, { type: t(`entities.howtos`, { count: 1 }) })}
|
|
125
125
|
type="text"
|
|
126
|
-
className="w-full
|
|
126
|
+
className="w-full pe-8 ps-8"
|
|
127
127
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchTerm(e.target.value)}
|
|
128
128
|
value={searchTerm}
|
|
129
129
|
/>
|
|
130
130
|
{isSearching ? (
|
|
131
|
-
<RefreshCwIcon className="text-muted-foreground absolute top-2.5
|
|
131
|
+
<RefreshCwIcon className="text-muted-foreground absolute top-2.5 end-2.5 h-4 w-4 animate-spin" />
|
|
132
132
|
) : searchTermRef.current ? (
|
|
133
133
|
<XIcon
|
|
134
|
-
className={`absolute top-2.5
|
|
134
|
+
className={`absolute top-2.5 end-2.5 h-4 w-4 ${searchTermRef.current ? "cursor-pointer" : "text-muted-foreground"}`}
|
|
135
135
|
onClick={() => {
|
|
136
136
|
setSearchTerm("");
|
|
137
137
|
search("");
|
|
@@ -44,7 +44,7 @@ export function NotificationsList({ archived }: NotificationsListProps) {
|
|
|
44
44
|
<Card key={i}>
|
|
45
45
|
<CardContent className="p-2">
|
|
46
46
|
<div className="flex w-full flex-row items-center">
|
|
47
|
-
<Skeleton className="
|
|
47
|
+
<Skeleton className="me-4 h-8 w-8 rounded-full" />
|
|
48
48
|
<div className="flex-1 space-y-2">
|
|
49
49
|
<Skeleton className="h-4 w-3/4" />
|
|
50
50
|
<Skeleton className="h-3 w-1/2" />
|
|
@@ -108,7 +108,7 @@ export function NotificationsList({ archived }: NotificationsListProps) {
|
|
|
108
108
|
e.stopPropagation();
|
|
109
109
|
archiveNotification(notification);
|
|
110
110
|
}}
|
|
111
|
-
className="text-muted-foreground hover:text-destructive
|
|
111
|
+
className="text-muted-foreground hover:text-destructive ms-2"
|
|
112
112
|
>
|
|
113
113
|
<ArchiveIcon className="h-4 w-4 cursor-pointer" />
|
|
114
114
|
</Button>
|
|
@@ -200,7 +200,7 @@ function NotificationModalContent({ isOpen, setIsOpen }: NotificationModalProps)
|
|
|
200
200
|
{t(`entities.notifications`, { count: 2 })}
|
|
201
201
|
</SidebarMenuButton>
|
|
202
202
|
</PopoverTrigger>
|
|
203
|
-
<PopoverContent className="relative
|
|
203
|
+
<PopoverContent className="relative start-10 w-80 border-0 p-0 shadow-none">
|
|
204
204
|
<Card>
|
|
205
205
|
<CardHeader className="p-4">
|
|
206
206
|
<CardTitle>{t(`entities.notifications`, { count: 2 })}</CardTitle>
|
|
@@ -68,7 +68,7 @@ export function OAuthClientCard({ client, onClick, onEdit, onDelete }: OAuthClie
|
|
|
68
68
|
onEdit();
|
|
69
69
|
}}
|
|
70
70
|
>
|
|
71
|
-
<Pencil className="h-4 w-4
|
|
71
|
+
<Pencil className="h-4 w-4 me-2" />
|
|
72
72
|
Edit
|
|
73
73
|
</DropdownMenuItem>
|
|
74
74
|
)}
|
|
@@ -80,7 +80,7 @@ export function OAuthClientCard({ client, onClick, onEdit, onDelete }: OAuthClie
|
|
|
80
80
|
}}
|
|
81
81
|
className="text-destructive"
|
|
82
82
|
>
|
|
83
|
-
<Trash2 className="h-4 w-4
|
|
83
|
+
<Trash2 className="h-4 w-4 me-2" />
|
|
84
84
|
Delete
|
|
85
85
|
</DropdownMenuItem>
|
|
86
86
|
)}
|
|
@@ -194,13 +194,13 @@ export function OAuthClientDetail({
|
|
|
194
194
|
<div className="flex gap-3 pt-4">
|
|
195
195
|
{onEdit && (
|
|
196
196
|
<Button variant="outline" onClick={onEdit} disabled={isLoading}>
|
|
197
|
-
<Pencil className="h-4 w-4
|
|
197
|
+
<Pencil className="h-4 w-4 me-2" />
|
|
198
198
|
Edit
|
|
199
199
|
</Button>
|
|
200
200
|
)}
|
|
201
201
|
{onDelete && (
|
|
202
202
|
<Button variant="destructive" onClick={() => setShowDeleteConfirm(true)} disabled={isLoading}>
|
|
203
|
-
<Trash2 className="h-4 w-4
|
|
203
|
+
<Trash2 className="h-4 w-4 me-2" />
|
|
204
204
|
Delete
|
|
205
205
|
</Button>
|
|
206
206
|
)}
|
|
@@ -80,7 +80,7 @@ export function OAuthClientList({
|
|
|
80
80
|
<SectionHeader level={2}>{title}</SectionHeader>
|
|
81
81
|
{onCreateClick && (
|
|
82
82
|
<Button onClick={onCreateClick}>
|
|
83
|
-
<Plus className="h-4 w-4
|
|
83
|
+
<Plus className="h-4 w-4 me-2" />
|
|
84
84
|
New App
|
|
85
85
|
</Button>
|
|
86
86
|
)}
|
|
@@ -91,7 +91,7 @@ export function OAuthClientList({
|
|
|
91
91
|
<p className="text-muted-foreground mb-4">{emptyStateMessage}</p>
|
|
92
92
|
{onCreateClick && (
|
|
93
93
|
<Button onClick={onCreateClick}>
|
|
94
|
-
<Plus className="h-4 w-4
|
|
94
|
+
<Plus className="h-4 w-4 me-2" />
|
|
95
95
|
Create Application
|
|
96
96
|
</Button>
|
|
97
97
|
)}
|
|
@@ -107,7 +107,7 @@ export function OAuthClientList({
|
|
|
107
107
|
<SectionHeader level={2}>{title}</SectionHeader>
|
|
108
108
|
{onCreateClick && (
|
|
109
109
|
<Button onClick={onCreateClick}>
|
|
110
|
-
<Plus className="h-4 w-4
|
|
110
|
+
<Plus className="h-4 w-4 me-2" />
|
|
111
111
|
New App
|
|
112
112
|
</Button>
|
|
113
113
|
)}
|
|
@@ -135,7 +135,7 @@ export function OAuthRedirectUriInput({
|
|
|
135
135
|
</div>
|
|
136
136
|
|
|
137
137
|
<Button type="button" variant="outline" size="sm" onClick={handleAdd} disabled={disabled} className="mt-2">
|
|
138
|
-
<Plus className="h-4 w-4
|
|
138
|
+
<Plus className="h-4 w-4 me-2" />
|
|
139
139
|
Add Redirect URI
|
|
140
140
|
</Button>
|
|
141
141
|
|
|
@@ -78,7 +78,7 @@ export function OAuthScopeSelector({
|
|
|
78
78
|
{Object.entries(groupedScopes).map(([groupName, scopes]) => (
|
|
79
79
|
<div key={groupName} className="space-y-2">
|
|
80
80
|
<h4 className="text-sm font-medium capitalize">{groupName}</h4>
|
|
81
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-2
|
|
81
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 ps-2">
|
|
82
82
|
{scopes.map((scopeInfo) => {
|
|
83
83
|
const isChecked = value.includes(scopeInfo.scope);
|
|
84
84
|
const isAdmin = scopeInfo.scope === "admin";
|
|
@@ -99,7 +99,7 @@ export function OAuthScopeSelector({
|
|
|
99
99
|
<div className="flex-1">
|
|
100
100
|
<Label htmlFor={`scope-${scopeInfo.scope}`} className="cursor-pointer">
|
|
101
101
|
{scopeInfo.name}
|
|
102
|
-
{isAdmin && <span className="
|
|
102
|
+
{isAdmin && <span className="ms-2 text-xs text-destructive">(Dangerous)</span>}
|
|
103
103
|
</Label>
|
|
104
104
|
<p className="text-xs text-muted-foreground">{scopeInfo.description}</p>
|
|
105
105
|
</div>
|
|
@@ -18,13 +18,7 @@ export function OnboardingCard({
|
|
|
18
18
|
}: OnboardingCardRenderProps) {
|
|
19
19
|
return (
|
|
20
20
|
<Card className="w-[320px] relative" data-shepherd-card>
|
|
21
|
-
<Button
|
|
22
|
-
variant="ghost"
|
|
23
|
-
size="icon"
|
|
24
|
-
className="absolute right-2 top-2"
|
|
25
|
-
onClick={onClose}
|
|
26
|
-
aria-label={labels.close}
|
|
27
|
-
>
|
|
21
|
+
<Button variant="ghost" size="icon" className="absolute end-2 top-2" onClick={onClose} aria-label={labels.close}>
|
|
28
22
|
<X className="h-4 w-4" />
|
|
29
23
|
</Button>
|
|
30
24
|
<CardHeader>
|
|
@@ -156,7 +156,7 @@ export default function RbacByRoleContainer() {
|
|
|
156
156
|
return (
|
|
157
157
|
<RoundPageContainer fullWidth forceHeader>
|
|
158
158
|
<div className="flex h-full w-full">
|
|
159
|
-
<aside className="w-60 shrink-0 overflow-y-auto border-
|
|
159
|
+
<aside className="w-60 shrink-0 overflow-y-auto border-e bg-muted/20">
|
|
160
160
|
<ul className="py-1">
|
|
161
161
|
{sortedRoleIds.map((id) => (
|
|
162
162
|
<li key={id}>
|
|
@@ -165,7 +165,7 @@ export default function RbacByRoleContainer() {
|
|
|
165
165
|
onClick={() => handleSelectRole(id)}
|
|
166
166
|
aria-current={id === selectedRoleId ? "true" : undefined}
|
|
167
167
|
className={cn(
|
|
168
|
-
"block w-full px-4 py-1.5 text-
|
|
168
|
+
"block w-full px-4 py-1.5 text-start text-sm hover:bg-muted",
|
|
169
169
|
id === selectedRoleId && "bg-muted font-medium text-foreground",
|
|
170
170
|
id !== selectedRoleId && "text-muted-foreground",
|
|
171
171
|
)}
|
|
@@ -184,7 +184,7 @@ export default function RbacByRoleContainer() {
|
|
|
184
184
|
<table className="w-full text-sm">
|
|
185
185
|
<thead className="sticky top-0 z-10">
|
|
186
186
|
<tr className="border-b bg-muted/80 backdrop-blur-sm">
|
|
187
|
-
<th className="w-40 px-4 py-2 text-
|
|
187
|
+
<th className="w-40 px-4 py-2 text-start text-xs font-medium text-muted-foreground">
|
|
188
188
|
{t("rbac.module")}
|
|
189
189
|
</th>
|
|
190
190
|
{ACTION_TYPES.map((action) => (
|
|
@@ -118,7 +118,7 @@ const ModuleEditor = memo(function ModuleEditor({
|
|
|
118
118
|
<table className="w-full text-sm">
|
|
119
119
|
<thead>
|
|
120
120
|
<tr className="border-b bg-muted/50">
|
|
121
|
-
<th className="w-40 px-4 py-2 text-
|
|
121
|
+
<th className="w-40 px-4 py-2 text-start text-xs font-medium text-muted-foreground">{t("rbac.role")}</th>
|
|
122
122
|
{ACTION_TYPES.map((action) => (
|
|
123
123
|
<th key={action} className="min-w-28 px-2 py-2 text-center text-xs font-medium text-muted-foreground">
|
|
124
124
|
{ACTION_LABELS[action]}
|
|
@@ -295,7 +295,7 @@ export default function RbacContainer() {
|
|
|
295
295
|
<RoundPageContainer fullWidth forceHeader>
|
|
296
296
|
<div className="flex h-full w-full">
|
|
297
297
|
{/* Sidebar: module list */}
|
|
298
|
-
<aside className="w-60 shrink-0 overflow-y-auto border-
|
|
298
|
+
<aside className="w-60 shrink-0 overflow-y-auto border-e bg-muted/20">
|
|
299
299
|
<ul className="py-1">
|
|
300
300
|
{sortedModuleIds.map((id) => (
|
|
301
301
|
<li key={id}>
|
|
@@ -304,7 +304,7 @@ export default function RbacContainer() {
|
|
|
304
304
|
onClick={() => handleSelectModule(id)}
|
|
305
305
|
aria-current={id === selectedModuleId ? "true" : undefined}
|
|
306
306
|
className={cn(
|
|
307
|
-
"block w-full px-4 py-1.5 text-
|
|
307
|
+
"block w-full px-4 py-1.5 text-start text-sm hover:bg-muted",
|
|
308
308
|
id === selectedModuleId && "bg-muted font-medium text-foreground",
|
|
309
309
|
id !== selectedModuleId && "text-muted-foreground",
|
|
310
310
|
)}
|
|
@@ -110,6 +110,7 @@ async function copyToClipboard(text: string): Promise<boolean> {
|
|
|
110
110
|
const textArea = document.createElement("textarea");
|
|
111
111
|
textArea.value = text;
|
|
112
112
|
textArea.style.position = "fixed";
|
|
113
|
+
// rtl-ok: off-screen clipboard fallback, not layout — physical offset is deliberate
|
|
113
114
|
textArea.style.left = "-999999px";
|
|
114
115
|
textArea.style.top = "-999999px";
|
|
115
116
|
document.body.appendChild(textArea);
|
|
@@ -47,7 +47,7 @@ export function FormRoles({ form, id, name, roles }: FormRolesProps) {
|
|
|
47
47
|
/>
|
|
48
48
|
<Tooltip>
|
|
49
49
|
<TooltipTrigger>
|
|
50
|
-
<FieldLabel htmlFor={`role-${role.id}`} className="
|
|
50
|
+
<FieldLabel htmlFor={`role-${role.id}`} className="ms-3 cursor-pointer font-normal">
|
|
51
51
|
{t(`role.roles`, { role: role.id.replaceAll(`-`, ``) })}
|
|
52
52
|
</FieldLabel>
|
|
53
53
|
</TooltipTrigger>
|
|
@@ -84,7 +84,7 @@ export function RemoveUserFromRole({ role, user, refresh }: RemoveUserFromRolePr
|
|
|
84
84
|
<>
|
|
85
85
|
{t(`role.remove_user.description_allowed`, { role: roleName, user: user.name })}
|
|
86
86
|
<div className="flex justify-end">
|
|
87
|
-
<Button className="
|
|
87
|
+
<Button className="me-2" variant={"outline"} type={`button`} onClick={() => setOpen(false)}>
|
|
88
88
|
{t(`ui.buttons.cancel`)}
|
|
89
89
|
</Button>
|
|
90
90
|
<Button
|
|
@@ -82,7 +82,7 @@ export function UserRoleAdd({ user, refresh }: UserRoleAddProps) {
|
|
|
82
82
|
return (
|
|
83
83
|
<>
|
|
84
84
|
<Button size="sm" onClick={() => setOpen(true)}>
|
|
85
|
-
<PlusCircle className="
|
|
85
|
+
<PlusCircle className="me-3 h-3.5 w-3.5" />
|
|
86
86
|
{t(`common.association.label`, {
|
|
87
87
|
source: t(`entities.roles`, { count: 1 }),
|
|
88
88
|
destination: t(`entities.users`, { count: 1 }),
|
|
@@ -104,7 +104,7 @@ export function TokenUsageBreakdownTable({ rows, metric }: Props) {
|
|
|
104
104
|
<TableHeader>
|
|
105
105
|
<TableRow>
|
|
106
106
|
{columns.map((column) => (
|
|
107
|
-
<TableHead key={column.key} className={cn(column.numeric && "text-
|
|
107
|
+
<TableHead key={column.key} className={cn(column.numeric && "text-end")}>
|
|
108
108
|
<button
|
|
109
109
|
type="button"
|
|
110
110
|
onClick={() => toggleSort(column.key)}
|
|
@@ -137,19 +137,19 @@ export function TokenUsageBreakdownTable({ rows, metric }: Props) {
|
|
|
137
137
|
</TableCell>
|
|
138
138
|
<TableCell className="text-muted-foreground text-xs">{row.sublabel ?? ""}</TableCell>
|
|
139
139
|
{showActiveUsers && (
|
|
140
|
-
<TableCell className="text-
|
|
140
|
+
<TableCell className="text-end text-xs tabular-nums">
|
|
141
141
|
{row.activeUsers === undefined ? "" : decimal(row.activeUsers, 0)}
|
|
142
142
|
</TableCell>
|
|
143
143
|
)}
|
|
144
|
-
<TableCell className="text-
|
|
145
|
-
<TableCell className="text-
|
|
146
|
-
<TableCell className="text-
|
|
147
|
-
<TableCell className="text-
|
|
144
|
+
<TableCell className="text-end text-xs tabular-nums">{decimal(row.calls, 0)}</TableCell>
|
|
145
|
+
<TableCell className="text-end text-xs tabular-nums">{decimal(row.tokensIn, 0)}</TableCell>
|
|
146
|
+
<TableCell className="text-end text-xs tabular-nums">{decimal(row.tokensOut, 0)}</TableCell>
|
|
147
|
+
<TableCell className="text-end text-xs tabular-nums">
|
|
148
148
|
{percent(cacheHitPercentage(row.cached, row.tokensIn))}
|
|
149
149
|
</TableCell>
|
|
150
|
-
<TableCell className="text-
|
|
151
|
-
<TableCell className="text-
|
|
152
|
-
<TableCell className="text-
|
|
150
|
+
<TableCell className="text-end text-xs tabular-nums">{formatValue(row.cost, "cost")}</TableCell>
|
|
151
|
+
<TableCell className="text-end text-xs tabular-nums">{formatValue(row.credits, "credits")}</TableCell>
|
|
152
|
+
<TableCell className="text-end text-xs tabular-nums">{percent(share)}</TableCell>
|
|
153
153
|
</TableRow>
|
|
154
154
|
);
|
|
155
155
|
})}
|