import classNames from 'classnames'; import type { FormikProps } from 'formik'; import { isEqual, pick } from 'lodash'; import React from 'react'; import type { Option } from 'react-select'; import { RunAsUserInput } from './RunAsUser'; import type { Application } from '../../../application'; import { TriggerArtifactConstraintSelectorInput } from './artifacts'; import { SETTINGS } from '../../../config/settings'; import type { IExpectedArtifact, IPipeline, ITrigger, ITriggerTypeConfig } from '../../../domain'; import { HelpField } from '../../../help/HelpField'; import type { IFormInputProps } from '../../../presentation'; import { CheckboxInput, FormField, FormikFormField, ReactSelectInput, SpinFormik, Tooltip, ValidationMessage, WatchValue, } from '../../../presentation'; import { Registry } from '../../../registry'; import './Trigger.less'; export interface ITriggerProps { application: Application; index: number; pipeline: IPipeline; removeTrigger: (index: number) => void; triggerInitialValues: ITrigger; updateTrigger: (index: number, changes: { [key: string]: any }) => void; addExpectedArtifact: (artifact: IExpectedArtifact) => void; updateExpectedArtifact: (artifact: IExpectedArtifact) => void; removeExpectedArtifact: (artifact: IExpectedArtifact) => void; } export const Trigger = (props: ITriggerProps) => { function getValidateFn() { const triggerType = Registry.pipeline .getTriggerTypes() .find((type) => type.key === props.triggerInitialValues.type); const validateWithContext = (values: ITrigger) => triggerType.validateFn(values, { pipeline: props.pipeline }); return triggerType && triggerType.validateFn ? validateWithContext : undefined; } return ( onSubmit={() => null} initialValues={props.triggerInitialValues} validate={getValidateFn()} render={(formik) => } /> ); }; const commonTriggerFields: Array = [ 'enabled', 'rebake', 'user', 'type', 'expectedArtifactIds', 'runAsUser', 'excludedArtifactTypePatterns', ]; function TriggerForm(triggerFormProps: ITriggerProps & { formik: FormikProps }) { const { formik, pipeline, index, updateTrigger, addExpectedArtifact, updateExpectedArtifact, removeExpectedArtifact, } = triggerFormProps; const trigger = formik.values as Readonly; const { type } = trigger; const triggerTypes = React.useMemo(() => Registry.pipeline.getTriggerTypes(), []); const triggerConfig = React.useMemo(() => triggerTypes.find((x) => x.key === trigger.type), [ triggerTypes, trigger.type, ]); const disableAutoTriggering = SETTINGS.disableAutoTriggering || []; // Clear out all non-common fields when the type is changed const handleTypeChange = (newType: string) => { const newValues = pick(trigger, commonTriggerFields) as ITrigger; newValues.enabled = disableAutoTriggering.includes(newType) ? false : trigger.enabled; newValues.type = newType; formik.setValues(newValues); }; const updateTriggerFields = (changes: { [key: string]: any }) => { const updatedTrigger = { ...trigger, ...changes }; formik.setValues(updatedTrigger); }; const updateTriggerExpectedArtifacts = (availableExpectedArtifactIds: string[]) => { formik.setFieldValue( 'expectedArtifactIds', (trigger.expectedArtifactIds || []).filter((artifactId) => availableExpectedArtifactIds.includes(artifactId)), ); }; const triggerComponentProps = { ...triggerFormProps, trigger: formik.values, formik, pipelineId: pipeline.id, triggerUpdated: updateTriggerFields, }; const EmptyComponent = () => <>; // The actual trigger component for the specific trigger type const TriggerComponent = (triggerConfig && triggerConfig.component) || EmptyComponent; const showRunAsUser = SETTINGS.feature.fiatEnabled && !SETTINGS.feature.managedServiceAccounts; const fieldSetClassName = classNames({ 'templated-pipeline-item': trigger.inherited, Trigger: true }); const availableExpectedArtifacts = pipeline.expectedArtifacts || []; const availableExpectedArtifactIds = availableExpectedArtifacts.map((a) => a.id); return (
updateTrigger(index, updatedTrigger)} />
) : ( triggerFormProps.removeTrigger(index)} /> ) } value={trigger.type} onChange={(e) => handleTypeChange(e.target.value)} input={(props) => } /> {showRunAsUser && ( } input={(props) => } /> )} } input={(props) => ( )} /> {type && disableAutoTriggering.includes(type) && } {type && !disableAutoTriggering.includes(type) && ( formik.setFieldValue('enabled', !trigger.enabled)} input={(props) => ( )} /> )}
); } function TriggerTypeSelectInput(props: IFormInputProps & { triggerConfig: ITriggerTypeConfig }) { const triggerTypes = Registry.pipeline .getTriggerTypes() .map((t) => ({ label: t.label, value: t.key, description: t.description })); const optionRenderer = (option: Option) => (

{option.label} {option.description}

); return ; } function RemoveTriggerButton(props: { onClick: () => void }) { return ( ); } function AutoTriggeringDisabledMessage() { const message = 'Automatic triggering is disabled for this trigger type. ' + 'You can still use this as a trigger to supply data ' + 'to downstream stages, but will need to manually execute this pipeline.'; return } />; } function FromTemplateMessage() { return ( From Template ); }