Add support for extending configs to the Settings UI (#268)

pull/374/head
Kelvin Schoofs 2 years ago
parent 796d1c245b
commit a5372a4d88

@ -36,6 +36,8 @@
- Start screen of Settings UI will use the cached list of configs instead of reloading them - Start screen of Settings UI will use the cached list of configs instead of reloading them
- This should make navigating to the start screen (especially when navigating back and forth between configs) faster - This should make navigating to the start screen (especially when navigating back and forth between configs) faster
- The Refresh button is now renamed to Reload and will still reload the configs (from disk, remote workspaces, ...) - The Refresh button is now renamed to Reload and will still reload the configs (from disk, remote workspaces, ...)
- Add support for extending configs to the Settings UI (#268)
- This adds a visual editor to the Settings UI for the `extend` config option
### Development changes ### Development changes

@ -89,7 +89,7 @@ export interface FileSystemConfig extends ConnectConfig {
group?: string; group?: string;
/** Whether to merge this "lower" config (e.g. from workspace settings) into higher configs (e.g. from global settings) */ /** Whether to merge this "lower" config (e.g. from workspace settings) into higher configs (e.g. from global settings) */
merge?: boolean; merge?: boolean;
/** Names of other configs to merge into this config. Errors if not found. Later entries have priority. Settings defined in this config itself have even higher priority */ /** Names of other existing configs to merge into this config. Earlier entries overridden by later entries overridden by this config itself */
extend?: string | string[]; extend?: string | string[];
/** Path on the remote server that should be opened by default when creating a terminal or using the `Add as Workspace folder` command/button. Defaults to `/` */ /** Path on the remote server that should be opened by default when creating a terminal or using the `Add as Workspace folder` command/button. Defaults to `/` */
root?: string; root?: string;

@ -3,6 +3,7 @@ import * as React from 'react';
import { FieldCheckbox } from '../FieldTypes/checkbox'; import { FieldCheckbox } from '../FieldTypes/checkbox';
import { FieldDropdown } from '../FieldTypes/dropdown'; import { FieldDropdown } from '../FieldTypes/dropdown';
import { FieldDropdownWithInput } from '../FieldTypes/dropdownwithinput'; import { FieldDropdownWithInput } from '../FieldTypes/dropdownwithinput';
import { FieldConfigList } from '../FieldTypes/list';
import { FieldNumber } from '../FieldTypes/number'; import { FieldNumber } from '../FieldTypes/number';
import { FieldPath } from '../FieldTypes/path'; import { FieldPath } from '../FieldTypes/path';
import { FieldString } from '../FieldTypes/string'; import { FieldString } from '../FieldTypes/string';
@ -27,14 +28,6 @@ export function name(config: FileSystemConfig, onChange: FSCChanged<'name'>): Re
return <FieldString key="name" label="Name" value={config.name} onChange={callback} validator={invalidConfigName} description={description} /> return <FieldString key="name" label="Name" value={config.name} onChange={callback} validator={invalidConfigName} description={description} />
} }
export function merge(config: FileSystemConfig, onChange: FSCChanged<'merge'>): React.ReactElement {
const callback = (newValue: string) => onChange('merge', newValue === 'Yes' || undefined);
const description = 'Whether to merge this "lower" config (e.g. from workspace settings) into higher configs (e.g. from global settings)';
const values = ['Yes', 'No'];
const value = config.merge ? 'Yes' : 'No';
return <FieldDropdown key="merge" label="Merge" {...{ value, values, description }} onChange={callback} />
}
export function label(config: FileSystemConfig, onChange: FSCChanged<'label'>): React.ReactElement { export function label(config: FileSystemConfig, onChange: FSCChanged<'label'>): React.ReactElement {
const callback = (newValue?: string) => onChange('label', newValue); const callback = (newValue?: string) => onChange('label', newValue);
const description = 'Label to display in some UI places (e.g. popups)'; const description = 'Label to display in some UI places (e.g. popups)';
@ -47,6 +40,21 @@ export function group(config: FileSystemConfig, onChange: FSCChanged<'group'>):
return <FieldConfigGroup key="group" label="Group" value={config.group} {...{ description }} onChange={callback} optional /> return <FieldConfigGroup key="group" label="Group" value={config.group} {...{ description }} onChange={callback} optional />
} }
export function merge(config: FileSystemConfig, onChange: FSCChanged<'merge'>): React.ReactElement {
const callback = (newValue: string) => onChange('merge', newValue === 'Yes' || undefined);
const description = 'Whether to merge this "lower" config (e.g. from workspace settings) into higher configs (e.g. from global settings)';
const values = ['Yes', 'No'];
const value = config.merge ? 'Yes' : 'No';
return <FieldDropdown key="merge" label="Merge" {...{ value, values, description }} onChange={callback} />
}
export function extend(config: FileSystemConfig, onChange: FSCChanged<'extend'>): React.ReactElement {
const callback = (newValue?: string | string[]) => onChange('extend', newValue);
const description = 'Names of other existing configs to merge into this config. Earlier entries overridden by later entries overridden by this config itself';
const value = typeof config.extend === 'string' ? [config.extend] : config.extend;
return <FieldConfigList key="extend" label="Extend" {...{ value, description }} onChange={callback} optional freeText />
}
export function putty(config: FileSystemConfig, onChange: FSCChanged<'putty'>): React.ReactElement { export function putty(config: FileSystemConfig, onChange: FSCChanged<'putty'>): React.ReactElement {
const callback = (newValue: string) => onChange('putty', newValue === '<Auto-detect>' ? true : newValue); const callback = (newValue: string) => onChange('putty', newValue === '<Auto-detect>' ? true : newValue);
const description = 'A name of a PuTTY session, or `true` to find the PuTTY session from the host address'; const description = 'A name of a PuTTY session, or `true` to find the PuTTY session from the host address';
@ -163,7 +171,7 @@ export function taskCommand(config: FileSystemConfig, onChange: FSCChanged<'task
export type FieldFactory = (config: FileSystemConfig, onChange: FSCChanged, onChangeMultiple: FSCChangedMultiple) => React.ReactElement | null; export type FieldFactory = (config: FileSystemConfig, onChange: FSCChanged, onChangeMultiple: FSCChangedMultiple) => React.ReactElement | null;
export const FIELDS: FieldFactory[] = [ export const FIELDS: FieldFactory[] = [
name, merge, label, group, putty, host, port, name, label, group, merge, extend, putty, host, port,
root, agent, username, password, privateKeyPath, passphrase, root, agent, username, password, privateKeyPath, passphrase,
newFileMode, agentForward, sftpCommand, sftpSudo, terminalCommand, taskCommand, newFileMode, agentForward, sftpCommand, sftpSudo, terminalCommand, taskCommand,
PROXY_FIELD]; PROXY_FIELD];

Loading…
Cancel
Save