import { groupBy, sortBy } from 'lodash'; import React from 'react'; import { Modal } from 'react-bootstrap'; import type { Option } from 'react-select'; import { AccountTag } from '../../../account'; import type { Application } from '../../../application'; import type { IDeployTemplate, ITemplateSelectionText } from './deployInitializer.component'; import type { IServerGroup } from '../../../domain'; import { ModalClose } from '../../../modal'; import { TetheredSelect } from '../../../presentation/TetheredSelect'; import { ReactInjector } from '../../../reactShims'; import type { IServerGroupCommand } from './serverGroupCommandBuilder.service'; import { ServerGroupReader } from '../../serverGroupReader.service'; export interface IDeployInitializerProps { application: Application; cloudProvider: string; command: IServerGroupCommand; onDismiss: () => void; onTemplateSelected: () => void; templateSelectionText?: ITemplateSelectionText; } export interface IDeployInitializerState { selectedTemplate: IDeployTemplate; templates: IDeployTemplate[]; } export class DeployInitializer extends React.Component { private noTemplate: IDeployTemplate = { label: 'None', serverGroup: null, cluster: null }; constructor(props: IDeployInitializerProps) { super(props); const templates: IDeployTemplate[] = []; let selectedTemplate: IDeployTemplate; const { viewState } = props.command; if (!viewState.disableNoTemplateSelection) { templates.push(this.noTemplate); } selectedTemplate = this.noTemplate; const serverGroups: IServerGroup[] = props.application .getDataSource('serverGroups') .data.filter((s: IServerGroup) => s.cloudProvider === props.cloudProvider && s.category === 'serverGroup'); const grouped = groupBy(serverGroups, (serverGroup) => [serverGroup.cluster, serverGroup.account, serverGroup.region].join(':'), ); Object.keys(grouped).forEach((key) => { const latest = sortBy(grouped[key], 'name').pop(); templates.push({ cluster: latest.cluster, account: latest.account, region: latest.region, serverGroupName: latest.name, serverGroup: latest, key: [latest.account, latest.region, latest.name].join(':'), }); }); if (viewState.disableNoTemplateSelection && templates.length === 1) { selectedTemplate = templates[0]; } else if (!viewState.disableNoTemplateSelection && templates.length === 2) { selectedTemplate = templates[1]; } this.state = { selectedTemplate, templates, }; } private applyCommandToScope(command: any) { const { viewState } = command; const baseCommand = this.props.command; viewState.disableImageSelection = true; viewState.showImageSourceSelector = true; viewState.disableStrategySelection = baseCommand.viewState.disableStrategySelection || false; viewState.expectedArtifacts = baseCommand.viewState.expectedArtifacts || []; viewState.imageId = null; viewState.readOnlyFields = baseCommand.viewState.readOnlyFields || {}; viewState.submitButtonLabel = 'Add'; viewState.hideClusterNamePreview = baseCommand.viewState.hideClusterNamePreview || false; viewState.templatingEnabled = true; viewState.imageSourceText = baseCommand.viewState.imageSourceText; Object.assign(command, baseCommand.viewState.overrides || {}); Object.assign(baseCommand, command); } private buildCommandFromTemplate(serverGroup: IServerGroup): PromiseLike { const { application, cloudProvider } = this.props; const commandBuilder: any = ReactInjector.providerServiceDelegate.getDelegate( cloudProvider, 'serverGroup.commandBuilder', ); return ServerGroupReader.getServerGroup( application.name, serverGroup.account, serverGroup.region, serverGroup.name, ).then((details) => { details.account = serverGroup.account; return commandBuilder.buildServerGroupCommandFromExisting(application, details, 'editPipeline'); }); } private buildEmptyCommand = (): PromiseLike => { const { application, cloudProvider } = this.props; const commandBuilder: any = ReactInjector.providerServiceDelegate.getDelegate( cloudProvider, 'serverGroup.commandBuilder', ); return commandBuilder.buildNewServerGroupCommand(application, { mode: 'createPipeline' }); }; private selectTemplate = (): PromiseLike => { const buildCommand = this.state.selectedTemplate === this.noTemplate ? this.buildEmptyCommand() : this.buildCommandFromTemplate(this.state.selectedTemplate.serverGroup); return buildCommand.then((command: any) => this.applyCommandToScope(command)); }; public useTemplate = (): void => { this.selectTemplate().then(() => this.props.onTemplateSelected()); }; public templateChanged = (option: Option) => { this.setState({ selectedTemplate: option as IDeployTemplate }); }; public componentDidMount() { if (this.state.templates.length === 1) { this.useTemplate(); } } public render() { const { command, onDismiss, templateSelectionText } = this.props; const { selectedTemplate, templates } = this.state; return (
Template Selection
Copy configuration from
{command.viewState.customTemplateMessage && (

{command.viewState.customTemplateMessage}

)} {selectedTemplate.serverGroup && templateSelectionText && (
{templateSelectionText.copied.length > 0 && (
These fields will be copied over from the most recent server group:
    {templateSelectionText.copied.map((text, i) => (
  • {text}
  • ))}
)} {templateSelectionText.notCopied.length > 0 && (
These fields will NOT be copied over, and will be reset to defaults:
    {templateSelectionText.notCopied.map((text, i) => (
  • {text}
  • ))}
)} {templateSelectionText.additionalCopyText &&
{templateSelectionText.additionalCopyText}
}
)}
{(selectedTemplate.serverGroup || !command.viewState.disableNoTemplateSelection) && ( )}
); } private templateValueRenderer = (option: Option) => { if (option.label) { return {option.label}; } return ( {option.serverGroup && {option.serverGroupName}} ({option.region}) ); }; private templateOptionRenderer = (option: Option) => { return ( <> {!option.label && (
{option.cluster} ({option.region})
)} {option.label &&
{option.label}
} {option.serverGroup && (
Most recent server group: {option.serverGroupName}
)} ); }; }