52 lines
3.8 KiB
TypeScript
52 lines
3.8 KiB
TypeScript
import {useState} from 'react'
|
|
import {Braces, PanelsTopLeft} from 'lucide-react'
|
|
import {validateAslDefinition, workflowCreateSubmission, type WorkflowCreateSubmission} from '@/lib/workflowCreate'
|
|
|
|
type CreationMode = 'studio' | 'asl'
|
|
|
|
export function WorkflowCreatePanel({isSubmitting, submitError, onCancel, onSubmit}: {isSubmitting: boolean; submitError: string | null; onCancel: () => void; onSubmit: (submission: WorkflowCreateSubmission) => void}) {
|
|
const [mode, setMode] = useState<CreationMode>('studio')
|
|
const [name, setName] = useState('')
|
|
const [definition, setDefinition] = useState('')
|
|
const [definitionError, setDefinitionError] = useState<string | null>(null)
|
|
const validName = /^[a-zA-Z0-9_-]{1,80}$/.test(name.trim())
|
|
|
|
return <form className="dynamic-form" onSubmit={(event) => {
|
|
event.preventDefault()
|
|
if (!validName) return
|
|
if (mode === 'asl') {
|
|
const error = validateAslDefinition(definition)
|
|
setDefinitionError(error)
|
|
if (error) return
|
|
onSubmit(workflowCreateSubmission(name, 'explorer', definition))
|
|
return
|
|
}
|
|
onSubmit(workflowCreateSubmission(name, 'studio'))
|
|
}}>
|
|
<div className="workflow-create-modes" role="group" aria-label="Creation mode">
|
|
<button className={`workflow-create-mode${mode === 'studio' ? ' active' : ''}`} type="button" aria-pressed={mode === 'studio'} disabled={isSubmitting} onClick={() => { setMode('studio'); setDefinitionError(null) }}>
|
|
<PanelsTopLeft size={18}/><span><strong>Workflow Studio</strong><small>Create a valid starter workflow, then design it visually.</small></span>
|
|
</button>
|
|
<button className={`workflow-create-mode${mode === 'asl' ? ' active' : ''}`} type="button" aria-pressed={mode === 'asl'} disabled={isSubmitting} onClick={() => setMode('asl')}>
|
|
<Braces size={18}/><span><strong>ASL definition</strong><small>Create directly from a complete Amazon States Language document.</small></span>
|
|
</button>
|
|
</div>
|
|
<label className="dynamic-field dynamic-field--span">
|
|
<span>State Machine Name<em className="field-required">*</em></span>
|
|
<input className="input" autoFocus value={name} disabled={isSubmitting} onChange={(event) => setName(event.target.value)} maxLength={80} required pattern="[a-zA-Z0-9_-]+" aria-describedby="workflow-name-help"/>
|
|
<small id="workflow-name-help">Up to 80 characters: letters, digits, hyphens, and underscores.</small>
|
|
</label>
|
|
{mode === 'asl' && <label className="dynamic-field dynamic-field--span">
|
|
<span>ASL Definition<em className="field-required">*</em></span>
|
|
<textarea className={`textarea workflow-definition-input${definitionError ? ' invalid' : ''}`} value={definition} disabled={isSubmitting} onChange={(event) => { setDefinition(event.target.value); setDefinitionError(null) }} rows={14} spellCheck={false} aria-describedby="workflow-definition-help workflow-definition-error"/>
|
|
<small id="workflow-definition-help">Enter the complete JSON definition. It must contain a string <code>StartAt</code> and an object <code>States</code>.</small>
|
|
{definitionError && <small className="field-error" id="workflow-definition-error" role="alert">{definitionError}</small>}
|
|
</label>}
|
|
{submitError && <p className="error-text" role="alert">{submitError}</p>}
|
|
<div className="form-actions">
|
|
<button className="button" type="button" disabled={isSubmitting} onClick={onCancel}>Cancel</button>
|
|
<button className="button primary" type="submit" disabled={!validName || isSubmitting}>{isSubmitting ? 'Creating' : mode === 'studio' ? 'Create and open Studio' : 'Create state machine'}</button>
|
|
</div>
|
|
</form>
|
|
}
|