@hed-hog/core 0.0.368 → 0.0.371
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/LICENSE.md +21 -0
- package/README.md +2 -0
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +10 -7
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/app-command/app-command.module.d.ts +3 -0
- package/dist/app-command/app-command.module.d.ts.map +1 -0
- package/dist/app-command/app-command.module.js +22 -0
- package/dist/app-command/app-command.module.js.map +1 -0
- package/dist/app-command/app-command.registry.d.ts +22 -0
- package/dist/app-command/app-command.registry.d.ts.map +1 -0
- package/dist/{webhook-integration/webhook-command.registry.js → app-command/app-command.registry.js} +6 -6
- package/dist/app-command/app-command.registry.js.map +1 -0
- package/dist/auth/auth.controller.d.ts +2 -2
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +20 -7
- package/dist/auth/auth.controller.js.map +1 -1
- package/dist/auth/auth.service.d.ts +3 -3
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +10 -36
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/auth/dto/forget.dto.d.ts +1 -0
- package/dist/auth/dto/forget.dto.d.ts.map +1 -1
- package/dist/auth/dto/forget.dto.js +5 -0
- package/dist/auth/dto/forget.dto.js.map +1 -1
- package/dist/auth/guards/auth.guard.d.ts.map +1 -1
- package/dist/auth/guards/auth.guard.js +4 -1
- package/dist/auth/guards/auth.guard.js.map +1 -1
- package/dist/challenge/challenge.service.d.ts +8 -7
- package/dist/challenge/challenge.service.d.ts.map +1 -1
- package/dist/challenge/challenge.service.js +27 -19
- package/dist/challenge/challenge.service.js.map +1 -1
- package/dist/file/dto/upload.dto.d.ts +3 -0
- package/dist/file/dto/upload.dto.d.ts.map +1 -1
- package/dist/file/dto/upload.dto.js +22 -0
- package/dist/file/dto/upload.dto.js.map +1 -1
- package/dist/file/file.controller.d.ts +2 -1
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +29 -16
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.service.d.ts +51 -1
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +250 -18
- package/dist/file/file.service.js.map +1 -1
- package/dist/file/image-optimization.service.d.ts +17 -4
- package/dist/file/image-optimization.service.d.ts.map +1 -1
- package/dist/file/image-optimization.service.js +101 -46
- package/dist/file/image-optimization.service.js.map +1 -1
- package/dist/file/provider/s3.provider.d.ts.map +1 -1
- package/dist/file/provider/s3.provider.js +15 -7
- package/dist/file/provider/s3.provider.js.map +1 -1
- package/dist/file/provider/spaces.provider.d.ts.map +1 -1
- package/dist/file/provider/spaces.provider.js +18 -8
- package/dist/file/provider/spaces.provider.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/integration/services/event-subscriber.registry.d.ts +5 -0
- package/dist/integration/services/event-subscriber.registry.d.ts.map +1 -1
- package/dist/integration/services/event-subscriber.registry.js +15 -0
- package/dist/integration/services/event-subscriber.registry.js.map +1 -1
- package/dist/integration/services/outbox.processor.d.ts.map +1 -1
- package/dist/integration/services/outbox.processor.js +2 -4
- package/dist/integration/services/outbox.processor.js.map +1 -1
- package/dist/integration/services/outbox.service.d.ts +4 -2
- package/dist/integration/services/outbox.service.d.ts.map +1 -1
- package/dist/integration/services/outbox.service.js +26 -15
- package/dist/integration/services/outbox.service.js.map +1 -1
- package/dist/integration-profile/integration-credential-crypto.service.d.ts +43 -0
- package/dist/integration-profile/integration-credential-crypto.service.d.ts.map +1 -0
- package/dist/integration-profile/integration-credential-crypto.service.js +142 -0
- package/dist/integration-profile/integration-credential-crypto.service.js.map +1 -0
- package/dist/integration-profile/integration-profile.controller.d.ts +6 -7
- package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.controller.js +4 -3
- package/dist/integration-profile/integration-profile.controller.js.map +1 -1
- package/dist/integration-profile/integration-profile.module.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.module.js +5 -2
- package/dist/integration-profile/integration-profile.module.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts +16 -0
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -0
- package/dist/integration-profile/integration-profile.secrets.js +56 -0
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -0
- package/dist/integration-profile/integration-profile.service.d.ts +125 -8
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +257 -68
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.d.ts +17 -0
- package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +31 -0
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/language/en.json +178 -0
- package/dist/language/pt.json +178 -0
- package/dist/mail/mail.controller.d.ts.map +1 -1
- package/dist/mail/mail.controller.js +5 -28
- package/dist/mail/mail.controller.js.map +1 -1
- package/dist/mail/mail.module.js +18 -18
- package/dist/mail/mail.module.js.map +1 -1
- package/dist/mail/mail.service.d.ts +13 -2
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +25 -15
- package/dist/mail/mail.service.js.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.js +6 -5
- package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
- package/dist/oauth/providers/facebook.provider.js +5 -5
- package/dist/oauth/providers/facebook.provider.js.map +1 -1
- package/dist/oauth/providers/github.provider.js +5 -5
- package/dist/oauth/providers/github.provider.js.map +1 -1
- package/dist/oauth/providers/google.provider.js +5 -5
- package/dist/oauth/providers/google.provider.js.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.js +5 -5
- package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
- package/dist/oauth/providers/microsoft.provider.js +5 -5
- package/dist/oauth/providers/microsoft.provider.js.map +1 -1
- package/dist/pdf/pdf.service.d.ts +4 -0
- package/dist/pdf/pdf.service.d.ts.map +1 -1
- package/dist/pdf/pdf.service.js +16 -9
- package/dist/pdf/pdf.service.js.map +1 -1
- package/dist/profile/profile.controller.d.ts +7 -7
- package/dist/profile/profile.controller.d.ts.map +1 -1
- package/dist/profile/profile.controller.js +28 -21
- package/dist/profile/profile.controller.js.map +1 -1
- package/dist/profile/profile.service.d.ts +7 -7
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +21 -25
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/setting/setting.service.d.ts +1 -0
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +15 -2
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/token/token.service.d.ts.map +1 -1
- package/dist/token/token.service.js +2 -1
- package/dist/token/token.service.js.map +1 -1
- package/dist/user/user.controller.d.ts +9 -0
- package/dist/user/user.controller.d.ts.map +1 -1
- package/dist/user/user.controller.js +13 -0
- package/dist/user/user.controller.js.map +1 -1
- package/dist/user/user.service.d.ts +7 -0
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +19 -0
- package/dist/user/user.service.js.map +1 -1
- package/dist/utils/webauthn-origin.d.ts +11 -0
- package/dist/utils/webauthn-origin.d.ts.map +1 -0
- package/dist/utils/webauthn-origin.js +37 -0
- package/dist/utils/webauthn-origin.js.map +1 -0
- package/dist/webhook-integration/webhook-integration.controller.d.ts +13 -0
- package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.controller.js +29 -0
- package/dist/webhook-integration/webhook-integration.controller.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.module.js +3 -3
- package/dist/webhook-integration/webhook-integration.module.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.d.ts +18 -2
- package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.js +110 -6
- package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
- package/hedhog/data/integration_event_catalog.yaml +118 -118
- package/hedhog/data/integration_provider.yaml +9 -0
- package/hedhog/data/integration_type.yaml +6 -0
- package/hedhog/data/menu.yaml +6 -0
- package/hedhog/data/role.yaml +7 -0
- package/hedhog/data/route.yaml +192 -207
- package/hedhog/data/setting_group.yaml +119 -13
- package/hedhog/frontend/app/access-log/page.tsx.ejs +35 -3
- package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +36 -3
- package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +39 -4
- package/hedhog/frontend/app/account/components/tokens.tsx.ejs +39 -4
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +35 -2
- package/hedhog/frontend/app/configurations/[slug]/components/byte-size-input.tsx.ejs +160 -0
- package/hedhog/frontend/app/configurations/[slug]/components/duration-input.tsx.ejs +157 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +244 -63
- package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +33 -1
- package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +35 -3
- package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +36 -4
- package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +35 -3
- package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +36 -4
- package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +35 -3
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +141 -29
- package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +118 -11
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +37 -4
- package/hedhog/frontend/app/menu/page.tsx.ejs +34 -2
- package/hedhog/frontend/app/preferences/page.tsx.ejs +77 -0
- package/hedhog/frontend/app/roles/menus.tsx.ejs +35 -3
- package/hedhog/frontend/app/roles/page.tsx.ejs +34 -2
- package/hedhog/frontend/app/roles/routes.tsx.ejs +36 -4
- package/hedhog/frontend/app/roles/users.tsx.ejs +36 -4
- package/hedhog/frontend/app/routes/page.tsx.ejs +34 -2
- package/hedhog/frontend/app/setting-list/page.tsx.ejs +34 -2
- package/hedhog/frontend/app/users/page.tsx.ejs +51 -21
- package/hedhog/frontend/messages/en.json +69 -4
- package/hedhog/frontend/messages/pt.json +69 -4
- package/hedhog/table/event_webhook.yaml +55 -55
- package/hedhog/table/event_webhook_delivery_log.yaml +66 -66
- package/hedhog/table/event_webhook_event.yaml +26 -26
- package/hedhog/table/integration_event_catalog.yaml +41 -41
- package/hedhog/table/mcp_conversation.yaml +12 -12
- package/hedhog/table/mcp_conversation_message.yaml +23 -23
- package/hedhog/table/mcp_tool_call_log.yaml +22 -22
- package/hedhog/table/route.yaml +33 -33
- package/hedhog/table/setting.yaml +2 -0
- package/hedhog/table/webhook_call_log.yaml +3 -0
- package/hedhog/table/webhook_integration.yaml +43 -43
- package/package.json +9 -4
- package/src/ai/ai.service.ts +9 -6
- package/src/app-command/app-command.module.ts +9 -0
- package/src/{webhook-integration/webhook-command.registry.ts → app-command/app-command.registry.ts} +9 -9
- package/src/auth/auth.controller.ts +20 -4
- package/src/auth/auth.service.ts +10 -36
- package/src/auth/dto/forget.dto.ts +5 -1
- package/src/auth/guards/auth.guard.ts +4 -1
- package/src/challenge/challenge.service.ts +30 -19
- package/src/file/dto/upload.dto.ts +25 -1
- package/src/file/file.controller.ts +31 -18
- package/src/file/file.service.ts +341 -16
- package/src/file/image-optimization.service.ts +111 -46
- package/src/file/provider/s3.provider.ts +16 -7
- package/src/file/provider/spaces.provider.ts +15 -5
- package/src/index.ts +4 -1
- package/src/integration/services/event-subscriber.registry.ts +15 -0
- package/src/integration/services/outbox.processor.ts +2 -5
- package/src/integration/services/outbox.service.ts +35 -17
- package/src/integration/types/event.types.ts +4 -4
- package/src/integration-profile/integration-credential-crypto.service.ts +146 -0
- package/src/integration-profile/integration-profile.controller.ts +2 -0
- package/src/integration-profile/integration-profile.module.ts +5 -2
- package/src/integration-profile/integration-profile.secrets.ts +51 -0
- package/src/integration-profile/integration-profile.service.ts +335 -54
- package/src/integration-profile/integration-profile.utils.ts +56 -0
- package/src/language/en.json +5 -1
- package/src/language/pt.json +5 -1
- package/src/mail/mail.controller.ts +5 -29
- package/src/mail/mail.module.ts +5 -5
- package/src/mail/mail.service.ts +37 -13
- package/src/mcp/decorators/mcp-tool.decorator.ts +7 -7
- package/src/mcp/guards/mcp-permission.guard.ts +51 -51
- package/src/mcp/interfaces/mcp-tool-definition.interface.ts +6 -6
- package/src/mcp/mcp-server.service.ts +87 -87
- package/src/mcp/types/mcp-context.type.ts +6 -6
- package/src/mcp-chat/dto/create-conversation.dto.ts +7 -7
- package/src/mcp-chat/dto/send-message.dto.ts +7 -7
- package/src/mcp-chat/mcp-chat.service.ts +5 -5
- package/src/notification/events/notification-stale-progress-check.event.ts +5 -5
- package/src/oauth/oauth-callback-coordinator.service.spec.ts +159 -0
- package/src/oauth/providers/facebook.provider.ts +3 -3
- package/src/oauth/providers/github.provider.ts +3 -3
- package/src/oauth/providers/google.provider.ts +3 -3
- package/src/oauth/providers/microsoft-entra-id.provider.ts +3 -3
- package/src/oauth/providers/microsoft.provider.ts +3 -3
- package/src/pdf/pdf.service.ts +19 -6
- package/src/profile/profile.controller.ts +21 -14
- package/src/profile/profile.service.ts +23 -20
- package/src/route/dto/create.dto.ts +32 -32
- package/src/route/dto/update.dto.ts +31 -31
- package/src/security/security.service.spec.ts +222 -0
- package/src/setting/setting.service.ts +15 -2
- package/src/token/token.service.ts +2 -1
- package/src/user/user.controller.ts +26 -16
- package/src/user/user.service.ts +25 -0
- package/src/utils/webauthn-origin.ts +38 -0
- package/src/webhook-integration/integration-event-catalog.controller.ts +50 -50
- package/src/webhook-integration/integration-event-catalog.service.ts +117 -117
- package/src/webhook-integration/webhook-integration.controller.ts +23 -0
- package/src/webhook-integration/webhook-integration.module.ts +3 -3
- package/src/webhook-integration/webhook-integration.service.ts +115 -5
- package/dist/webhook-integration/webhook-command.registry.d.ts +0 -22
- package/dist/webhook-integration/webhook-command.registry.d.ts.map +0 -1
- package/dist/webhook-integration/webhook-command.registry.js.map +0 -1
- package/src/menu/menu.service.spec.ts +0 -247
- package/src/route/route.service.spec.ts +0 -300
- package/src/screen/screen.service.spec.ts +0 -298
- package/src/user/user.service.spec.ts +0 -294
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
IconX,
|
|
69
69
|
} from '@tabler/icons-react';
|
|
70
70
|
import { useTranslations } from 'next-intl';
|
|
71
|
-
import { useState } from 'react';
|
|
71
|
+
import { useMemo, useState } from 'react';
|
|
72
72
|
import { toast } from 'sonner';
|
|
73
73
|
|
|
74
74
|
interface Component {
|
|
@@ -111,6 +111,8 @@ interface RoleOption {
|
|
|
111
111
|
name?: string;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
|
|
115
|
+
|
|
114
116
|
export function ComponentsTab() {
|
|
115
117
|
const t = useTranslations('core.DashboardManagement');
|
|
116
118
|
const { request, locales, currentLocaleCode } = useApp();
|
|
@@ -133,10 +135,40 @@ export function ComponentsTab() {
|
|
|
133
135
|
useState<Component | null>(null);
|
|
134
136
|
const [selectedRoleIds, setSelectedRoleIds] = useState<number[]>([]);
|
|
135
137
|
const [page, setPage] = useState(1);
|
|
138
|
+
const { data: generalSettings } = useQuery<{
|
|
139
|
+
data: Array<{ slug: string; value: string }>;
|
|
140
|
+
}>({
|
|
141
|
+
queryKey: ['setting-group-general'],
|
|
142
|
+
queryFn: async () => {
|
|
143
|
+
const response = await request<{
|
|
144
|
+
data: Array<{ slug: string; value: string }>;
|
|
145
|
+
}>({ url: '/setting/group/general', method: 'GET' });
|
|
146
|
+
return response.data;
|
|
147
|
+
},
|
|
148
|
+
staleTime: 5 * 60 * 1000,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const pageSizeOptions = useMemo(() => {
|
|
152
|
+
const setting = generalSettings?.data?.find(
|
|
153
|
+
(s) => s.slug === 'pagination-page-sizes'
|
|
154
|
+
);
|
|
155
|
+
if (!setting?.value) return DEFAULT_PAGE_SIZES;
|
|
156
|
+
try {
|
|
157
|
+
const parsed = JSON.parse(setting.value) as string[];
|
|
158
|
+
const sizes = parsed
|
|
159
|
+
.map(Number)
|
|
160
|
+
.filter((n) => !isNaN(n) && n > 0)
|
|
161
|
+
.sort((a, b) => a - b);
|
|
162
|
+
return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
|
|
163
|
+
} catch {
|
|
164
|
+
return DEFAULT_PAGE_SIZES;
|
|
165
|
+
}
|
|
166
|
+
}, [generalSettings]);
|
|
167
|
+
|
|
136
168
|
const [pageSize, setPageSize] = usePersistedPageSize({
|
|
137
169
|
storageKey: 'pagination:global:pageSize',
|
|
138
|
-
defaultValue:
|
|
139
|
-
allowedValues:
|
|
170
|
+
defaultValue: 12,
|
|
171
|
+
allowedValues: pageSizeOptions,
|
|
140
172
|
});
|
|
141
173
|
const [searchQuery, setSearchQuery] = useState('');
|
|
142
174
|
const [roleSearchQuery, setRoleSearchQuery] = useState('');
|
|
@@ -909,7 +941,7 @@ export function ComponentsTab() {
|
|
|
909
941
|
<SelectValue />
|
|
910
942
|
</SelectTrigger>
|
|
911
943
|
<SelectContent>
|
|
912
|
-
{
|
|
944
|
+
{pageSizeOptions.map((size) => (
|
|
913
945
|
<SelectItem key={size} value={String(size)}>
|
|
914
946
|
{size}
|
|
915
947
|
</SelectItem>
|
|
@@ -133,6 +133,8 @@ type RequestError = {
|
|
|
133
133
|
};
|
|
134
134
|
};
|
|
135
135
|
|
|
136
|
+
const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
|
|
137
|
+
|
|
136
138
|
export function DashboardRolesTab() {
|
|
137
139
|
const t = useTranslations('core.DashboardManagement');
|
|
138
140
|
const { request, currentLocaleCode, getSettingValue } = useApp();
|
|
@@ -146,10 +148,40 @@ export function DashboardRolesTab() {
|
|
|
146
148
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
147
149
|
const [roleToDelete, setRoleToDelete] = useState<number | null>(null);
|
|
148
150
|
const [page, setPage] = useState(1);
|
|
151
|
+
const { data: generalSettings } = useQuery<{
|
|
152
|
+
data: Array<{ slug: string; value: string }>;
|
|
153
|
+
}>({
|
|
154
|
+
queryKey: ['setting-group-general'],
|
|
155
|
+
queryFn: async () => {
|
|
156
|
+
const response = await request<{
|
|
157
|
+
data: Array<{ slug: string; value: string }>;
|
|
158
|
+
}>({ url: '/setting/group/general', method: 'GET' });
|
|
159
|
+
return response.data;
|
|
160
|
+
},
|
|
161
|
+
staleTime: 5 * 60 * 1000,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const pageSizeOptions = useMemo(() => {
|
|
165
|
+
const setting = generalSettings?.data?.find(
|
|
166
|
+
(s) => s.slug === 'pagination-page-sizes'
|
|
167
|
+
);
|
|
168
|
+
if (!setting?.value) return DEFAULT_PAGE_SIZES;
|
|
169
|
+
try {
|
|
170
|
+
const parsed = JSON.parse(setting.value) as string[];
|
|
171
|
+
const sizes = parsed
|
|
172
|
+
.map(Number)
|
|
173
|
+
.filter((n) => !isNaN(n) && n > 0)
|
|
174
|
+
.sort((a, b) => a - b);
|
|
175
|
+
return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
|
|
176
|
+
} catch {
|
|
177
|
+
return DEFAULT_PAGE_SIZES;
|
|
178
|
+
}
|
|
179
|
+
}, [generalSettings]);
|
|
180
|
+
|
|
149
181
|
const [pageSize, setPageSize] = usePersistedPageSize({
|
|
150
182
|
storageKey: 'pagination:global:pageSize',
|
|
151
|
-
defaultValue:
|
|
152
|
-
allowedValues:
|
|
183
|
+
defaultValue: 12,
|
|
184
|
+
allowedValues: pageSizeOptions,
|
|
153
185
|
});
|
|
154
186
|
const searchQuery = '';
|
|
155
187
|
const debouncedSearch = useDebounce(searchQuery, 500);
|
|
@@ -539,7 +571,7 @@ export function DashboardRolesTab() {
|
|
|
539
571
|
<SelectValue />
|
|
540
572
|
</SelectTrigger>
|
|
541
573
|
<SelectContent>
|
|
542
|
-
{
|
|
574
|
+
{pageSizeOptions.map((size) => (
|
|
543
575
|
<SelectItem key={size} value={String(size)}>
|
|
544
576
|
{size}
|
|
545
577
|
</SelectItem>
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
IconX,
|
|
68
68
|
} from '@tabler/icons-react';
|
|
69
69
|
import { useTranslations } from 'next-intl';
|
|
70
|
-
import { useState } from 'react';
|
|
70
|
+
import { useMemo, useState } from 'react';
|
|
71
71
|
import { toast } from 'sonner';
|
|
72
72
|
|
|
73
73
|
interface Dashboard {
|
|
@@ -98,6 +98,8 @@ interface RoleOption {
|
|
|
98
98
|
name?: string;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
|
|
102
|
+
|
|
101
103
|
export function DashboardsTab() {
|
|
102
104
|
const t = useTranslations('core.DashboardManagement');
|
|
103
105
|
const { request, locales, currentLocaleCode } = useApp();
|
|
@@ -120,10 +122,40 @@ export function DashboardsTab() {
|
|
|
120
122
|
useState<Dashboard | null>(null);
|
|
121
123
|
const [selectedRoleIds, setSelectedRoleIds] = useState<number[]>([]);
|
|
122
124
|
const [page, setPage] = useState(1);
|
|
125
|
+
const { data: generalSettings } = useQuery<{
|
|
126
|
+
data: Array<{ slug: string; value: string }>;
|
|
127
|
+
}>({
|
|
128
|
+
queryKey: ['setting-group-general'],
|
|
129
|
+
queryFn: async () => {
|
|
130
|
+
const response = await request<{
|
|
131
|
+
data: Array<{ slug: string; value: string }>;
|
|
132
|
+
}>({ url: '/setting/group/general', method: 'GET' });
|
|
133
|
+
return response.data;
|
|
134
|
+
},
|
|
135
|
+
staleTime: 5 * 60 * 1000,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const pageSizeOptions = useMemo(() => {
|
|
139
|
+
const setting = generalSettings?.data?.find(
|
|
140
|
+
(s) => s.slug === 'pagination-page-sizes'
|
|
141
|
+
);
|
|
142
|
+
if (!setting?.value) return DEFAULT_PAGE_SIZES;
|
|
143
|
+
try {
|
|
144
|
+
const parsed = JSON.parse(setting.value) as string[];
|
|
145
|
+
const sizes = parsed
|
|
146
|
+
.map(Number)
|
|
147
|
+
.filter((n) => !isNaN(n) && n > 0)
|
|
148
|
+
.sort((a, b) => a - b);
|
|
149
|
+
return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
|
|
150
|
+
} catch {
|
|
151
|
+
return DEFAULT_PAGE_SIZES;
|
|
152
|
+
}
|
|
153
|
+
}, [generalSettings]);
|
|
154
|
+
|
|
123
155
|
const [pageSize, setPageSize] = usePersistedPageSize({
|
|
124
156
|
storageKey: 'pagination:global:pageSize',
|
|
125
|
-
defaultValue:
|
|
126
|
-
allowedValues:
|
|
157
|
+
defaultValue: 12,
|
|
158
|
+
allowedValues: pageSizeOptions,
|
|
127
159
|
});
|
|
128
160
|
const [searchQuery, setSearchQuery] = useState('');
|
|
129
161
|
const [roleSearchQuery, setRoleSearchQuery] = useState('');
|
|
@@ -653,7 +685,7 @@ export function DashboardsTab() {
|
|
|
653
685
|
<SelectValue />
|
|
654
686
|
</SelectTrigger>
|
|
655
687
|
<SelectContent>
|
|
656
|
-
{
|
|
688
|
+
{pageSizeOptions.map((size) => (
|
|
657
689
|
<SelectItem key={size} value={String(size)}>
|
|
658
690
|
{size}
|
|
659
691
|
</SelectItem>
|
|
@@ -127,6 +127,8 @@ type ComponentListResponse = {
|
|
|
127
127
|
data?: Component[];
|
|
128
128
|
};
|
|
129
129
|
|
|
130
|
+
const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
|
|
131
|
+
|
|
130
132
|
export function ItemsTab() {
|
|
131
133
|
const t = useTranslations('core.DashboardManagement');
|
|
132
134
|
const { request, currentLocaleCode, getSettingValue } = useApp();
|
|
@@ -144,10 +146,40 @@ export function ItemsTab() {
|
|
|
144
146
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
145
147
|
const [itemToDelete, setItemToDelete] = useState<number | null>(null);
|
|
146
148
|
const [page, setPage] = useState(1);
|
|
149
|
+
const { data: generalSettings } = useQuery<{
|
|
150
|
+
data: Array<{ slug: string; value: string }>;
|
|
151
|
+
}>({
|
|
152
|
+
queryKey: ['setting-group-general'],
|
|
153
|
+
queryFn: async () => {
|
|
154
|
+
const response = await request<{
|
|
155
|
+
data: Array<{ slug: string; value: string }>;
|
|
156
|
+
}>({ url: '/setting/group/general', method: 'GET' });
|
|
157
|
+
return response.data;
|
|
158
|
+
},
|
|
159
|
+
staleTime: 5 * 60 * 1000,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const pageSizeOptions = useMemo(() => {
|
|
163
|
+
const setting = generalSettings?.data?.find(
|
|
164
|
+
(s) => s.slug === 'pagination-page-sizes'
|
|
165
|
+
);
|
|
166
|
+
if (!setting?.value) return DEFAULT_PAGE_SIZES;
|
|
167
|
+
try {
|
|
168
|
+
const parsed = JSON.parse(setting.value) as string[];
|
|
169
|
+
const sizes = parsed
|
|
170
|
+
.map(Number)
|
|
171
|
+
.filter((n) => !isNaN(n) && n > 0)
|
|
172
|
+
.sort((a, b) => a - b);
|
|
173
|
+
return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
|
|
174
|
+
} catch {
|
|
175
|
+
return DEFAULT_PAGE_SIZES;
|
|
176
|
+
}
|
|
177
|
+
}, [generalSettings]);
|
|
178
|
+
|
|
147
179
|
const [pageSize, setPageSize] = usePersistedPageSize({
|
|
148
180
|
storageKey: 'pagination:global:pageSize',
|
|
149
|
-
defaultValue:
|
|
150
|
-
allowedValues:
|
|
181
|
+
defaultValue: 12,
|
|
182
|
+
allowedValues: pageSizeOptions,
|
|
151
183
|
});
|
|
152
184
|
const searchQuery = '';
|
|
153
185
|
const debouncedSearch = useDebounce(searchQuery, 500);
|
|
@@ -647,7 +679,7 @@ export function ItemsTab() {
|
|
|
647
679
|
<SelectValue />
|
|
648
680
|
</SelectTrigger>
|
|
649
681
|
<SelectContent>
|
|
650
|
-
{
|
|
682
|
+
{pageSizeOptions.map((size) => (
|
|
651
683
|
<SelectItem key={size} value={String(size)}>
|
|
652
684
|
{size}
|
|
653
685
|
</SelectItem>
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
AlertDialogHeader,
|
|
20
20
|
AlertDialogTitle,
|
|
21
21
|
} from '@/components/ui/alert-dialog';
|
|
22
|
+
import { DoNodePoolPicker } from '@/components/integration-profile/do-node-pool-picker';
|
|
22
23
|
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
|
23
24
|
import { Badge } from '@/components/ui/badge';
|
|
24
25
|
import { Button } from '@/components/ui/button';
|
|
@@ -166,6 +167,9 @@ type ImportValidationResponse = {
|
|
|
166
167
|
|
|
167
168
|
// ─── Provider field definitions ───────────────────────────────────────────────
|
|
168
169
|
|
|
170
|
+
/** Placeholder devolvido pelo backend no lugar de um segredo armazenado. */
|
|
171
|
+
const SECRET_MASK = '********';
|
|
172
|
+
|
|
169
173
|
const PROVIDER_FIELDS: Record<string, FieldDef[]> = {
|
|
170
174
|
smtp: [
|
|
171
175
|
{
|
|
@@ -653,6 +657,61 @@ const PROVIDER_FIELDS: Record<string, FieldDef[]> = {
|
|
|
653
657
|
placeholder: 'https://eu.altcha.org/api/v1',
|
|
654
658
|
},
|
|
655
659
|
],
|
|
660
|
+
// O node pool de vídeo NÃO é um campo de texto: é escolhido por nome via picker
|
|
661
|
+
// dedicado (carrega os pools da DO API com o token + cluster_id). Ver DoNodePoolPicker.
|
|
662
|
+
digitalocean: [
|
|
663
|
+
{
|
|
664
|
+
key: 'api_token',
|
|
665
|
+
labelKey: 'fieldApiToken',
|
|
666
|
+
type: 'password',
|
|
667
|
+
required: true,
|
|
668
|
+
colSpan: true,
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
key: 'cluster_id',
|
|
672
|
+
labelKey: 'fieldClusterId',
|
|
673
|
+
type: 'text',
|
|
674
|
+
required: true,
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
key: 'region',
|
|
678
|
+
labelKey: 'fieldRegion',
|
|
679
|
+
type: 'text',
|
|
680
|
+
required: true,
|
|
681
|
+
placeholder: 'nyc1',
|
|
682
|
+
},
|
|
683
|
+
],
|
|
684
|
+
kubernetes: [
|
|
685
|
+
{
|
|
686
|
+
key: 'api_server',
|
|
687
|
+
labelKey: 'fieldApiServer',
|
|
688
|
+
type: 'url',
|
|
689
|
+
required: true,
|
|
690
|
+
colSpan: true,
|
|
691
|
+
placeholder: 'https://10.0.0.1:6443',
|
|
692
|
+
},
|
|
693
|
+
{
|
|
694
|
+
key: 'token',
|
|
695
|
+
labelKey: 'fieldToken',
|
|
696
|
+
type: 'password',
|
|
697
|
+
required: true,
|
|
698
|
+
colSpan: true,
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
key: 'ca_cert',
|
|
702
|
+
labelKey: 'fieldCaCert',
|
|
703
|
+
type: 'password',
|
|
704
|
+
required: false,
|
|
705
|
+
colSpan: true,
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
key: 'namespace',
|
|
709
|
+
labelKey: 'fieldNamespace',
|
|
710
|
+
type: 'text',
|
|
711
|
+
required: false,
|
|
712
|
+
placeholder: 'hcode',
|
|
713
|
+
},
|
|
714
|
+
],
|
|
656
715
|
};
|
|
657
716
|
|
|
658
717
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
@@ -1075,6 +1134,10 @@ export default function IntegrationProfilesPage() {
|
|
|
1075
1134
|
{};
|
|
1076
1135
|
const providerSlug =
|
|
1077
1136
|
providers.find((p) => p.id === data.provider_id)?.slug ?? '';
|
|
1137
|
+
// Segredos chegam mascarados (********) do backend e PERMANECEM mascarados no
|
|
1138
|
+
// form: o campo fica desabilitado mostrando ********; o botão "trocar" limpa e
|
|
1139
|
+
// reabilita para digitar um novo valor. Em branco ou mascarado, o backend
|
|
1140
|
+
// preserva o segredo armazenado.
|
|
1078
1141
|
if (
|
|
1079
1142
|
providerSlug.endsWith('-oauth') &&
|
|
1080
1143
|
!Array.isArray(loadedConfig.callback_urls)
|
|
@@ -1844,6 +1907,15 @@ export default function IntegrationProfilesPage() {
|
|
|
1844
1907
|
|
|
1845
1908
|
const isPassword = field.type === 'password';
|
|
1846
1909
|
const isVisible = visibleFields[field.key] ?? false;
|
|
1910
|
+
const currentValue = String(
|
|
1911
|
+
formData.config[field.key] ?? ''
|
|
1912
|
+
);
|
|
1913
|
+
// Segredo já armazenado: campo desabilitado mostrando ******** +
|
|
1914
|
+
// botão "trocar" que limpa o valor e reabilita para digitar um novo.
|
|
1915
|
+
const isLockedSecret =
|
|
1916
|
+
isPassword &&
|
|
1917
|
+
Boolean(editingProfile) &&
|
|
1918
|
+
currentValue === SECRET_MASK;
|
|
1847
1919
|
|
|
1848
1920
|
return (
|
|
1849
1921
|
<div
|
|
@@ -1865,49 +1937,76 @@ export default function IntegrationProfilesPage() {
|
|
|
1865
1937
|
id={`ip-cfg-${field.key}`}
|
|
1866
1938
|
type={
|
|
1867
1939
|
isPassword
|
|
1868
|
-
? isVisible
|
|
1940
|
+
? isVisible && !isLockedSecret
|
|
1869
1941
|
? 'text'
|
|
1870
1942
|
: 'password'
|
|
1871
1943
|
: field.type === 'number'
|
|
1872
1944
|
? 'number'
|
|
1873
1945
|
: 'text'
|
|
1874
1946
|
}
|
|
1875
|
-
value={
|
|
1947
|
+
value={currentValue}
|
|
1876
1948
|
onChange={(e) =>
|
|
1877
1949
|
updateConfig(field.key, e.target.value)
|
|
1878
1950
|
}
|
|
1879
|
-
placeholder={
|
|
1880
|
-
|
|
1951
|
+
placeholder={
|
|
1952
|
+
isPassword && editingProfile
|
|
1953
|
+
? t('leaveBlankToKeep')
|
|
1954
|
+
: field.placeholder
|
|
1955
|
+
}
|
|
1956
|
+
required={
|
|
1957
|
+
field.required &&
|
|
1958
|
+
!(isPassword && Boolean(editingProfile))
|
|
1959
|
+
}
|
|
1881
1960
|
autoComplete={
|
|
1882
1961
|
isPassword ? 'new-password' : undefined
|
|
1883
1962
|
}
|
|
1884
1963
|
className={isPassword ? 'pr-10' : undefined}
|
|
1964
|
+
disabled={isLockedSecret}
|
|
1885
1965
|
/>
|
|
1886
|
-
{isPassword &&
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1966
|
+
{isPassword &&
|
|
1967
|
+
(isLockedSecret ? (
|
|
1968
|
+
<Button
|
|
1969
|
+
type="button"
|
|
1970
|
+
variant="ghost"
|
|
1971
|
+
size="icon"
|
|
1972
|
+
className="absolute right-1 top-1/2 h-8 w-8 -translate-y-1/2"
|
|
1973
|
+
onClick={() => {
|
|
1974
|
+
updateConfig(field.key, '');
|
|
1975
|
+
setVisibleFields((p) => ({
|
|
1976
|
+
...p,
|
|
1977
|
+
[field.key]: true,
|
|
1978
|
+
}));
|
|
1979
|
+
}}
|
|
1980
|
+
aria-label={t('changeSecret')}
|
|
1981
|
+
title={t('changeSecret')}
|
|
1982
|
+
>
|
|
1983
|
+
<Pencil className="h-4 w-4" />
|
|
1984
|
+
</Button>
|
|
1985
|
+
) : (
|
|
1986
|
+
<Button
|
|
1987
|
+
type="button"
|
|
1988
|
+
variant="ghost"
|
|
1989
|
+
size="icon"
|
|
1990
|
+
className="absolute right-1 top-1/2 h-8 w-8 -translate-y-1/2"
|
|
1991
|
+
onClick={() =>
|
|
1992
|
+
setVisibleFields((p) => ({
|
|
1993
|
+
...p,
|
|
1994
|
+
[field.key]: !p[field.key],
|
|
1995
|
+
}))
|
|
1996
|
+
}
|
|
1997
|
+
aria-label={
|
|
1998
|
+
isVisible
|
|
1999
|
+
? t('hidePassword')
|
|
2000
|
+
: t('showPassword')
|
|
2001
|
+
}
|
|
2002
|
+
>
|
|
2003
|
+
{isVisible ? (
|
|
2004
|
+
<EyeOff className="h-4 w-4" />
|
|
2005
|
+
) : (
|
|
2006
|
+
<Eye className="h-4 w-4" />
|
|
2007
|
+
)}
|
|
2008
|
+
</Button>
|
|
2009
|
+
))}
|
|
1911
2010
|
</div>
|
|
1912
2011
|
</div>
|
|
1913
2012
|
);
|
|
@@ -1916,6 +2015,19 @@ export default function IntegrationProfilesPage() {
|
|
|
1916
2015
|
</div>
|
|
1917
2016
|
)}
|
|
1918
2017
|
|
|
2018
|
+
{/* ── DigitalOcean: node pool de vídeo (escolha por nome via API) ── */}
|
|
2019
|
+
{selectedProvider?.slug === 'digitalocean' && (
|
|
2020
|
+
<DoNodePoolPicker
|
|
2021
|
+
apiToken={String(formData.config.api_token ?? '')}
|
|
2022
|
+
clusterId={String(formData.config.cluster_id ?? '')}
|
|
2023
|
+
value={String(formData.config.video_node_pool_name ?? '')}
|
|
2024
|
+
profileId={editingProfile?.id}
|
|
2025
|
+
onChange={(name) =>
|
|
2026
|
+
updateConfig('video_node_pool_name', name)
|
|
2027
|
+
}
|
|
2028
|
+
/>
|
|
2029
|
+
)}
|
|
2030
|
+
|
|
1919
2031
|
{/* ── Callback URLs (OAuth only) ── */}
|
|
1920
2032
|
{isOAuthProvider && (
|
|
1921
2033
|
<div className="rounded-lg border">
|