Re-add Configure/New command (+ UI navigation/ConfigLocator)

feature/search
Kelvin Schoofs 6 years ago
parent 517a31301e
commit 4a98297155

@ -83,8 +83,7 @@
"commandPalette": [ "commandPalette": [
{ {
"command": "sshfs.new", "command": "sshfs.new",
"group": "SSH FS@1", "group": "SSH FS@1"
"when": "view == 'DISABLED'"
}, },
{ {
"command": "sshfs.connect", "command": "sshfs.connect",
@ -100,8 +99,7 @@
}, },
{ {
"command": "sshfs.configure", "command": "sshfs.configure",
"group": "SSH FS@5", "group": "SSH FS@5"
"when": "view == 'DISABLED'"
}, },
{ {
"command": "sshfs.reload", "command": "sshfs.reload",
@ -115,7 +113,7 @@
"view/item/context": [ "view/item/context": [
{ {
"command": "sshfs.new", "command": "sshfs.new",
"when": "view == 'sshfs-configs' && !viewItem && view == 'DISABLED'" "when": "view == 'sshfs-configs' && !viewItem"
}, },
{ {
"command": "sshfs.connect", "command": "sshfs.connect",
@ -134,7 +132,7 @@
}, },
{ {
"command": "sshfs.configure", "command": "sshfs.configure",
"when": "view == 'sshfs-configs' && viewItem && view == 'DISABLED'", "when": "view == 'sshfs-configs' && viewItem",
"group": "SSH FS@3" "group": "SSH FS@3"
} }
] ]

@ -53,10 +53,8 @@ export function activate(context: vscode.ExtensionContext) {
if (name) func.call(manager, name); if (name) func.call(manager, name);
} }
registerCommand('sshfs.new', async () => { registerCommand('sshfs.new', async () => manager.openSettings({ type: 'newconfig' }));
const name = await vscode.window.showInputBox({ placeHolder: 'Name for the new SSH file system', validateInput: invalidConfigName }); registerCommand('sshfs.settings', () => manager.openSettings());
if (name) vscode.window.showTextDocument(vscode.Uri.parse(`ssh://<config>/${name}.sshfs.jsonc`), { preview: false });
});
registerCommand('sshfs.connect', (name?: string) => pickAndClick(manager.commandConnect, name, false)); registerCommand('sshfs.connect', (name?: string) => pickAndClick(manager.commandConnect, name, false));
registerCommand('sshfs.disconnect', (name?: string) => pickAndClick(manager.commandDisconnect, name, true)); registerCommand('sshfs.disconnect', (name?: string) => pickAndClick(manager.commandDisconnect, name, true));
@ -65,7 +63,5 @@ export function activate(context: vscode.ExtensionContext) {
registerCommand('sshfs.reload', loadConfigs); registerCommand('sshfs.reload', loadConfigs);
registerCommand('sshfs.settings', () => manager.openSettings());
vscode.window.createTreeView('sshfs-configs', { treeDataProvider: manager }); vscode.window.createTreeView('sshfs-configs', { treeDataProvider: manager });
} }

@ -1,11 +1,12 @@
import { Client, ClientChannel } from 'ssh2'; import { Client, ClientChannel } from 'ssh2';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { getConfig, getConfigs, loadConfigs, UPDATE_LISTENERS } from './config'; import { getConfig, getConfigs, loadConfigs, loadConfigsRaw, UPDATE_LISTENERS } from './config';
import { FileSystemConfig } from './fileSystemConfig'; import { FileSystemConfig } from './fileSystemConfig';
import * as Logging from './logging'; import * as Logging from './logging';
import SSHFileSystem from './sshFileSystem'; import SSHFileSystem from './sshFileSystem';
import { catchingPromise, toPromise } from './toPromise'; import { catchingPromise, toPromise } from './toPromise';
import { Navigation } from './webviewMessages';
async function assertFs(man: Manager, uri: vscode.Uri) { async function assertFs(man: Manager, uri: vscode.Uri) {
const fs = await man.getFs(uri); const fs = await man.getFs(uri);
@ -269,16 +270,16 @@ export class Manager implements vscode.FileSystemProvider, vscode.TreeDataProvid
} }
public async commandConfigure(name: string) { public async commandConfigure(name: string) {
Logging.info(`Command received to configure ${name}`); Logging.info(`Command received to configure ${name}`);
// openConfigurationEditor(name); name = name.toLowerCase();
vscode.window.showWarningMessage('Use the SSH FS config editor to modify/delete configurations'); let configs = await loadConfigsRaw();
// TODO: Make this work with the following code: configs = configs.filter(c => c.name === name);
// this.openSettings(name); if (configs.length === 0) throw new Error('Unexpectedly found no matching configs?');
// Would open the Settings UI, list all locations the (potentially) merged config originates from, const config = configs.length === 1 ? configs[0] : configs;
// and allow the user to pick (and edit) one of them. Maybe have a back-to-the-list button? this.openSettings({ config, type: 'editconfig' });
} }
public async openSettings() { public async openSettings(navigation?: Navigation) {
const { open } = await import('./settings'); const { open, navigate } = await import('./settings');
return open(this.context.extensionPath); return navigation ? navigate(navigation) : open();
} }
} }

