From a10dd3f18498d4e36fef29318162cde2073fa431 Mon Sep 17 00:00:00 2001 From: Alexander Matyushentsev Date: Thu, 22 Aug 2019 15:53:16 -0700 Subject: [PATCH] Issue #1059 - Use ApplicationParameters panel on ApplicationCreatePanel (#2197) --- .../application-create-panel.tsx | 128 +++++++----------- .../application-parameters.tsx | 12 +- .../applications-list/applications-list.tsx | 6 +- .../editable-panel/editable-panel.tsx | 17 ++- 4 files changed, 79 insertions(+), 84 deletions(-) diff --git a/ui/src/app/applications/components/application-create-panel/application-create-panel.tsx b/ui/src/app/applications/components/application-create-panel/application-create-panel.tsx index d5bd56c871..17d88aa59d 100644 --- a/ui/src/app/applications/components/application-create-panel/application-create-panel.tsx +++ b/ui/src/app/applications/components/application-create-panel/application-create-panel.tsx @@ -1,10 +1,11 @@ import {Checkbox, DataLoader, DropDownMenu, FormField, Select} from 'argo-ui'; import * as deepMerge from 'deepmerge'; import * as React from 'react'; -import {FieldApi, Form, FormApi, FormField as ReactFormField, Text, TextArea} from 'react-form'; -import {AutocompleteField, CheckboxField, clusterTitle, TagsInputField, YamlEditor} from '../../../shared/components'; +import {FieldApi, Form, FormApi, FormField as ReactFormField, Text} from 'react-form'; +import {AutocompleteField, clusterTitle, YamlEditor} from '../../../shared/components'; import * as models from '../../../shared/models'; import {services} from '../../../shared/services'; +import { ApplicationParameters } from '../application-parameters/application-parameters'; const jsonMergePatch = require('json-merge-patch'); @@ -176,80 +177,55 @@ export const ApplicationCreatePanel = (props: { ); const typePanel = () => ( -
- { - if (src.repoURL && src.path) { - return services.repos.appDetails(src.repoURL, src.path, src.targetRevision).catch(() => ({ - type: 'Directory', - details: {}, - })); - } else { - return { - type: 'Directory', - details: {}, - }; - } - }}> - {(details: models.RepoAppDetails) => { - const type = explicitPathType && explicitPathType.path === app.spec.source.path && explicitPathType.type || details.type; - return ( - - (

{type}

)} items={appTypes.map( - (item) => ({ title: item.type, action: () => { - setExplicitPathType({ type: item.type, path: app.spec.source.path }); - normalizeTypeFields(api, item.type); - }}))} - /> - {type === 'Directory' && ( - - ) || type === 'Kustomize' && ( -
- -
- ) || type === 'Ksonnet' && ( -
- -
- ) || type === 'Helm' && ( - -
- -
-
- -
-
- {details.helm && details.helm.values && ( -
- -
{details.helm.values}
-
- )} -
- ) || type === 'Plugin' && ( -
- -
- )} -
- ); - }} -
-
+ { + if (src.repoURL && src.path) { + return services.repos.appDetails(src.repoURL, src.path, src.targetRevision).catch(() => ({ + type: 'Directory', + details: {}, + })); + } else { + return { + type: 'Directory', + details: {}, + }; + } + }}> + {(details: models.RepoAppDetails) => { + const type = explicitPathType && explicitPathType.path === app.spec.source.path && explicitPathType.type || details.type; + if (details.type !== type) { + switch (type) { + case 'Helm': + details = {type, path: details.path, helm: { name: '', valueFiles: [], path: '', parameters: [] } }; + break; + case 'Kustomize': + details = {type, path: details.path, kustomize: { path: '' } }; + break; + case 'Ksonnet': + details = {type, path: details.path, ksonnet: { name: '', path: '', environments: {}, parameters: []} }; + break; + // Directory or Plugin + default: + details = {type, path: details.path, directory: {} }; + break; + } + } + return ( + + (

{type}

)} items={appTypes.map( + (item) => ({ title: item.type, action: () => { + setExplicitPathType({ type: item.type, path: app.spec.source.path }); + normalizeTypeFields(api, item.type); + }}))} + /> + { + api.setAllValues(updatedApp); + }} /> +
+ ); + }} +
); return ( diff --git a/ui/src/app/applications/components/application-parameters/application-parameters.tsx b/ui/src/app/applications/components/application-parameters/application-parameters.tsx index fac214007e..f79489a513 100644 --- a/ui/src/app/applications/components/application-parameters/application-parameters.tsx +++ b/ui/src/app/applications/components/application-parameters/application-parameters.tsx @@ -27,7 +27,7 @@ function overridesFirst(first: { overrideIndex: number}, second: { overrideIndex return first.overrideIndex - second.overrideIndex; } -function getParamsEditableItems( +function getParamsEditableItems( app: models.Application, title: string, fieldsPath: string, @@ -84,7 +84,13 @@ function getParamsEditableItems( }).map((item, i) => ({...item, before: i === 0 &&

{title}

|| null })); } -export const ApplicationParameters = (props: { application: models.Application, details: models.RepoAppDetails, save?: (application: models.Application) => Promise }) => { +export const ApplicationParameters = (props: { + application: models.Application, + details: models.RepoAppDetails, + save?: (application: models.Application) => Promise, + noReadonlyMode?: boolean, +}) => { + const app = props.application; const source = props.application.spec.source; const [removedOverrides, setRemovedOverrides] = React.useState(new Array()); @@ -222,6 +228,6 @@ export const ApplicationParameters = (props: { application: models.Application, await props.save(input); setRemovedOverrides(new Array()); })} - values={app} title={props.details.type.toLocaleUpperCase()} items={attributes} /> + values={app} title={props.details.type.toLocaleUpperCase()} items={attributes} noReadonlyMode={props.noReadonlyMode} /> ); }; diff --git a/ui/src/app/applications/components/applications-list/applications-list.tsx b/ui/src/app/applications/components/applications-list/applications-list.tsx index 2b3782548a..a853571883 100644 --- a/ui/src/app/applications/components/applications-list/applications-list.tsx +++ b/ui/src/app/applications/components/applications-list/applications-list.tsx @@ -252,7 +252,7 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => { )} - ctx.navigation.goto('.', { new: null })} header={ + ctx.navigation.goto('.', { new: null })} header={
}> - {appInput && { + {appInput && { + setCreateApi(api); + }} createApp={ async (app) => { try { await services.applications.create(app); ctx.navigation.goto('.', { new: null }); diff --git a/ui/src/app/shared/components/editable-panel/editable-panel.tsx b/ui/src/app/shared/components/editable-panel/editable-panel.tsx index 5e542ecbe6..08b843ec8e 100644 --- a/ui/src/app/shared/components/editable-panel/editable-panel.tsx +++ b/ui/src/app/shared/components/editable-panel/editable-panel.tsx @@ -21,6 +21,7 @@ export interface EditablePanelProps { save?: (input: T) => Promise; items: EditablePanelItem[]; onModeSwitch?: () => any; + noReadonlyMode?: boolean; } interface EditablePanelState { edit: boolean; saving: boolean; } @@ -33,7 +34,13 @@ export class EditablePanel extends React.Component constructor(props: EditablePanelProps) { super(props); - this.state = { edit: false, saving: false }; + this.state = { edit: !!props.noReadonlyMode, saving: false }; + } + + public UNSAFE_componentWillReceiveProps(nextProps: EditablePanelProps) { + if (JSON.stringify(this.props.values) !== JSON.stringify(nextProps.values)) { + this.formApi.setAllValues(nextProps.values); + } } public render() { @@ -41,7 +48,7 @@ export class EditablePanel extends React.Component {(ctx) => (
- {this.props.save && ( + {!this.props.noReadonlyMode && this.props.save && (
{!this.state.edit && (