argo-cd
110 строк · 5.3 Кб
1import {ErrorNotification, NotificationType} from 'argo-ui';
2import * as jsYaml from 'js-yaml';
3import * as monacoEditor from 'monaco-editor';
4import * as React from 'react';
5
6import {Consumer} from '../../context';
7import {MonacoEditor} from '../monaco-editor';
8
9const jsonMergePatch = require('json-merge-patch');
10require('./yaml-editor.scss');
11
12export class YamlEditor<T> extends React.Component<
13{
14input: T;
15hideModeButtons?: boolean;
16initialEditMode?: boolean;
17vScrollbar?: boolean;
18onSave?: (patch: string, patchType: string) => Promise<any>;
19onCancel?: () => any;
20minHeight?: number;
21},
22{
23editing: boolean;
24}
25> {
26private model: monacoEditor.editor.ITextModel;
27
28constructor(props: any) {
29super(props);
30this.state = {editing: props.initialEditMode};
31}
32
33public render() {
34const props = this.props;
35const yaml = props.input ? jsYaml.safeDump(props.input) : '';
36
37return (
38<div className='yaml-editor'>
39{!props.hideModeButtons && (
40<div className='yaml-editor__buttons'>
41{(this.state.editing && (
42<Consumer>
43{ctx => (
44<React.Fragment>
45<button
46onClick={async () => {
47try {
48const updated = jsYaml.load(this.model.getLinesContent().join('\n'));
49const patch = jsonMergePatch.generate(props.input, updated);
50try {
51const unmounted = await this.props.onSave(JSON.stringify(patch || {}), 'application/merge-patch+json');
52if (unmounted !== true) {
53this.setState({editing: false});
54}
55} catch (e) {
56ctx.notifications.show({
57content: (
58<div className='yaml-editor__error'>
59<ErrorNotification title='Unable to save changes' e={e} />
60</div>
61),
62type: NotificationType.Error
63});
64}
65} catch (e) {
66ctx.notifications.show({
67content: <ErrorNotification title='Unable to validate changes' e={e} />,
68type: NotificationType.Error
69});
70}
71}}
72className='argo-button argo-button--base'>
73Save
74</button>{' '}
75<button
76onClick={() => {
77this.model.setValue(jsYaml.safeDump(props.input));
78this.setState({editing: !this.state.editing});
79if (props.onCancel) {
80props.onCancel();
81}
82}}
83className='argo-button argo-button--base-o'>
84Cancel
85</button>
86</React.Fragment>
87)}
88</Consumer>
89)) || (
90<button onClick={() => this.setState({editing: true})} className='argo-button argo-button--base'>
91Edit
92</button>
93)}
94</div>
95)}
96<MonacoEditor
97minHeight={props.minHeight}
98vScrollBar={props.vScrollbar}
99editor={{
100input: {text: yaml, language: 'yaml'},
101options: {readOnly: !this.state.editing, minimap: {enabled: false}},
102getApi: api => {
103this.model = api.getModel() as monacoEditor.editor.ITextModel;
104}
105}}
106/>
107</div>
108);
109}
110}
111