diff --git a/web/src/components/projects/integration-form.tsx b/web/src/components/projects/integration-form.tsx index 0a752bc7..0db0b7fa 100644 --- a/web/src/components/projects/integration-form.tsx +++ b/web/src/components/projects/integration-form.tsx @@ -156,6 +156,141 @@ function CredentialSelector({ ); } +// ============================================================================ +// Known key constants for constrained editors +// ============================================================================ + +interface KeyOption { + value: string; + label: string; +} + +const TRELLO_LIST_KEYS: KeyOption[] = [ + { value: 'briefing', label: 'briefing' }, + { value: 'stories', label: 'stories' }, + { value: 'planning', label: 'planning' }, + { value: 'todo', label: 'todo' }, + { value: 'inProgress', label: 'inProgress' }, + { value: 'inReview', label: 'inReview' }, + { value: 'done', label: 'done' }, + { value: 'merged', label: 'merged' }, + { value: 'debug', label: 'debug' }, +]; + +const TRELLO_LABEL_KEYS: KeyOption[] = [ + { value: 'readyToProcess', label: 'readyToProcess' }, + { value: 'processing', label: 'processing' }, + { value: 'processed', label: 'processed' }, + { value: 'error', label: 'error' }, +]; + +const JIRA_STATUS_KEYS: KeyOption[] = [ + { value: 'briefing', label: 'briefing' }, + { value: 'planning', label: 'planning' }, + { value: 'todo', label: 'todo' }, + { value: 'inProgress', label: 'inProgress' }, + { value: 'inReview', label: 'inReview' }, + { value: 'done', label: 'done' }, + { value: 'merged', label: 'merged' }, +]; + +const JIRA_LABEL_KEYS: KeyOption[] = [ + { value: 'processing', label: 'processing' }, + { value: 'processed', label: 'processed' }, + { value: 'error', label: 'error' }, + { value: 'readyToProcess', label: 'readyToProcess' }, +]; + +// ============================================================================ +// ConstrainedKeyValueEditor — key column is a dropdown of allowed keys +// ============================================================================ + +function ConstrainedKeyValueEditor({ + label, + pairs, + onChange, + allowedKeys, + valuePlaceholder, +}: { + label: string; + pairs: KVPair[]; + onChange: (pairs: KVPair[]) => void; + allowedKeys: KeyOption[]; + valuePlaceholder?: string; +}) { + const usedKeys = new Set(pairs.map((p) => p.key)); + const availableKeys = allowedKeys.filter((k) => !usedKeys.has(k.value)); + const allUsed = availableKeys.length === 0; + + const handleAdd = () => { + // Pick the first unused allowed key, or empty string if all used + const firstAvailable = availableKeys[0]?.value ?? ''; + onChange([...pairs, { key: firstAvailable, value: '' }]); + }; + + return ( +
No entries
} +- Map CASCADE statuses (briefing, planning, todo, inProgress, inReview, done, merged) to - JIRA status names. + Map each CASCADE status key to the corresponding JIRA status name.
- JIRA label names used by CASCADE. Keys: processing, processed, error, readyToProcess. + Map each CASCADE label key to the corresponding JIRA label name.