@nextsparkjs/theme-default 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/about/business.md +49 -0
- package/about/features.json +302 -0
- package/about/team.md +79 -0
- package/api/ai/chat/stream/route.ts +212 -0
- package/api/ai/orchestrator/route.ts +226 -0
- package/api/ai/single-agent/route.ts +291 -0
- package/api/ai/usage/route.ts +122 -0
- package/blocks/benefits/component.tsx +100 -0
- package/blocks/benefits/config.ts +11 -0
- package/blocks/benefits/examples.ts +85 -0
- package/blocks/benefits/fields.ts +156 -0
- package/blocks/benefits/schema.ts +33 -0
- package/blocks/cta-section/component.tsx +100 -0
- package/blocks/cta-section/config.ts +11 -0
- package/blocks/cta-section/examples.ts +41 -0
- package/blocks/cta-section/fields.ts +89 -0
- package/blocks/cta-section/index.ts +6 -0
- package/blocks/cta-section/schema.ts +32 -0
- package/blocks/cta-section/thumbnail.png +1 -0
- package/blocks/faq-accordion/component.tsx +156 -0
- package/blocks/faq-accordion/config.ts +11 -0
- package/blocks/faq-accordion/examples.ts +77 -0
- package/blocks/faq-accordion/fields.ts +119 -0
- package/blocks/faq-accordion/index.ts +6 -0
- package/blocks/faq-accordion/schema.ts +45 -0
- package/blocks/features-grid/component.tsx +112 -0
- package/blocks/features-grid/config.ts +11 -0
- package/blocks/features-grid/examples.ts +63 -0
- package/blocks/features-grid/fields.ts +97 -0
- package/blocks/features-grid/index.ts +6 -0
- package/blocks/features-grid/schema.ts +40 -0
- package/blocks/features-grid/thumbnail.png +1 -0
- package/blocks/hero/component.tsx +100 -0
- package/blocks/hero/config.ts +11 -0
- package/blocks/hero/examples.ts +35 -0
- package/blocks/hero/fields.ts +60 -0
- package/blocks/hero/index.ts +6 -0
- package/blocks/hero/schema.ts +32 -0
- package/blocks/hero/thumbnail.png +1 -0
- package/blocks/hero/thumbnail.png.txt +6 -0
- package/blocks/hero-with-form/component.tsx +232 -0
- package/blocks/hero-with-form/config.ts +11 -0
- package/blocks/hero-with-form/examples.ts +16 -0
- package/blocks/hero-with-form/fields.ts +207 -0
- package/blocks/hero-with-form/index.ts +6 -0
- package/blocks/hero-with-form/schema.ts +54 -0
- package/blocks/jumbotron/component.tsx +136 -0
- package/blocks/jumbotron/config.ts +11 -0
- package/blocks/jumbotron/examples.ts +36 -0
- package/blocks/jumbotron/fields.ts +202 -0
- package/blocks/jumbotron/index.ts +6 -0
- package/blocks/jumbotron/schema.ts +55 -0
- package/blocks/logo-cloud/component.tsx +154 -0
- package/blocks/logo-cloud/config.ts +11 -0
- package/blocks/logo-cloud/examples.ts +34 -0
- package/blocks/logo-cloud/fields.ts +133 -0
- package/blocks/logo-cloud/index.ts +6 -0
- package/blocks/logo-cloud/schema.ts +46 -0
- package/blocks/post-content/component.tsx +197 -0
- package/blocks/post-content/config.ts +11 -0
- package/blocks/post-content/examples.ts +33 -0
- package/blocks/post-content/fields.ts +165 -0
- package/blocks/post-content/index.ts +4 -0
- package/blocks/post-content/schema.ts +46 -0
- package/blocks/pricing-table/component.tsx +154 -0
- package/blocks/pricing-table/config.ts +11 -0
- package/blocks/pricing-table/examples.ts +96 -0
- package/blocks/pricing-table/fields.ts +161 -0
- package/blocks/pricing-table/index.ts +4 -0
- package/blocks/pricing-table/schema.ts +50 -0
- package/blocks/split-content/component.tsx +135 -0
- package/blocks/split-content/config.ts +11 -0
- package/blocks/split-content/examples.ts +38 -0
- package/blocks/split-content/fields.ts +198 -0
- package/blocks/split-content/index.ts +6 -0
- package/blocks/split-content/schema.ts +67 -0
- package/blocks/stats-counter/component.tsx +124 -0
- package/blocks/stats-counter/config.ts +11 -0
- package/blocks/stats-counter/examples.ts +61 -0
- package/blocks/stats-counter/fields.ts +134 -0
- package/blocks/stats-counter/index.ts +6 -0
- package/blocks/stats-counter/schema.ts +47 -0
- package/blocks/testimonials/component.tsx +114 -0
- package/blocks/testimonials/config.ts +11 -0
- package/blocks/testimonials/examples.ts +65 -0
- package/blocks/testimonials/fields.ts +105 -0
- package/blocks/testimonials/index.ts +6 -0
- package/blocks/testimonials/schema.ts +41 -0
- package/blocks/testimonials/thumbnail.png +1 -0
- package/blocks/text-content/component.tsx +97 -0
- package/blocks/text-content/config.ts +11 -0
- package/blocks/text-content/examples.ts +30 -0
- package/blocks/text-content/fields.ts +88 -0
- package/blocks/text-content/index.ts +6 -0
- package/blocks/text-content/schema.ts +30 -0
- package/blocks/text-content/thumbnail.png +1 -0
- package/blocks/timeline/component.tsx +267 -0
- package/blocks/timeline/config.ts +11 -0
- package/blocks/timeline/examples.ts +68 -0
- package/blocks/timeline/fields.ts +147 -0
- package/blocks/timeline/index.ts +6 -0
- package/blocks/timeline/schema.ts +49 -0
- package/blocks/video-hero/component.tsx +270 -0
- package/blocks/video-hero/config.ts +11 -0
- package/blocks/video-hero/examples.ts +24 -0
- package/blocks/video-hero/fields.ts +98 -0
- package/blocks/video-hero/index.ts +6 -0
- package/blocks/video-hero/schema.ts +39 -0
- package/components/ai-chat/ChatPanel.tsx +575 -0
- package/components/ai-chat/ConversationItem.tsx +266 -0
- package/components/ai-chat/ConversationSidebar.tsx +99 -0
- package/components/ai-chat/MarkdownRenderer.tsx +15 -0
- package/components/ai-chat/Message.tsx +42 -0
- package/components/ai-chat/MessageInput.tsx +49 -0
- package/components/ai-chat/MessageList.tsx +46 -0
- package/components/ai-chat/TypingIndicator.tsx +11 -0
- package/config/app.config.ts +367 -0
- package/config/billing.config.ts +349 -0
- package/config/dashboard.config.ts +506 -0
- package/config/dev.config.ts +104 -0
- package/config/features.config.ts +203 -0
- package/config/flows.config.ts +129 -0
- package/config/permissions.config.ts +245 -0
- package/config/theme.config.ts +74 -0
- package/docs/01-overview/01-introduction.md +335 -0
- package/docs/01-overview/02-customization.md +671 -0
- package/docs/02-features/01-components.md +155 -0
- package/docs/02-features/02-styling.md +139 -0
- package/docs/02-features/03-tasks-entity.md +407 -0
- package/docs/03-ai/01-overview.md +211 -0
- package/docs/03-ai/02-customization.md +436 -0
- package/entities/customers/customers.config.ts +75 -0
- package/entities/customers/customers.fields.ts +165 -0
- package/entities/customers/customers.service.ts +516 -0
- package/entities/customers/customers.types.ts +83 -0
- package/entities/customers/messages/en.json +66 -0
- package/entities/customers/messages/es.json +66 -0
- package/entities/customers/migrations/001_customers_table.sql +102 -0
- package/entities/customers/migrations/002_customers_metas.sql +92 -0
- package/entities/pages/messages/en.json +41 -0
- package/entities/pages/messages/es.json +41 -0
- package/entities/pages/migrations/001_pages_table.sql +112 -0
- package/entities/pages/migrations/002_pages_metas.sql +56 -0
- package/entities/pages/migrations/003_add_status.sql +50 -0
- package/entities/pages/pages-management.service.ts +610 -0
- package/entities/pages/pages.config.ts +94 -0
- package/entities/pages/pages.fields.ts +101 -0
- package/entities/pages/pages.service.ts +290 -0
- package/entities/pages/pages.types.ts +124 -0
- package/entities/posts/components/post-header.tsx +97 -0
- package/entities/posts/messages/en.json +55 -0
- package/entities/posts/messages/es.json +55 -0
- package/entities/posts/migrations/001_posts_table.sql +115 -0
- package/entities/posts/migrations/003_add_status.sql +44 -0
- package/entities/posts/migrations/004_entity_taxonomy_relations.sql +129 -0
- package/entities/posts/migrations/006_posts_metas.sql +56 -0
- package/entities/posts/posts.config.ts +101 -0
- package/entities/posts/posts.fields.ts +116 -0
- package/entities/posts/posts.service.ts +376 -0
- package/entities/posts/posts.types.ts +74 -0
- package/entities/tasks/messages/en.json +204 -0
- package/entities/tasks/messages/es.json +204 -0
- package/entities/tasks/migrations/001_tasks_table.sql +105 -0
- package/entities/tasks/migrations/002_task_metas.sql +85 -0
- package/entities/tasks/migrations/sample_data.json +77 -0
- package/entities/tasks/tasks.config.ts +79 -0
- package/entities/tasks/tasks.fields.ts +196 -0
- package/entities/tasks/tasks.service.ts +541 -0
- package/entities/tasks/tasks.types.ts +56 -0
- package/lib/hooks/useAiChat.ts +114 -0
- package/lib/hooks/useConversations.ts +376 -0
- package/lib/hooks/useOrchestratorChat.ts +122 -0
- package/lib/hooks/usePersistentChat.ts +315 -0
- package/lib/hooks/useStreamingChat.ts +127 -0
- package/lib/hooks/useTokenUsage.ts +63 -0
- package/lib/langchain/agents/customer-assistant.md +69 -0
- package/lib/langchain/agents/index.ts +61 -0
- package/lib/langchain/agents/orchestrator.md +59 -0
- package/lib/langchain/agents/page-assistant.md +85 -0
- package/lib/langchain/agents/single-agent.md +46 -0
- package/lib/langchain/agents/task-assistant.md +55 -0
- package/lib/langchain/config.ts +45 -0
- package/lib/langchain/handlers/customer-handler.ts +338 -0
- package/lib/langchain/handlers/page-handler.ts +232 -0
- package/lib/langchain/handlers/task-handler.ts +323 -0
- package/lib/langchain/langchain.config.ts +223 -0
- package/lib/langchain/observability.config.ts +30 -0
- package/lib/langchain/orchestrator.ts +562 -0
- package/lib/langchain/tools/customers.ts +176 -0
- package/lib/langchain/tools/index.ts +10 -0
- package/lib/langchain/tools/orchestrator.ts +92 -0
- package/lib/langchain/tools/pages.ts +289 -0
- package/lib/langchain/tools/tasks.ts +167 -0
- package/lib/scheduled-actions/billing.ts +149 -0
- package/lib/scheduled-actions/index.ts +170 -0
- package/lib/scheduled-actions/webhook.ts +231 -0
- package/lib/selectors.ts +197 -0
- package/messages/de/admin.json +219 -0
- package/messages/de/aiUsage.json +36 -0
- package/messages/de/buttons.json +19 -0
- package/messages/de/categories.json +35 -0
- package/messages/de/common.json +16 -0
- package/messages/de/dev.json +101 -0
- package/messages/de/docs.json +27 -0
- package/messages/de/entities.json +7 -0
- package/messages/de/features.json +119 -0
- package/messages/de/footer.json +22 -0
- package/messages/de/home.json +57 -0
- package/messages/de/index.ts +39 -0
- package/messages/de/mobileNav.json +13 -0
- package/messages/de/navigation.json +8 -0
- package/messages/de/observability.json +74 -0
- package/messages/de/posts.json +54 -0
- package/messages/de/pricing.json +102 -0
- package/messages/de/support.json +9 -0
- package/messages/de/teams.json +8 -0
- package/messages/en/admin.json +219 -0
- package/messages/en/aiUsage.json +36 -0
- package/messages/en/buttons.json +19 -0
- package/messages/en/categories.json +35 -0
- package/messages/en/common.json +16 -0
- package/messages/en/dev.json +106 -0
- package/messages/en/docs.json +27 -0
- package/messages/en/entities.json +7 -0
- package/messages/en/features.json +119 -0
- package/messages/en/footer.json +22 -0
- package/messages/en/home.json +57 -0
- package/messages/en/index.ts +39 -0
- package/messages/en/mobileNav.json +13 -0
- package/messages/en/navigation.json +8 -0
- package/messages/en/observability.json +74 -0
- package/messages/en/posts.json +54 -0
- package/messages/en/pricing.json +102 -0
- package/messages/en/support.json +9 -0
- package/messages/en/teams.json +8 -0
- package/messages/es/admin.json +219 -0
- package/messages/es/aiUsage.json +36 -0
- package/messages/es/buttons.json +19 -0
- package/messages/es/categories.json +35 -0
- package/messages/es/common.json +16 -0
- package/messages/es/dev.json +101 -0
- package/messages/es/docs.json +27 -0
- package/messages/es/entities.json +7 -0
- package/messages/es/features.json +119 -0
- package/messages/es/footer.json +22 -0
- package/messages/es/home.json +57 -0
- package/messages/es/index.ts +39 -0
- package/messages/es/mobileNav.json +13 -0
- package/messages/es/navigation.json +8 -0
- package/messages/es/observability.json +74 -0
- package/messages/es/posts.json +54 -0
- package/messages/es/pricing.json +102 -0
- package/messages/es/support.json +9 -0
- package/messages/es/teams.json +8 -0
- package/messages/fr/admin.json +219 -0
- package/messages/fr/aiUsage.json +36 -0
- package/messages/fr/buttons.json +19 -0
- package/messages/fr/categories.json +35 -0
- package/messages/fr/common.json +16 -0
- package/messages/fr/dev.json +101 -0
- package/messages/fr/docs.json +27 -0
- package/messages/fr/entities.json +7 -0
- package/messages/fr/features.json +119 -0
- package/messages/fr/footer.json +22 -0
- package/messages/fr/home.json +57 -0
- package/messages/fr/index.ts +39 -0
- package/messages/fr/mobileNav.json +13 -0
- package/messages/fr/navigation.json +8 -0
- package/messages/fr/observability.json +74 -0
- package/messages/fr/posts.json +54 -0
- package/messages/fr/pricing.json +102 -0
- package/messages/fr/support.json +9 -0
- package/messages/fr/teams.json +8 -0
- package/messages/it/admin.json +219 -0
- package/messages/it/aiUsage.json +36 -0
- package/messages/it/buttons.json +19 -0
- package/messages/it/categories.json +35 -0
- package/messages/it/common.json +16 -0
- package/messages/it/dev.json +101 -0
- package/messages/it/docs.json +27 -0
- package/messages/it/entities.json +7 -0
- package/messages/it/features.json +119 -0
- package/messages/it/footer.json +22 -0
- package/messages/it/home.json +57 -0
- package/messages/it/index.ts +39 -0
- package/messages/it/mobileNav.json +13 -0
- package/messages/it/navigation.json +8 -0
- package/messages/it/observability.json +74 -0
- package/messages/it/posts.json +54 -0
- package/messages/it/pricing.json +102 -0
- package/messages/it/support.json +9 -0
- package/messages/it/teams.json +8 -0
- package/messages/pt/admin.json +219 -0
- package/messages/pt/aiUsage.json +36 -0
- package/messages/pt/buttons.json +19 -0
- package/messages/pt/categories.json +35 -0
- package/messages/pt/common.json +16 -0
- package/messages/pt/dev.json +101 -0
- package/messages/pt/docs.json +27 -0
- package/messages/pt/entities.json +7 -0
- package/messages/pt/features.json +119 -0
- package/messages/pt/footer.json +22 -0
- package/messages/pt/home.json +57 -0
- package/messages/pt/index.ts +39 -0
- package/messages/pt/mobileNav.json +13 -0
- package/messages/pt/navigation.json +8 -0
- package/messages/pt/observability.json +74 -0
- package/messages/pt/posts.json +54 -0
- package/messages/pt/pricing.json +102 -0
- package/messages/pt/support.json +9 -0
- package/messages/pt/teams.json +8 -0
- package/migrations/089_add_editor_team_role.sql +39 -0
- package/migrations/090_demo_users_teams.sql +540 -0
- package/migrations/091_greek_teams_billing.sql +523 -0
- package/migrations/092_billing_sample_data.sql +774 -0
- package/migrations/093_pages_sample_data.sql +1158 -0
- package/migrations/094_posts_sample_data.sql +278 -0
- package/migrations/095_tasks_sample_data.sql +440 -0
- package/migrations/096_customers_sample_data.sql +358 -0
- package/migrations/097_scheduled_actions_sample_data.sql +111 -0
- package/package.json +22 -0
- package/public/docs/desktop-layout-example.png +0 -0
- package/styles/components.css +11 -0
- package/styles/globals.css +179 -0
- package/templates/(public)/blog/[slug]/page.tsx +65 -0
- package/templates/(public)/layout.tsx +25 -0
- package/templates/(public)/page.tsx +200 -0
- package/templates/(public)/support/page.tsx +321 -0
- package/templates/dashboard/(main)/agent-multi/page.tsx +63 -0
- package/templates/dashboard/(main)/agent-single/page.tsx +142 -0
- package/templates/dashboard/(main)/settings/ai-usage/page.tsx +157 -0
- package/templates/superadmin/ai-observability/[traceId]/page.tsx +27 -0
- package/templates/superadmin/ai-observability/page.tsx +17 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook Scheduled Action Handler - Multi-Endpoint Support
|
|
3
|
+
*
|
|
4
|
+
* This handler supports multiple webhook endpoints configured in app.config.ts.
|
|
5
|
+
* Each endpoint can be:
|
|
6
|
+
* 1. Explicitly called by key (webhookKey in payload)
|
|
7
|
+
* 2. Auto-matched by event pattern (e.g., 'task:created' -> 'tasks' endpoint)
|
|
8
|
+
* 3. Fallback to default endpoint
|
|
9
|
+
* 4. Legacy single webhookUrl support for backward compatibility
|
|
10
|
+
*
|
|
11
|
+
* @module contents/themes/default/lib/scheduled-actions/webhook
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { registerScheduledAction } from '@nextsparkjs/core/lib/scheduled-actions'
|
|
15
|
+
import type { ScheduledAction } from '@nextsparkjs/core/lib/scheduled-actions'
|
|
16
|
+
import { APP_CONFIG_OVERRIDES } from '@/themes/default/config/app.config'
|
|
17
|
+
import type { WebhookEndpointConfig } from '@nextsparkjs/core/lib/config/types'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Webhook payload interface with optional explicit key
|
|
21
|
+
*/
|
|
22
|
+
interface WebhookPayload {
|
|
23
|
+
/** Event type (e.g., 'created', 'updated', 'deleted', 'renewed') */
|
|
24
|
+
eventType: string
|
|
25
|
+
/** Entity type (e.g., 'task', 'subscription') */
|
|
26
|
+
entityType: string
|
|
27
|
+
/** Entity ID */
|
|
28
|
+
entityId: string
|
|
29
|
+
/** Full entity data */
|
|
30
|
+
data: unknown
|
|
31
|
+
/** Team ID context */
|
|
32
|
+
teamId?: string
|
|
33
|
+
/** Explicit webhook endpoint key (overrides pattern matching) */
|
|
34
|
+
webhookKey?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolved webhook endpoint
|
|
39
|
+
*/
|
|
40
|
+
interface ResolvedWebhook {
|
|
41
|
+
url: string
|
|
42
|
+
key: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get typed scheduledActions config from APP_CONFIG_OVERRIDES
|
|
47
|
+
*/
|
|
48
|
+
function getScheduledActionsConfig() {
|
|
49
|
+
return APP_CONFIG_OVERRIDES.scheduledActions as {
|
|
50
|
+
webhookUrl?: string
|
|
51
|
+
webhooks?: {
|
|
52
|
+
endpoints: Record<string, WebhookEndpointConfig>
|
|
53
|
+
defaultEndpoint?: string
|
|
54
|
+
}
|
|
55
|
+
} | undefined
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Resolve webhook URL based on payload
|
|
60
|
+
*
|
|
61
|
+
* Resolution priority:
|
|
62
|
+
* 1. Explicit webhookKey in payload
|
|
63
|
+
* 2. Pattern matching based on entityType:eventType
|
|
64
|
+
* 3. Default endpoint
|
|
65
|
+
* 4. Legacy webhookUrl (backward compatibility)
|
|
66
|
+
*
|
|
67
|
+
* @param payload - Webhook payload with event info
|
|
68
|
+
* @returns Resolved webhook with URL and key, or null if no match
|
|
69
|
+
*/
|
|
70
|
+
function resolveWebhookUrl(payload: WebhookPayload): ResolvedWebhook | null {
|
|
71
|
+
const config = getScheduledActionsConfig()
|
|
72
|
+
const webhooksConfig = config?.webhooks
|
|
73
|
+
const legacyUrl = config?.webhookUrl
|
|
74
|
+
|
|
75
|
+
// 1. Explicit webhook key provided
|
|
76
|
+
if (payload.webhookKey && webhooksConfig?.endpoints[payload.webhookKey]) {
|
|
77
|
+
const endpoint = webhooksConfig.endpoints[payload.webhookKey]
|
|
78
|
+
if (endpoint.enabled !== false) {
|
|
79
|
+
const url = process.env[endpoint.envVar]
|
|
80
|
+
if (url) {
|
|
81
|
+
return { url, key: payload.webhookKey }
|
|
82
|
+
}
|
|
83
|
+
console.warn(`[webhook:send] Endpoint '${payload.webhookKey}' envVar '${endpoint.envVar}' not set`)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 2. Pattern matching
|
|
88
|
+
if (webhooksConfig?.endpoints) {
|
|
89
|
+
const eventPattern = `${payload.entityType}:${payload.eventType}`
|
|
90
|
+
|
|
91
|
+
for (const [key, endpoint] of Object.entries(webhooksConfig.endpoints)) {
|
|
92
|
+
if (endpoint.enabled === false) continue
|
|
93
|
+
if (!endpoint.patterns) continue
|
|
94
|
+
|
|
95
|
+
for (const pattern of endpoint.patterns) {
|
|
96
|
+
if (matchesPattern(eventPattern, pattern)) {
|
|
97
|
+
const url = process.env[endpoint.envVar]
|
|
98
|
+
if (url) {
|
|
99
|
+
return { url, key }
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 3. Default endpoint
|
|
107
|
+
if (webhooksConfig?.defaultEndpoint && webhooksConfig.endpoints[webhooksConfig.defaultEndpoint]) {
|
|
108
|
+
const endpoint = webhooksConfig.endpoints[webhooksConfig.defaultEndpoint]
|
|
109
|
+
if (endpoint.enabled !== false) {
|
|
110
|
+
const url = process.env[endpoint.envVar]
|
|
111
|
+
if (url) {
|
|
112
|
+
return { url, key: webhooksConfig.defaultEndpoint }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 4. Legacy webhookUrl (backward compatibility)
|
|
118
|
+
if (legacyUrl) {
|
|
119
|
+
return { url: legacyUrl, key: 'legacy' }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return null
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Pattern matching for event routing
|
|
127
|
+
*
|
|
128
|
+
* Supports wildcard patterns:
|
|
129
|
+
* - 'task:*' matches 'task:created', 'task:updated', etc.
|
|
130
|
+
* - '*:created' matches 'task:created', 'subscription:created', etc.
|
|
131
|
+
* - '*:*' matches all events
|
|
132
|
+
*
|
|
133
|
+
* @param event - Actual event (e.g., 'task:created')
|
|
134
|
+
* @param pattern - Pattern to match (e.g., 'task:*')
|
|
135
|
+
* @returns True if pattern matches event
|
|
136
|
+
*/
|
|
137
|
+
function matchesPattern(event: string, pattern: string): boolean {
|
|
138
|
+
const [eventEntity, eventAction] = event.split(':')
|
|
139
|
+
const [patternEntity, patternAction] = pattern.split(':')
|
|
140
|
+
|
|
141
|
+
const entityMatch = patternEntity === '*' || patternEntity === eventEntity
|
|
142
|
+
const actionMatch = patternAction === '*' || patternAction === eventAction
|
|
143
|
+
|
|
144
|
+
return entityMatch && actionMatch
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Register the webhook action handler
|
|
149
|
+
*
|
|
150
|
+
* This function registers the 'webhook:send' action handler that sends POST
|
|
151
|
+
* requests to configured webhook endpoints.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // Register at app startup
|
|
155
|
+
* registerWebhookAction()
|
|
156
|
+
*
|
|
157
|
+
* // Schedule a webhook with explicit key
|
|
158
|
+
* await scheduleAction('webhook:send', {
|
|
159
|
+
* eventType: 'created',
|
|
160
|
+
* entityType: 'task',
|
|
161
|
+
* entityId: task.id,
|
|
162
|
+
* data: task,
|
|
163
|
+
* webhookKey: 'tasks', // Explicit routing
|
|
164
|
+
* })
|
|
165
|
+
*
|
|
166
|
+
* // Schedule a webhook with auto-matching
|
|
167
|
+
* await scheduleAction('webhook:send', {
|
|
168
|
+
* eventType: 'created',
|
|
169
|
+
* entityType: 'subscription',
|
|
170
|
+
* entityId: sub.id,
|
|
171
|
+
* data: sub,
|
|
172
|
+
* // Will auto-match to 'subscriptions' endpoint via pattern
|
|
173
|
+
* })
|
|
174
|
+
*/
|
|
175
|
+
export function registerWebhookAction() {
|
|
176
|
+
registerScheduledAction(
|
|
177
|
+
'webhook:send',
|
|
178
|
+
async (payload: unknown, action: ScheduledAction) => {
|
|
179
|
+
const webhookPayload = payload as WebhookPayload
|
|
180
|
+
|
|
181
|
+
// Validate required fields
|
|
182
|
+
if (!webhookPayload.eventType || !webhookPayload.entityType || !webhookPayload.entityId) {
|
|
183
|
+
throw new Error('Invalid webhook payload: missing required fields (eventType, entityType, entityId)')
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Resolve webhook URL
|
|
187
|
+
const resolved = resolveWebhookUrl(webhookPayload)
|
|
188
|
+
|
|
189
|
+
if (!resolved) {
|
|
190
|
+
// No URL configured - skip silently (not an error, just not configured)
|
|
191
|
+
console.log(`[webhook:send] No webhook URL configured for ${webhookPayload.entityType}:${webhookPayload.eventType}, skipping`)
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
console.log(`[webhook:send] Sending to '${resolved.key}' for ${webhookPayload.entityType}:${webhookPayload.eventType}`)
|
|
196
|
+
|
|
197
|
+
// Send webhook POST request
|
|
198
|
+
const response = await fetch(resolved.url, {
|
|
199
|
+
method: 'POST',
|
|
200
|
+
headers: {
|
|
201
|
+
'Content-Type': 'application/json',
|
|
202
|
+
'User-Agent': 'NextSpark-Webhook/1.0',
|
|
203
|
+
'X-Webhook-Key': resolved.key,
|
|
204
|
+
},
|
|
205
|
+
body: JSON.stringify({
|
|
206
|
+
event: webhookPayload.eventType,
|
|
207
|
+
entity: webhookPayload.entityType,
|
|
208
|
+
entityId: webhookPayload.entityId,
|
|
209
|
+
data: webhookPayload.data,
|
|
210
|
+
teamId: webhookPayload.teamId,
|
|
211
|
+
timestamp: new Date().toISOString(),
|
|
212
|
+
actionId: action.id,
|
|
213
|
+
}),
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// Check if webhook was successful
|
|
217
|
+
if (!response.ok) {
|
|
218
|
+
const errorText = await response.text()
|
|
219
|
+
throw new Error(
|
|
220
|
+
`Webhook '${resolved.key}' failed with status ${response.status}: ${errorText.substring(0, 200)}`
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
console.log(`[webhook:send] Webhook '${resolved.key}' sent successfully (status: ${response.status})`)
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
description: 'Send webhook notification to configured endpoint',
|
|
228
|
+
timeout: 15000, // 15 seconds timeout for webhooks
|
|
229
|
+
}
|
|
230
|
+
)
|
|
231
|
+
}
|
package/lib/selectors.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Block Selectors
|
|
3
|
+
*
|
|
4
|
+
* This file defines selectors for block components in the theme.
|
|
5
|
+
* It's placed in lib/ instead of tests/ so TypeScript can resolve imports.
|
|
6
|
+
*
|
|
7
|
+
* Used by:
|
|
8
|
+
* - Block components (for data-cy attributes)
|
|
9
|
+
* - Cypress tests (via tests/cypress/src/selectors.ts)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createSelectorHelpers } from '@nextsparkjs/core/lib/test/selector-factory'
|
|
13
|
+
import { CORE_SELECTORS } from '@nextsparkjs/core/lib/test/core-selectors'
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// BLOCK SELECTORS
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Block-specific selectors for the default theme.
|
|
21
|
+
* Each block has at minimum a 'container' selector.
|
|
22
|
+
* Dynamic selectors use {index} placeholder.
|
|
23
|
+
*/
|
|
24
|
+
export const BLOCK_SELECTORS = {
|
|
25
|
+
hero: {
|
|
26
|
+
container: 'block-hero',
|
|
27
|
+
},
|
|
28
|
+
faqAccordion: {
|
|
29
|
+
container: 'block-faq-accordion',
|
|
30
|
+
item: 'faq-item-{index}',
|
|
31
|
+
question: 'faq-question-{index}',
|
|
32
|
+
answer: 'faq-answer-{index}',
|
|
33
|
+
},
|
|
34
|
+
benefits: {
|
|
35
|
+
container: 'block-benefits',
|
|
36
|
+
},
|
|
37
|
+
ctaSection: {
|
|
38
|
+
container: 'block-cta-section',
|
|
39
|
+
},
|
|
40
|
+
featuresGrid: {
|
|
41
|
+
container: 'block-features-grid',
|
|
42
|
+
},
|
|
43
|
+
heroWithForm: {
|
|
44
|
+
container: 'block-hero-with-form',
|
|
45
|
+
form: {
|
|
46
|
+
firstname: 'hero-form-firstname',
|
|
47
|
+
lastname: 'hero-form-lastname',
|
|
48
|
+
email: 'hero-form-email',
|
|
49
|
+
phone: 'hero-form-phone',
|
|
50
|
+
area: 'hero-form-area',
|
|
51
|
+
consent: 'hero-form-consent',
|
|
52
|
+
submit: 'hero-form-submit',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
jumbotron: {
|
|
56
|
+
container: 'block-jumbotron',
|
|
57
|
+
},
|
|
58
|
+
logoCloud: {
|
|
59
|
+
container: 'block-logo-cloud',
|
|
60
|
+
item: 'logo-item-{index}',
|
|
61
|
+
link: 'logo-link-{index}',
|
|
62
|
+
},
|
|
63
|
+
postContent: {
|
|
64
|
+
container: 'block-post-content',
|
|
65
|
+
divider: 'post-content-divider',
|
|
66
|
+
cta: 'post-content-cta',
|
|
67
|
+
},
|
|
68
|
+
pricingTable: {
|
|
69
|
+
container: 'block-pricing-table',
|
|
70
|
+
plan: 'pricing-plan-{index}',
|
|
71
|
+
features: 'plan-features',
|
|
72
|
+
cta: 'plan-cta-{index}',
|
|
73
|
+
},
|
|
74
|
+
splitContent: {
|
|
75
|
+
container: 'block-split-content',
|
|
76
|
+
},
|
|
77
|
+
statsCounter: {
|
|
78
|
+
container: 'block-stats-counter',
|
|
79
|
+
},
|
|
80
|
+
testimonials: {
|
|
81
|
+
container: 'block-testimonials',
|
|
82
|
+
},
|
|
83
|
+
textContent: {
|
|
84
|
+
container: 'block-text-content',
|
|
85
|
+
},
|
|
86
|
+
timeline: {
|
|
87
|
+
container: 'block-timeline',
|
|
88
|
+
},
|
|
89
|
+
videoHero: {
|
|
90
|
+
container: 'block-video-hero',
|
|
91
|
+
},
|
|
92
|
+
} as const
|
|
93
|
+
|
|
94
|
+
// =============================================================================
|
|
95
|
+
// THEME SELECTORS (CORE + BLOCKS)
|
|
96
|
+
// =============================================================================
|
|
97
|
+
|
|
98
|
+
// =============================================================================
|
|
99
|
+
// DEVTOOLS SELECTORS
|
|
100
|
+
// =============================================================================
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* DevTools-specific selectors for the default theme.
|
|
104
|
+
*/
|
|
105
|
+
export const DEVTOOLS_SELECTORS = {
|
|
106
|
+
scheduledActions: {
|
|
107
|
+
page: 'devtools-scheduled-actions-page',
|
|
108
|
+
filterStatus: 'scheduled-actions-filter-status',
|
|
109
|
+
filterType: 'scheduled-actions-filter-type',
|
|
110
|
+
filterApply: 'scheduled-actions-filter-apply',
|
|
111
|
+
filterReset: 'scheduled-actions-filter-reset',
|
|
112
|
+
table: 'scheduled-actions-table',
|
|
113
|
+
row: 'scheduled-actions-row-{id}',
|
|
114
|
+
cellType: 'scheduled-actions-cell-type',
|
|
115
|
+
cellStatus: 'scheduled-actions-cell-status',
|
|
116
|
+
cellScheduledAt: 'scheduled-actions-cell-scheduled-at',
|
|
117
|
+
cellTeam: 'scheduled-actions-cell-team',
|
|
118
|
+
cellPayload: 'scheduled-actions-cell-payload',
|
|
119
|
+
cellError: 'scheduled-actions-cell-error',
|
|
120
|
+
statusPending: 'scheduled-actions-status-pending',
|
|
121
|
+
statusRunning: 'scheduled-actions-status-running',
|
|
122
|
+
statusCompleted: 'scheduled-actions-status-completed',
|
|
123
|
+
statusFailed: 'scheduled-actions-status-failed',
|
|
124
|
+
pagination: 'scheduled-actions-pagination',
|
|
125
|
+
paginationPrev: 'scheduled-actions-pagination-prev',
|
|
126
|
+
paginationNext: 'scheduled-actions-pagination-next',
|
|
127
|
+
emptyState: 'scheduled-actions-empty-state',
|
|
128
|
+
},
|
|
129
|
+
} as const
|
|
130
|
+
|
|
131
|
+
// =============================================================================
|
|
132
|
+
// THEME SELECTORS (CORE + BLOCKS + DEVTOOLS)
|
|
133
|
+
// =============================================================================
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Complete theme selectors merging core and blocks.
|
|
137
|
+
*/
|
|
138
|
+
export const THEME_SELECTORS = {
|
|
139
|
+
...CORE_SELECTORS,
|
|
140
|
+
blocks: BLOCK_SELECTORS,
|
|
141
|
+
devtools: DEVTOOLS_SELECTORS,
|
|
142
|
+
} as const
|
|
143
|
+
|
|
144
|
+
// =============================================================================
|
|
145
|
+
// EXPORTS
|
|
146
|
+
// =============================================================================
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Create helpers bound to theme selectors
|
|
150
|
+
*/
|
|
151
|
+
const helpers = createSelectorHelpers(THEME_SELECTORS)
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Full selectors object (core + theme extensions)
|
|
155
|
+
*/
|
|
156
|
+
export const SELECTORS = helpers.SELECTORS
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get a selector value by path
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* sel('auth.login.form') // 'login-form'
|
|
163
|
+
* sel('blocks.hero.container') // 'block-hero'
|
|
164
|
+
* sel('blocks.faqAccordion.item', { index: '0' }) // 'faq-item-0'
|
|
165
|
+
*/
|
|
166
|
+
export const sel = helpers.sel
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Alias for sel
|
|
170
|
+
*/
|
|
171
|
+
export const s = helpers.s
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get selector only in dev/test environments
|
|
175
|
+
*/
|
|
176
|
+
export const selDev = helpers.selDev
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get Cypress selector string [data-cy="..."]
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* cySelector('blocks.hero.container') // '[data-cy="block-hero"]'
|
|
183
|
+
*/
|
|
184
|
+
export const cySelector = helpers.cySelector
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Create entity-specific selector helpers
|
|
188
|
+
*/
|
|
189
|
+
export const entitySelectors = helpers.entitySelectors
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Type exports
|
|
193
|
+
*/
|
|
194
|
+
export type ThemeSelectorsType = typeof THEME_SELECTORS
|
|
195
|
+
export type BlockSelectorsType = typeof BLOCK_SELECTORS
|
|
196
|
+
export type { Replacements } from '@nextsparkjs/core/lib/test/selector-factory'
|
|
197
|
+
export { CORE_SELECTORS }
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pages": {
|
|
3
|
+
"title": "Seiten",
|
|
4
|
+
"description": "Verwalten Sie Ihre dynamischen Seiten",
|
|
5
|
+
"loading": "Seiten werden geladen...",
|
|
6
|
+
"empty": "Keine Seiten gefunden. Erstellen Sie Ihre erste Seite, um zu beginnen.",
|
|
7
|
+
"search": {
|
|
8
|
+
"placeholder": "Seiten suchen..."
|
|
9
|
+
},
|
|
10
|
+
"filters": {
|
|
11
|
+
"locale": "Sprache",
|
|
12
|
+
"allLocales": "Alle Sprachen",
|
|
13
|
+
"status": "Status",
|
|
14
|
+
"allStatuses": "Alle Status",
|
|
15
|
+
"published": "Veroeffentlicht",
|
|
16
|
+
"draft": "Entwurf"
|
|
17
|
+
},
|
|
18
|
+
"table": {
|
|
19
|
+
"title": "Titel",
|
|
20
|
+
"slug": "Slug",
|
|
21
|
+
"locale": "Sprache",
|
|
22
|
+
"status": "Status",
|
|
23
|
+
"updated": "Zuletzt aktualisiert"
|
|
24
|
+
},
|
|
25
|
+
"status": {
|
|
26
|
+
"published": "Veroeffentlicht",
|
|
27
|
+
"draft": "Entwurf",
|
|
28
|
+
"unsaved": "Ungespeicherte Aenderungen"
|
|
29
|
+
},
|
|
30
|
+
"actions": {
|
|
31
|
+
"create": "Seite erstellen",
|
|
32
|
+
"edit": "Bearbeiten",
|
|
33
|
+
"view": "Ansehen",
|
|
34
|
+
"delete": "Loeschen",
|
|
35
|
+
"save": "Speichern",
|
|
36
|
+
"saving": "Speichern...",
|
|
37
|
+
"publish": "Veroeffentlichen",
|
|
38
|
+
"preview": "Vorschau"
|
|
39
|
+
},
|
|
40
|
+
"new": {
|
|
41
|
+
"title": "Neue Seite erstellen",
|
|
42
|
+
"description": "Erstellen Sie eine neue dynamische Seite fuer Ihre Website",
|
|
43
|
+
"back": "Zurueck zu Seiten",
|
|
44
|
+
"success": "Seite erfolgreich erstellt",
|
|
45
|
+
"form": {
|
|
46
|
+
"title": "Seitendetails",
|
|
47
|
+
"description": "Geben Sie die grundlegenden Informationen Ihrer Seite ein",
|
|
48
|
+
"fields": {
|
|
49
|
+
"title": "Seitentitel",
|
|
50
|
+
"slug": "URL-Slug",
|
|
51
|
+
"locale": "Sprache"
|
|
52
|
+
},
|
|
53
|
+
"placeholders": {
|
|
54
|
+
"title": "Ueber uns",
|
|
55
|
+
"slug": "ueber-uns"
|
|
56
|
+
},
|
|
57
|
+
"hints": {
|
|
58
|
+
"slug": "URL-freundliche Version des Titels (Kleinbuchstaben, keine Leerzeichen)"
|
|
59
|
+
},
|
|
60
|
+
"actions": {
|
|
61
|
+
"cancel": "Abbrechen",
|
|
62
|
+
"create": "Seite erstellen",
|
|
63
|
+
"creating": "Erstellen..."
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"edit": {
|
|
68
|
+
"title": "Seite bearbeiten",
|
|
69
|
+
"loading": "Seite wird geladen...",
|
|
70
|
+
"back": "Zurueck zu Seiten",
|
|
71
|
+
"fields": {
|
|
72
|
+
"title": "Titel",
|
|
73
|
+
"slug": "Slug"
|
|
74
|
+
},
|
|
75
|
+
"placeholders": {
|
|
76
|
+
"title": "Seitentitel",
|
|
77
|
+
"slug": "seiten-slug"
|
|
78
|
+
},
|
|
79
|
+
"status": {
|
|
80
|
+
"published": "Veroeffentlicht",
|
|
81
|
+
"unsaved": "Ungespeicherte Aenderungen"
|
|
82
|
+
},
|
|
83
|
+
"actions": {
|
|
84
|
+
"save": "Speichern",
|
|
85
|
+
"saving": "Speichern...",
|
|
86
|
+
"publish": "Veroeffentlichen",
|
|
87
|
+
"preview": "Vorschau",
|
|
88
|
+
"viewPage": "Ansehen"
|
|
89
|
+
},
|
|
90
|
+
"viewMode": {
|
|
91
|
+
"layout": "Layout",
|
|
92
|
+
"preview": "Vorschau"
|
|
93
|
+
},
|
|
94
|
+
"messages": {
|
|
95
|
+
"saved": "Seite erfolgreich gespeichert"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"settings": {
|
|
99
|
+
"title": "Seiteneinstellungen",
|
|
100
|
+
"seo": {
|
|
101
|
+
"title": "SEO-Einstellungen",
|
|
102
|
+
"metaTitle": "Meta-Titel",
|
|
103
|
+
"metaTitlePlaceholder": "Geben Sie den Titel fuer Suchmaschinen ein",
|
|
104
|
+
"metaTitleHint": "Empfohlen: 50-60 Zeichen",
|
|
105
|
+
"metaDescription": "Meta-Beschreibung",
|
|
106
|
+
"metaDescriptionPlaceholder": "Geben Sie eine kurze Beschreibung fuer Suchmaschinen ein",
|
|
107
|
+
"characters": "Zeichen",
|
|
108
|
+
"metaKeywords": "Schluesselwoerter",
|
|
109
|
+
"metaKeywordsPlaceholder": "wort1, wort2, wort3",
|
|
110
|
+
"metaKeywordsHint": "Durch Komma getrennte Schluesselwoerter",
|
|
111
|
+
"ogImage": "Social-Media-Bild (OG Image)",
|
|
112
|
+
"ogImagePlaceholder": "https://beispiel.de/bild.jpg",
|
|
113
|
+
"ogImageHint": "Bild, das beim Teilen in sozialen Netzwerken angezeigt wird"
|
|
114
|
+
},
|
|
115
|
+
"customFields": {
|
|
116
|
+
"title": "Benutzerdefinierte Felder",
|
|
117
|
+
"empty": "Keine benutzerdefinierten Felder hinzugefuegt",
|
|
118
|
+
"keyPlaceholder": "Feldschluessel",
|
|
119
|
+
"valuePlaceholder": "Feldwert",
|
|
120
|
+
"add": "Feld hinzufuegen"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"blockEditor": {
|
|
125
|
+
"picker": {
|
|
126
|
+
"title": "Block-Bibliothek",
|
|
127
|
+
"description": "Bloecke ziehen oder klicken zum Hinzufuegen",
|
|
128
|
+
"empty": "Keine Bloecke gefunden",
|
|
129
|
+
"search": {
|
|
130
|
+
"placeholder": "Bloecke suchen..."
|
|
131
|
+
},
|
|
132
|
+
"categories": {
|
|
133
|
+
"all": "Alle"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"canvas": {
|
|
137
|
+
"empty": {
|
|
138
|
+
"message": "Noch keine Bloecke hinzugefuegt",
|
|
139
|
+
"hint": "Ziehen Sie Bloecke aus der Bibliothek, um Ihre Seite zu erstellen"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"block": {
|
|
143
|
+
"error": {
|
|
144
|
+
"notFound": "Block '{slug}' nicht gefunden"
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"settings": {
|
|
148
|
+
"empty": {
|
|
149
|
+
"message": "Kein Block ausgewaehlt",
|
|
150
|
+
"hint": "Waehlen Sie einen Block auf der Arbeitsflaeche aus, um seine Einstellungen zu bearbeiten"
|
|
151
|
+
},
|
|
152
|
+
"error": {
|
|
153
|
+
"notFound": "Block-Einstellungen nicht gefunden"
|
|
154
|
+
},
|
|
155
|
+
"noFields": "Dieser Block hat keine konfigurierbaren Felder",
|
|
156
|
+
"actions": {
|
|
157
|
+
"reset": "Zuruecksetzen",
|
|
158
|
+
"remove": "Entfernen"
|
|
159
|
+
},
|
|
160
|
+
"tabs": {
|
|
161
|
+
"content": "Inhalt",
|
|
162
|
+
"design": "Design",
|
|
163
|
+
"advanced": "Erweitert",
|
|
164
|
+
"noContentFields": "Keine Inhaltsfelder verfuegbar",
|
|
165
|
+
"noDesignFields": "Keine Designfelder verfuegbar",
|
|
166
|
+
"noAdvancedFields": "Keine erweiterten Felder verfuegbar"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"form": {
|
|
170
|
+
"selectPlaceholder": "Option auswaehlen",
|
|
171
|
+
"emptyArray": "Keine Elemente hinzugefuegt",
|
|
172
|
+
"itemNumber": "Element {number}",
|
|
173
|
+
"addItem": "Element hinzufuegen",
|
|
174
|
+
"itemCount": "{current} von {max} Elementen"
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"builder": {
|
|
178
|
+
"back": "Zurueck",
|
|
179
|
+
"loading": "Laden...",
|
|
180
|
+
"fields": {
|
|
181
|
+
"title": "Titel",
|
|
182
|
+
"slug": "Slug"
|
|
183
|
+
},
|
|
184
|
+
"placeholders": {
|
|
185
|
+
"title": "Titel eingeben...",
|
|
186
|
+
"slug": "url-slug",
|
|
187
|
+
"excerpt": "Kurze Beschreibung...",
|
|
188
|
+
"imageUrl": "https://beispiel.de/bild.jpg"
|
|
189
|
+
},
|
|
190
|
+
"status": {
|
|
191
|
+
"published": "Veroeffentlicht",
|
|
192
|
+
"draft": "Entwurf",
|
|
193
|
+
"scheduled": "Geplant",
|
|
194
|
+
"archived": "Archiviert",
|
|
195
|
+
"unsaved": "Ungespeicherte Aenderungen"
|
|
196
|
+
},
|
|
197
|
+
"actions": {
|
|
198
|
+
"save": "Speichern",
|
|
199
|
+
"saving": "Speichern...",
|
|
200
|
+
"viewPage": "Ansehen"
|
|
201
|
+
},
|
|
202
|
+
"viewMode": {
|
|
203
|
+
"layout": "Layout",
|
|
204
|
+
"preview": "Vorschau"
|
|
205
|
+
},
|
|
206
|
+
"sidebar": {
|
|
207
|
+
"blocks": "Bloecke",
|
|
208
|
+
"fields": "Felder",
|
|
209
|
+
"fieldsTitle": "Entitaetsfelder",
|
|
210
|
+
"fieldsDescription": "Zusaetzliche Eigenschaften konfigurieren",
|
|
211
|
+
"noFields": "Keine zusaetzlichen Felder verfuegbar",
|
|
212
|
+
"noCategories": "Keine Kategorien verfuegbar"
|
|
213
|
+
},
|
|
214
|
+
"messages": {
|
|
215
|
+
"saved": "Erfolgreich gespeichert",
|
|
216
|
+
"created": "Erfolgreich erstellt"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "KI-Nutzung",
|
|
3
|
+
"description": "Ueberwachen Sie Ihre KI-Token-Nutzung und Kosten",
|
|
4
|
+
"loading": "Nutzungsdaten werden geladen...",
|
|
5
|
+
"error": "Fehler beim Laden der Nutzungsdaten",
|
|
6
|
+
"period": {
|
|
7
|
+
"today": "Heute",
|
|
8
|
+
"7d": "7 Tage",
|
|
9
|
+
"30d": "30 Tage",
|
|
10
|
+
"all": "Gesamte Zeit"
|
|
11
|
+
},
|
|
12
|
+
"stats": {
|
|
13
|
+
"totalTokens": {
|
|
14
|
+
"title": "Tokens Gesamt",
|
|
15
|
+
"input": "Eingabe",
|
|
16
|
+
"output": "Ausgabe"
|
|
17
|
+
},
|
|
18
|
+
"estimatedCost": {
|
|
19
|
+
"title": "Geschaetzte Kosten",
|
|
20
|
+
"currency": "EUR"
|
|
21
|
+
},
|
|
22
|
+
"requests": {
|
|
23
|
+
"title": "Anfragen",
|
|
24
|
+
"description": "Gesamte KI-Anfragen"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"usageByModel": {
|
|
28
|
+
"title": "Nutzung nach Modell",
|
|
29
|
+
"tokens": "Tokens"
|
|
30
|
+
},
|
|
31
|
+
"dailyUsage": {
|
|
32
|
+
"title": "Taegliche Nutzung",
|
|
33
|
+
"noData": "Keine Nutzungsdaten fuer diesen Zeitraum",
|
|
34
|
+
"tokens": "Tokens"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"save": "Speichern",
|
|
3
|
+
"cancel": "Abbrechen",
|
|
4
|
+
"delete": "Loeschen",
|
|
5
|
+
"edit": "Bearbeiten",
|
|
6
|
+
"add": "Hinzufuegen",
|
|
7
|
+
"update": "Aktualisieren",
|
|
8
|
+
"submit": "Absenden",
|
|
9
|
+
"close": "Schliessen",
|
|
10
|
+
"back": "Zurueck",
|
|
11
|
+
"next": "Weiter",
|
|
12
|
+
"previous": "Zurueck",
|
|
13
|
+
"continue": "Fortfahren",
|
|
14
|
+
"finish": "Abschliessen",
|
|
15
|
+
"signIn": "Anmelden",
|
|
16
|
+
"signUp": "Registrieren",
|
|
17
|
+
"signOut": "Abmelden",
|
|
18
|
+
"signingOut": "Abmelden..."
|
|
19
|
+
}
|