argo-cd/ui/src/app/shared/components/editable-panel/editable-panel.tsx
schakrad faa7331f9d
feat: UI write support CMP (#11754) (#12137)
* #11602 fix : Object options menu truncated when selected in ApplicationListView.

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* CMP parameter changes

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* fix: pointers to param values

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

better?

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

fix silliness

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

terrible hacks

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

maybe better codegen

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

fix tests

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* same prefix issue fixed

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* fix for delete param name

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* lint changes

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* lint fix

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* lint fix

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* finalChanges

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* Delete application-resource-list.tsx

Not needed for this PR.

Signed-off-by: schakrad <58915923+schakrad@users.noreply.github.com>

* added file which was deleted as it was not the change needed for this feature.

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* refactored MapValuField and added fix for some edge cases

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* Update application-resource-list.tsx

Reverting the change as this is not related to this PR.

Signed-off-by: schakrad <58915923+schakrad@users.noreply.github.com>

* Reverting the change in application-resource-list

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* Showing application parameter values irrespective of parameter present or not in plugin.yaml

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* fix for lint errors

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* fix false source mismatch

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* fix equals

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* fix swagger doc

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* Tooltip description change.

Signed-off-by: schakrad <chakradari.sindhu@gmail.com>

* fixed lint

Signed-off-by: schakrad <chakradari.sindhu@gmail.com>

* CMP fix for empty array.

Signed-off-by: schakrad <chakradari.sindhu@gmail.com>

---------

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: schakrad <58915923+schakrad@users.noreply.github.com>
Signed-off-by: schakrad <chakradari.sindhu@gmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-03-21 14:39:10 -04:00

166 lines
8.4 KiB
TypeScript

import {ErrorNotification, NotificationType} from 'argo-ui';
import * as classNames from 'classnames';
import * as React from 'react';
import {Form, FormApi} from 'react-form';
import {helpTip} from '../../../applications/components/utils';
import {Consumer} from '../../context';
import {Spinner} from '../spinner';
export interface EditablePanelItem {
title: string;
customTitle?: string | React.ReactNode;
key?: string;
before?: React.ReactNode;
view: string | React.ReactNode;
edit?: (formApi: FormApi) => React.ReactNode;
titleEdit?: (formApi: FormApi) => React.ReactNode;
}
export interface EditablePanelProps<T> {
title?: string | React.ReactNode;
values: T;
validate?: (values: T) => any;
save?: (input: T, query: {validate?: boolean}) => Promise<any>;
items: EditablePanelItem[];
onModeSwitch?: () => any;
noReadonlyMode?: boolean;
view?: string | React.ReactNode;
edit?: (formApi: FormApi) => React.ReactNode;
hasMultipleSources?: boolean;
}
interface EditablePanelState {
edit: boolean;
saving: boolean;
}
require('./editable-panel.scss');
export class EditablePanel<T = {}> extends React.Component<EditablePanelProps<T>, EditablePanelState> {
private formApi: FormApi;
constructor(props: EditablePanelProps<T>) {
super(props);
this.state = {edit: !!props.noReadonlyMode, saving: false};
}
public UNSAFE_componentWillReceiveProps(nextProps: EditablePanelProps<T>) {
if (this.formApi && JSON.stringify(this.props.values) !== JSON.stringify(nextProps.values)) {
if (!!nextProps.noReadonlyMode) {
this.formApi.setAllValues(nextProps.values);
}
}
}
public render() {
return (
<Consumer>
{ctx => (
<div className={classNames('white-box editable-panel', {'editable-panel--disabled': this.state.saving})}>
<div className='white-box__details'>
{!this.props.noReadonlyMode && this.props.save && (
<div className='editable-panel__buttons'>
{!this.state.edit && (
<button
onClick={() => {
this.setState({edit: true});
this.onModeSwitch();
}}
disabled={this.props.hasMultipleSources}
className='argo-button argo-button--base'>
{this.props.hasMultipleSources &&
helpTip('Parameters are not editable for applications with multiple sources. You can edit them in the "Manifest" tab.')}{' '}
Edit
</button>
)}
{this.state.edit && (
<React.Fragment>
<button
disabled={this.state.saving}
onClick={() => !this.state.saving && this.formApi.submitForm(null)}
className='argo-button argo-button--base'>
<Spinner show={this.state.saving} style={{marginRight: '5px'}} />
Save
</button>{' '}
<button
onClick={() => {
this.setState({edit: false});
this.onModeSwitch();
}}
className='argo-button argo-button--base-o'>
Cancel
</button>
</React.Fragment>
)}
</div>
)}
{this.props.title && <p>{this.props.title}</p>}
{(!this.state.edit && (
<React.Fragment>
{this.props.view}
{this.props.items
.filter(item => item.view)
.map(item => (
<React.Fragment key={item.key || item.title}>
{item.before}
<div className='row white-box__details-row'>
<div className='columns small-3'>{item.customTitle || item.title}</div>
<div className='columns small-9'>{item.view}</div>
</div>
</React.Fragment>
))}
</React.Fragment>
)) || (
<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, {});
this.setState({edit: false, saving: false});
this.onModeSwitch();
} catch (e) {
ctx.notifications.show({
content: <ErrorNotification title='Unable to save changes' e={e} />,
type: NotificationType.Error
});
} finally {
this.setState({saving: false});
}
}}
defaultValues={this.props.values}
validateError={this.props.validate}>
{api => (
<React.Fragment>
{this.props.edit && this.props.edit(api)}
{this.props.items.map(item => (
<React.Fragment key={item.key || item.title}>
{item.before}
<div className='row white-box__details-row'>
<div className='columns small-3'>{(item.titleEdit && item.titleEdit(api)) || item.customTitle || item.title}</div>
<div className='columns small-9'>{(item.edit && item.edit(api)) || item.view}</div>
</div>
</React.Fragment>
))}
</React.Fragment>
)}
</Form>
)}
</div>
</div>
)}
</Consumer>
);
}
private onModeSwitch() {
if (this.props.onModeSwitch) {
this.props.onModeSwitch();
}
}
}