mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 22:04:10 +00:00
feat: add Workflows Collection for complex process management
Hybrid solution for process visualization: ## Timeline Collection (Simple Processes) Enhanced with process-specific fields for simple linear flows: - Step number, duration, responsible person - Action required indicator (customer/internal/both/automatic) - Deliverables/documents per step Ideal for: Onboarding, Bewerbungsprozess, simple customer journeys ## Workflows Collection (Complex Processes) New dedicated collection for multi-phase workflows with: **Phases:** - Named sections with icons, colors, estimated duration - Responsible person/role assignment - Phase-level deliverables **Steps:** - Multiple types: task, decision, milestone, approval, wait, automatic - Priority levels: critical, high, normal, low, optional - Dependencies between steps (blocking, parallel) - Conditions/branches for decision steps - Checklists with required/optional items - Resources (documents, templates, links, tools) - Outputs per step **Properties:** - Workflow types: project, business, approval, onboarding, support, development, marketing - Complexity levels, iterative flag, parallel phases flag - Display options: vertical, horizontal, flowchart, kanban, gantt layouts **API Features:** - Public endpoint at /api/workflows with tenant isolation - Filter by type, complexity - Statistics: phase count, step count, checklist count, step type breakdown Database: 20 new tables (18 for workflows, 2 for timeline process fields) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3f61050fb3
commit
5df2139bbd
8 changed files with 25902 additions and 3 deletions
364
src/app/(frontend)/api/workflows/route.ts
Normal file
364
src/app/(frontend)/api/workflows/route.ts
Normal file
|
|
@ -0,0 +1,364 @@
|
||||||
|
// src/app/(frontend)/api/workflows/route.ts
|
||||||
|
// Dedizierte Workflows-API für Frontend-Anwendungen
|
||||||
|
|
||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { getPayload } from 'payload'
|
||||||
|
import config from '@payload-config'
|
||||||
|
import type { Media } from '@/payload-types'
|
||||||
|
import {
|
||||||
|
searchLimiter,
|
||||||
|
rateLimitHeaders,
|
||||||
|
getClientIpFromRequest,
|
||||||
|
isIpBlocked,
|
||||||
|
} from '@/lib/security'
|
||||||
|
|
||||||
|
// Validation constants
|
||||||
|
const WORKFLOW_RATE_LIMIT = 30
|
||||||
|
|
||||||
|
// Valid workflow types
|
||||||
|
const WORKFLOW_TYPES = [
|
||||||
|
'project',
|
||||||
|
'business',
|
||||||
|
'approval',
|
||||||
|
'onboarding',
|
||||||
|
'support',
|
||||||
|
'development',
|
||||||
|
'marketing',
|
||||||
|
'other',
|
||||||
|
] as const
|
||||||
|
type WorkflowType = (typeof WORKFLOW_TYPES)[number]
|
||||||
|
|
||||||
|
// Step types for filtering
|
||||||
|
const STEP_TYPES = ['task', 'decision', 'milestone', 'approval', 'wait', 'automatic'] as const
|
||||||
|
|
||||||
|
interface WorkflowStep {
|
||||||
|
name: string
|
||||||
|
description?: unknown
|
||||||
|
shortDescription?: string
|
||||||
|
stepType?: string
|
||||||
|
priority?: string
|
||||||
|
estimatedDuration?: string
|
||||||
|
responsible?: string
|
||||||
|
icon?: string
|
||||||
|
dependencies?: {
|
||||||
|
dependsOnSteps?: string
|
||||||
|
canRunParallel?: boolean
|
||||||
|
isBlocking?: boolean
|
||||||
|
}
|
||||||
|
conditions?: Array<{
|
||||||
|
condition: string
|
||||||
|
nextStep?: string
|
||||||
|
color?: string
|
||||||
|
}>
|
||||||
|
checklist?: Array<{
|
||||||
|
item: string
|
||||||
|
isRequired?: boolean
|
||||||
|
}>
|
||||||
|
resources?: Array<{
|
||||||
|
name: string
|
||||||
|
type?: string
|
||||||
|
file?: Media | number
|
||||||
|
url?: string
|
||||||
|
description?: string
|
||||||
|
}>
|
||||||
|
outputs?: Array<{
|
||||||
|
name: string
|
||||||
|
description?: string
|
||||||
|
}>
|
||||||
|
metadata?: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WorkflowPhase {
|
||||||
|
name: string
|
||||||
|
description?: string
|
||||||
|
icon?: string
|
||||||
|
color?: string
|
||||||
|
estimatedDuration?: string
|
||||||
|
responsible?: string
|
||||||
|
steps: WorkflowStep[]
|
||||||
|
deliverables?: Array<{
|
||||||
|
name: string
|
||||||
|
description?: string
|
||||||
|
}>
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
// IP-Blocklist prüfen
|
||||||
|
const ip = getClientIpFromRequest(request)
|
||||||
|
if (isIpBlocked(ip)) {
|
||||||
|
return NextResponse.json({ error: 'Access denied' }, { status: 403 })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rate limiting
|
||||||
|
const rateLimit = await searchLimiter.check(ip)
|
||||||
|
if (!rateLimit.allowed) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Too many requests. Please try again later.' },
|
||||||
|
{ status: 429, headers: rateLimitHeaders(rateLimit, WORKFLOW_RATE_LIMIT) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse query parameters
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
|
||||||
|
const tenantParam = searchParams.get('tenant')
|
||||||
|
const slugParam = searchParams.get('slug')?.trim()
|
||||||
|
const typeParam = searchParams.get('type')?.trim()
|
||||||
|
const localeParam = searchParams.get('locale')?.trim()
|
||||||
|
const complexityParam = searchParams.get('complexity')?.trim()
|
||||||
|
|
||||||
|
// Validate tenant - REQUIRED for tenant isolation
|
||||||
|
if (!tenantParam) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Tenant ID is required. Use ?tenant=<id> to specify the tenant.' },
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const tenantId = parseInt(tenantParam, 10)
|
||||||
|
if (isNaN(tenantId) || tenantId < 1) {
|
||||||
|
return NextResponse.json({ error: 'Invalid tenant ID' }, { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate locale
|
||||||
|
const validLocales = ['de', 'en']
|
||||||
|
const locale = localeParam && validLocales.includes(localeParam) ? localeParam : 'de'
|
||||||
|
|
||||||
|
// Validate type if provided
|
||||||
|
if (typeParam && !WORKFLOW_TYPES.includes(typeParam as WorkflowType)) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: `Invalid type. Must be one of: ${WORKFLOW_TYPES.join(', ')}` },
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build where clause
|
||||||
|
const where: Record<string, unknown> = {
|
||||||
|
status: { equals: 'published' },
|
||||||
|
tenant: { equals: tenantId },
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by slug (single workflow)
|
||||||
|
if (slugParam) {
|
||||||
|
where.slug = { equals: slugParam }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by type
|
||||||
|
if (typeParam) {
|
||||||
|
where.type = { equals: typeParam }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get payload instance
|
||||||
|
const payload = await getPayload({ config })
|
||||||
|
|
||||||
|
// Execute query
|
||||||
|
const result = await payload.find({
|
||||||
|
collection: 'workflows',
|
||||||
|
where,
|
||||||
|
sort: '-updatedAt',
|
||||||
|
limit: slugParam ? 1 : 100, // Single or list
|
||||||
|
locale,
|
||||||
|
depth: 2, // Load media relations
|
||||||
|
})
|
||||||
|
|
||||||
|
if (slugParam && result.docs.length === 0) {
|
||||||
|
return NextResponse.json({ error: 'Workflow not found' }, { status: 404 })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform workflows
|
||||||
|
const transformedDocs = result.docs.map((workflow) => {
|
||||||
|
const phases = (workflow.phases || []) as WorkflowPhase[]
|
||||||
|
|
||||||
|
// Filter by complexity if specified
|
||||||
|
if (
|
||||||
|
complexityParam &&
|
||||||
|
(workflow.properties as { complexity?: string })?.complexity !== complexityParam
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate statistics
|
||||||
|
let totalSteps = 0
|
||||||
|
let totalChecklists = 0
|
||||||
|
const stepTypes: Record<string, number> = {}
|
||||||
|
|
||||||
|
// Transform phases
|
||||||
|
const transformedPhases = phases.map((phase, phaseIndex) => {
|
||||||
|
const steps = (phase.steps || []) as WorkflowStep[]
|
||||||
|
|
||||||
|
const transformedSteps = steps.map((step, stepIndex) => {
|
||||||
|
totalSteps++
|
||||||
|
|
||||||
|
// Count step types
|
||||||
|
const stepType = step.stepType || 'task'
|
||||||
|
stepTypes[stepType] = (stepTypes[stepType] || 0) + 1
|
||||||
|
|
||||||
|
// Count checklists
|
||||||
|
totalChecklists += (step.checklist || []).length
|
||||||
|
|
||||||
|
// Transform resources
|
||||||
|
const resources = (step.resources || []).map((resource) => {
|
||||||
|
const file = resource.file as Media | null
|
||||||
|
return {
|
||||||
|
name: resource.name,
|
||||||
|
type: resource.type || 'document',
|
||||||
|
fileUrl: file?.url || null,
|
||||||
|
url: resource.url || null,
|
||||||
|
description: resource.description || null,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
index: stepIndex + 1,
|
||||||
|
globalIndex: totalSteps,
|
||||||
|
name: step.name,
|
||||||
|
description: step.description || null,
|
||||||
|
shortDescription: step.shortDescription || null,
|
||||||
|
stepType: step.stepType || 'task',
|
||||||
|
priority: step.priority || 'normal',
|
||||||
|
estimatedDuration: step.estimatedDuration || null,
|
||||||
|
responsible: step.responsible || null,
|
||||||
|
icon: step.icon || null,
|
||||||
|
dependencies: step.dependencies
|
||||||
|
? {
|
||||||
|
dependsOnSteps: step.dependencies.dependsOnSteps || null,
|
||||||
|
canRunParallel: step.dependencies.canRunParallel || false,
|
||||||
|
isBlocking: step.dependencies.isBlocking !== false,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
conditions:
|
||||||
|
step.stepType === 'decision'
|
||||||
|
? (step.conditions || []).map((c) => ({
|
||||||
|
condition: c.condition,
|
||||||
|
nextStep: c.nextStep || null,
|
||||||
|
color: c.color || null,
|
||||||
|
}))
|
||||||
|
: null,
|
||||||
|
checklist: (step.checklist || []).map((item) => ({
|
||||||
|
item: item.item,
|
||||||
|
isRequired: item.isRequired !== false,
|
||||||
|
})),
|
||||||
|
resources: resources.length > 0 ? resources : null,
|
||||||
|
outputs: (step.outputs || []).map((o) => ({
|
||||||
|
name: o.name,
|
||||||
|
description: o.description || null,
|
||||||
|
})),
|
||||||
|
metadata: step.metadata || null,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
index: phaseIndex + 1,
|
||||||
|
name: phase.name,
|
||||||
|
description: phase.description || null,
|
||||||
|
icon: phase.icon || null,
|
||||||
|
color: phase.color || null,
|
||||||
|
estimatedDuration: phase.estimatedDuration || null,
|
||||||
|
responsible: phase.responsible || null,
|
||||||
|
stepCount: transformedSteps.length,
|
||||||
|
steps: transformedSteps,
|
||||||
|
deliverables: (phase.deliverables || []).map((d) => ({
|
||||||
|
name: d.name,
|
||||||
|
description: d.description || null,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Transform global resources
|
||||||
|
const globalResources = (
|
||||||
|
workflow.globalResources as Array<{
|
||||||
|
name: string
|
||||||
|
type?: string
|
||||||
|
file?: Media | number
|
||||||
|
url?: string
|
||||||
|
description?: string
|
||||||
|
}>
|
||||||
|
)?.map((resource) => {
|
||||||
|
const file = resource.file as Media | null
|
||||||
|
return {
|
||||||
|
name: resource.name,
|
||||||
|
type: resource.type || 'document',
|
||||||
|
fileUrl: file?.url || null,
|
||||||
|
url: resource.url || null,
|
||||||
|
description: resource.description || null,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const image = workflow.image as Media | null
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: workflow.id,
|
||||||
|
name: workflow.name,
|
||||||
|
slug: workflow.slug,
|
||||||
|
description: workflow.description || null,
|
||||||
|
shortDescription: workflow.shortDescription || null,
|
||||||
|
type: workflow.type,
|
||||||
|
image: image
|
||||||
|
? {
|
||||||
|
url: image.url,
|
||||||
|
alt: image.alt || workflow.name,
|
||||||
|
width: image.width,
|
||||||
|
height: image.height,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
properties: workflow.properties || null,
|
||||||
|
displayOptions: workflow.displayOptions || null,
|
||||||
|
phases: transformedPhases,
|
||||||
|
globalResources: globalResources?.length ? globalResources : null,
|
||||||
|
statistics: {
|
||||||
|
phaseCount: transformedPhases.length,
|
||||||
|
totalSteps,
|
||||||
|
totalChecklists,
|
||||||
|
stepTypes,
|
||||||
|
},
|
||||||
|
seo: workflow.seo || null,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Filter out null entries (from complexity filter)
|
||||||
|
const filteredDocs = transformedDocs.filter(Boolean)
|
||||||
|
|
||||||
|
// Single workflow response
|
||||||
|
if (slugParam) {
|
||||||
|
if (filteredDocs.length === 0) {
|
||||||
|
return NextResponse.json({ error: 'Workflow not found' }, { status: 404 })
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
workflow: filteredDocs[0],
|
||||||
|
locale,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
...rateLimitHeaders(rateLimit, WORKFLOW_RATE_LIMIT),
|
||||||
|
'Cache-Control': 'public, max-age=60, s-maxage=300',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// List response
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
docs: filteredDocs,
|
||||||
|
total: filteredDocs.length,
|
||||||
|
filters: {
|
||||||
|
tenant: tenantId,
|
||||||
|
type: typeParam || null,
|
||||||
|
complexity: complexityParam || null,
|
||||||
|
locale,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
...rateLimitHeaders(rateLimit, WORKFLOW_RATE_LIMIT),
|
||||||
|
'Cache-Control': 'public, max-age=60, s-maxage=120',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Workflow API] Error:', error)
|
||||||
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -398,6 +398,81 @@ export const Timelines: CollectionConfig = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Prozess-spezifische Felder (für einfache Prozesse wie Onboarding, Bewerbung)
|
||||||
|
{
|
||||||
|
name: 'stepNumber',
|
||||||
|
type: 'number',
|
||||||
|
label: 'Schritt-Nummer',
|
||||||
|
admin: {
|
||||||
|
description: 'Explizite Nummerierung (optional, sonst wird Reihenfolge verwendet)',
|
||||||
|
condition: (data) => data?.type === 'process',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'duration',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Dauer',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'z.B. "2-3 Tage", "1 Woche", "30 Minuten"',
|
||||||
|
condition: (data) => data?.type === 'process',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'responsible',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Verantwortlich',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'Person oder Rolle (z.B. "HR-Team", "Projektleiter")',
|
||||||
|
condition: (data) => data?.type === 'process',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actionRequired',
|
||||||
|
type: 'select',
|
||||||
|
label: 'Aktion erforderlich von',
|
||||||
|
admin: {
|
||||||
|
description: 'Wer muss in diesem Schritt aktiv werden?',
|
||||||
|
condition: (data) => data?.type === 'process',
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{ label: 'Kunde/Bewerber', value: 'customer' },
|
||||||
|
{ label: 'Internes Team', value: 'internal' },
|
||||||
|
{ label: 'Beide Seiten', value: 'both' },
|
||||||
|
{ label: 'Automatisch', value: 'automatic' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'deliverables',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Ergebnisse/Dokumente',
|
||||||
|
admin: {
|
||||||
|
description: 'Was wird in diesem Schritt erstellt oder benötigt?',
|
||||||
|
condition: (data) => data?.type === 'process',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Name',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'output',
|
||||||
|
label: 'Typ',
|
||||||
|
options: [
|
||||||
|
{ label: 'Ergebnis (Output)', value: 'output' },
|
||||||
|
{ label: 'Benötigt (Input)', value: 'input' },
|
||||||
|
{ label: 'Dokument', value: 'document' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
// Icon & Styling
|
// Icon & Styling
|
||||||
{
|
{
|
||||||
name: 'icon',
|
name: 'icon',
|
||||||
|
|
|
||||||
683
src/collections/Workflows.ts
Normal file
683
src/collections/Workflows.ts
Normal file
|
|
@ -0,0 +1,683 @@
|
||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workflows Collection
|
||||||
|
*
|
||||||
|
* Komplexe Prozess- und Workflow-Darstellungen mit:
|
||||||
|
* - Phasen und Schritten
|
||||||
|
* - Abhängigkeiten zwischen Schritten
|
||||||
|
* - Verzweigungen und Bedingungen
|
||||||
|
* - Status-Tracking
|
||||||
|
* - Checklisten und Dokumente
|
||||||
|
* - Verantwortlichkeiten und Zeitschätzungen
|
||||||
|
*
|
||||||
|
* Ideal für:
|
||||||
|
* - Projektabläufe
|
||||||
|
* - Komplexe Geschäftsprozesse
|
||||||
|
* - Genehmigungs-Workflows
|
||||||
|
* - Produktentwicklungs-Pipelines
|
||||||
|
*
|
||||||
|
* Multi-Tenant-fähig
|
||||||
|
*/
|
||||||
|
export const Workflows: CollectionConfig = {
|
||||||
|
slug: 'workflows',
|
||||||
|
labels: {
|
||||||
|
singular: 'Workflow',
|
||||||
|
plural: 'Workflows',
|
||||||
|
},
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'name',
|
||||||
|
group: 'Inhalte',
|
||||||
|
defaultColumns: ['name', 'type', 'status', 'updatedAt'],
|
||||||
|
description: 'Komplexe Prozesse und Workflows mit Phasen, Abhängigkeiten und Status-Tracking',
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
read: () => true, // Öffentlich lesbar
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
// Workflow-Metadaten
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Workflow-Name',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'Name des Workflows (z.B. "Projektablauf Webentwicklung")',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'slug',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
label: 'Slug',
|
||||||
|
admin: {
|
||||||
|
description: 'URL-freundlicher Identifier',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'richText',
|
||||||
|
label: 'Beschreibung',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'Ausführliche Beschreibung des Workflows',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'shortDescription',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Kurzbeschreibung',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'Kurze Zusammenfassung für Übersichten',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
type: 'select',
|
||||||
|
required: true,
|
||||||
|
defaultValue: 'project',
|
||||||
|
label: 'Workflow-Typ',
|
||||||
|
options: [
|
||||||
|
{ label: 'Projektablauf', value: 'project' },
|
||||||
|
{ label: 'Geschäftsprozess', value: 'business' },
|
||||||
|
{ label: 'Genehmigung', value: 'approval' },
|
||||||
|
{ label: 'Onboarding', value: 'onboarding' },
|
||||||
|
{ label: 'Support/Service', value: 'support' },
|
||||||
|
{ label: 'Entwicklung', value: 'development' },
|
||||||
|
{ label: 'Marketing', value: 'marketing' },
|
||||||
|
{ label: 'Sonstiges', value: 'other' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
type: 'select',
|
||||||
|
required: true,
|
||||||
|
defaultValue: 'draft',
|
||||||
|
label: 'Status',
|
||||||
|
options: [
|
||||||
|
{ label: 'Entwurf', value: 'draft' },
|
||||||
|
{ label: 'Veröffentlicht', value: 'published' },
|
||||||
|
{ label: 'Archiviert', value: 'archived' },
|
||||||
|
],
|
||||||
|
admin: {
|
||||||
|
position: 'sidebar',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'image',
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'media',
|
||||||
|
label: 'Vorschaubild',
|
||||||
|
admin: {
|
||||||
|
description: 'Optionales Bild für den Workflow',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Workflow-Eigenschaften
|
||||||
|
{
|
||||||
|
name: 'properties',
|
||||||
|
type: 'group',
|
||||||
|
label: 'Workflow-Eigenschaften',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'estimatedDuration',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Geschätzte Gesamtdauer',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'z.B. "4-6 Wochen", "3 Monate"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'complexity',
|
||||||
|
type: 'select',
|
||||||
|
label: 'Komplexität',
|
||||||
|
options: [
|
||||||
|
{ label: 'Einfach', value: 'simple' },
|
||||||
|
{ label: 'Mittel', value: 'medium' },
|
||||||
|
{ label: 'Komplex', value: 'complex' },
|
||||||
|
{ label: 'Sehr komplex', value: 'very_complex' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'isIterative',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Iterativer Prozess',
|
||||||
|
defaultValue: false,
|
||||||
|
admin: {
|
||||||
|
description: 'Kann der Workflow wiederholt durchlaufen werden?',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'allowParallelPhases',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Parallele Phasen erlaubt',
|
||||||
|
defaultValue: false,
|
||||||
|
admin: {
|
||||||
|
description: 'Können mehrere Phasen gleichzeitig aktiv sein?',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Display-Optionen
|
||||||
|
{
|
||||||
|
name: 'displayOptions',
|
||||||
|
type: 'group',
|
||||||
|
label: 'Darstellungsoptionen',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'layout',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'vertical',
|
||||||
|
label: 'Layout',
|
||||||
|
options: [
|
||||||
|
{ label: 'Vertikal (Schritte untereinander)', value: 'vertical' },
|
||||||
|
{ label: 'Horizontal (Schritte nebeneinander)', value: 'horizontal' },
|
||||||
|
{ label: 'Flowchart (mit Verbindungen)', value: 'flowchart' },
|
||||||
|
{ label: 'Kanban (Spalten)', value: 'kanban' },
|
||||||
|
{ label: 'Gantt (Zeitstrahl)', value: 'gantt' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'showPhaseNumbers',
|
||||||
|
type: 'checkbox',
|
||||||
|
defaultValue: true,
|
||||||
|
label: 'Phasen-Nummern anzeigen',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'showStepNumbers',
|
||||||
|
type: 'checkbox',
|
||||||
|
defaultValue: true,
|
||||||
|
label: 'Schritt-Nummern anzeigen',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'showDurations',
|
||||||
|
type: 'checkbox',
|
||||||
|
defaultValue: true,
|
||||||
|
label: 'Zeitangaben anzeigen',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'showResponsible',
|
||||||
|
type: 'checkbox',
|
||||||
|
defaultValue: true,
|
||||||
|
label: 'Verantwortliche anzeigen',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'showProgress',
|
||||||
|
type: 'checkbox',
|
||||||
|
defaultValue: false,
|
||||||
|
label: 'Fortschrittsanzeige',
|
||||||
|
admin: {
|
||||||
|
description: 'Zeigt Fortschrittsbalken basierend auf abgeschlossenen Schritten',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'colorScheme',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'phase',
|
||||||
|
label: 'Farbschema',
|
||||||
|
options: [
|
||||||
|
{ label: 'Nach Phase', value: 'phase' },
|
||||||
|
{ label: 'Nach Status', value: 'status' },
|
||||||
|
{ label: 'Nach Priorität', value: 'priority' },
|
||||||
|
{ label: 'Einheitlich (Brand)', value: 'brand' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Phasen (Hauptabschnitte des Workflows)
|
||||||
|
{
|
||||||
|
name: 'phases',
|
||||||
|
type: 'array',
|
||||||
|
required: true,
|
||||||
|
minRows: 1,
|
||||||
|
label: 'Phasen',
|
||||||
|
admin: {
|
||||||
|
description: 'Hauptabschnitte des Workflows',
|
||||||
|
initCollapsed: false,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Phasen-Name',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Beschreibung',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'icon',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Icon',
|
||||||
|
admin: {
|
||||||
|
description: 'Lucide Icon-Name (z.B. "rocket", "settings", "check-circle")',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'color',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Farbe',
|
||||||
|
admin: {
|
||||||
|
description: 'HEX-Farbe (z.B. "#3B82F6") oder Tailwind-Klasse',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'estimatedDuration',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Geschätzte Dauer',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'z.B. "1 Woche", "2-3 Tage"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'responsible',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Verantwortlich',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'Rolle oder Person (z.B. "Projektleiter", "Design-Team")',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Schritte innerhalb der Phase
|
||||||
|
{
|
||||||
|
name: 'steps',
|
||||||
|
type: 'array',
|
||||||
|
required: true,
|
||||||
|
minRows: 1,
|
||||||
|
label: 'Schritte',
|
||||||
|
admin: {
|
||||||
|
description: 'Einzelne Schritte in dieser Phase',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Schritt-Name',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'richText',
|
||||||
|
label: 'Beschreibung',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'shortDescription',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Kurzbeschreibung',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'Für kompakte Ansichten',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'stepType',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'task',
|
||||||
|
label: 'Schritt-Typ',
|
||||||
|
options: [
|
||||||
|
{ label: 'Aufgabe', value: 'task' },
|
||||||
|
{ label: 'Entscheidung', value: 'decision' },
|
||||||
|
{ label: 'Meilenstein', value: 'milestone' },
|
||||||
|
{ label: 'Genehmigung', value: 'approval' },
|
||||||
|
{ label: 'Warten/Pause', value: 'wait' },
|
||||||
|
{ label: 'Automatisch', value: 'automatic' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'priority',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'normal',
|
||||||
|
label: 'Priorität',
|
||||||
|
options: [
|
||||||
|
{ label: 'Kritisch', value: 'critical' },
|
||||||
|
{ label: 'Hoch', value: 'high' },
|
||||||
|
{ label: 'Normal', value: 'normal' },
|
||||||
|
{ label: 'Niedrig', value: 'low' },
|
||||||
|
{ label: 'Optional', value: 'optional' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'estimatedDuration',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Geschätzte Dauer',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'z.B. "2 Stunden", "1 Tag"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'responsible',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Verantwortlich',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'icon',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Icon',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Abhängigkeiten
|
||||||
|
{
|
||||||
|
name: 'dependencies',
|
||||||
|
type: 'group',
|
||||||
|
label: 'Abhängigkeiten',
|
||||||
|
admin: {
|
||||||
|
description: 'Welche Schritte müssen vorher abgeschlossen sein?',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'dependsOnSteps',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Abhängig von Schritten',
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
'IDs oder Namen der Vorgänger-Schritte (komma-separiert). Leer = vorheriger Schritt',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'canRunParallel',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Kann parallel laufen',
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'isBlocking',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Blockierend',
|
||||||
|
defaultValue: true,
|
||||||
|
admin: {
|
||||||
|
description: 'Muss abgeschlossen sein, bevor der nächste Schritt beginnt',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Bedingungen (für Entscheidungen)
|
||||||
|
{
|
||||||
|
name: 'conditions',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Bedingungen/Verzweigungen',
|
||||||
|
admin: {
|
||||||
|
description: 'Für Entscheidungsschritte: Welche Wege gibt es?',
|
||||||
|
condition: (_, siblingData) => siblingData?.stepType === 'decision',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'condition',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Bedingung',
|
||||||
|
localized: true,
|
||||||
|
admin: {
|
||||||
|
description: 'z.B. "Wenn genehmigt", "Bei Budget > 10.000€"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'nextStep',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Nächster Schritt',
|
||||||
|
admin: {
|
||||||
|
description: 'ID oder Name des nächsten Schritts',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'color',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Farbe',
|
||||||
|
admin: {
|
||||||
|
description: 'z.B. "green" für positiv, "red" für negativ',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Checkliste
|
||||||
|
{
|
||||||
|
name: 'checklist',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Checkliste',
|
||||||
|
admin: {
|
||||||
|
description: 'To-Do-Punkte für diesen Schritt',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'item',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Aufgabe',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'isRequired',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Pflicht',
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Dokumente und Ressourcen
|
||||||
|
{
|
||||||
|
name: 'resources',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Ressourcen & Dokumente',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Name',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'document',
|
||||||
|
label: 'Typ',
|
||||||
|
options: [
|
||||||
|
{ label: 'Dokument', value: 'document' },
|
||||||
|
{ label: 'Template', value: 'template' },
|
||||||
|
{ label: 'Link', value: 'link' },
|
||||||
|
{ label: 'Tool', value: 'tool' },
|
||||||
|
{ label: 'Video', value: 'video' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'file',
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'media',
|
||||||
|
label: 'Datei',
|
||||||
|
admin: {
|
||||||
|
condition: (_, siblingData) =>
|
||||||
|
['document', 'template'].includes(siblingData?.type),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'url',
|
||||||
|
type: 'text',
|
||||||
|
label: 'URL',
|
||||||
|
admin: {
|
||||||
|
condition: (_, siblingData) =>
|
||||||
|
['link', 'tool', 'video'].includes(siblingData?.type),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Beschreibung',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Outputs/Ergebnisse
|
||||||
|
{
|
||||||
|
name: 'outputs',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Ergebnisse/Outputs',
|
||||||
|
admin: {
|
||||||
|
description: 'Was wird in diesem Schritt produziert?',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Output',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Beschreibung',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Zusätzliche Daten
|
||||||
|
{
|
||||||
|
name: 'metadata',
|
||||||
|
type: 'json',
|
||||||
|
label: 'Zusätzliche Daten (JSON)',
|
||||||
|
admin: {
|
||||||
|
description: 'Für spezielle Anwendungsfälle',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Phase-Level Outputs
|
||||||
|
{
|
||||||
|
name: 'deliverables',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Liefergegenstände der Phase',
|
||||||
|
admin: {
|
||||||
|
description: 'Was wird am Ende dieser Phase abgeliefert?',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Deliverable',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Beschreibung',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Globale Ressourcen
|
||||||
|
{
|
||||||
|
name: 'globalResources',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Globale Ressourcen',
|
||||||
|
admin: {
|
||||||
|
description: 'Ressourcen, die für den gesamten Workflow relevant sind',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Name',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'document',
|
||||||
|
label: 'Typ',
|
||||||
|
options: [
|
||||||
|
{ label: 'Dokument', value: 'document' },
|
||||||
|
{ label: 'Template', value: 'template' },
|
||||||
|
{ label: 'Checkliste', value: 'checklist' },
|
||||||
|
{ label: 'Link', value: 'link' },
|
||||||
|
{ label: 'Tool', value: 'tool' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'file',
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'media',
|
||||||
|
label: 'Datei',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'url',
|
||||||
|
type: 'text',
|
||||||
|
label: 'URL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Beschreibung',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// SEO
|
||||||
|
{
|
||||||
|
name: 'seo',
|
||||||
|
type: 'group',
|
||||||
|
label: 'SEO',
|
||||||
|
admin: {
|
||||||
|
position: 'sidebar',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'metaTitle',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Meta-Titel',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'metaDescription',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Meta-Beschreibung',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
hooks: {
|
||||||
|
beforeChange: [
|
||||||
|
({ data }) => {
|
||||||
|
// Auto-generate slug from name if not provided
|
||||||
|
if (data && !data.slug && data.name) {
|
||||||
|
data.slug = data.name
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[äöüß]/g, (match: string) => {
|
||||||
|
const map: Record<string, string> = { ä: 'ae', ö: 'oe', ü: 'ue', ß: 'ss' }
|
||||||
|
return map[match] || match
|
||||||
|
})
|
||||||
|
.replace(/[^a-z0-9]+/g, '-')
|
||||||
|
.replace(/^-|-$/g, '')
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,324 @@
|
||||||
|
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||||
|
|
||||||
|
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
CREATE TYPE "public"."enum_timelines_events_deliverables_type" AS ENUM('output', 'input', 'document');
|
||||||
|
CREATE TYPE "public"."enum_timelines_events_action_required" AS ENUM('customer', 'internal', 'both', 'automatic');
|
||||||
|
CREATE TYPE "public"."enum_workflows_phases_steps_resources_type" AS ENUM('document', 'template', 'link', 'tool', 'video');
|
||||||
|
CREATE TYPE "public"."enum_workflows_phases_steps_step_type" AS ENUM('task', 'decision', 'milestone', 'approval', 'wait', 'automatic');
|
||||||
|
CREATE TYPE "public"."enum_workflows_phases_steps_priority" AS ENUM('critical', 'high', 'normal', 'low', 'optional');
|
||||||
|
CREATE TYPE "public"."enum_workflows_global_resources_type" AS ENUM('document', 'template', 'checklist', 'link', 'tool');
|
||||||
|
CREATE TYPE "public"."enum_workflows_type" AS ENUM('project', 'business', 'approval', 'onboarding', 'support', 'development', 'marketing', 'other');
|
||||||
|
CREATE TYPE "public"."enum_workflows_status" AS ENUM('draft', 'published', 'archived');
|
||||||
|
CREATE TYPE "public"."enum_workflows_properties_complexity" AS ENUM('simple', 'medium', 'complex', 'very_complex');
|
||||||
|
CREATE TYPE "public"."enum_workflows_display_options_layout" AS ENUM('vertical', 'horizontal', 'flowchart', 'kanban', 'gantt');
|
||||||
|
CREATE TYPE "public"."enum_workflows_display_options_color_scheme" AS ENUM('phase', 'status', 'priority', 'brand');
|
||||||
|
CREATE TABLE "timelines_events_deliverables" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL,
|
||||||
|
"type" "enum_timelines_events_deliverables_type" DEFAULT 'output'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "timelines_events_deliverables_locales" (
|
||||||
|
"name" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_conditions" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL,
|
||||||
|
"next_step" varchar,
|
||||||
|
"color" varchar
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_conditions_locales" (
|
||||||
|
"condition" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_checklist" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL,
|
||||||
|
"is_required" boolean DEFAULT true
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_checklist_locales" (
|
||||||
|
"item" varchar NOT NULL,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_resources" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL,
|
||||||
|
"type" "enum_workflows_phases_steps_resources_type" DEFAULT 'document',
|
||||||
|
"file_id" integer,
|
||||||
|
"url" varchar
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_resources_locales" (
|
||||||
|
"name" varchar NOT NULL,
|
||||||
|
"description" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_outputs" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_outputs_locales" (
|
||||||
|
"name" varchar NOT NULL,
|
||||||
|
"description" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL,
|
||||||
|
"step_type" "enum_workflows_phases_steps_step_type" DEFAULT 'task',
|
||||||
|
"priority" "enum_workflows_phases_steps_priority" DEFAULT 'normal',
|
||||||
|
"icon" varchar,
|
||||||
|
"dependencies_depends_on_steps" varchar,
|
||||||
|
"dependencies_can_run_parallel" boolean DEFAULT false,
|
||||||
|
"dependencies_is_blocking" boolean DEFAULT true,
|
||||||
|
"metadata" jsonb
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_steps_locales" (
|
||||||
|
"name" varchar NOT NULL,
|
||||||
|
"description" jsonb,
|
||||||
|
"short_description" varchar,
|
||||||
|
"estimated_duration" varchar,
|
||||||
|
"responsible" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_deliverables" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_deliverables_locales" (
|
||||||
|
"name" varchar NOT NULL,
|
||||||
|
"description" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" integer NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL,
|
||||||
|
"icon" varchar,
|
||||||
|
"color" varchar
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_phases_locales" (
|
||||||
|
"name" varchar NOT NULL,
|
||||||
|
"description" varchar,
|
||||||
|
"estimated_duration" varchar,
|
||||||
|
"responsible" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_global_resources" (
|
||||||
|
"_order" integer NOT NULL,
|
||||||
|
"_parent_id" integer NOT NULL,
|
||||||
|
"id" varchar PRIMARY KEY NOT NULL,
|
||||||
|
"type" "enum_workflows_global_resources_type" DEFAULT 'document',
|
||||||
|
"file_id" integer,
|
||||||
|
"url" varchar
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_global_resources_locales" (
|
||||||
|
"name" varchar NOT NULL,
|
||||||
|
"description" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" varchar NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows" (
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"tenant_id" integer,
|
||||||
|
"slug" varchar NOT NULL,
|
||||||
|
"type" "enum_workflows_type" DEFAULT 'project' NOT NULL,
|
||||||
|
"status" "enum_workflows_status" DEFAULT 'draft' NOT NULL,
|
||||||
|
"image_id" integer,
|
||||||
|
"properties_complexity" "enum_workflows_properties_complexity",
|
||||||
|
"properties_is_iterative" boolean DEFAULT false,
|
||||||
|
"properties_allow_parallel_phases" boolean DEFAULT false,
|
||||||
|
"display_options_layout" "enum_workflows_display_options_layout" DEFAULT 'vertical',
|
||||||
|
"display_options_show_phase_numbers" boolean DEFAULT true,
|
||||||
|
"display_options_show_step_numbers" boolean DEFAULT true,
|
||||||
|
"display_options_show_durations" boolean DEFAULT true,
|
||||||
|
"display_options_show_responsible" boolean DEFAULT true,
|
||||||
|
"display_options_show_progress" boolean DEFAULT false,
|
||||||
|
"display_options_color_scheme" "enum_workflows_display_options_color_scheme" DEFAULT 'phase',
|
||||||
|
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||||
|
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "workflows_locales" (
|
||||||
|
"name" varchar NOT NULL,
|
||||||
|
"description" jsonb,
|
||||||
|
"short_description" varchar,
|
||||||
|
"properties_estimated_duration" varchar,
|
||||||
|
"seo_meta_title" varchar,
|
||||||
|
"seo_meta_description" varchar,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" integer NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE "timelines_events" ADD COLUMN "step_number" numeric;
|
||||||
|
ALTER TABLE "timelines_events" ADD COLUMN "action_required" "enum_timelines_events_action_required";
|
||||||
|
ALTER TABLE "timelines_events_locales" ADD COLUMN "duration" varchar;
|
||||||
|
ALTER TABLE "timelines_events_locales" ADD COLUMN "responsible" varchar;
|
||||||
|
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "workflows_id" integer;
|
||||||
|
ALTER TABLE "timelines_events_deliverables" ADD CONSTRAINT "timelines_events_deliverables_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."timelines_events"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "timelines_events_deliverables_locales" ADD CONSTRAINT "timelines_events_deliverables_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."timelines_events_deliverables"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_conditions" ADD CONSTRAINT "workflows_phases_steps_conditions_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_conditions_locales" ADD CONSTRAINT "workflows_phases_steps_conditions_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps_conditions"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_checklist" ADD CONSTRAINT "workflows_phases_steps_checklist_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_checklist_locales" ADD CONSTRAINT "workflows_phases_steps_checklist_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps_checklist"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_resources" ADD CONSTRAINT "workflows_phases_steps_resources_file_id_media_id_fk" FOREIGN KEY ("file_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_resources" ADD CONSTRAINT "workflows_phases_steps_resources_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_resources_locales" ADD CONSTRAINT "workflows_phases_steps_resources_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps_resources"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_outputs" ADD CONSTRAINT "workflows_phases_steps_outputs_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_outputs_locales" ADD CONSTRAINT "workflows_phases_steps_outputs_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps_outputs"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps" ADD CONSTRAINT "workflows_phases_steps_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_steps_locales" ADD CONSTRAINT "workflows_phases_steps_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_steps"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_deliverables" ADD CONSTRAINT "workflows_phases_deliverables_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_deliverables_locales" ADD CONSTRAINT "workflows_phases_deliverables_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases_deliverables"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases" ADD CONSTRAINT "workflows_phases_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_phases_locales" ADD CONSTRAINT "workflows_phases_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_phases"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_global_resources" ADD CONSTRAINT "workflows_global_resources_file_id_media_id_fk" FOREIGN KEY ("file_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_global_resources" ADD CONSTRAINT "workflows_global_resources_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_global_resources_locales" ADD CONSTRAINT "workflows_global_resources_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows_global_resources"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows" ADD CONSTRAINT "workflows_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows" ADD CONSTRAINT "workflows_image_id_media_id_fk" FOREIGN KEY ("image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
ALTER TABLE "workflows_locales" ADD CONSTRAINT "workflows_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."workflows"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
CREATE INDEX "timelines_events_deliverables_order_idx" ON "timelines_events_deliverables" USING btree ("_order");
|
||||||
|
CREATE INDEX "timelines_events_deliverables_parent_id_idx" ON "timelines_events_deliverables" USING btree ("_parent_id");
|
||||||
|
CREATE UNIQUE INDEX "timelines_events_deliverables_locales_locale_parent_id_uniqu" ON "timelines_events_deliverables_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_phases_steps_conditions_order_idx" ON "workflows_phases_steps_conditions" USING btree ("_order");
|
||||||
|
CREATE INDEX "workflows_phases_steps_conditions_parent_id_idx" ON "workflows_phases_steps_conditions" USING btree ("_parent_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_phases_steps_conditions_locales_locale_parent_id_u" ON "workflows_phases_steps_conditions_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_phases_steps_checklist_order_idx" ON "workflows_phases_steps_checklist" USING btree ("_order");
|
||||||
|
CREATE INDEX "workflows_phases_steps_checklist_parent_id_idx" ON "workflows_phases_steps_checklist" USING btree ("_parent_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_phases_steps_checklist_locales_locale_parent_id_un" ON "workflows_phases_steps_checklist_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_phases_steps_resources_order_idx" ON "workflows_phases_steps_resources" USING btree ("_order");
|
||||||
|
CREATE INDEX "workflows_phases_steps_resources_parent_id_idx" ON "workflows_phases_steps_resources" USING btree ("_parent_id");
|
||||||
|
CREATE INDEX "workflows_phases_steps_resources_file_idx" ON "workflows_phases_steps_resources" USING btree ("file_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_phases_steps_resources_locales_locale_parent_id_un" ON "workflows_phases_steps_resources_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_phases_steps_outputs_order_idx" ON "workflows_phases_steps_outputs" USING btree ("_order");
|
||||||
|
CREATE INDEX "workflows_phases_steps_outputs_parent_id_idx" ON "workflows_phases_steps_outputs" USING btree ("_parent_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_phases_steps_outputs_locales_locale_parent_id_uniq" ON "workflows_phases_steps_outputs_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_phases_steps_order_idx" ON "workflows_phases_steps" USING btree ("_order");
|
||||||
|
CREATE INDEX "workflows_phases_steps_parent_id_idx" ON "workflows_phases_steps" USING btree ("_parent_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_phases_steps_locales_locale_parent_id_unique" ON "workflows_phases_steps_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_phases_deliverables_order_idx" ON "workflows_phases_deliverables" USING btree ("_order");
|
||||||
|
CREATE INDEX "workflows_phases_deliverables_parent_id_idx" ON "workflows_phases_deliverables" USING btree ("_parent_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_phases_deliverables_locales_locale_parent_id_uniqu" ON "workflows_phases_deliverables_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_phases_order_idx" ON "workflows_phases" USING btree ("_order");
|
||||||
|
CREATE INDEX "workflows_phases_parent_id_idx" ON "workflows_phases" USING btree ("_parent_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_phases_locales_locale_parent_id_unique" ON "workflows_phases_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_global_resources_order_idx" ON "workflows_global_resources" USING btree ("_order");
|
||||||
|
CREATE INDEX "workflows_global_resources_parent_id_idx" ON "workflows_global_resources" USING btree ("_parent_id");
|
||||||
|
CREATE INDEX "workflows_global_resources_file_idx" ON "workflows_global_resources" USING btree ("file_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_global_resources_locales_locale_parent_id_unique" ON "workflows_global_resources_locales" USING btree ("_locale","_parent_id");
|
||||||
|
CREATE INDEX "workflows_tenant_idx" ON "workflows" USING btree ("tenant_id");
|
||||||
|
CREATE UNIQUE INDEX "workflows_slug_idx" ON "workflows" USING btree ("slug");
|
||||||
|
CREATE INDEX "workflows_image_idx" ON "workflows" USING btree ("image_id");
|
||||||
|
CREATE INDEX "workflows_updated_at_idx" ON "workflows" USING btree ("updated_at");
|
||||||
|
CREATE INDEX "workflows_created_at_idx" ON "workflows" USING btree ("created_at");
|
||||||
|
CREATE UNIQUE INDEX "workflows_locales_locale_parent_id_unique" ON "workflows_locales" USING btree ("_locale","_parent_id");
|
||||||
|
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_workflows_fk" FOREIGN KEY ("workflows_id") REFERENCES "public"."workflows"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
CREATE INDEX "payload_locked_documents_rels_workflows_id_idx" ON "payload_locked_documents_rels" USING btree ("workflows_id");`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
ALTER TABLE "timelines_events_deliverables" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "timelines_events_deliverables_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_conditions" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_conditions_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_checklist" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_checklist_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_resources" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_resources_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_outputs" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_outputs_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_steps_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_deliverables" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_deliverables_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_phases_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_global_resources" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_global_resources_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows" DISABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE "workflows_locales" DISABLE ROW LEVEL SECURITY;
|
||||||
|
DROP TABLE "timelines_events_deliverables" CASCADE;
|
||||||
|
DROP TABLE "timelines_events_deliverables_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_conditions" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_conditions_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_checklist" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_checklist_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_resources" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_resources_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_outputs" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_outputs_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_steps_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_deliverables" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_deliverables_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases" CASCADE;
|
||||||
|
DROP TABLE "workflows_phases_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows_global_resources" CASCADE;
|
||||||
|
DROP TABLE "workflows_global_resources_locales" CASCADE;
|
||||||
|
DROP TABLE "workflows" CASCADE;
|
||||||
|
DROP TABLE "workflows_locales" CASCADE;
|
||||||
|
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT "payload_locked_documents_rels_workflows_fk";
|
||||||
|
|
||||||
|
DROP INDEX "payload_locked_documents_rels_workflows_id_idx";
|
||||||
|
ALTER TABLE "timelines_events" DROP COLUMN "step_number";
|
||||||
|
ALTER TABLE "timelines_events" DROP COLUMN "action_required";
|
||||||
|
ALTER TABLE "timelines_events_locales" DROP COLUMN "duration";
|
||||||
|
ALTER TABLE "timelines_events_locales" DROP COLUMN "responsible";
|
||||||
|
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN "workflows_id";
|
||||||
|
DROP TYPE "public"."enum_timelines_events_deliverables_type";
|
||||||
|
DROP TYPE "public"."enum_timelines_events_action_required";
|
||||||
|
DROP TYPE "public"."enum_workflows_phases_steps_resources_type";
|
||||||
|
DROP TYPE "public"."enum_workflows_phases_steps_step_type";
|
||||||
|
DROP TYPE "public"."enum_workflows_phases_steps_priority";
|
||||||
|
DROP TYPE "public"."enum_workflows_global_resources_type";
|
||||||
|
DROP TYPE "public"."enum_workflows_type";
|
||||||
|
DROP TYPE "public"."enum_workflows_status";
|
||||||
|
DROP TYPE "public"."enum_workflows_properties_complexity";
|
||||||
|
DROP TYPE "public"."enum_workflows_display_options_layout";
|
||||||
|
DROP TYPE "public"."enum_workflows_display_options_color_scheme";`)
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ import * as migration_20251210_073811_add_services_collections from './20251210_
|
||||||
import * as migration_20251210_090000_enhance_form_submissions from './20251210_090000_enhance_form_submissions';
|
import * as migration_20251210_090000_enhance_form_submissions from './20251210_090000_enhance_form_submissions';
|
||||||
import * as migration_20251212_211506_add_products_collections from './20251212_211506_add_products_collections';
|
import * as migration_20251212_211506_add_products_collections from './20251212_211506_add_products_collections';
|
||||||
import * as migration_20251213_100753_add_timelines_collection from './20251213_100753_add_timelines_collection';
|
import * as migration_20251213_100753_add_timelines_collection from './20251213_100753_add_timelines_collection';
|
||||||
|
import * as migration_20251213_104523_add_workflows_and_timeline_process_fields from './20251213_104523_add_workflows_and_timeline_process_fields';
|
||||||
|
|
||||||
export const migrations = [
|
export const migrations = [
|
||||||
{
|
{
|
||||||
|
|
@ -70,6 +71,11 @@ export const migrations = [
|
||||||
{
|
{
|
||||||
up: migration_20251213_100753_add_timelines_collection.up,
|
up: migration_20251213_100753_add_timelines_collection.up,
|
||||||
down: migration_20251213_100753_add_timelines_collection.down,
|
down: migration_20251213_100753_add_timelines_collection.down,
|
||||||
name: '20251213_100753_add_timelines_collection'
|
name: '20251213_100753_add_timelines_collection',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
up: migration_20251213_104523_add_workflows_and_timeline_process_fields.up,
|
||||||
|
down: migration_20251213_104523_add_workflows_and_timeline_process_fields.down,
|
||||||
|
name: '20251213_104523_add_workflows_and_timeline_process_fields'
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ export interface Config {
|
||||||
'product-categories': ProductCategory;
|
'product-categories': ProductCategory;
|
||||||
products: Product;
|
products: Product;
|
||||||
timelines: Timeline;
|
timelines: Timeline;
|
||||||
|
workflows: Workflow;
|
||||||
'cookie-configurations': CookieConfiguration;
|
'cookie-configurations': CookieConfiguration;
|
||||||
'cookie-inventory': CookieInventory;
|
'cookie-inventory': CookieInventory;
|
||||||
'consent-logs': ConsentLog;
|
'consent-logs': ConsentLog;
|
||||||
|
|
@ -119,6 +120,7 @@ export interface Config {
|
||||||
'product-categories': ProductCategoriesSelect<false> | ProductCategoriesSelect<true>;
|
'product-categories': ProductCategoriesSelect<false> | ProductCategoriesSelect<true>;
|
||||||
products: ProductsSelect<false> | ProductsSelect<true>;
|
products: ProductsSelect<false> | ProductsSelect<true>;
|
||||||
timelines: TimelinesSelect<false> | TimelinesSelect<true>;
|
timelines: TimelinesSelect<false> | TimelinesSelect<true>;
|
||||||
|
workflows: WorkflowsSelect<false> | WorkflowsSelect<true>;
|
||||||
'cookie-configurations': CookieConfigurationsSelect<false> | CookieConfigurationsSelect<true>;
|
'cookie-configurations': CookieConfigurationsSelect<false> | CookieConfigurationsSelect<true>;
|
||||||
'cookie-inventory': CookieInventorySelect<false> | CookieInventorySelect<true>;
|
'cookie-inventory': CookieInventorySelect<false> | CookieInventorySelect<true>;
|
||||||
'consent-logs': ConsentLogsSelect<false> | ConsentLogsSelect<true>;
|
'consent-logs': ConsentLogsSelect<false> | ConsentLogsSelect<true>;
|
||||||
|
|
@ -1897,6 +1899,32 @@ export interface Timeline {
|
||||||
* Highlights werden visuell hervorgehoben
|
* Highlights werden visuell hervorgehoben
|
||||||
*/
|
*/
|
||||||
importance?: ('highlight' | 'normal' | 'minor') | null;
|
importance?: ('highlight' | 'normal' | 'minor') | null;
|
||||||
|
/**
|
||||||
|
* Explizite Nummerierung (optional, sonst wird Reihenfolge verwendet)
|
||||||
|
*/
|
||||||
|
stepNumber?: number | null;
|
||||||
|
/**
|
||||||
|
* z.B. "2-3 Tage", "1 Woche", "30 Minuten"
|
||||||
|
*/
|
||||||
|
duration?: string | null;
|
||||||
|
/**
|
||||||
|
* Person oder Rolle (z.B. "HR-Team", "Projektleiter")
|
||||||
|
*/
|
||||||
|
responsible?: string | null;
|
||||||
|
/**
|
||||||
|
* Wer muss in diesem Schritt aktiv werden?
|
||||||
|
*/
|
||||||
|
actionRequired?: ('customer' | 'internal' | 'both' | 'automatic') | null;
|
||||||
|
/**
|
||||||
|
* Was wird in diesem Schritt erstellt oder benötigt?
|
||||||
|
*/
|
||||||
|
deliverables?:
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
type?: ('output' | 'input' | 'document') | null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
/**
|
/**
|
||||||
* Emoji oder Lucide Icon-Name (z.B. "rocket", "award", "users")
|
* Emoji oder Lucide Icon-Name (z.B. "rocket", "award", "users")
|
||||||
*/
|
*/
|
||||||
|
|
@ -1934,6 +1962,242 @@ export interface Timeline {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Komplexe Prozesse und Workflows mit Phasen, Abhängigkeiten und Status-Tracking
|
||||||
|
*
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "workflows".
|
||||||
|
*/
|
||||||
|
export interface Workflow {
|
||||||
|
id: number;
|
||||||
|
tenant?: (number | null) | Tenant;
|
||||||
|
/**
|
||||||
|
* Name des Workflows (z.B. "Projektablauf Webentwicklung")
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* URL-freundlicher Identifier
|
||||||
|
*/
|
||||||
|
slug: string;
|
||||||
|
/**
|
||||||
|
* Ausführliche Beschreibung des Workflows
|
||||||
|
*/
|
||||||
|
description?: {
|
||||||
|
root: {
|
||||||
|
type: string;
|
||||||
|
children: {
|
||||||
|
type: any;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
direction: ('ltr' | 'rtl') | null;
|
||||||
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
|
indent: number;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
/**
|
||||||
|
* Kurze Zusammenfassung für Übersichten
|
||||||
|
*/
|
||||||
|
shortDescription?: string | null;
|
||||||
|
type: 'project' | 'business' | 'approval' | 'onboarding' | 'support' | 'development' | 'marketing' | 'other';
|
||||||
|
status: 'draft' | 'published' | 'archived';
|
||||||
|
/**
|
||||||
|
* Optionales Bild für den Workflow
|
||||||
|
*/
|
||||||
|
image?: (number | null) | Media;
|
||||||
|
properties?: {
|
||||||
|
/**
|
||||||
|
* z.B. "4-6 Wochen", "3 Monate"
|
||||||
|
*/
|
||||||
|
estimatedDuration?: string | null;
|
||||||
|
complexity?: ('simple' | 'medium' | 'complex' | 'very_complex') | null;
|
||||||
|
/**
|
||||||
|
* Kann der Workflow wiederholt durchlaufen werden?
|
||||||
|
*/
|
||||||
|
isIterative?: boolean | null;
|
||||||
|
/**
|
||||||
|
* Können mehrere Phasen gleichzeitig aktiv sein?
|
||||||
|
*/
|
||||||
|
allowParallelPhases?: boolean | null;
|
||||||
|
};
|
||||||
|
displayOptions?: {
|
||||||
|
layout?: ('vertical' | 'horizontal' | 'flowchart' | 'kanban' | 'gantt') | null;
|
||||||
|
showPhaseNumbers?: boolean | null;
|
||||||
|
showStepNumbers?: boolean | null;
|
||||||
|
showDurations?: boolean | null;
|
||||||
|
showResponsible?: boolean | null;
|
||||||
|
/**
|
||||||
|
* Zeigt Fortschrittsbalken basierend auf abgeschlossenen Schritten
|
||||||
|
*/
|
||||||
|
showProgress?: boolean | null;
|
||||||
|
colorScheme?: ('phase' | 'status' | 'priority' | 'brand') | null;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Hauptabschnitte des Workflows
|
||||||
|
*/
|
||||||
|
phases: {
|
||||||
|
name: string;
|
||||||
|
description?: string | null;
|
||||||
|
/**
|
||||||
|
* Lucide Icon-Name (z.B. "rocket", "settings", "check-circle")
|
||||||
|
*/
|
||||||
|
icon?: string | null;
|
||||||
|
/**
|
||||||
|
* HEX-Farbe (z.B. "#3B82F6") oder Tailwind-Klasse
|
||||||
|
*/
|
||||||
|
color?: string | null;
|
||||||
|
/**
|
||||||
|
* z.B. "1 Woche", "2-3 Tage"
|
||||||
|
*/
|
||||||
|
estimatedDuration?: string | null;
|
||||||
|
/**
|
||||||
|
* Rolle oder Person (z.B. "Projektleiter", "Design-Team")
|
||||||
|
*/
|
||||||
|
responsible?: string | null;
|
||||||
|
/**
|
||||||
|
* Einzelne Schritte in dieser Phase
|
||||||
|
*/
|
||||||
|
steps: {
|
||||||
|
name: string;
|
||||||
|
description?: {
|
||||||
|
root: {
|
||||||
|
type: string;
|
||||||
|
children: {
|
||||||
|
type: any;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
direction: ('ltr' | 'rtl') | null;
|
||||||
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
|
indent: number;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
/**
|
||||||
|
* Für kompakte Ansichten
|
||||||
|
*/
|
||||||
|
shortDescription?: string | null;
|
||||||
|
stepType?: ('task' | 'decision' | 'milestone' | 'approval' | 'wait' | 'automatic') | null;
|
||||||
|
priority?: ('critical' | 'high' | 'normal' | 'low' | 'optional') | null;
|
||||||
|
/**
|
||||||
|
* z.B. "2 Stunden", "1 Tag"
|
||||||
|
*/
|
||||||
|
estimatedDuration?: string | null;
|
||||||
|
responsible?: string | null;
|
||||||
|
icon?: string | null;
|
||||||
|
/**
|
||||||
|
* Welche Schritte müssen vorher abgeschlossen sein?
|
||||||
|
*/
|
||||||
|
dependencies?: {
|
||||||
|
/**
|
||||||
|
* IDs oder Namen der Vorgänger-Schritte (komma-separiert). Leer = vorheriger Schritt
|
||||||
|
*/
|
||||||
|
dependsOnSteps?: string | null;
|
||||||
|
canRunParallel?: boolean | null;
|
||||||
|
/**
|
||||||
|
* Muss abgeschlossen sein, bevor der nächste Schritt beginnt
|
||||||
|
*/
|
||||||
|
isBlocking?: boolean | null;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Für Entscheidungsschritte: Welche Wege gibt es?
|
||||||
|
*/
|
||||||
|
conditions?:
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* z.B. "Wenn genehmigt", "Bei Budget > 10.000€"
|
||||||
|
*/
|
||||||
|
condition: string;
|
||||||
|
/**
|
||||||
|
* ID oder Name des nächsten Schritts
|
||||||
|
*/
|
||||||
|
nextStep?: string | null;
|
||||||
|
/**
|
||||||
|
* z.B. "green" für positiv, "red" für negativ
|
||||||
|
*/
|
||||||
|
color?: string | null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
/**
|
||||||
|
* To-Do-Punkte für diesen Schritt
|
||||||
|
*/
|
||||||
|
checklist?:
|
||||||
|
| {
|
||||||
|
item: string;
|
||||||
|
isRequired?: boolean | null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
resources?:
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
type?: ('document' | 'template' | 'link' | 'tool' | 'video') | null;
|
||||||
|
file?: (number | null) | Media;
|
||||||
|
url?: string | null;
|
||||||
|
description?: string | null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
/**
|
||||||
|
* Was wird in diesem Schritt produziert?
|
||||||
|
*/
|
||||||
|
outputs?:
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
description?: string | null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
/**
|
||||||
|
* Für spezielle Anwendungsfälle
|
||||||
|
*/
|
||||||
|
metadata?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
id?: string | null;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* Was wird am Ende dieser Phase abgeliefert?
|
||||||
|
*/
|
||||||
|
deliverables?:
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
description?: string | null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
id?: string | null;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* Ressourcen, die für den gesamten Workflow relevant sind
|
||||||
|
*/
|
||||||
|
globalResources?:
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
type?: ('document' | 'template' | 'checklist' | 'link' | 'tool') | null;
|
||||||
|
file?: (number | null) | Media;
|
||||||
|
url?: string | null;
|
||||||
|
description?: string | null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
seo?: {
|
||||||
|
metaTitle?: string | null;
|
||||||
|
metaDescription?: string | null;
|
||||||
|
};
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Cookie-Banner Konfiguration pro Tenant
|
* Cookie-Banner Konfiguration pro Tenant
|
||||||
*
|
*
|
||||||
|
|
@ -2591,6 +2855,10 @@ export interface PayloadLockedDocument {
|
||||||
relationTo: 'timelines';
|
relationTo: 'timelines';
|
||||||
value: number | Timeline;
|
value: number | Timeline;
|
||||||
} | null)
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'workflows';
|
||||||
|
value: number | Workflow;
|
||||||
|
} | null)
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'cookie-configurations';
|
relationTo: 'cookie-configurations';
|
||||||
value: number | CookieConfiguration;
|
value: number | CookieConfiguration;
|
||||||
|
|
@ -3699,6 +3967,17 @@ export interface TimelinesSelect<T extends boolean = true> {
|
||||||
};
|
};
|
||||||
category?: T;
|
category?: T;
|
||||||
importance?: T;
|
importance?: T;
|
||||||
|
stepNumber?: T;
|
||||||
|
duration?: T;
|
||||||
|
responsible?: T;
|
||||||
|
actionRequired?: T;
|
||||||
|
deliverables?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
name?: T;
|
||||||
|
type?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
icon?: T;
|
icon?: T;
|
||||||
color?: T;
|
color?: T;
|
||||||
links?:
|
links?:
|
||||||
|
|
@ -3721,6 +4000,128 @@ export interface TimelinesSelect<T extends boolean = true> {
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "workflows_select".
|
||||||
|
*/
|
||||||
|
export interface WorkflowsSelect<T extends boolean = true> {
|
||||||
|
tenant?: T;
|
||||||
|
name?: T;
|
||||||
|
slug?: T;
|
||||||
|
description?: T;
|
||||||
|
shortDescription?: T;
|
||||||
|
type?: T;
|
||||||
|
status?: T;
|
||||||
|
image?: T;
|
||||||
|
properties?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
estimatedDuration?: T;
|
||||||
|
complexity?: T;
|
||||||
|
isIterative?: T;
|
||||||
|
allowParallelPhases?: T;
|
||||||
|
};
|
||||||
|
displayOptions?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
layout?: T;
|
||||||
|
showPhaseNumbers?: T;
|
||||||
|
showStepNumbers?: T;
|
||||||
|
showDurations?: T;
|
||||||
|
showResponsible?: T;
|
||||||
|
showProgress?: T;
|
||||||
|
colorScheme?: T;
|
||||||
|
};
|
||||||
|
phases?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
name?: T;
|
||||||
|
description?: T;
|
||||||
|
icon?: T;
|
||||||
|
color?: T;
|
||||||
|
estimatedDuration?: T;
|
||||||
|
responsible?: T;
|
||||||
|
steps?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
name?: T;
|
||||||
|
description?: T;
|
||||||
|
shortDescription?: T;
|
||||||
|
stepType?: T;
|
||||||
|
priority?: T;
|
||||||
|
estimatedDuration?: T;
|
||||||
|
responsible?: T;
|
||||||
|
icon?: T;
|
||||||
|
dependencies?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
dependsOnSteps?: T;
|
||||||
|
canRunParallel?: T;
|
||||||
|
isBlocking?: T;
|
||||||
|
};
|
||||||
|
conditions?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
condition?: T;
|
||||||
|
nextStep?: T;
|
||||||
|
color?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
checklist?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
item?: T;
|
||||||
|
isRequired?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
resources?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
name?: T;
|
||||||
|
type?: T;
|
||||||
|
file?: T;
|
||||||
|
url?: T;
|
||||||
|
description?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
outputs?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
name?: T;
|
||||||
|
description?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
metadata?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
deliverables?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
name?: T;
|
||||||
|
description?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
globalResources?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
name?: T;
|
||||||
|
type?: T;
|
||||||
|
file?: T;
|
||||||
|
url?: T;
|
||||||
|
description?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
seo?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
metaTitle?: T;
|
||||||
|
metaDescription?: T;
|
||||||
|
};
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "cookie-configurations_select".
|
* via the `definition` "cookie-configurations_select".
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ import { Products } from './collections/Products'
|
||||||
// Timeline Collection
|
// Timeline Collection
|
||||||
import { Timelines } from './collections/Timelines'
|
import { Timelines } from './collections/Timelines'
|
||||||
|
|
||||||
|
// Workflow Collection
|
||||||
|
import { Workflows } from './collections/Workflows'
|
||||||
|
|
||||||
// Consent Management Collections
|
// Consent Management Collections
|
||||||
import { CookieConfigurations } from './collections/CookieConfigurations'
|
import { CookieConfigurations } from './collections/CookieConfigurations'
|
||||||
import { CookieInventory } from './collections/CookieInventory'
|
import { CookieInventory } from './collections/CookieInventory'
|
||||||
|
|
@ -155,8 +158,9 @@ export default buildConfig({
|
||||||
// Products
|
// Products
|
||||||
ProductCategories,
|
ProductCategories,
|
||||||
Products,
|
Products,
|
||||||
// Timelines
|
// Timelines & Workflows
|
||||||
Timelines,
|
Timelines,
|
||||||
|
Workflows,
|
||||||
// Consent Management
|
// Consent Management
|
||||||
CookieConfigurations,
|
CookieConfigurations,
|
||||||
CookieInventory,
|
CookieInventory,
|
||||||
|
|
@ -205,8 +209,9 @@ export default buildConfig({
|
||||||
// Product Collections
|
// Product Collections
|
||||||
'product-categories': {},
|
'product-categories': {},
|
||||||
products: {},
|
products: {},
|
||||||
// Timeline Collection
|
// Timeline & Workflow Collections
|
||||||
timelines: {},
|
timelines: {},
|
||||||
|
workflows: {},
|
||||||
// Consent Management Collections - customTenantField: true weil sie bereits ein tenant-Feld haben
|
// Consent Management Collections - customTenantField: true weil sie bereits ein tenant-Feld haben
|
||||||
'cookie-configurations': { customTenantField: true },
|
'cookie-configurations': { customTenantField: true },
|
||||||
'cookie-inventory': { customTenantField: true },
|
'cookie-inventory': { customTenantField: true },
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue