From 45e2992c50991185ca38ce797627feb8c99d316a Mon Sep 17 00:00:00 2001 From: Hengchang Lu <44047106+luhc228@users.noreply.github.com> Date: Fri, 10 Jul 2020 14:55:54 +0800 Subject: [PATCH] feat: iceworks project viewer style(#177) * feat: add stop command * feat: add stop command * feat: auto install deps * feat: refresh when file changed * fix: fix terminal dispose * fix: treeItem class name * fix: comment * feat: add inputboxs * chore: inputBox text --- extensions/iceworks-app/CHANGELOG.md | 5 ++ extensions/iceworks-app/assets/dark/stop.svg | 1 + extensions/iceworks-app/assets/light/stop.svg | 1 + extensions/iceworks-app/package.json | 17 +++- .../src/commands/executeCommand.ts | 28 +++++++ .../iceworks-app/src/commands/stopCommand.ts | 9 +++ extensions/iceworks-app/src/constants.ts | 2 + extensions/iceworks-app/src/extension.ts | 10 ++- .../src/inputBoxs/showDepsInputBox.ts | 14 ++++ extensions/iceworks-app/src/openEntryFile.ts | 14 ++++ .../src/quickPicks/showDepsQuickPick.ts | 17 ++++ .../showExtensionsQuickPick.ts} | 15 +--- .../statusBar/createExtensionsStatusBar.ts | 10 +++ extensions/iceworks-app/src/utils.ts | 56 ------------- .../iceworks-app/src/views/componentsView.ts | 80 ++++++++++++------- .../src/views/nodeDependenciesView.ts | 77 ++++++++---------- .../iceworks-app/src/views/npmScriptsView.ts | 56 ++++++++----- .../iceworks-app/src/views/pagesView.ts | 32 +++++--- packages/common-service/package.json | 4 +- packages/common-service/src/index.ts | 6 +- 20 files changed, 271 insertions(+), 183 deletions(-) create mode 100644 extensions/iceworks-app/assets/dark/stop.svg create mode 100644 extensions/iceworks-app/assets/light/stop.svg create mode 100644 extensions/iceworks-app/src/commands/executeCommand.ts create mode 100644 extensions/iceworks-app/src/commands/stopCommand.ts create mode 100644 extensions/iceworks-app/src/inputBoxs/showDepsInputBox.ts create mode 100644 extensions/iceworks-app/src/openEntryFile.ts create mode 100644 extensions/iceworks-app/src/quickPicks/showDepsQuickPick.ts rename extensions/iceworks-app/src/{createStatusBarItem.ts => quickPicks/showExtensionsQuickPick.ts} (68%) create mode 100644 extensions/iceworks-app/src/statusBar/createExtensionsStatusBar.ts delete mode 100644 extensions/iceworks-app/src/utils.ts diff --git a/extensions/iceworks-app/CHANGELOG.md b/extensions/iceworks-app/CHANGELOG.md index 5bdd916e9..296e43945 100644 --- a/extensions/iceworks-app/CHANGELOG.md +++ b/extensions/iceworks-app/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 0.2.0 +- feat: install dependencies automatically when node_modules does not exist +- feat: refresh dependencies list、pages list and components list automatically +- feat: support stopping scripts + ## 0.1.34 - feat: add Iceworks status bar entry diff --git a/extensions/iceworks-app/assets/dark/stop.svg b/extensions/iceworks-app/assets/dark/stop.svg new file mode 100644 index 000000000..6ed5ae5af --- /dev/null +++ b/extensions/iceworks-app/assets/dark/stop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions/iceworks-app/assets/light/stop.svg b/extensions/iceworks-app/assets/light/stop.svg new file mode 100644 index 000000000..2538b4940 --- /dev/null +++ b/extensions/iceworks-app/assets/light/stop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions/iceworks-app/package.json b/extensions/iceworks-app/package.json index b8d5fc055..0a7adc1af 100644 --- a/extensions/iceworks-app/package.json +++ b/extensions/iceworks-app/package.json @@ -3,7 +3,7 @@ "displayName": "Iceworks Application Viewer", "description": "Quick view your Universal Application(React/Rax/Vue, etc).", "publisher": "iceworks-team", - "version": "0.1.34", + "version": "0.2.0", "engines": { "vscode": "^1.41.0" }, @@ -108,6 +108,14 @@ "dark": "assets/dark/run.svg" } }, + { + "command": "iceworksApp.npmScripts.stop", + "title": "%iceworksApp.npmScripts.stop.title%", + "icon": { + "light": "assets/light/stop.svg", + "dark": "assets/dark/stop.svg" + } + }, { "command": "iceworksApp.pages.add", "title": "%iceworksApp.command.pages.add.title%", @@ -252,7 +260,12 @@ ], "view/item/context": [ { - "command": "iceworksApp.npmScripts.executeCommand", + "command": "iceworksApp.npmScripts.run", + "when": "view == npmScripts && viewItem == script", + "group": "inline" + }, + { + "command": "iceworksApp.npmScripts.stop", "when": "view == npmScripts && viewItem == script", "group": "inline" }, diff --git a/extensions/iceworks-app/src/commands/executeCommand.ts b/extensions/iceworks-app/src/commands/executeCommand.ts new file mode 100644 index 000000000..53ee58d89 --- /dev/null +++ b/extensions/iceworks-app/src/commands/executeCommand.ts @@ -0,0 +1,28 @@ +import * as vscode from 'vscode'; +import { Terminal, TerminalOptions } from 'vscode'; +import { ITerminalMap } from '../types'; + +export default function executeCommand(terminalMapping: ITerminalMap, script: vscode.Command, id?: string) { + if (!script.arguments) { + return; + } + const args = script.arguments; + const [cwd, command] = args; + if (!command) { + return; + } + + const terminalId = id || command; + let terminal: Terminal; + + if (terminalMapping.has(terminalId)) { + terminal = terminalMapping.get(terminalId)!; + } else { + const terminalOptions: TerminalOptions = { cwd, name: command }; + terminal = vscode.window.createTerminal(terminalOptions); + terminalMapping.set(terminalId, terminal); + } + + terminal.show(); + terminal.sendText(command); +} \ No newline at end of file diff --git a/extensions/iceworks-app/src/commands/stopCommand.ts b/extensions/iceworks-app/src/commands/stopCommand.ts new file mode 100644 index 000000000..e6c4b7f53 --- /dev/null +++ b/extensions/iceworks-app/src/commands/stopCommand.ts @@ -0,0 +1,9 @@ +import { ITerminalMap } from '../types'; + +export default function stopCommand(terminalMapping: ITerminalMap, scriptId: string) { + const currentTerminal = terminalMapping.get(scriptId); + if (currentTerminal) { + currentTerminal.dispose(); + terminalMapping.delete(scriptId); + } +} \ No newline at end of file diff --git a/extensions/iceworks-app/src/constants.ts b/extensions/iceworks-app/src/constants.ts index 9d63cbd32..a82ac4134 100644 --- a/extensions/iceworks-app/src/constants.ts +++ b/extensions/iceworks-app/src/constants.ts @@ -11,3 +11,5 @@ export const nodeDepTypes: NodeDepTypes[] = [ 'dependencies', 'devDependencies' ]; + +export const showExtensionsQuickPickCommandId = 'iceworksApp.showExtensionsQuickPick'; diff --git a/extensions/iceworks-app/src/extension.ts b/extensions/iceworks-app/src/extension.ts index df9bde2f1..f58b6a428 100644 --- a/extensions/iceworks-app/src/extension.ts +++ b/extensions/iceworks-app/src/extension.ts @@ -9,7 +9,9 @@ import { createComponentsTreeProvider } from './views/componentsView'; import { createPagesTreeProvider } from './views/pagesView'; import { ITerminalMap } from './types'; import services from './services'; -import { createStatusBarItem, openCommandPaletteCommandId, registerOpenCommandPalette } from './createStatusBarItem'; +import { showExtensionsQuickPickCommandId } from './constants'; +import showExtensionsQuickPick from './quickPicks/showExtensionsQuickPick'; +import createExtensionsStatusBar from './statusBar/createExtensionsStatusBar'; // eslint-disable-next-line const { name, version } = require('../package.json'); @@ -27,9 +29,9 @@ export async function activate(context: vscode.ExtensionContext) { initExtension(context); // init statusBarItem - const statusBarItem = createStatusBarItem(); - subscriptions.push(vscode.commands.registerCommand(openCommandPaletteCommandId, registerOpenCommandPalette)); - subscriptions.push(statusBarItem); + const extensionsStatusBar = createExtensionsStatusBar(); + subscriptions.push(vscode.commands.registerCommand(showExtensionsQuickPickCommandId, showExtensionsQuickPick)); + subscriptions.push(extensionsStatusBar); // init webview function activeWebview() { const webviewPanel: vscode.WebviewPanel = window.createWebviewPanel('iceworks', '设置 - Iceworks', ViewColumn.One, { diff --git a/extensions/iceworks-app/src/inputBoxs/showDepsInputBox.ts b/extensions/iceworks-app/src/inputBoxs/showDepsInputBox.ts new file mode 100644 index 000000000..47b5e72b2 --- /dev/null +++ b/extensions/iceworks-app/src/inputBoxs/showDepsInputBox.ts @@ -0,0 +1,14 @@ +import * as vscode from 'vscode'; +import { NodeDepTypes, ITerminalMap } from '../types'; +import executeCommand from '../commands/executeCommand'; + +export default async function showDepsInputBox(terminals: ITerminalMap, nodeDependenciesInstance: any, depType: NodeDepTypes) { + const result = await vscode.window.showInputBox({ + placeHolder: '例如: lodash react@latest', + prompt: `请输入需要添加到 ${depType} 的依赖名称, 支持通过空格添加多个依赖` + }); + if (!result) { + return; + } + executeCommand(terminals, nodeDependenciesInstance.getAddDependencyScript(depType, result)); +} diff --git a/extensions/iceworks-app/src/openEntryFile.ts b/extensions/iceworks-app/src/openEntryFile.ts new file mode 100644 index 000000000..057ebd9bf --- /dev/null +++ b/extensions/iceworks-app/src/openEntryFile.ts @@ -0,0 +1,14 @@ +import * as path from 'path'; +import * as vscode from 'vscode'; +import * as fsExtra from 'fs-extra'; +import { entryFileSuffix } from './constants'; + +export default function openEntryFile(p: string) { + const currentSuffix = entryFileSuffix.find((suffix) => fsExtra.pathExistsSync(path.join(p, `index${suffix}`))); + if (currentSuffix) { + const resource = vscode.Uri.file(path.join(p, `index${currentSuffix}`)); + vscode.window.showTextDocument(resource); + } else { + vscode.window.showErrorMessage('Entry file not found.'); + } +} diff --git a/extensions/iceworks-app/src/quickPicks/showDepsQuickPick.ts b/extensions/iceworks-app/src/quickPicks/showDepsQuickPick.ts new file mode 100644 index 000000000..0b31f98d7 --- /dev/null +++ b/extensions/iceworks-app/src/quickPicks/showDepsQuickPick.ts @@ -0,0 +1,17 @@ +import * as vscode from 'vscode'; +import { nodeDepTypes } from '../constants'; +import { NodeDepTypes, ITerminalMap } from '../types'; +import showDepsInputBox from '../inputBoxs/showDepsInputBox'; + +export default function showDepsQuickPick(terminals: ITerminalMap, nodeDependenciesInstance: any) { + const quickPick = vscode.window.createQuickPick(); + quickPick.items = nodeDepTypes.map(label => ({ label, detail: `Install ${label}` })); + quickPick.onDidChangeSelection(selection => { + if (selection[0]) { + showDepsInputBox(terminals, nodeDependenciesInstance, selection[0].label as NodeDepTypes) + .catch(console.error); + } + }); + quickPick.onDidHide(() => quickPick.dispose()); + quickPick.show(); +}; \ No newline at end of file diff --git a/extensions/iceworks-app/src/createStatusBarItem.ts b/extensions/iceworks-app/src/quickPicks/showExtensionsQuickPick.ts similarity index 68% rename from extensions/iceworks-app/src/createStatusBarItem.ts rename to extensions/iceworks-app/src/quickPicks/showExtensionsQuickPick.ts index d4b87453a..2d55d9d64 100644 --- a/extensions/iceworks-app/src/createStatusBarItem.ts +++ b/extensions/iceworks-app/src/quickPicks/showExtensionsQuickPick.ts @@ -1,16 +1,7 @@ import * as vscode from 'vscode'; -const { window } = vscode; +const { window, commands } = vscode; -export const openCommandPaletteCommandId = 'iceworksApp.openVSCodePanel'; - -export function createStatusBarItem() { - const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100); - statusBarItem.text = 'Iceworks'; - statusBarItem.command = openCommandPaletteCommandId; - statusBarItem.show(); - return statusBarItem; -} const extensionOptions = [ { label: 'Iceworks 创建应用', detail: '快速创建多端应用(例如:React/Rax/Vue...)', command: 'iceworks-project-creator.start', }, { label: 'Iceworks 生成页面', detail: '使用低代码的方式生成网页视图', command: 'iceworks-page-builder.create', }, @@ -18,13 +9,13 @@ const extensionOptions = [ { label: 'Iceworks 导入物料', detail: '使用可视化的方式添加物料到应用中', command: 'iceworks-material-import.start' }, ] -export function registerOpenCommandPalette() { +export default function showExtensionsQuickPick() { const quickPick = window.createQuickPick(); quickPick.items = extensionOptions.map((options) => ({ label: options.label, detail: options.detail })); quickPick.onDidChangeSelection(selection => { if (selection[0]) { const currentExtension = extensionOptions.find(option => option.label === selection[0].label)!; - vscode.commands.executeCommand(currentExtension.command); + commands.executeCommand(currentExtension.command); quickPick.dispose(); } }); diff --git a/extensions/iceworks-app/src/statusBar/createExtensionsStatusBar.ts b/extensions/iceworks-app/src/statusBar/createExtensionsStatusBar.ts new file mode 100644 index 000000000..21c6711f9 --- /dev/null +++ b/extensions/iceworks-app/src/statusBar/createExtensionsStatusBar.ts @@ -0,0 +1,10 @@ +import * as vscode from 'vscode'; +import { showExtensionsQuickPickCommandId } from '../constants'; + +export default function createExtensionsStatusBar() { + const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100); + statusBarItem.text = 'Iceworks'; + statusBarItem.command = showExtensionsQuickPickCommandId; + statusBarItem.show(); + return statusBarItem; +} \ No newline at end of file diff --git a/extensions/iceworks-app/src/utils.ts b/extensions/iceworks-app/src/utils.ts deleted file mode 100644 index 467d8c7e1..000000000 --- a/extensions/iceworks-app/src/utils.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as path from 'path'; -import * as fse from 'fs-extra'; -import * as vscode from 'vscode'; -import { Terminal, TerminalOptions } from 'vscode'; -import { entryFileSuffix } from './constants'; -import { ITerminalMap } from './types'; - -export function createTerminalName(cwd: string, command: string): string { - return `${path.basename(cwd)} - ${command}`; -} - -export function pathExists(p: string) { - try { - fse.accessSync(p); - } catch (err) { - return false; - } - return true; -} - -export function executeCommand(terminalMapping: ITerminalMap, script: vscode.Command) { - if (!script.arguments) { - return; - } - const args = script.arguments; - const [cwd, command] = args; - let terminalName = args[2]; - if (!command) { - return; - } - terminalName = terminalName || command; - const name: string = createTerminalName(cwd, terminalName); - - let terminal: Terminal; - - if (terminalMapping.has(name)) { - terminal = terminalMapping.get(name)!; - } else { - const terminalOptions: TerminalOptions = { cwd, name }; - terminal = vscode.window.createTerminal(terminalOptions); - terminalMapping.set(name, terminal); - } - - terminal.show(); - terminal.sendText(command); -} - -export function openEntryFile(p: string) { - const currentSuffix = entryFileSuffix.find(suffix => pathExists(path.join(p, `index${suffix}`))); - if (currentSuffix) { - const resource = vscode.Uri.file(path.join(p, `index${currentSuffix}`)); - vscode.window.showTextDocument(resource); - } else { - vscode.window.showErrorMessage('Entry file not found.'); - } -} diff --git a/extensions/iceworks-app/src/views/componentsView.ts b/extensions/iceworks-app/src/views/componentsView.ts index 26c051232..30b4d9b69 100644 --- a/extensions/iceworks-app/src/views/componentsView.ts +++ b/extensions/iceworks-app/src/views/componentsView.ts @@ -1,16 +1,18 @@ import * as vscode from 'vscode'; import * as fse from 'fs-extra'; import * as path from 'path'; -import { pathExists, openEntryFile } from '../utils'; +import { checkPathExists } from '@iceworks/common-service'; +import { componentsPath } from '@iceworks/project-service'; +import openEntryFile from '../openEntryFile'; -class ComponentsProvider implements vscode.TreeDataProvider { +class ComponentsProvider implements vscode.TreeDataProvider { private workspaceRoot: string; private extensionContext: vscode.ExtensionContext; - private onDidChange: vscode.EventEmitter = new vscode.EventEmitter(); + private onDidChange: vscode.EventEmitter = new vscode.EventEmitter(); - readonly onDidChangeTreeData: vscode.Event = this.onDidChange.event; + readonly onDidChangeTreeData: vscode.Event = this.onDidChange.event; constructor(context: vscode.ExtensionContext, workspaceRoot: string) { this.extensionContext = context; @@ -21,54 +23,64 @@ class ComponentsProvider implements vscode.TreeDataProvider { this.onDidChange.fire(undefined); } - getTreeItem(element: Component): vscode.TreeItem { + getTreeItem(element: ComponentTreeItem): vscode.TreeItem { return element; } - getChildren() { + async getChildren() { if (!this.workspaceRoot) { return Promise.resolve([]); } const componentsPath = path.join(this.workspaceRoot, 'src', 'components'); - if (pathExists(componentsPath)) { - const components = this.getComponents(componentsPath); - return Promise.resolve(components); - } else { + try { + const isComponentPathExists = await checkPathExists(componentsPath); + if (isComponentPathExists) { + const components = this.getComponents(componentsPath); + return Promise.resolve(components); + } else { + return Promise.resolve([]); + } + } catch (error) { return Promise.resolve([]); } } private async getComponents(componentsPath: string) { - if (pathExists(componentsPath)) { - const toComponent = (componentName: string) => { - const pageEntryPath = path.join(componentsPath, componentName); - - const cmdObj: vscode.Command = { - command: 'iceworksApp.components.openFile', - title: 'Open File', - arguments: [pageEntryPath] - }; + try { + const isComponentPathExists = await checkPathExists(componentsPath); + if (isComponentPathExists) { + const toComponent = (componentName: string) => { + const pageEntryPath = path.join(componentsPath, componentName); + + const command: vscode.Command = { + command: 'iceworksApp.components.openFile', + title: 'Open File', + arguments: [pageEntryPath] + }; - return new Component(this.extensionContext, componentName, cmdObj); - }; - const dirNames = await fse.readdir(componentsPath); - // except file - const componentNames = dirNames.filter(dirname => { - const stat = fse.statSync(path.join(componentsPath, dirname)); - return stat.isDirectory(); - }); - return componentNames.map(componentName => toComponent(componentName)); - } else { + return new ComponentTreeItem(this.extensionContext, componentName, command); + }; + const dirNames = await fse.readdir(componentsPath); + // except file + const componentNames = dirNames.filter(dirname => { + const stat = fse.statSync(path.join(componentsPath, dirname)); + return stat.isDirectory(); + }); + return componentNames.map(componentName => toComponent(componentName)); + } else { + return []; + } + } catch (e) { return []; } } } -class Component extends vscode.TreeItem { +class ComponentTreeItem extends vscode.TreeItem { constructor( public readonly extensionContext: vscode.ExtensionContext, public readonly label: string, - public readonly command?: vscode.Command + public readonly command: vscode.Command ) { super(label); } @@ -90,4 +102,10 @@ export function createComponentsTreeProvider(context: vscode.ExtensionContext, r }); vscode.commands.registerCommand('iceworksApp.components.refresh', () => componentsProvider.refresh()); vscode.commands.registerCommand('iceworksApp.components.openFile', (p) => openEntryFile(p)); + + const pattern = path.join(componentsPath); + const fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); + fileWatcher.onDidChange(() => componentsProvider.refresh()); + fileWatcher.onDidCreate(() => componentsProvider.refresh()); + fileWatcher.onDidDelete(() => componentsProvider.refresh()); } \ No newline at end of file diff --git a/extensions/iceworks-app/src/views/nodeDependenciesView.ts b/extensions/iceworks-app/src/views/nodeDependenciesView.ts index 25b242e58..f078a9a89 100644 --- a/extensions/iceworks-app/src/views/nodeDependenciesView.ts +++ b/extensions/iceworks-app/src/views/nodeDependenciesView.ts @@ -8,22 +8,25 @@ import { getPackageLocalVersion } from 'ice-npm-utils'; import { getDataFromSettingJson, createNpmCommand, + checkPathExists } from '@iceworks/common-service'; -import { pathExists, executeCommand } from '../utils'; -import { NodeDepTypes, ITerminalMap } from '../types'; +import { dependencyDir } from '@iceworks/project-service'; +import executeCommand from '../commands/executeCommand'; +import { NodeDepTypes } from '../types'; import { nodeDepTypes } from '../constants'; - +import showDepsInputBox from '../inputBoxs/showDepsInputBox'; +import showDepsQuickPick from '../quickPicks/showDepsQuickPick'; const rimrafAsync = util.promisify(rimraf); -class DepNodeProvider implements vscode.TreeDataProvider { +class DepNodeProvider implements vscode.TreeDataProvider { private workspaceRoot: string; private extensionContext: vscode.ExtensionContext; - private onDidChange: vscode.EventEmitter = new vscode.EventEmitter(); + private onDidChange: vscode.EventEmitter = new vscode.EventEmitter(); - readonly onDidChangeTreeData: vscode.Event = this.onDidChange.event; + readonly onDidChangeTreeData: vscode.Event = this.onDidChange.event; packageJsonPath: string; @@ -41,11 +44,11 @@ class DepNodeProvider implements vscode.TreeDataProvider { this.onDidChange.fire(undefined); } - getTreeItem(element: DependencyNode): vscode.TreeItem { + getTreeItem(element: DependencyTreeItem): vscode.TreeItem { return element; } - getChildren(element?: DependencyNode) { + getChildren(element?: DependencyTreeItem) { if (!this.workspaceRoot) { return Promise.resolve([]); } @@ -56,7 +59,7 @@ class DepNodeProvider implements vscode.TreeDataProvider { return deps; } else { return Promise.resolve( - nodeDepTypes.map(nodeDepType => new DependencyNode(this.extensionContext, nodeDepType, vscode.TreeItemCollapsibleState.Collapsed))); + nodeDepTypes.map(nodeDepType => new DependencyTreeItem(this.extensionContext, nodeDepType, vscode.TreeItemCollapsibleState.Collapsed, nodeDepType))); } } @@ -70,11 +73,11 @@ class DepNodeProvider implements vscode.TreeDataProvider { }; private async getDepsInPackageJson(packageJsonPath: string, label: NodeDepTypes) { - if (pathExists(packageJsonPath)) { + if (await checkPathExists(packageJsonPath)) { const packageJson = JSON.parse(await fse.readFile(packageJsonPath, 'utf-8')); const workspaceDir: string = path.dirname(packageJsonPath); - let deps: DependencyNode[] = []; + let deps: DependencyTreeItem[] = []; if (packageJson[label]) { deps = await Promise.all(Object.keys(packageJson[label]).map(async dep => { const version = this.getDepVersion(dep); @@ -105,14 +108,14 @@ class DepNodeProvider implements vscode.TreeDataProvider { }; }; - public packageJsonExists() { - return pathExists(this.packageJsonPath); + public async packageJsonExists() { + return await checkPathExists(this.packageJsonPath); } public async getReinstallScript() { const workspaceDir: string = path.dirname(this.packageJsonPath); const nodeModulesPath = path.join(workspaceDir, 'node_modules'); - if (pathExists(nodeModulesPath)) { + if (await checkPathExists(nodeModulesPath)) { await rimrafAsync(nodeModulesPath); } const npmCommand = createNpmCommand('install'); @@ -147,16 +150,18 @@ class DepNodeProvider implements vscode.TreeDataProvider { } } -class DependencyNode extends vscode.TreeItem { +class DependencyTreeItem extends vscode.TreeItem { constructor( public readonly extensionContext: vscode.ExtensionContext, public readonly label: string, public readonly collapsibleState: vscode.TreeItemCollapsibleState, + public readonly id: string, public readonly command?: vscode.Command, public readonly version?: string, public readonly outDated?: boolean ) { super(label, collapsibleState); + this.id = id; } get description(): string { @@ -181,40 +186,26 @@ export function createNodeDependenciesTreeProvider(context, rootPath, terminals) const nodeDependenciesProvider = new DepNodeProvider(context, rootPath); vscode.window.registerTreeDataProvider('nodeDependencies', nodeDependenciesProvider); vscode.commands.registerCommand('iceworksApp.nodeDependencies.refresh', () => nodeDependenciesProvider.refresh()); - vscode.commands.registerCommand('iceworksApp.nodeDependencies.upgrade', (node: DependencyNode) => executeCommand(terminals, node.command!)); + vscode.commands.registerCommand('iceworksApp.nodeDependencies.upgrade', (node: DependencyTreeItem) => { + if (node.command) + executeCommand(terminals, node.command, node.id); + }); vscode.commands.registerCommand('iceworksApp.nodeDependencies.reinstall', async () => { - if (nodeDependenciesProvider.packageJsonExists()) { + if (await nodeDependenciesProvider.packageJsonExists()) { const script = await nodeDependenciesProvider.getReinstallScript(); executeCommand(terminals, script!); } }); - context.subscriptions.push(vscode.commands.registerCommand('iceworksApp.nodeDependencies.dependencies.add', () => showDepInputBox(terminals, nodeDependenciesProvider, 'dependencies'))); - context.subscriptions.push(vscode.commands.registerCommand('iceworksApp.nodeDependencies.devDependencies.add', () => showDepInputBox(terminals, nodeDependenciesProvider, 'devDependencies'))); - context.subscriptions.push(vscode.commands.registerCommand('iceworksApp.nodeDependencies.addDepsAndDevDeps', () => addDepCommandHandler(terminals, nodeDependenciesProvider))); -} + context.subscriptions.push(vscode.commands.registerCommand('iceworksApp.nodeDependencies.dependencies.add', () => showDepsInputBox(terminals, nodeDependenciesProvider, 'dependencies'))); + context.subscriptions.push(vscode.commands.registerCommand('iceworksApp.nodeDependencies.devDependencies.add', () => showDepsInputBox(terminals, nodeDependenciesProvider, 'devDependencies'))); + context.subscriptions.push(vscode.commands.registerCommand('iceworksApp.nodeDependencies.addDepsAndDevDeps', () => showDepsQuickPick(terminals, nodeDependenciesProvider))); -export function addDepCommandHandler(terminals: ITerminalMap, nodeDependenciesInstance: any) { - const quickPick = vscode.window.createQuickPick(); - quickPick.items = nodeDepTypes.map(label => ({ label, detail: `Install ${label}` })); - quickPick.onDidChangeSelection(selection => { - if (selection[0]) { - showDepInputBox(terminals, nodeDependenciesInstance, selection[0].label as NodeDepTypes) - .catch(console.error); - } - }); - quickPick.onDidHide(() => quickPick.dispose()); - quickPick.show(); -}; - -async function showDepInputBox(terminals: ITerminalMap, nodeDependenciesInstance: any, depType: NodeDepTypes) { - const result = await vscode.window.showInputBox({ - placeHolder: 'Please input the module name you want to install. For example lodash / loadsh@latest', - }); - if (!result) { - return; - } - executeCommand(terminals, nodeDependenciesInstance.getAddDependencyScript(depType, result)); + const pattern = path.join(rootPath, dependencyDir); + const fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); + fileWatcher.onDidChange(() => nodeDependenciesProvider.refresh()); + fileWatcher.onDidCreate(() => nodeDependenciesProvider.refresh()); + fileWatcher.onDidDelete(() => nodeDependenciesProvider.refresh()); } function toDep(extensionContext: vscode.ExtensionContext, workspaceDir: string, moduleName: string, version: string, outdated: boolean) { @@ -228,5 +219,5 @@ function toDep(extensionContext: vscode.ExtensionContext, workspaceDir: string, arguments: [workspaceDir, npmCommand] } : undefined; - return new DependencyNode(extensionContext, moduleName, vscode.TreeItemCollapsibleState.None, command, version, outdated); + return new DependencyTreeItem(extensionContext, moduleName, vscode.TreeItemCollapsibleState.None, `dependency-${moduleName}`, command, version, outdated); }; diff --git a/extensions/iceworks-app/src/views/npmScriptsView.ts b/extensions/iceworks-app/src/views/npmScriptsView.ts index 886694e1b..6e614d0bc 100644 --- a/extensions/iceworks-app/src/views/npmScriptsView.ts +++ b/extensions/iceworks-app/src/views/npmScriptsView.ts @@ -1,25 +1,27 @@ import * as vscode from 'vscode'; import * as fse from 'fs-extra'; import * as path from 'path'; -import { createNpmCommand } from '@iceworks/common-service' -import { pathExists, executeCommand } from '../utils'; +import { createNpmCommand, checkPathExists } from '@iceworks/common-service'; +import { dependencyDir, packageJSONFilename } from '@iceworks/project-service'; +import executeCommand from '../commands/executeCommand'; +import stopCommand from '../commands/stopCommand'; import { ITerminalMap } from '../types'; -export class NpmScriptsProvider implements vscode.TreeDataProvider