From de69287584bccf00a1edc53e32a12b0ee1388acb Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Apr 2020 20:08:01 -0700 Subject: [PATCH 1/3] replace workspaceRoot logic with env variable Signed-off-by: shmck --- src/actions/setupActions.ts | 4 +--- src/actions/solutionActions.ts | 9 ++------- src/actions/utils/loadWatchers.ts | 10 +++------- src/actions/utils/runCommands.ts | 4 ++-- src/channel/index.ts | 12 ++++-------- src/editor/commands.ts | 4 +--- src/editor/index.ts | 9 +-------- src/environment.ts | 5 +++++ src/services/dependencies/index.ts | 4 ++-- src/services/git/index.ts | 22 +++++++++++----------- src/services/node/index.ts | 30 ++++++++---------------------- src/services/testRunner/index.ts | 4 ++-- src/services/workspace/index.ts | 18 ++++++++++++++++-- src/webview/index.ts | 4 +--- 14 files changed, 59 insertions(+), 80 deletions(-) diff --git a/src/actions/setupActions.ts b/src/actions/setupActions.ts index c4de8e56..cb58a3a1 100644 --- a/src/actions/setupActions.ts +++ b/src/actions/setupActions.ts @@ -1,6 +1,5 @@ import * as T from 'typings' import * as TT from 'typings/tutorial' -import * as vscode from 'vscode' import * as git from '../services/git' import loadWatchers from './utils/loadWatchers' import openFiles from './utils/openFiles' @@ -8,7 +7,6 @@ import runCommands from './utils/runCommands' import onError from '../services/sentry/onError' const setupActions = async ( - workspaceRoot: vscode.WorkspaceFolder, actions: TT.StepActions, send: (action: T.Action) => void, // send messages to client ): Promise => { @@ -26,7 +24,7 @@ const setupActions = async ( openFiles(files || []) // 3. start file watchers - loadWatchers(watchers || [], workspaceRoot.uri) + loadWatchers(watchers || []) // 4. run command await runCommands(commands || [], send).catch(onError) diff --git a/src/actions/solutionActions.ts b/src/actions/solutionActions.ts index 0f26b61f..d269dec3 100644 --- a/src/actions/solutionActions.ts +++ b/src/actions/solutionActions.ts @@ -1,17 +1,12 @@ import * as T from 'typings' import * as TT from 'typings/tutorial' -import * as vscode from 'vscode' import * as git from '../services/git' import setupActions from './setupActions' import onError from '../services/sentry/onError' -const solutionActions = async ( - workspaceRoot: vscode.WorkspaceFolder, - stepActions: TT.StepActions, - send: (action: T.Action) => void, -): Promise => { +const solutionActions = async (stepActions: TT.StepActions, send: (action: T.Action) => void): Promise => { await git.clear() - return setupActions(workspaceRoot, stepActions, send).catch(onError) + return setupActions(stepActions, send).catch(onError) } export default solutionActions diff --git a/src/actions/utils/loadWatchers.ts b/src/actions/utils/loadWatchers.ts index c1d54c94..e2b5660c 100644 --- a/src/actions/utils/loadWatchers.ts +++ b/src/actions/utils/loadWatchers.ts @@ -1,6 +1,7 @@ import * as chokidar from 'chokidar' import * as vscode from 'vscode' import { COMMANDS } from '../../editor/commands' +import environment from '../../environment' // NOTE: vscode createFileWatcher doesn't seem to detect changes outside of vscode // such as `npm install` of a package. Went with chokidar instead @@ -13,7 +14,7 @@ const disposeWatcher = (watcher: string) => { delete watcherObject[watcher] } -const loadWatchers = (watchers: string[], workspaceUri: vscode.Uri) => { +const loadWatchers = (watchers: string[]) => { if (!watchers.length) { // remove all watchers for (const watcher of Object.keys(watcherObject)) { @@ -24,13 +25,8 @@ const loadWatchers = (watchers: string[], workspaceUri: vscode.Uri) => { if (!watcherObject[watcher]) { // see how glob patterns are used in VSCode (not like a regex) // https://code.visualstudio.com/api/references/vscode-api#GlobPattern - const rootUri = vscode.workspace.getWorkspaceFolder(workspaceUri) - if (!rootUri) { - return - } - const fsWatcher: chokidar.FSWatcher = chokidar.watch(watcher, { - cwd: rootUri.uri.path, + cwd: environment.WORKSPACE_ROOT, interval: 1000, }) diff --git a/src/actions/utils/runCommands.ts b/src/actions/utils/runCommands.ts index 01edf27a..2ddda75b 100644 --- a/src/actions/utils/runCommands.ts +++ b/src/actions/utils/runCommands.ts @@ -1,5 +1,5 @@ import * as T from 'typings' -import node from '../../services/node' +import { exec } from '../../services/node' const runCommands = async (commands: string[], send: (action: T.Action) => void) => { if (!commands.length) { @@ -13,7 +13,7 @@ const runCommands = async (commands: string[], send: (action: T.Action) => void) send({ type: 'COMMAND_START', payload: { process: { ...process, status: 'RUNNING' } } }) let result: { stdout: string; stderr: string } try { - result = await node.exec(command) + result = await exec(command) } catch (error) { console.log(error) send({ type: 'COMMAND_FAIL', payload: { process: { ...process, status: 'FAIL' } } }) diff --git a/src/channel/index.ts b/src/channel/index.ts index 629a735b..64d52e4e 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -14,7 +14,6 @@ import { openWorkspace, checkWorkspaceEmpty } from '../services/workspace' import { readFile } from 'fs' import { join } from 'path' import { promisify } from 'util' -import { compare } from 'semver' const readFileAsync = promisify(readFile) @@ -26,18 +25,15 @@ interface Channel { interface ChannelProps { postMessage: (action: T.Action) => Thenable workspaceState: vscode.Memento - workspaceRoot: vscode.WorkspaceFolder } class Channel implements Channel { private postMessage: (action: T.Action) => Thenable private workspaceState: vscode.Memento - private workspaceRoot: vscode.WorkspaceFolder private context: Context - constructor({ postMessage, workspaceState, workspaceRoot }: ChannelProps) { + constructor({ postMessage, workspaceState }: ChannelProps) { // workspaceState used for local storage this.workspaceState = workspaceState - this.workspaceRoot = workspaceRoot this.postMessage = postMessage this.context = new Context(workspaceState) } @@ -181,7 +177,7 @@ class Channel implements Channel { return case 'EDITOR_VALIDATE_SETUP': // 1. check workspace is selected - const isEmptyWorkspace = await checkWorkspaceEmpty(this.workspaceRoot.uri.path) + const isEmptyWorkspace = await checkWorkspaceEmpty() if (!isEmptyWorkspace) { const error: E.ErrorMessage = { type: 'WorkspaceNotEmpty', @@ -225,11 +221,11 @@ class Channel implements Channel { // load step actions (git commits, commands, open files) case 'SETUP_ACTIONS': await vscode.commands.executeCommand(COMMANDS.SET_CURRENT_STEP, action.payload) - setupActions(this.workspaceRoot, action.payload, this.send) + setupActions(action.payload, this.send) return // load solution step actions (git commits, commands, open files) case 'SOLUTION_ACTIONS': - await solutionActions(this.workspaceRoot, action.payload, this.send) + await solutionActions(action.payload, this.send) // run test following solution to update position vscode.commands.executeCommand(COMMANDS.RUN_TEST, action.payload) return diff --git a/src/editor/commands.ts b/src/editor/commands.ts index cd8e53f3..5c356750 100644 --- a/src/editor/commands.ts +++ b/src/editor/commands.ts @@ -14,10 +14,9 @@ export const COMMANDS = { interface CreateCommandProps { extensionPath: string workspaceState: vscode.Memento - workspaceRoot: vscode.WorkspaceFolder } -export const createCommands = ({ extensionPath, workspaceState, workspaceRoot }: CreateCommandProps) => { +export const createCommands = ({ extensionPath, workspaceState }: CreateCommandProps) => { // React panel webview let webview: any let currentStepId = '' @@ -41,7 +40,6 @@ export const createCommands = ({ extensionPath, workspaceState, workspaceRoot }: webview = createWebView({ extensionPath, workspaceState, - workspaceRoot, }) }, // open React webview diff --git a/src/editor/index.ts b/src/editor/index.ts index e4a8c6df..2ca1a7be 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -1,4 +1,5 @@ import * as vscode from 'vscode' +import notify from '../services/notify' import { createCommands } from './commands' class Editor { @@ -28,18 +29,10 @@ class Editor { } private activateCommands = (): void => { - // set workspace root for node executions - const workspaceRoots: vscode.WorkspaceFolder[] | undefined = vscode.workspace.workspaceFolders - if (!workspaceRoots || !workspaceRoots.length) { - throw new Error('No workspace root path') - } - const workspaceRoot: vscode.WorkspaceFolder = workspaceRoots[0] - const commands = createCommands({ extensionPath: this.vscodeExt.extensionPath, // NOTE: local storage must be bound to the vscodeExt.workspaceState workspaceState: this.vscodeExt.workspaceState, - workspaceRoot, }) // register commands diff --git a/src/environment.ts b/src/environment.ts index ee2f5639..e21495ec 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -2,12 +2,16 @@ require('dotenv').config({ path: './web-app/.env', }) +import * as vscode from 'vscode' +import { getWorkspaceRoot } from './services/workspace' + interface Environment { VERSION: string NODE_ENV: string LOG: boolean API_URL: string SENTRY_DSN: string | null + WORKSPACE_ROOT: string } const environment: Environment = { @@ -16,6 +20,7 @@ const environment: Environment = { LOG: (process.env.LOG || '').toLowerCase() === 'true', API_URL: process.env.REACT_APP_GQL_URI || '', SENTRY_DSN: process.env.SENTRY_DSN || null, + WORKSPACE_ROOT: getWorkspaceRoot(), } export default environment diff --git a/src/services/dependencies/index.ts b/src/services/dependencies/index.ts index 83393fe9..92994717 100644 --- a/src/services/dependencies/index.ts +++ b/src/services/dependencies/index.ts @@ -1,11 +1,11 @@ import { satisfies } from 'semver' -import node from '../node' +import { exec } from '../node' const semverRegex = /(?<=^v?|\sv?)(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[\da-z-]*[a-z-][\da-z-]*)(?:\.(?:0|[1-9]\d*|[\da-z-]*[a-z-][\da-z-]*))*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?(?=$|\s)/gi export const version = async (name: string): Promise => { try { - const { stdout, stderr } = await node.exec(`${name} --version`) + const { stdout, stderr } = await exec(`${name} --version`) if (!stderr) { const match = stdout.match(semverRegex) if (match) { diff --git a/src/services/git/index.ts b/src/services/git/index.ts index d6e422a2..f2dfc23f 100644 --- a/src/services/git/index.ts +++ b/src/services/git/index.ts @@ -1,12 +1,12 @@ import * as TT from 'typings/tutorial' -import node from '../node' +import { exec, exists } from '../node' import logger from '../logger' const gitOrigin = 'coderoad' const stashAllFiles = async (): Promise => { // stash files including untracked (eg. newly created file) - const { stdout, stderr } = await node.exec(`git stash --include-untracked`) + const { stdout, stderr } = await exec(`git stash --include-untracked`) if (stderr) { console.error(stderr) throw new Error('Error stashing files') @@ -21,7 +21,7 @@ const cherryPickCommit = async (commit: string, count = 0): Promise { */ export async function saveCommit(message: string): Promise { - const { stdout, stderr } = await node.exec(`git commit -am '${message}'`) + const { stdout, stderr } = await exec(`git commit -am '${message}'`) if (stderr) { console.error(stderr) throw new Error('Error saving progress to Git') @@ -58,7 +58,7 @@ export async function saveCommit(message: string): Promise { export async function clear(): Promise { try { // commit progress to git - const { stderr } = await node.exec('git reset HEAD --hard && git clean -fd') + const { stderr } = await exec('git reset HEAD --hard && git clean -fd') if (!stderr) { return } @@ -70,14 +70,14 @@ export async function clear(): Promise { } async function init(): Promise { - const { stderr } = await node.exec('git init') + const { stderr } = await exec('git init') if (stderr) { throw new Error('Error initializing Git') } } export async function initIfNotExists(): Promise { - const hasGitInit = node.exists('.git') + const hasGitInit = exists('.git') if (!hasGitInit) { await init() } @@ -85,13 +85,13 @@ export async function initIfNotExists(): Promise { export async function checkRemoteConnects(repo: TT.TutorialRepo): Promise { // check for git repo - const externalRepoExists = await node.exec(`git ls-remote --exit-code --heads ${repo.uri}`) + const externalRepoExists = await exec(`git ls-remote --exit-code --heads ${repo.uri}`) if (externalRepoExists.stderr) { // no repo found or no internet connection throw new Error(externalRepoExists.stderr) } // check for git repo branch - const { stderr, stdout } = await node.exec(`git ls-remote --exit-code --heads ${repo.uri} ${repo.branch}`) + const { stderr, stdout } = await exec(`git ls-remote --exit-code --heads ${repo.uri} ${repo.branch}`) if (stderr) { throw new Error(stderr) } @@ -101,7 +101,7 @@ export async function checkRemoteConnects(repo: TT.TutorialRepo): Promise { - const { stderr } = await node.exec(`git remote add ${gitOrigin} ${repo} && git fetch ${gitOrigin}`) + const { stderr } = await exec(`git remote add ${gitOrigin} ${repo} && git fetch ${gitOrigin}`) if (stderr) { const alreadyExists = stderr.match(`${gitOrigin} already exists.`) const successfulNewBranch = stderr.match('new branch') @@ -116,7 +116,7 @@ export async function addRemote(repo: string): Promise { export async function checkRemoteExists(): Promise { try { - const { stdout, stderr } = await node.exec('git remote -v') + const { stdout, stderr } = await exec('git remote -v') if (stderr) { return false } diff --git a/src/services/node/index.ts b/src/services/node/index.ts index 252076e6..18a914dc 100644 --- a/src/services/node/index.ts +++ b/src/services/node/index.ts @@ -2,30 +2,16 @@ import { exec as cpExec } from 'child_process' import * as fs from 'fs' import { join } from 'path' import { promisify } from 'util' -import * as vscode from 'vscode' -import onError from '../sentry/onError' +import environment from '../../environment' const asyncExec = promisify(cpExec) -class Node { - private workspaceRootPath: string - constructor() { - // set workspace root for node executions - const workspaceRoots: vscode.WorkspaceFolder[] | undefined = vscode.workspace.workspaceFolders - if (!workspaceRoots || !workspaceRoots.length) { - const error = new Error('No workspace root path') - onError(error) - throw error - } - const workspaceRoot: vscode.WorkspaceFolder = workspaceRoots[0] - this.workspaceRootPath = workspaceRoot.uri.path - } - public exec = (cmd: string): Promise<{ stdout: string; stderr: string }> => - asyncExec(cmd, { - cwd: this.workspaceRootPath, - }) - - public exists = (...paths: string[]): boolean => fs.existsSync(join(this.workspaceRootPath, ...paths)) +export const exec = (cmd: string): Promise<{ stdout: string; stderr: string }> | never => { + return asyncExec(cmd, { + cwd: environment.WORKSPACE_ROOT, + }) } -export default new Node() +export const exists = (...paths: string[]): boolean | never => { + return fs.existsSync(join(environment.WORKSPACE_ROOT, ...paths)) +} diff --git a/src/services/testRunner/index.ts b/src/services/testRunner/index.ts index 63c7e216..b36d9575 100644 --- a/src/services/testRunner/index.ts +++ b/src/services/testRunner/index.ts @@ -1,4 +1,4 @@ -import node from '../node' +import { exec } from '../node' import logger from '../logger' import parser from './parser' import { debounce, throttle } from './throttle' @@ -39,7 +39,7 @@ const createTestRunner = (config: TestRunnerConfig, callbacks: Callbacks) => { let result: { stdout: string | undefined; stderr: string | undefined } try { - result = await node.exec(config.command) + result = await exec(config.command) } catch (err) { result = { stdout: err.stdout, stderr: err.stack } } diff --git a/src/services/workspace/index.ts b/src/services/workspace/index.ts index b62b17a9..05a3d2cf 100644 --- a/src/services/workspace/index.ts +++ b/src/services/workspace/index.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode' import * as fs from 'fs' import { promisify } from 'util' +import environment from '../../environment' const readDir = promisify(fs.readdir) @@ -9,12 +10,25 @@ export const openWorkspace = () => { vscode.commands.executeCommand('vscode.openFolder', undefined, openInNewWindow) } -export const checkWorkspaceEmpty = async (dirname: string) => { +export const checkWorkspaceEmpty = async () => { let files try { - files = await readDir(dirname) + files = await readDir(environment.WORKSPACE_ROOT) } catch (error) { throw new Error('Failed to check workspace') } return files.length === 0 } + +// capture the workspace root to use the users dirname in processes +export const getWorkspaceRoot = (): string => { + const workspaceRoots: vscode.WorkspaceFolder[] | undefined = vscode.workspace.workspaceFolders + if (!workspaceRoots || !workspaceRoots.length) { + // no workspace root + return 'NO_WORKSPACE_FOUND' + } + // a user may have multiple workspace folders + // for simplicity, assume the first is the active workspace + const workspaceRoot: vscode.WorkspaceFolder = workspaceRoots[0] + return workspaceRoot.uri.path +} diff --git a/src/webview/index.ts b/src/webview/index.ts index 322d8dd0..e6fd4a3e 100644 --- a/src/webview/index.ts +++ b/src/webview/index.ts @@ -7,10 +7,9 @@ import render from './render' interface ReactWebViewProps { extensionPath: string workspaceState: vscode.Memento - workspaceRoot: vscode.WorkspaceFolder } -const createReactWebView = ({ extensionPath, workspaceState, workspaceRoot }: ReactWebViewProps) => { +const createReactWebView = ({ extensionPath, workspaceState }: ReactWebViewProps) => { let loaded = false // TODO add disposables const disposables: vscode.Disposable[] = [] @@ -40,7 +39,6 @@ const createReactWebView = ({ extensionPath, workspaceState, workspaceRoot }: Re const channel = new Channel({ workspaceState, - workspaceRoot, postMessage: (action: Action): Thenable => { return panel.webview.postMessage(action) }, From a23644e4cdc18bb526de6e086b90b334b422261e Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Apr 2020 20:16:56 -0700 Subject: [PATCH 2/3] add no workspace validation checks Signed-off-by: shmck --- errors/NoWorkspaceFolder.md | 3 +++ src/channel/index.ts | 16 ++++++++++++++-- src/services/workspace/index.ts | 2 +- typings/error.d.ts | 3 ++- 4 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 errors/NoWorkspaceFolder.md diff --git a/errors/NoWorkspaceFolder.md b/errors/NoWorkspaceFolder.md new file mode 100644 index 00000000..547e6bbf --- /dev/null +++ b/errors/NoWorkspaceFolder.md @@ -0,0 +1,3 @@ +### Open a Workspace Folder + +CodeRoad requires a workspace folder to run. Open a new workspace and re-launch CodeRoad. diff --git a/src/channel/index.ts b/src/channel/index.ts index 64d52e4e..208b0a2d 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -14,6 +14,7 @@ import { openWorkspace, checkWorkspaceEmpty } from '../services/workspace' import { readFile } from 'fs' import { join } from 'path' import { promisify } from 'util' +import environment from 'environment' const readFileAsync = promisify(readFile) @@ -176,7 +177,18 @@ class Channel implements Channel { vscode.commands.executeCommand(COMMANDS.SET_CURRENT_STEP, action.payload) return case 'EDITOR_VALIDATE_SETUP': - // 1. check workspace is selected + // check if a workspace is open + const noActiveWorksapce = !environment.WORKSPACE_ROOT.length + if (noActiveWorksapce) { + const error: E.ErrorMessage = { + type: 'NoWorkspaceFound', + message: '', + } + this.send({ type: 'VALIDATE_SETUP_FAILED', payload: { error } }) + return + } + + // check workspace is selected const isEmptyWorkspace = await checkWorkspaceEmpty() if (!isEmptyWorkspace) { const error: E.ErrorMessage = { @@ -196,7 +208,7 @@ class Channel implements Channel { this.send({ type: 'VALIDATE_SETUP_FAILED', payload: { error } }) return } - // 2. check Git is installed. + // check Git is installed. // Should wait for workspace before running otherwise requires access to root folder const isGitInstalled = await version('git') if (!isGitInstalled) { diff --git a/src/services/workspace/index.ts b/src/services/workspace/index.ts index 05a3d2cf..a262322a 100644 --- a/src/services/workspace/index.ts +++ b/src/services/workspace/index.ts @@ -25,7 +25,7 @@ export const getWorkspaceRoot = (): string => { const workspaceRoots: vscode.WorkspaceFolder[] | undefined = vscode.workspace.workspaceFolders if (!workspaceRoots || !workspaceRoots.length) { // no workspace root - return 'NO_WORKSPACE_FOUND' + return '' } // a user may have multiple workspace folders // for simplicity, assume the first is the active workspace diff --git a/typings/error.d.ts b/typings/error.d.ts index 79abc3c6..a72b175a 100644 --- a/typings/error.d.ts +++ b/typings/error.d.ts @@ -2,11 +2,12 @@ export type ErrorMessageView = 'FULL_PAGE' | 'NOTIFY' | 'NONE' export type ErrorMessageType = | 'UnknownError' + | 'NoWorkspaceFound' | 'GitNotFound' + | 'WorkspaceNotEmpty' | 'FailedToConnectToGitRepo' | 'GitProjectAlreadyExists' | 'GitRemoteAlreadyExists' - | 'WorkspaceNotEmpty' export type ErrorAction = { label: string From 15f619cbe685d0d78743dd84a962206c5e4559f4 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Apr 2020 20:50:56 -0700 Subject: [PATCH 3/3] workspace folder error page Signed-off-by: shmck --- ...WorkspaceFolder.md => NoWorkspaceFound.md} | 0 package-lock.json | 2 +- package.json | 3 +- src/channel/index.ts | 29 +++++++++++-------- src/editor/index.ts | 1 - src/services/notify/index.ts | 11 ------- web-app/src/services/state/machine.ts | 7 +++++ 7 files changed, 26 insertions(+), 27 deletions(-) rename errors/{NoWorkspaceFolder.md => NoWorkspaceFound.md} (100%) delete mode 100644 src/services/notify/index.ts diff --git a/errors/NoWorkspaceFolder.md b/errors/NoWorkspaceFound.md similarity index 100% rename from errors/NoWorkspaceFolder.md rename to errors/NoWorkspaceFound.md diff --git a/package-lock.json b/package-lock.json index 05c32c43..d9c15328 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "coderoad", - "version": "0.2.1", + "version": "0.2.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index bb4c42dd..8d3067e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coderoad", - "version": "0.2.1", + "version": "0.2.2", "description": "Play interactive coding tutorials in your editor", "keywords": [ "tutorial", @@ -26,7 +26,6 @@ "scripts": { "build": "./scripts/build.sh", "postinstall": "node ./node_modules/vscode/bin/install", - "publish": "vsce publish -p $PERSONAL_ACCESS_TOKEN --packagePath ./releases/coderoad-$npm_package_version.vsix --baseContentUrl https://github.com/coderoad/coderoad-vscode/blob/master --baseImagesUrl https://github.com/coderoad/coderoad-vscode/blob/master", "lint": "eslint src/**/*ts", "package": "./scripts/package.sh", "storybook": "cd web-app && npm run storybook", diff --git a/src/channel/index.ts b/src/channel/index.ts index 208b0a2d..4a64f987 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -14,7 +14,7 @@ import { openWorkspace, checkWorkspaceEmpty } from '../services/workspace' import { readFile } from 'fs' import { join } from 'path' import { promisify } from 'util' -import environment from 'environment' +import environment from '../environment' const readFileAsync = promisify(readFile) @@ -49,6 +49,22 @@ class Channel implements Channel { switch (actionType) { case 'EDITOR_ENV_GET': + // check if a workspace is open, otherwise nothing works + const noActiveWorksapce = !environment.WORKSPACE_ROOT.length + if (noActiveWorksapce) { + const error: E.ErrorMessage = { + type: 'NoWorkspaceFound', + message: '', + actions: [ + { + label: 'Open Workspace', + transition: 'REQUEST_WORKSPACE', + }, + ], + } + this.send({ type: 'NO_WORKSPACE', payload: { error } }) + return + } this.send({ type: 'ENV_LOAD', payload: { @@ -177,17 +193,6 @@ class Channel implements Channel { vscode.commands.executeCommand(COMMANDS.SET_CURRENT_STEP, action.payload) return case 'EDITOR_VALIDATE_SETUP': - // check if a workspace is open - const noActiveWorksapce = !environment.WORKSPACE_ROOT.length - if (noActiveWorksapce) { - const error: E.ErrorMessage = { - type: 'NoWorkspaceFound', - message: '', - } - this.send({ type: 'VALIDATE_SETUP_FAILED', payload: { error } }) - return - } - // check workspace is selected const isEmptyWorkspace = await checkWorkspaceEmpty() if (!isEmptyWorkspace) { diff --git a/src/editor/index.ts b/src/editor/index.ts index 2ca1a7be..f934699f 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -1,5 +1,4 @@ import * as vscode from 'vscode' -import notify from '../services/notify' import { createCommands } from './commands' class Editor { diff --git a/src/services/notify/index.ts b/src/services/notify/index.ts deleted file mode 100644 index 6b9176f1..00000000 --- a/src/services/notify/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as vscode from 'vscode' - -interface Props { - message: string -} - -const notify = ({ message }: Props) => { - vscode.window.setStatusBarMessage(message, 15000) -} - -export default notify diff --git a/web-app/src/services/state/machine.ts b/web-app/src/services/state/machine.ts index 25d89669..787d5f73 100644 --- a/web-app/src/services/state/machine.ts +++ b/web-app/src/services/state/machine.ts @@ -35,11 +35,18 @@ export const createMachine = (options: any) => { states: { Startup: { onEntry: ['loadEnv'], + onExit: ['clearError'], on: { ENV_LOAD: { target: 'LoadStoredTutorial', actions: ['setEnv'], }, + NO_WORKSPACE: { + actions: ['setError'], + }, + REQUEST_WORKSPACE: { + actions: 'requestWorkspaceSelect', + }, }, }, LoadStoredTutorial: {