diff --git a/packages/vscode-extension/README.md b/packages/vscode-extension/README.md index bcfe0ea..ddb71d1 100644 --- a/packages/vscode-extension/README.md +++ b/packages/vscode-extension/README.md @@ -25,6 +25,13 @@ alt="Screenshot of projects view" width="300px" /> Similar to the projects view, the tags view displays projects grouped by their `tags`. +For each tag, two sections are shown: + +- **Tasks** – Lists tasks that exist across projects with that tag. These tasks can be executed for all projects with the tag. +- **Projects** – Lists the projects associated with the tag. + +Running a task from the **Tasks** section will execute the task for all projects matching the tag. + Screenshot of tags view diff --git a/packages/vscode-extension/images/tags-view.png b/packages/vscode-extension/images/tags-view.png index 9fc6f94..8a8ccd9 100644 Binary files a/packages/vscode-extension/images/tags-view.png and b/packages/vscode-extension/images/tags-view.png differ diff --git a/packages/vscode-extension/src/extension.ts b/packages/vscode-extension/src/extension.ts index 34e09ca..4b4d48e 100644 --- a/packages/vscode-extension/src/extension.ts +++ b/packages/vscode-extension/src/extension.ts @@ -34,6 +34,8 @@ export function activate(context: vscode.ExtensionContext) { appendSchemasConfig(context, workspace), ), + vscode.commands.registerCommand('moon.projectTag.runTagTask', (item) => tagsProvider.runTagTask(item)), + // Create a tree view for all moon projects vscode.window.createTreeView('moonProjects', { showCollapseAll: true, diff --git a/packages/vscode-extension/src/projectsView.ts b/packages/vscode-extension/src/projectsView.ts index 8084b1d..a19b3ca 100644 --- a/packages/vscode-extension/src/projectsView.ts +++ b/packages/vscode-extension/src/projectsView.ts @@ -269,6 +269,49 @@ class ProjectTagItem extends TreeItem { } } +class TagTaskItem extends TreeItem { + tag: string; + taskId: string; + + constructor(tag: string, taskId: string) { + super(taskId, TreeItemCollapsibleState.None); + + this.tag = tag; + this.taskId = taskId; + this.id = `tag-${tag}-task-${taskId}`; + this.contextValue = 'tagTask'; + this.iconPath = new ThemeIcon('play'); + + this.command = { + command: 'moon.projectTag.runTagTask', + title: 'Run Tag Task', + arguments: [this], + }; + } +} + +class TagTasksGroup extends TreeItem { + parent: ProjectTagItem; + + constructor(parent: ProjectTagItem) { + super('Tasks', TreeItemCollapsibleState.Expanded); + this.parent = parent; + this.contextValue = 'tagTasksGroup'; + this.iconPath = new ThemeIcon('list-unordered'); + } +} + +class TagProjectsGroup extends TreeItem { + parent: ProjectTagItem; + + constructor(parent: ProjectTagItem) { + super('Projects', TreeItemCollapsibleState.Expanded); + this.parent = parent; + this.contextValue = 'tagProjectsGroup'; + this.iconPath = new ThemeIcon('repo'); + } +} + export type ProjectsType = 'category' | 'tag'; export class ProjectsProvider implements vscode.TreeDataProvider { @@ -354,9 +397,36 @@ export class ProjectsProvider implements vscode.TreeDataProvider { } if (element instanceof ProjectTagItem) { - return element.projects; + if (element.id === `tag-${UNTAGGED}`) { + return element.projects; + } + return [ + new TagTasksGroup(element), + new TagProjectsGroup(element) + ]; + } + + if (element instanceof TagTasksGroup) { + const projects = element.parent.projects; + + const taskIds = new Set(); + + projects.forEach((projectItem) => { + projectItem.tasks.forEach((taskItem) => { + taskIds.add(taskItem.task.id); + }); + }); + + const tag = element.parent.label!.replace('#', ''); + + return Array.from(taskIds) + .sort() + .map((taskId) => new TagTaskItem(tag, taskId)); } + if (element instanceof TagProjectsGroup) { + return element.parent.projects; + } if (!this.projects) { const version = await this.workspace.getMoonVersion(); const args = ['query', 'projects']; @@ -450,6 +520,14 @@ export class ProjectsProvider implements vscode.TreeDataProvider { }); } + async runTagTask(item: TagTaskItem) { + const target = `'#${item.tag}:${item.taskId}'`; + + await runTask(target, this.workspace, (task) => { + task.group = TaskGroup.Build; + }); + } + async checkProject(item: ProjectItem) { await checkProject(item.project.id, this.workspace); }