Skip to content

Commit

Permalink
feat(ui): Change default language for Resource Editor to YAML and sto…
Browse files Browse the repository at this point in the history
…re preference in localStorage. Fixes #3543 (#3560)
  • Loading branch information
rbreeze committed Jul 23, 2020
1 parent c583bc0 commit 1b757ea
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 40 deletions.
90 changes: 58 additions & 32 deletions ui/src/app/shared/components/resource-editor/resource-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,36 @@ interface Props<T> {

interface State {
editing: boolean;
type: string;
lang: string;
value: string;
error?: Error;
}

const LOCAL_STORAGE_KEY = 'ResourceEditorLang';

export class ResourceEditor<T> extends React.Component<Props<T>, State> {
constructor(props: Readonly<Props<T>>) {
super(props);
this.state = {editing: this.props.editing, type: 'json', value: stringify(this.props.value, 'json')};
private set lang(lang: string) {
this.setState({lang, value: stringify(parse(this.state.value), lang)});
}

private static saveLang(newLang: string) {
localStorage.setItem(LOCAL_STORAGE_KEY, newLang);
}

private set type(type: string) {
this.setState({type, value: stringify(parse(this.state.value), type)});
private static loadLang(): string {
const stored = localStorage.getItem(LOCAL_STORAGE_KEY);
if (stored !== null) {
if (stored === 'yaml' || stored === 'json') {
return stored;
}
}
return 'yaml';
}

constructor(props: Readonly<Props<T>>) {
super(props);
const storedLang = ResourceEditor.loadLang();
this.state = {editing: this.props.editing, lang: storedLang, value: stringify(this.props.value, storedLang)};
}

public componentDidMount() {
Expand Down Expand Up @@ -60,14 +77,14 @@ export class ResourceEditor<T> extends React.Component<Props<T>, State> {

public componentDidUpdate(prevProps: Props<T>) {
if (prevProps.value !== this.props.value) {
this.setState({value: stringify(this.props.value, this.state.type)});
this.setState({value: stringify(this.props.value, this.state.lang)});
}
}

public handleFiles(files: FileList) {
files[0]
.text()
.then(value => this.setState({value: stringify(parse(value), this.state.type)}))
.then(value => this.setState({value: stringify(parse(value), this.state.lang)}))
.catch(error => this.setState(error));
}

Expand All @@ -81,38 +98,46 @@ export class ResourceEditor<T> extends React.Component<Props<T>, State> {
<i className='fa fa-exclamation-triangle status-icon--failed' /> {this.state.error.message}
</p>
)}
<MonacoEditor
value={this.state.value}
language={this.state.type}
height={'600px'}
onChange={value => this.setState({value})}
options={{
readOnly: !this.state.editing,
extraEditorClassName: 'resource',
minimap: {enabled: false},
lineNumbers: 'off',
renderIndentGuides: false
}}
/>
{this.renderFooter()}
<div className='resource-editor-panel__editor'>
<MonacoEditor
value={this.state.value}
language={this.state.lang}
height={'600px'}
onChange={value => this.setState({value})}
options={{
readOnly: !this.state.editing,
extraEditorClassName: 'resource',
minimap: {enabled: false},
lineNumbers: 'off',
renderIndentGuides: false
}}
/>
</div>
{this.renderWarning()}
</>
);
}

private changeLang() {
const newLang = this.state.lang === 'yaml' ? 'json' : 'yaml';
this.lang = newLang;
ResourceEditor.saveLang(newLang);
}

private renderButtons() {
return (
<div>
{(this.state.editing && (
<>
<label className='argo-button argo-button--base-o'>
<input type={'checkbox'} checked={this.state.type === 'yaml'} onChange={e => (this.type = e.target.checked ? 'yaml' : 'json')} /> YAML
</label>{' '}
<label className={`argo-button argo-button--base-o ${this.state.lang}`} style={{marginRight: '5px'}} onClick={e => this.changeLang()}>
{this.state.lang === 'yaml' ? <i className='fa fa-check' /> : <i className='fa fa-times' />} YAML
</label>
{this.props.upload && (
<label className='argo-button argo-button--base-o'>
<input type='file' onChange={e => this.handleFiles(e.target.files)} style={{display: 'none'}} />
<i className='fa fa-upload' /> Upload file
</label>
)}{' '}
)}
<button onClick={() => this.submit()} className='argo-button argo-button--base'>
<i className='fa fa-plus' /> Submit
</button>
Expand All @@ -135,11 +160,12 @@ export class ResourceEditor<T> extends React.Component<Props<T>, State> {
}
}

private renderFooter() {
return this.state.editing ? (
<small>
<i className='fa fa-info-circle' /> {this.state.type === 'json' ? <>Full auto-completion</> : <>Basic completion</>} for {this.state.type.toUpperCase()}
</small>
) : null;
private renderWarning() {
return (
<div style={{marginTop: '1em'}}>
<i className='fa fa-info-circle' /> Note:{' '}
{this.state.lang === 'json' ? <>Full auto-completion enabled</> : <>Basic completion for YAML. Switch to JSON for full auto-completion.</>}
</div>
);
}
}
21 changes: 13 additions & 8 deletions ui/src/app/shared/components/resource-editor/resource.scss
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
@import 'node_modules/argo-ui/src/styles/config';

.resource {
margin: 10px 0;
padding: 10px 5px;
font: normal 13px/1.2 'Courier New', monospace;
padding-top: 1em;
white-space: pre;
color: $argo-color-gray-7;
border-color: $argo-color-gray-2;;
border-width: thin;
border-style: inset;
overflow-y: scroll;
width: 100%;
min-height: 300px;
}
}

.resource-editor-panel {
&__editor {
border: 1px solid $argo-color-gray-3;
border-radius: 5px;
margin-top: 1em;
padding-bottom: 1em;
overflow: hidden;
}
}

0 comments on commit 1b757ea

Please sign in to comment.