@ -5,14 +5,20 @@ import * as vscode from 'vscode';
import { deleteConfig, loadConfigsRaw, updateConfig } from './config'; import { deleteConfig, loadConfigsRaw, updateConfig } from './config';
import { getLocations } from './fileSystemConfig'; import { getLocations } from './fileSystemConfig';
import { toPromise } from './toPromise'; import { toPromise } from './toPromise';
import { Message } from './webviewMessages'; import { Message, Navigation } from './webviewMessages';
let webviewPanel: vscode.WebviewPanel | undefined; let webviewPanel: vscode.WebviewPanel | undefined;
let pendingNavigation: Navigation | undefined;
// Since the Extension Development Host runs with debugger, we can use this to detect if we're debugging // Since the Extension Development Host runs with debugger, we can use this to detect if we're debugging
const DEBUG: number | undefined = process.execArgv.find(a => a.includes('--inspect')) ? 3000 : undefined; const DEBUG: number | undefined = process.execArgv.find(a => a.includes('--inspect')) ? 3000 : undefined;
if (DEBUG) console.warn('[vscode-sshfs] Detected we are running in debug mode'); if (DEBUG) console.warn('[vscode-sshfs] Detected we are running in debug mode');
function getExtensionPath(): string | undefined {
const ext = vscode.extensions.getExtension('Kelvin.vscode-sshfs');
return ext && ext.extensionPath;
}
async function getDebugContent(): Promise<string | false> { async function getDebugContent(): Promise<string | false> {
if (!DEBUG) return false; if (!DEBUG) return false;
const URL = `http://localhost:${DEBUG}/`; const URL = `http://localhost:${DEBUG}/`;
@ -25,13 +31,15 @@ async function getDebugContent(): Promise<string | false> {
})); }));
} }
export async function open(extensionPath: string) { export async function open() {
if (!webviewPanel) { if (!webviewPanel) {
webviewPanel = vscode.window.createWebviewPanel('sshfs-settings', 'SSH-FS Settings', vscode.ViewColumn.One, { enableFindWidget: true, enableScripts: true }); webviewPanel = vscode.window.createWebviewPanel('sshfs-settings', 'SSH-FS Settings', vscode.ViewColumn.One, { enableFindWidget: true, enableScripts: true });
webviewPanel.onDidDispose(() => webviewPanel = undefined); webviewPanel.onDidDispose(() => webviewPanel = undefined);
webviewPanel.webview.onDidReceiveMessage(handleMessage); webviewPanel.webview.onDidReceiveMessage(handleMessage);
let content = await getDebugContent().catch((e: Error) => (vscode.window.showErrorMessage(e.message), null)); let content = await getDebugContent().catch((e: Error) => (vscode.window.showErrorMessage(e.message), null));
if (!content) { if (!content) {
const extensionPath = getExtensionPath();
if (!extensionPath) throw new Error('Could not get extensionPath');
// If we got here, we're either not in debug mode, or something went wrong (and an error message is shown) // If we got here, we're either not in debug mode, or something went wrong (and an error message is shown)
content = fs.readFileSync(path.resolve(extensionPath, 'webview/build/index.html')).toString(); content = fs.readFileSync(path.resolve(extensionPath, 'webview/build/index.html')).toString();
// Built index.html has e.g. `href="/static/js/stuff.js"`, need to make it use vscode-resource: and point to the built static directory // Built index.html has e.g. `href="/static/js/stuff.js"`, need to make it use vscode-resource: and point to the built static directory
@ -42,13 +50,27 @@ export async function open(extensionPath: string) {
webviewPanel.reveal(); webviewPanel.reveal();
} }
function postMessage(message: Message) { export async function navigate(navigation: Navigation) {
pendingNavigation = navigation;
postMessage({ navigation, type: 'navigate' });
return open();
}
function postMessage<T extends Message>(message: T) {
if (!webviewPanel) return; if (!webviewPanel) return;
webviewPanel.webview.postMessage(message); webviewPanel.webview.postMessage(message);
} }
async function handleMessage(message: Message): Promise<any> { async function handleMessage(message: Message): Promise<any> {
console.log('Got message:', message); console.log('Got message:', message);
if (message.type === 'navigated') pendingNavigation = undefined;
if (pendingNavigation) {
postMessage({
type: 'navigate',
navigation: pendingNavigation,
});
pendingNavigation = undefined;
}
switch (message.type) { switch (message.type) {
case 'requestData': { case 'requestData': {
const configs = await loadConfigsRaw(); const configs = await loadConfigsRaw();

@ -1,5 +1,7 @@
import { ConfigLocation, FileSystemConfig } from './fileSystemConfig'; import { ConfigLocation, FileSystemConfig } from './fileSystemConfig';
/* Type of messages*/
export interface RequestDataMessage { export interface RequestDataMessage {
type: 'requestData'; type: 'requestData';
} }
@ -34,6 +36,15 @@ export interface PromptPathResultMessage {
uniqueId?: string; uniqueId?: string;
} }
export interface NavigateMessage {
type: 'navigate';
navigation: Navigation;
}
export interface NavigatedMessage {
type: 'navigated';
navigation: Navigation;
}
export interface MessageTypes { export interface MessageTypes {
requestData: RequestDataMessage; requestData: RequestDataMessage;
responseData: ResponseDataMessage; responseData: ResponseDataMessage;
@ -41,6 +52,19 @@ export interface MessageTypes {
saveConfigResult: SaveConfigResultMessage; saveConfigResult: SaveConfigResultMessage;
promptPath: PromptPathMessage; promptPath: PromptPathMessage;
promptPathResult: PromptPathResultMessage; promptPathResult: PromptPathResultMessage;
navigate: NavigateMessage;
navigated: NavigatedMessage;
} }
export type Message = MessageTypes[keyof MessageTypes]; export type Message = MessageTypes[keyof MessageTypes];
/* Types related to NavigateMessage */
export interface NewConfigNavigation {
type: 'newconfig';
}
export interface EditConfigNavigation {
type: 'editconfig';
config: FileSystemConfig | FileSystemConfig[];
}
export type Navigation = NewConfigNavigation | EditConfigNavigation;

@ -12,6 +12,7 @@ interface DispatchProps {
} }
interface OwnProps { interface OwnProps {
configs?: FileSystemConfig[]; configs?: FileSystemConfig[];
displayName?(config: FileSystemConfig): string | undefined;
} }
class ConfigList extends React.Component<StateProps & DispatchProps & OwnProps> { class ConfigList extends React.Component<StateProps & DispatchProps & OwnProps> {
public render() { public render() {
@ -24,8 +25,10 @@ class ConfigList extends React.Component<StateProps & DispatchProps & OwnProps>
</div>; </div>;
} }
public editConfigClickHandler(config: FileSystemConfig) { public editConfigClickHandler(config: FileSystemConfig) {
const { displayName } = this.props;
const name = displayName && displayName(config) || config.label || config.name;
const onClick = () => this.props.editConfig(config); const onClick = () => this.props.editConfig(config);
return <li key={config.name} onClick={onClick}>{config.label || config.name}</li>; return <li key={config.name} onClick={onClick}>{name}</li>;
} }
} }

@ -0,0 +1,4 @@
div.ConfigLocator {
padding: 5px;
}

@ -0,0 +1,29 @@
import * as React from 'react';
import ConfigList from 'src/ConfigList';
import { connect, pickProperties } from 'src/redux';
import { FileSystemConfig, formatConfigLocation } from 'src/types/fileSystemConfig';
import { IConfigLocatorState } from 'src/view';
import './index.css';
function displayName(config: FileSystemConfig) {
return formatConfigLocation(config._location);
}
interface StateProps {
configs: FileSystemConfig[];
name: string;
}
class ConfigLocator extends React.Component<StateProps> {
public render() {
const { configs, name } = this.props;
return <div className="ConfigLocator">
<h2>Locations of {name}</h2>
<ConfigList configs={configs} displayName={displayName} />
</div>;
}
}
interface SubState { view: IConfigLocatorState }
export default connect(ConfigLocator)<StateProps, SubState>(
state => pickProperties(state.view, 'configs', 'name'),
);

@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import ConfigList from 'src/ConfigList'; import ConfigList from 'src/ConfigList';
import { receivedData } from 'src/data/actions'; import { receivedData } from 'src/data/actions';
import { connect } from 'src/redux'; import { connect, pickProperties } from 'src/redux';
import { ConfigLocation, FileSystemConfig, formatConfigLocation, groupByLocation } from 'src/types/fileSystemConfig'; import { ConfigLocation, FileSystemConfig, formatConfigLocation, groupByLocation } from 'src/types/fileSystemConfig';
import { openNewConfig } from 'src/view/actions'; import { openNewConfig } from 'src/view/actions';
import { API } from 'src/vscode'; import { API } from 'src/vscode';
@ -9,11 +9,10 @@ import './index.css';
interface StateProps { interface StateProps {
configs: FileSystemConfig[]; configs: FileSystemConfig[];
locations: ConfigLocation[];
} }
interface DispatchProps { interface DispatchProps {
refresh(): void; refresh(): void;
add(locations: ConfigLocation[]): void; add(): void;
} }
class Homescreen extends React.Component<StateProps & DispatchProps> { class Homescreen extends React.Component<StateProps & DispatchProps> {
public componentDidMount() { public componentDidMount() {
@ -25,7 +24,7 @@ class Homescreen extends React.Component<StateProps & DispatchProps> {
return <div className="Homescreen"> return <div className="Homescreen">
<h2>Configurations</h2> <h2>Configurations</h2>
<button onClick={this.props.refresh}>Refresh</button> <button onClick={this.props.refresh}>Refresh</button>
<button onClick={this.add}>Add</button> <button onClick={this.props.add}>Add</button>
{grouped.map(([loc, configs]) => this.createGroup(loc, configs))} {grouped.map(([loc, configs]) => this.createGroup(loc, configs))}
</div>; </div>;
} }
@ -35,13 +34,12 @@ class Homescreen extends React.Component<StateProps & DispatchProps> {
<ConfigList configs={configs} /> <ConfigList configs={configs} />
</div>; </div>;
} }
public add = () => this.props.add(this.props.locations);
} }
export default connect(Homescreen)<StateProps, DispatchProps>( export default connect(Homescreen)<StateProps, DispatchProps>(
state => ({ configs: state.data.configs, locations: state.data.locations }), state => pickProperties(state.data, 'configs'),
dispatch => ({ dispatch => ({
add: locations => dispatch(openNewConfig(locations)), add: () => dispatch(openNewConfig()),
refresh: () => (dispatch(receivedData([], [])), API.postMessage({ type: 'requestData' })), refresh: () => (dispatch(receivedData([], [])), API.postMessage({ type: 'requestData' })),
}), }),
); );

@ -2,7 +2,7 @@ import * as React from 'react';
import { FieldDropdown } from 'src/FieldTypes/dropdown'; import { FieldDropdown } from 'src/FieldTypes/dropdown';
import { FieldGroup } from 'src/FieldTypes/group'; import { FieldGroup } from 'src/FieldTypes/group';
import { FieldString } from 'src/FieldTypes/string'; import { FieldString } from 'src/FieldTypes/string';
import { connect, pickProperties } from 'src/redux'; import { connect, pickProperties, State } from 'src/redux';
import { ConfigLocation, formatConfigLocation, invalidConfigName } from 'src/types/fileSystemConfig'; import { ConfigLocation, formatConfigLocation, invalidConfigName } from 'src/types/fileSystemConfig';
import { INewConfigState } from 'src/view'; import { INewConfigState } from 'src/view';
import { newConfigSetLocation, newConfigSetName, openConfigEditor, openStartScreen } from 'src/view/actions'; import { newConfigSetLocation, newConfigSetName, openConfigEditor, openStartScreen } from 'src/view/actions';
@ -53,9 +53,13 @@ class NewConfig extends React.Component<StateProps & DispatchProps> {
public confirm = () => this.props.confirm(this.props.name, this.props.location); public confirm = () => this.props.confirm(this.props.name, this.props.location);
} }
interface SubState { view: INewConfigState } interface SubState extends State { view: INewConfigState }
export default connect(NewConfig)<StateProps, DispatchProps, SubState>( export default connect(NewConfig)<StateProps, DispatchProps, SubState>(
(state) => pickProperties(state.view, 'location', 'locations', 'name'), (state) => ({
...pickProperties(state.view, 'name'),
...pickProperties(state.data, 'locations'),
location: state.view.location || state.data.locations[0],
}),
(dispatch) => ({ (dispatch) => ({
cancel: () => dispatch(openStartScreen()), cancel: () => dispatch(openStartScreen()),
setLocation: loc => dispatch(newConfigSetLocation(loc)), setLocation: loc => dispatch(newConfigSetLocation(loc)),

@ -1,5 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import ConfigEditor from './ConfigEditor'; import ConfigEditor from './ConfigEditor';
import ConfigLocator from './ConfigLocator';
import Homescreen from './Homescreen'; import Homescreen from './Homescreen';
import NewConfig from './NewConfig'; import NewConfig from './NewConfig';
import { connect, State } from './redux'; import { connect, State } from './redux';
@ -11,6 +12,8 @@ function Router(props: StateProps) {
switch (props.view) { switch (props.view) {
case 'configeditor': case 'configeditor':
return <ConfigEditor />; return <ConfigEditor />;
case 'configlocator':
return <ConfigLocator />;
case 'newconfig': case 'newconfig':
return <NewConfig />; return <NewConfig />;
case 'startscreen': case 'startscreen':

@ -1,5 +1,7 @@
import { ConfigLocation, FileSystemConfig } from './fileSystemConfig'; import { ConfigLocation, FileSystemConfig } from './fileSystemConfig';
/* Type of messages*/
export interface RequestDataMessage { export interface RequestDataMessage {
type: 'requestData'; type: 'requestData';
} }
@ -34,6 +36,15 @@ export interface PromptPathResultMessage {
uniqueId?: string; uniqueId?: string;
} }
export interface NavigateMessage {
type: 'navigate';
navigation: Navigation;
}
export interface NavigatedMessage {
type: 'navigated';
navigation: Navigation;
}
export interface MessageTypes { export interface MessageTypes {
requestData: RequestDataMessage; requestData: RequestDataMessage;
responseData: ResponseDataMessage; responseData: ResponseDataMessage;
@ -41,6 +52,19 @@ export interface MessageTypes {
saveConfigResult: SaveConfigResultMessage; saveConfigResult: SaveConfigResultMessage;
promptPath: PromptPathMessage; promptPath: PromptPathMessage;
promptPathResult: PromptPathResultMessage; promptPathResult: PromptPathResultMessage;
navigate: NavigateMessage;
navigated: NavigatedMessage;
} }
export type Message = MessageTypes[keyof MessageTypes]; export type Message = MessageTypes[keyof MessageTypes];
/* Types related to NavigateMessage */
export interface NewConfigNavigation {
type: 'newconfig';
}
export interface EditConfigNavigation {
type: 'editconfig';
config: FileSystemConfig | FileSystemConfig[];
}
export type Navigation = NewConfigNavigation | EditConfigNavigation;

@ -9,6 +9,7 @@ export enum ActionType {
NEWCONFIG_SETLOCATION = 'NEWCONFIG_SETLOCATION', NEWCONFIG_SETLOCATION = 'NEWCONFIG_SETLOCATION',
// ConfigEditor // ConfigEditor
OPEN_CONFIGEDITOR = 'OPEN_CONFIGEDITOR', OPEN_CONFIGEDITOR = 'OPEN_CONFIGEDITOR',
OPEN_CONFIGLOCATOR = 'OPEN_CONFIGLOCATOR',
CONFIGEDITOR_SETNEWCONFIG = 'CONFIGEDITOR_SETNEWCONFIG', CONFIGEDITOR_SETNEWCONFIG = 'CONFIGEDITOR_SETNEWCONFIG',
CONFIGEDITOR_SETSTATUSMESSAGE = 'CONFIGEDITOR_SETSTATUSMESSAGE', CONFIGEDITOR_SETSTATUSMESSAGE = 'CONFIGEDITOR_SETSTATUSMESSAGE',
} }
@ -22,6 +23,7 @@ export interface ActionTypes {
NEWCONFIG_SETLOCATION: IActionNewConfigSetLocation; NEWCONFIG_SETLOCATION: IActionNewConfigSetLocation;
// ConfigEditor // ConfigEditor
OPEN_CONFIGEDITOR: IActionOpenConfigEditor; OPEN_CONFIGEDITOR: IActionOpenConfigEditor;
OPEN_CONFIGLOCATOR: IActionOpenConfigLocator;
CONFIGEDITOR_SETNEWCONFIG: IActionConfigEditorSetNewConfig; CONFIGEDITOR_SETNEWCONFIG: IActionConfigEditorSetNewConfig;
CONFIGEDITOR_SETSTATUSMESSAGE: IActionConfigEditorSetStatusMessage; CONFIGEDITOR_SETSTATUSMESSAGE: IActionConfigEditorSetStatusMessage;
} }
@ -44,11 +46,10 @@ export function openStartScreen(): IActionOpenStartscreen {
export interface IActionOpenNewConfig extends IAction { export interface IActionOpenNewConfig extends IAction {
type: ActionType.OPEN_NEWCONFIG; type: ActionType.OPEN_NEWCONFIG;
locations: ConfigLocation[];
name: string; name: string;
} }
export function openNewConfig(locations: ConfigLocation[], name = 'unnamed'): IActionOpenNewConfig { export function openNewConfig(name = 'unnamed'): IActionOpenNewConfig {
return { type: ActionType.OPEN_NEWCONFIG, locations, name }; return { type: ActionType.OPEN_NEWCONFIG, name };
} }
export interface IActionNewConfigSetLocation extends IAction { export interface IActionNewConfigSetLocation extends IAction {
@ -77,6 +78,15 @@ export function openConfigEditor(config: FileSystemConfig): IActionOpenConfigEdi
return { type: ActionType.OPEN_CONFIGEDITOR, config }; return { type: ActionType.OPEN_CONFIGEDITOR, config };
} }
export interface IActionOpenConfigLocator extends IAction {
type: ActionType.OPEN_CONFIGLOCATOR;
configs: FileSystemConfig[];
name: string;
}
export function openConfigLocator(configs: FileSystemConfig[], name: string): IActionOpenConfigLocator {
return { type: ActionType.OPEN_CONFIGLOCATOR, configs, name };
}
export interface IActionConfigEditorSetNewConfig extends IAction { export interface IActionConfigEditorSetNewConfig extends IAction {
type: ActionType.CONFIGEDITOR_SETNEWCONFIG; type: ActionType.CONFIGEDITOR_SETNEWCONFIG;
config: FileSystemConfig; config: FileSystemConfig;

@ -1,5 +1,6 @@
import { Store } from 'redux'; import { Store } from 'redux';
import { addListener, API } from 'src/vscode';
import * as actions from './actions'; import * as actions from './actions';
export { reducer } from './reducers'; export { reducer } from './reducers';
@ -7,5 +8,22 @@ export { actions }
export * from './state'; export * from './state';
export function initStore(store: Store) { export function initStore(store: Store) {
// Nothing really addListener((msg) => {
const { navigation } = msg;
switch (navigation.type) {
case 'newconfig':
return store.dispatch(actions.openNewConfig());
case 'editconfig': {
let { config } = navigation;
if (Array.isArray(config)) {
if (config.length !== 1) {
return store.dispatch(actions.openConfigLocator(config, config[0].name));
}
config = config[0];
}
return store.dispatch(actions.openConfigEditor(config));
}
}
API.postMessage({ type: 'navigated', navigation });
}, 'navigate');
} }

@ -8,8 +8,8 @@ export function reducer(state = DEFAULT_STATE, action: Action): IState {
return { ...state, view: 'startscreen' }; return { ...state, view: 'startscreen' };
// New Config // New Config
case ActionType.OPEN_NEWCONFIG: { case ActionType.OPEN_NEWCONFIG: {
const { locations, name } = action; const { name } = action;
return { ...state, view: 'newconfig', name, locations, location: locations[0] }; return { ...state, view: 'newconfig', name, location: undefined };
} }
case ActionType.NEWCONFIG_SETNAME: case ActionType.NEWCONFIG_SETNAME:
return { ...state as INewConfigState, name: action.name }; return { ...state as INewConfigState, name: action.name };
@ -20,6 +20,10 @@ export function reducer(state = DEFAULT_STATE, action: Action): IState {
const { config } = action; const { config } = action;
return { ...state, view: 'configeditor', oldConfig: config, newConfig: config }; return { ...state, view: 'configeditor', oldConfig: config, newConfig: config };
} }
case ActionType.OPEN_CONFIGLOCATOR: {
const { name, configs } = action;
return { ...state, view: 'configlocator', name, configs };
}
case ActionType.CONFIGEDITOR_SETNEWCONFIG: case ActionType.CONFIGEDITOR_SETNEWCONFIG:
return { ...state as IConfigEditorState, newConfig: action.config }; return { ...state as IConfigEditorState, newConfig: action.config };
case ActionType.CONFIGEDITOR_SETSTATUSMESSAGE: case ActionType.CONFIGEDITOR_SETSTATUSMESSAGE:

@ -7,8 +7,7 @@ interface IViewState<V extends string> {
export type IStartScreenState = IViewState<'startscreen'>; export type IStartScreenState = IViewState<'startscreen'>;
export interface INewConfigState extends IViewState<'newconfig'> { export interface INewConfigState extends IViewState<'newconfig'> {
locations: ConfigLocation[]; location?: ConfigLocation;
location: ConfigLocation;
name: string; name: string;
} }
@ -18,7 +17,12 @@ export interface IConfigEditorState extends IViewState<'configeditor'> {
statusMessage?: string; statusMessage?: string;
} }
export type IState = IStartScreenState | INewConfigState | IConfigEditorState; export interface IConfigLocatorState extends IViewState<'configlocator'> {
configs: FileSystemConfig[];
name: string;
}
export type IState = IStartScreenState | INewConfigState | IConfigEditorState | IConfigLocatorState;
export const DEFAULT_STATE: IState = { export const DEFAULT_STATE: IState = {
view: 'startscreen', view: 'startscreen',

Loading…
Cancel
Save