From e0f6cf7d8921ca7eb5cda80552579c46365030bb Mon Sep 17 00:00:00 2001 From: Miles Johnson Date: Thu, 25 Jan 2024 16:16:13 -0800 Subject: [PATCH] new: Add Tags view for moon console. (#62) * Add tag support. * Update manifest. * Bump version. * Update readme. * Collapse by default. --- packages/vscode-extension/CHANGELOG.md | 4 + packages/vscode-extension/README.md | 15 ++- .../vscode-extension/images/tags-view.png | Bin 0 -> 16128 bytes packages/vscode-extension/moon.yml | 3 +- packages/vscode-extension/package.json | 109 ++++++++++------- packages/vscode-extension/src/extension.ts | 23 ++-- packages/vscode-extension/src/projectsView.ts | 113 +++++++++++++++--- 7 files changed, 195 insertions(+), 72 deletions(-) create mode 100644 packages/vscode-extension/images/tags-view.png diff --git a/packages/vscode-extension/CHANGELOG.md b/packages/vscode-extension/CHANGELOG.md index a11fde9..ef38b63 100644 --- a/packages/vscode-extension/CHANGELOG.md +++ b/packages/vscode-extension/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.0 + +- Added a "Tags" view for projects in the moon console sidebar. + ## 0.8.0 - Added a `moon.logLevel` setting, to control the log level of all moon executed commands. diff --git a/packages/vscode-extension/README.md b/packages/vscode-extension/README.md index 937584f..2168387 100644 --- a/packages/vscode-extension/README.md +++ b/packages/vscode-extension/README.md @@ -21,6 +21,16 @@ alt="Screenshot of projects view" width="300px" /> > This view is available in both the "Explorer" and "moon" sections. +### Tags view + +Similar to the projects view, the tags view displays projects grouped by their `tags`. + + + +> This view is only available in the "moon" section. + ### Last run view Information about the last ran task will be displayed in a beautiful table with detailed stats. @@ -29,6 +39,8 @@ Information about the last ran task will be displayed in a beautiful table with src="https://raw.githubusercontent.com/moonrepo/dev/master/packages/vscode-extension/images/last-run-view.png" alt="Screenshot of last run view" width="300px" /> +> This view is only available in the "moon" section. + ### Control panel To provide the best experience, all major features, enhancements, and integrations can be found @@ -63,8 +75,6 @@ prefixed with "moon". - **Open settings** - Opens the settings page and filters to all moon applicable settings. - **Run task** - Prompts the user for a task(s) and runs it in the terminal. -- **Refresh projects** - Refreshes the projects view. _This happens automatically when - `.moon/workspace.yml` changes!_ - **View action graph** - Opens a panel that renders an interactive action graph visualization. - **View project graph** - Opens a panel that renders an interactive project graph visualization. @@ -76,6 +86,7 @@ prefixed with "moon". - [x] Categorize tasks based on type - [x] Run a task - [x] Check a project +- [x] Tags view - [x] Last run view - [x] Commands and command palette - [x] Watches and reacts to file system changes. diff --git a/packages/vscode-extension/images/tags-view.png b/packages/vscode-extension/images/tags-view.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc6f9446194e8c66330ae68e417689444dbe2da GIT binary patch literal 16128 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 Y8-_CBvrua%$lK$eBo!no#S8-e7i2f#p8x;= literal 0 HcmV?d00001 diff --git a/packages/vscode-extension/moon.yml b/packages/vscode-extension/moon.yml index 5a4a1dc..b374061 100644 --- a/packages/vscode-extension/moon.yml +++ b/packages/vscode-extension/moon.yml @@ -1,4 +1,5 @@ -type: 'library' +type: 'tool' +tags: ['extension'] project: name: 'VS Code extension' diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index 1473bc3..39d4c2c 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "0.8.0", + "version": "0.9.0", "name": "moon-console", "publisher": "moonrepo", "displayName": "moon console", @@ -38,7 +38,8 @@ "directory": "packages/vscode-extension" }, "activationEvents": [ - "workspaceContains:moon.yml" + "workspaceContains:.moon", + "workspaceContains:**/moon.yml" ], "main": "./lib/extension.js", "contributes": { @@ -75,62 +76,66 @@ "title": "moon: Open settings" }, { - "command": "moon.refreshProjects", + "command": "moon.runTaskByInput", + "title": "moon: Run one or many tasks" + }, + { + "command": "moon.viewActionGraph", + "title": "moon: View action graph", + "icon": "$(gather)" + }, + { + "command": "moon.viewProjectGraph", + "title": "moon: View project graph", + "icon": "$(type-hierarchy-sub)" + }, + { + "command": "moon.projectCategory.refreshProjects", "title": "moon: Refresh projects", "icon": "$(refresh)" }, { - "command": "moon.checkProject", + "command": "moon.projectCategory.checkProject", "title": "moon: Run all buildable and testable tasks for a project", "icon": "$(run-all)" }, { - "command": "moon.runTask", + "command": "moon.projectCategory.runTask", "title": "moon: Run the task", "icon": "$(run)" }, { - "command": "moon.runTaskByInput", - "title": "moon: Run one or many tasks" - }, - { - "command": "moon.viewProject", + "command": "moon.projectCategory.viewProject", "title": "moon: View selected project", "icon": "$(open-preview)" }, { - "command": "moon.viewActionGraph", - "title": "moon: View action graph", - "icon": "$(gather)" + "command": "moon.projectTag.refreshProjects", + "title": "moon: Refresh projects", + "icon": "$(refresh)" }, { - "command": "moon.viewProjectGraph", - "title": "moon: View project graph", - "icon": "$(type-hierarchy-sub)" + "command": "moon.projectTag.checkProject", + "title": "moon: Run all buildable and testable tasks for a project", + "icon": "$(run-all)" + }, + { + "command": "moon.projectTag.runTask", + "title": "moon: Run the task", + "icon": "$(run)" + }, + { + "command": "moon.projectTag.viewProject", + "title": "moon: View selected project", + "icon": "$(open-preview)" } ], "menus": { "commandPalette": [ - { - "command": "moon.refreshProjects", - "when": "moon.hasBinary" - }, - { - "command": "moon.checkProject", - "when": "false" - }, - { - "command": "moon.runTask", - "when": "false" - }, { "command": "moon.runTaskByInput", "when": "moon.hasBinary" }, - { - "command": "moon.viewProject", - "when": "false" - }, { "command": "moon.viewActionGraph", "when": "moon.hasBinary" @@ -142,12 +147,17 @@ ], "view/title": [ { - "command": "moon.refreshProjects", + "command": "moon.projectTag.refreshProjects", + "when": "view == moonTags && moon.hasBinary", + "group": "navigation" + }, + { + "command": "moon.projectCategory.refreshProjects", "when": "view == moonProjects && moon.hasBinary", "group": "navigation" }, { - "command": "moon.refreshProjects", + "command": "moon.projectCategory.refreshProjects", "when": "view == moonProjectsExternal && moon.hasBinary", "group": "navigation" }, @@ -174,32 +184,47 @@ ], "view/item/context": [ { - "command": "moon.runTask", + "command": "moon.projectTag.runTask", + "when": "view == moonTags && viewItem == projectTask", + "group": "inline" + }, + { + "command": "moon.projectTag.viewProject", + "when": "view == moonTags && viewItem == project", + "group": "inline@0" + }, + { + "command": "moon.projectTag.checkProject", + "when": "view == moonTags && viewItem == project", + "group": "inline@1" + }, + { + "command": "moon.projectCategory.runTask", "when": "view == moonProjects && viewItem == projectTask", "group": "inline" }, { - "command": "moon.viewProject", + "command": "moon.projectCategory.viewProject", "when": "view == moonProjects && viewItem == project", "group": "inline@0" }, { - "command": "moon.checkProject", + "command": "moon.projectCategory.checkProject", "when": "view == moonProjects && viewItem == project", "group": "inline@1" }, { - "command": "moon.runTask", + "command": "moon.projectCategory.runTask", "when": "view == moonProjectsExternal && viewItem == projectTask", "group": "inline" }, { - "command": "moon.viewProject", + "command": "moon.projectCategory.viewProject", "when": "view == moonProjectsExternal && viewItem == project", "group": "inline@0" }, { - "command": "moon.checkProject", + "command": "moon.projectCategory.checkProject", "when": "view == moonProjectsExternal && viewItem == project", "group": "inline@1" } @@ -226,6 +251,10 @@ "id": "moonProjects", "name": "Projects" }, + { + "id": "moonTags", + "name": "Tags" + }, { "id": "moonLastRun", "name": "Last run", diff --git a/packages/vscode-extension/src/extension.ts b/packages/vscode-extension/src/extension.ts index 859dedf..50231fb 100644 --- a/packages/vscode-extension/src/extension.ts +++ b/packages/vscode-extension/src/extension.ts @@ -6,15 +6,22 @@ import { Workspace } from './workspace'; export function activate(context: vscode.ExtensionContext) { const workspace = new Workspace(); - const projectsProvider = new ProjectsProvider(context, workspace); + const projectsProvider = new ProjectsProvider(context, workspace, 'category'); + const tagsProvider = new ProjectsProvider(context, workspace, 'tag'); context.subscriptions.push( vscode.commands.registerCommand('moon.openSettings', () => vscode.commands.executeCommand('workbench.action.openSettings', '@ext:moonrepo.moon-console'), ), - // Create a "moon run " task + // Create commands vscode.commands.registerCommand('moon.runTaskByInput', () => runTaskByInput(workspace)), + vscode.commands.registerCommand('moon.viewActionGraph', () => + viewActionGraph(context, workspace), + ), + vscode.commands.registerCommand('moon.viewProjectGraph', () => + viewProjectGraph(context, workspace), + ), // Create a tree view for all moon projects vscode.window.createTreeView('moonProjects', { @@ -25,14 +32,10 @@ export function activate(context: vscode.ExtensionContext) { showCollapseAll: true, treeDataProvider: projectsProvider, }), - - // Create graph visualizers - vscode.commands.registerCommand('moon.viewActionGraph', () => - viewActionGraph(context, workspace), - ), - vscode.commands.registerCommand('moon.viewProjectGraph', () => - viewProjectGraph(context, workspace), - ), + vscode.window.createTreeView('moonTags', { + showCollapseAll: true, + treeDataProvider: tagsProvider, + }), // Create a webview for last run report vscode.window.registerWebviewViewProvider( diff --git a/packages/vscode-extension/src/projectsView.ts b/packages/vscode-extension/src/projectsView.ts index 242e95f..7b67e7b 100644 --- a/packages/vscode-extension/src/projectsView.ts +++ b/packages/vscode-extension/src/projectsView.ts @@ -14,6 +14,7 @@ import type { LanguageType, Project, ProjectType, Task as ProjectTask } from '@m import { checkProject, runTask } from './commands'; import type { Workspace } from './workspace'; +const UNTAGGED = '__untagged__'; const LANGUAGE_MANIFESTS: Record = { bash: '', batch: '', @@ -112,13 +113,17 @@ class TaskItem extends TreeItem { class ProjectItem extends TreeItem { context: vscode.ExtensionContext; - parent: ProjectCategoryItem; + parent: ProjectCategoryItem | ProjectTagItem; project: Project; tasks: TaskItem[]; - constructor(context: vscode.ExtensionContext, parent: ProjectCategoryItem, project: Project) { + constructor( + context: vscode.ExtensionContext, + parent: ProjectCategoryItem | ProjectTagItem, + project: Project, + ) { super(project.id, TreeItemCollapsibleState.Collapsed); this.context = context; @@ -138,6 +143,8 @@ class ProjectItem extends TreeItem { .filter((task) => canShowTask(task.target, this.parent.hideTasks)) .map((task) => new TaskItem(this, task)); + this.tasks.sort((a, d) => a.id!.localeCompare(d.id!)); + this.resourceUri = Uri.file( path.join(project.root, LANGUAGE_MANIFESTS[language] || 'moon.yml'), ); @@ -188,28 +195,60 @@ class ProjectCategoryItem extends TreeItem { } } +class ProjectTagItem extends TreeItem { + context: vscode.ExtensionContext; + + projects: ProjectItem[] = []; + + hideTasks: Set; + + constructor(context: vscode.ExtensionContext, tag: string, projects: Project[]) { + super(tag, TreeItemCollapsibleState.Collapsed); + + this.context = context; + this.id = tag; + this.contextValue = 'projectTag'; + + this.hideTasks = new Set(vscode.workspace.getConfiguration('moon').get('hideTasks', [])); + this.projects = projects.map((project) => new ProjectItem(context, this, project)); + + this.label = tag === UNTAGGED ? 'Untagged' : `#${tag}`; + } +} + +export type ProjectsType = 'category' | 'tag'; + export class ProjectsProvider implements vscode.TreeDataProvider { context: vscode.ExtensionContext; projects?: Project[]; + type: ProjectsType; + workspace: Workspace; onDidChangeTreeDataEmitter: EventEmitter; onDidChangeTreeData: Event; - constructor(context: vscode.ExtensionContext, workspace: Workspace) { + constructor(context: vscode.ExtensionContext, workspace: Workspace, type: ProjectsType) { this.context = context; this.workspace = workspace; + this.type = type; this.onDidChangeTreeDataEmitter = new EventEmitter(); this.onDidChangeTreeData = this.onDidChangeTreeDataEmitter.event; + const commandPrefix = type === 'category' ? 'projectCategory' : 'projectTag'; + context.subscriptions.push( - vscode.commands.registerCommand('moon.refreshProjects', this.refresh, this), - vscode.commands.registerCommand('moon.runTask', this.runTask, this), - vscode.commands.registerCommand('moon.checkProject', this.checkProject, this), - vscode.commands.registerCommand('moon.viewProject', this.viewProject, this), + vscode.commands.registerCommand(`moon.${commandPrefix}.refreshProjects`, this.refresh, this), + vscode.commands.registerCommand(`moon.${commandPrefix}.runTask`, this.runTask, this), + vscode.commands.registerCommand( + `moon.${commandPrefix}.checkProject`, + this.checkProject, + this, + ), + vscode.commands.registerCommand(`moon.${commandPrefix}.viewProject`, this.viewProject, this), ); workspace.onDidChangeWorkspace((folder) => { @@ -261,6 +300,10 @@ export class ProjectsProvider implements vscode.TreeDataProvider { return element.projects; } + if (element instanceof ProjectTagItem) { + return element.projects; + } + if (!this.projects) { const { projects } = JSON.parse( await this.workspace.execMoon(['query', 'projects', '--json']), @@ -271,20 +314,52 @@ export class ProjectsProvider implements vscode.TreeDataProvider { this.projects = projects.sort((a, d) => a.id.localeCompare(d.id)); } - const categories = [ - new ProjectCategoryItem(this.context, 'application', this.projects), - new ProjectCategoryItem(this.context, 'automation', this.projects), - new ProjectCategoryItem(this.context, 'library', this.projects), - new ProjectCategoryItem(this.context, 'tool', this.projects), - new ProjectCategoryItem(this.context, 'unknown', this.projects), - ].filter((cat) => cat.projects.length > 0); - - // If only 1 category, flatten the projects list - if (categories.length === 1) { - return categories[0].projects; + const sections = ( + this.type === 'category' ? this.getCategoryChildren() : this.getTagChildren() + ).filter((section) => section.projects.length > 0); + + // If only 1 section, flatten the projects list + if (this.type === 'category' && sections.length === 1) { + return sections[0].projects; } - return categories; + return sections; + } + + getCategoryChildren(): ProjectCategoryItem[] { + const projects = this.projects!; + + return [ + new ProjectCategoryItem(this.context, 'application', projects), + new ProjectCategoryItem(this.context, 'automation', projects), + new ProjectCategoryItem(this.context, 'library', projects), + new ProjectCategoryItem(this.context, 'tool', projects), + new ProjectCategoryItem(this.context, 'unknown', projects), + ]; + } + + getTagChildren(): ProjectTagItem[] { + const tags: Record = {}; + const untagged: Project[] = []; + + this.projects!.forEach((project) => { + if (project.config.tags.length === 0) { + untagged.push(project); + } else { + project.config.tags.forEach((tag) => { + tags[tag] ||= []; + tags[tag].push(project); + }); + } + }); + + const sections = Object.entries(tags).map( + ([tag, projects]) => new ProjectTagItem(this.context, tag, projects), + ); + + sections.push(new ProjectTagItem(this.context, UNTAGGED, untagged)); + + return sections; } getTreeItem(element: TreeItem): Thenable | TreeItem {