mirror of
https://github.com/argoproj/argo-cd
synced 2026-05-23 01:08:33 +00:00
This commit is contained in:
parent
f9286cfab9
commit
a10dd3f184
4 changed files with 79 additions and 84 deletions
|
|
@ -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 = () => (
|
||||
<div className='white-box'>
|
||||
<DataLoader
|
||||
input={{repoURL: app.spec.source.repoURL, path: app.spec.source.path, targetRevision: app.spec.source.targetRevision }}
|
||||
load={async (src) => {
|
||||
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 (
|
||||
<React.Fragment>
|
||||
<DropDownMenu anchor={() => (<p>{type} <i className='fa fa-caret-down'/></p>)} items={appTypes.map(
|
||||
(item) => ({ title: item.type, action: () => {
|
||||
setExplicitPathType({ type: item.type, path: app.spec.source.path });
|
||||
normalizeTypeFields(api, item.type);
|
||||
}}))}
|
||||
/>
|
||||
{type === 'Directory' && (
|
||||
<FormField formApi={api}
|
||||
label='Include subdirectories' field='spec.source.directory.recurse' component={CheckboxField}/>
|
||||
) || type === 'Kustomize' && (
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={api} label='Name Prefix' field='spec.source.kustomize.namePrefix' component={Text} />
|
||||
</div>
|
||||
) || type === 'Ksonnet' && (
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={api} label='Environment' field='spec.source.ksonnet.environment'
|
||||
component={AutocompleteField} componentProps={{
|
||||
items: details.ksonnet && Object.keys(details.ksonnet.environments) || [],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) || type === 'Helm' && (
|
||||
<React.Fragment>
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={api} label='Values Files'
|
||||
field='spec.source.helm.valueFiles'
|
||||
componentProps={{
|
||||
options: details.helm && details.helm.valueFiles,
|
||||
noTagsLabel: 'No values files selected',
|
||||
}} component={TagsInputField}/>
|
||||
</div>
|
||||
<div className='argo-form-row'>
|
||||
<label>Values</label>
|
||||
<pre><FormField formApi={api}
|
||||
field='spec.source.helm.values'
|
||||
component={TextArea}/></pre>
|
||||
</div>
|
||||
{details.helm && details.helm.values && (
|
||||
<div className='argo-form-row'>
|
||||
<label>values.yaml</label>
|
||||
<pre>{details.helm.values}</pre>
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
) || type === 'Plugin' && (
|
||||
<div className='argo-form-row'>
|
||||
<FormField formApi={api} label='Name' field='spec.source.plugin.name' component={Text} />
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
}}
|
||||
</DataLoader>
|
||||
</div>
|
||||
<DataLoader
|
||||
input={{repoURL: app.spec.source.repoURL, path: app.spec.source.path, targetRevision: app.spec.source.targetRevision }}
|
||||
load={async (src) => {
|
||||
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 (
|
||||
<React.Fragment>
|
||||
<DropDownMenu anchor={() => (<p>{type} <i className='fa fa-caret-down'/></p>)} items={appTypes.map(
|
||||
(item) => ({ title: item.type, action: () => {
|
||||
setExplicitPathType({ type: item.type, path: app.spec.source.path });
|
||||
normalizeTypeFields(api, item.type);
|
||||
}}))}
|
||||
/>
|
||||
<ApplicationParameters noReadonlyMode={true} application={app} details={details} save={async (updatedApp) => {
|
||||
api.setAllValues(updatedApp);
|
||||
}} />
|
||||
</React.Fragment>
|
||||
);
|
||||
}}
|
||||
</DataLoader>
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ function overridesFirst(first: { overrideIndex: number}, second: { overrideIndex
|
|||
return first.overrideIndex - second.overrideIndex;
|
||||
}
|
||||
|
||||
function getParamsEditableItems<T extends { name: string, value: string }>(
|
||||
function getParamsEditableItems(
|
||||
app: models.Application,
|
||||
title: string,
|
||||
fieldsPath: string,
|
||||
|
|
@ -84,7 +84,13 @@ function getParamsEditableItems<T extends { name: string, value: string }>(
|
|||
}).map((item, i) => ({...item, before: i === 0 && <p style={{ marginTop: '1em' }}>{title}</p> || null }));
|
||||
}
|
||||
|
||||
export const ApplicationParameters = (props: { application: models.Application, details: models.RepoAppDetails, save?: (application: models.Application) => Promise<any> }) => {
|
||||
export const ApplicationParameters = (props: {
|
||||
application: models.Application,
|
||||
details: models.RepoAppDetails,
|
||||
save?: (application: models.Application) => Promise<any>,
|
||||
noReadonlyMode?: boolean,
|
||||
}) => {
|
||||
|
||||
const app = props.application;
|
||||
const source = props.application.spec.source;
|
||||
const [removedOverrides, setRemovedOverrides] = React.useState(new Array<boolean>());
|
||||
|
|
@ -222,6 +228,6 @@ export const ApplicationParameters = (props: { application: models.Application,
|
|||
await props.save(input);
|
||||
setRemovedOverrides(new Array<boolean>());
|
||||
})}
|
||||
values={app} title={props.details.type.toLocaleUpperCase()} items={attributes} />
|
||||
values={app} title={props.details.type.toLocaleUpperCase()} items={attributes} noReadonlyMode={props.noReadonlyMode} />
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => {
|
|||
</DataLoader>
|
||||
)}
|
||||
</ObservableQuery>
|
||||
<SlidingPanel isMiddle={true} isShown={!!appInput} onClose={() => ctx.navigation.goto('.', { new: null })} header={
|
||||
<SlidingPanel isShown={!!appInput} onClose={() => ctx.navigation.goto('.', { new: null })} header={
|
||||
<div>
|
||||
<button className='argo-button argo-button--base'
|
||||
onClick={() => createApi && createApi.submitForm(null)}>
|
||||
|
|
@ -262,7 +262,9 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => {
|
|||
</button>
|
||||
</div>
|
||||
}>
|
||||
{appInput && <ApplicationCreatePanel getFormApi={setCreateApi} createApp={ async (app) => {
|
||||
{appInput && <ApplicationCreatePanel getFormApi={(api) => {
|
||||
setCreateApi(api);
|
||||
}} createApp={ async (app) => {
|
||||
try {
|
||||
await services.applications.create(app);
|
||||
ctx.navigation.goto('.', { new: null });
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export interface EditablePanelProps<T> {
|
|||
save?: (input: T) => Promise<any>;
|
||||
items: EditablePanelItem[];
|
||||
onModeSwitch?: () => any;
|
||||
noReadonlyMode?: boolean;
|
||||
}
|
||||
|
||||
interface EditablePanelState { edit: boolean; saving: boolean; }
|
||||
|
|
@ -33,7 +34,13 @@ export class EditablePanel<T = {}> extends React.Component<EditablePanelProps<T>
|
|||
|
||||
constructor(props: EditablePanelProps<T>) {
|
||||
super(props);
|
||||
this.state = { edit: false, saving: false };
|
||||
this.state = { edit: !!props.noReadonlyMode, saving: false };
|
||||
}
|
||||
|
||||
public UNSAFE_componentWillReceiveProps(nextProps: EditablePanelProps<T>) {
|
||||
if (JSON.stringify(this.props.values) !== JSON.stringify(nextProps.values)) {
|
||||
this.formApi.setAllValues(nextProps.values);
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
@ -41,7 +48,7 @@ export class EditablePanel<T = {}> extends React.Component<EditablePanelProps<T>
|
|||
<Consumer>{(ctx) => (
|
||||
<div className={classNames('white-box editable-panel', {'editable-panel--disabled': this.state.saving})}>
|
||||
<div className='white-box__details'>
|
||||
{this.props.save && (
|
||||
{!this.props.noReadonlyMode && this.props.save && (
|
||||
<div className='editable-panel__buttons'>
|
||||
{!this.state.edit && (
|
||||
<button onClick={() => {
|
||||
|
|
@ -78,7 +85,11 @@ export class EditablePanel<T = {}> extends React.Component<EditablePanelProps<T>
|
|||
))}
|
||||
</React.Fragment>
|
||||
) || (
|
||||
<Form getApi={(api) => this.formApi = api} onSubmit={async (input) => {
|
||||
<Form getApi={(api) => this.formApi = api} formDidUpdate={async (form) => {
|
||||
if (this.props.noReadonlyMode && this.props.save) {
|
||||
await this.props.save(form.values as any);
|
||||
}
|
||||
}} onSubmit={async (input) => {
|
||||
try {
|
||||
this.setState({ saving: true });
|
||||
await this.props.save(input as any);
|
||||
|
|
|
|||
Loading…
Reference in a new issue