From 049b6bdc8fe2bcf77f479d4c868edc51d5396f66 Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Thu, 21 Nov 2024 21:48:27 -0500 Subject: [PATCH] Add actions to add and open secret, variable, and input files Signed-off-by: Sanjula Ganepola --- package.json | 79 ++++++++++++++++++- src/act.ts | 36 ++++----- src/historyManager.ts | 4 +- src/settingsManager.ts | 46 ++++++++++- src/storageManager.ts | 3 + src/views/history/history.ts | 2 +- src/views/settings/inputs.ts | 20 ++++- src/views/settings/secrets.ts | 20 ++++- src/views/settings/setting.ts | 9 ++- src/views/settings/settingFile.ts | 59 ++++++++++++++ .../settings/settingsTreeDataProvider.ts | 71 +++++++++++++++-- src/views/settings/variables.ts | 20 ++++- 12 files changed, 325 insertions(+), 44 deletions(-) create mode 100644 src/views/settings/settingFile.ts diff --git a/package.json b/package.json index 422e76c..42c8094 100644 --- a/package.json +++ b/package.json @@ -240,6 +240,12 @@ "title": "Refresh", "icon": "$(refresh)" }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.addSecretFiles", + "title": "Add Secret Files", + "icon": "$(add)" + }, { "category": "GitHub Local Actions", "command": "githubLocalActions.show", @@ -252,12 +258,36 @@ "title": "Hide", "icon": "$(eye-closed)" }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.addVariableFiles", + "title": "Add Variable Files", + "icon": "$(add)" + }, { "category": "GitHub Local Actions", "command": "githubLocalActions.importFromGithub", "title": "Import from GitHub", "icon": "$(github)" }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.addInputFiles", + "title": "Add Input Files", + "icon": "$(add)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.openSettingFile", + "title": "Open", + "icon": "$(go-to-file)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.removeSettingFile", + "title": "Remove", + "icon": "$(close)" + }, { "category": "GitHub Local Actions", "command": "githubLocalActions.editSetting", @@ -352,6 +382,10 @@ "command": "githubLocalActions.refreshSettings", "when": "never" }, + { + "command": "githubLocalActions.addSecretFiles", + "when": "never" + }, { "command": "githubLocalActions.show", "when": "never" @@ -360,10 +394,26 @@ "command": "githubLocalActions.hide", "when": "never" }, + { + "command": "githubLocalActions.addVariableFiles", + "when": "never" + }, { "command": "githubLocalActions.importFromGithub", "when": "never" }, + { + "command": "githubLocalActions.addInputFiles", + "when": "never" + }, + { + "command": "githubLocalActions.openSettingFile", + "when": "never" + }, + { + "command": "githubLocalActions.removeSettingFile", + "when": "never" + }, { "command": "githubLocalActions.editSetting", "when": "never" @@ -495,6 +545,11 @@ "when": "view == history && viewItem =~ /^githubLocalActions.history.*/", "group": "inline@3" }, + { + "command": "githubLocalActions.addSecretFiles", + "when": "view == settings && viewItem =~ /^githubLocalActions.secrets.*/", + "group": "inline@0" + }, { "command": "githubLocalActions.show", "when": "view == settings && viewItem =~ /^githubLocalActions.secret(?!s)_hide.*/", @@ -506,13 +561,33 @@ "group": "inline@0" }, { - "command": "githubLocalActions.importFromGithub", + "command": "githubLocalActions.addVariableFiles", "when": "view == settings && viewItem =~ /^githubLocalActions.variables.*/", "group": "inline@0" }, + { + "command": "githubLocalActions.importFromGithub", + "when": "view == settings && viewItem =~ /^githubLocalActions.variables.*/", + "group": "inline@1" + }, + { + "command": "githubLocalActions.addInputFiles", + "when": "view == settings && viewItem =~ /^githubLocalActions.inputs.*/", + "group": "inline@0" + }, + { + "command": "githubLocalActions.openSettingFile", + "when": "view == settings && viewItem =~ /^githubLocalActions.(secret|variable|input)File.*/", + "group": "inline@0" + }, + { + "command": "githubLocalActions.removeSettingFile", + "when": "view == settings && viewItem =~ /^githubLocalActions.(secret|variable|input)File.*/", + "group": "inline@1" + }, { "command": "githubLocalActions.editSetting", - "when": "view == settings && viewItem =~ /^githubLocalActions.(secret|variable|input|runner)(?!s).*/", + "when": "view == settings && viewItem =~ /^githubLocalActions.(secret|variable|input|runner)(?!(File|s)).*/", "group": "inline@1" } ] diff --git a/src/act.ts b/src/act.ts index feb2a0b..051cc4e 100644 --- a/src/act.ts +++ b/src/act.ts @@ -55,7 +55,7 @@ export enum Option { } export interface CommandArgs { - fsPath: string, + path: string, options: string, name: string, extraHeader: { key: string, value: string }[] @@ -168,7 +168,7 @@ export class Act { const historyIndex = taskDefinition.historyIndex; // Add new entry to workspace history - this.historyManager.workspaceHistory[commandArgs.fsPath].push({ + this.historyManager.workspaceHistory[commandArgs.path].push({ index: historyIndex, count: taskDefinition.count, name: `${commandArgs.name}`, @@ -191,18 +191,18 @@ export class Act { const historyIndex = taskDefinition.historyIndex; // Set end status - if (this.historyManager.workspaceHistory[commandArgs.fsPath][historyIndex].status === HistoryStatus.Running) { + if (this.historyManager.workspaceHistory[commandArgs.path][historyIndex].status === HistoryStatus.Running) { if (e.exitCode === 0) { - this.historyManager.workspaceHistory[commandArgs.fsPath][historyIndex].status = HistoryStatus.Success; + this.historyManager.workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Success; } else if (!e.exitCode) { - this.historyManager.workspaceHistory[commandArgs.fsPath][historyIndex].status = HistoryStatus.Cancelled; + this.historyManager.workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Cancelled; } else { - this.historyManager.workspaceHistory[commandArgs.fsPath][historyIndex].status = HistoryStatus.Failed; + this.historyManager.workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Failed; } } // Set end time - this.historyManager.workspaceHistory[commandArgs.fsPath][historyIndex].date.end = new Date().toString(); + this.historyManager.workspaceHistory[commandArgs.path][historyIndex].date.end = new Date().toString(); historyTreeDataProvider.refresh(); this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); @@ -212,7 +212,7 @@ export class Act { async runAllWorkflows(workspaceFolder: WorkspaceFolder) { return await this.runCommand({ - fsPath: workspaceFolder.uri.fsPath, + path: workspaceFolder.uri.fsPath, options: ``, name: workspaceFolder.name, extraHeader: [] @@ -221,7 +221,7 @@ export class Act { async runWorkflow(workspaceFolder: WorkspaceFolder, workflow: Workflow) { return await this.runCommand({ - fsPath: workspaceFolder.uri.fsPath, + path: workspaceFolder.uri.fsPath, options: `${Option.Workflows} ".github/workflows/${path.parse(workflow.uri.fsPath).base}"`, name: workflow.name, extraHeader: [ @@ -232,7 +232,7 @@ export class Act { async runJob(workspaceFolder: WorkspaceFolder, workflow: Workflow, job: Job) { return await this.runCommand({ - fsPath: workspaceFolder.uri.fsPath, + path: workspaceFolder.uri.fsPath, options: `${Option.Workflows} ".github/workflows/${path.parse(workflow.uri.fsPath).base}" ${Option.Job} "${job.id}"`, name: `${workflow.name}/${job.name}`, extraHeader: [ @@ -244,7 +244,7 @@ export class Act { async runEvent(workspaceFolder: WorkspaceFolder, event: Event) { return await this.runCommand({ - fsPath: workspaceFolder.uri.fsPath, + path: workspaceFolder.uri.fsPath, options: event, name: event, extraHeader: [ @@ -266,21 +266,21 @@ export class Act { // } // Map to workspace folder - const workspaceFolder = workspace.getWorkspaceFolder(Uri.file(commandArgs.fsPath)); + const workspaceFolder = workspace.getWorkspaceFolder(Uri.file(commandArgs.path)); if (!workspaceFolder) { - window.showErrorMessage(`Failed to locate workspace folder for ${commandArgs.fsPath}`); + window.showErrorMessage(`Failed to locate workspace folder for ${commandArgs.path}`); return; } // Initialize history for workspace - if (!this.historyManager.workspaceHistory[commandArgs.fsPath]) { - this.historyManager.workspaceHistory[commandArgs.fsPath] = []; + if (!this.historyManager.workspaceHistory[commandArgs.path]) { + this.historyManager.workspaceHistory[commandArgs.path] = []; this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); } // Process task count suffix - const historyIndex = this.historyManager.workspaceHistory[commandArgs.fsPath].length; - const matchingTasks = this.historyManager.workspaceHistory[commandArgs.fsPath] + const historyIndex = this.historyManager.workspaceHistory[commandArgs.path].length; + const matchingTasks = this.historyManager.workspaceHistory[commandArgs.path] .filter(history => history.name === commandArgs.name) .sort((a, b) => b.count - a.count); const count = matchingTasks && matchingTasks.length > 0 ? matchingTasks[0].count + 1 : 1; @@ -341,7 +341,7 @@ export class Act { execution: new ShellExecution( command, { - cwd: commandArgs.fsPath, + cwd: commandArgs.path, env: settings.secrets .filter(secret => secret.value) .reduce((previousValue, currentValue) => { diff --git a/src/historyManager.ts b/src/historyManager.ts index cf38f5d..3bc45b8 100644 --- a/src/historyManager.ts +++ b/src/historyManager.ts @@ -74,8 +74,8 @@ export class HistoryManager { } async remove(history: History) { - const historyIndex = this.workspaceHistory[history.commandArgs.fsPath].findIndex(workspaceHistory => workspaceHistory.index === history.index); - this.workspaceHistory[history.commandArgs.fsPath].splice(historyIndex, 1); + const historyIndex = this.workspaceHistory[history.commandArgs.path].findIndex(workspaceHistory => workspaceHistory.index === history.index); + this.workspaceHistory[history.commandArgs.path].splice(historyIndex, 1); this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); try { diff --git a/src/settingsManager.ts b/src/settingsManager.ts index 01ae06c..95424e0 100644 --- a/src/settingsManager.ts +++ b/src/settingsManager.ts @@ -4,6 +4,17 @@ import { GitHubManager } from "./githubManager"; import { SecretManager } from "./secretManager"; import { StorageKey, StorageManager } from "./storageManager"; +export interface Settings { + secrets: Setting[]; + secretFiles: SettingFile[]; + variables: Setting[]; + variableFiles: SettingFile[]; + inputs: Setting[]; + inputFiles: SettingFile[]; + runners: Setting[]; + environments: Setting[]; +} + export interface Setting { key: string, value: string, @@ -12,6 +23,12 @@ export interface Setting { visible: Visibility } +export interface SettingFile { + name: string, + path: string, + selected: boolean +} + export enum Visibility { show = 'show', hide = 'hide' @@ -32,17 +49,23 @@ export class SettingsManager { this.githubManager = new GitHubManager(); } - async getSettings(workspaceFolder: WorkspaceFolder, isUserSelected: boolean) { + async getSettings(workspaceFolder: WorkspaceFolder, isUserSelected: boolean): Promise { const secrets = (await this.getSetting(workspaceFolder, SettingsManager.secretsRegExp, StorageKey.Secrets, true, Visibility.hide)).filter(secret => !isUserSelected || secret.selected); + const secretFiles = await this.getSettingFiles(workspaceFolder, StorageKey.SecretFiles); const variables = (await this.getSetting(workspaceFolder, SettingsManager.variablesRegExp, StorageKey.Variables, false, Visibility.show)).filter(variable => !isUserSelected || variable.selected); + const variableFiles = await this.getSettingFiles(workspaceFolder, StorageKey.VariableFiles); const inputs = (await this.getSetting(workspaceFolder, SettingsManager.inputsRegExp, StorageKey.Inputs, false, Visibility.show)).filter(input => !isUserSelected || (input.selected && input.value)); + const inputFiles = await this.getSettingFiles(workspaceFolder, StorageKey.InputFiles); const runners = (await this.getSetting(workspaceFolder, SettingsManager.runnersRegExp, StorageKey.Runners, false, Visibility.show)).filter(runner => !isUserSelected || (runner.selected && runner.value)); const environments = await this.getEnvironments(workspaceFolder); return { secrets: secrets, + secretFiles: secretFiles, variables: variables, + variableFiles: variableFiles, inputs: inputs, + inputFiles: inputFiles, runners: runners, environments: environments }; @@ -94,6 +117,11 @@ export class SettingsManager { return settings; } + async getSettingFiles(workspaceFolder: WorkspaceFolder, storageKey: StorageKey): Promise { + const existingSettingFiles = this.storageManager.get<{ [path: string]: SettingFile[] }>(storageKey) || {}; + return existingSettingFiles[workspaceFolder.uri.fsPath] || []; + } + async getEnvironments(workspaceFolder: WorkspaceFolder): Promise { const environments: Setting[] = []; @@ -125,6 +153,22 @@ export class SettingsManager { return environments; } + async editSettingFile(workspaceFolder: WorkspaceFolder, newSettingFile: SettingFile, storageKey: StorageKey) { + const existingSettingFiles = this.storageManager.get<{ [path: string]: SettingFile[] }>(storageKey) || {}; + if (existingSettingFiles[workspaceFolder.uri.fsPath]) { + const index = existingSettingFiles[workspaceFolder.uri.fsPath].findIndex(settingFile => settingFile.path === newSettingFile.path); + if (index > -1) { + existingSettingFiles[workspaceFolder.uri.fsPath][index] = newSettingFile; + } else { + existingSettingFiles[workspaceFolder.uri.fsPath].push(newSettingFile); + } + } else { + existingSettingFiles[workspaceFolder.uri.fsPath] = [newSettingFile]; + } + + await this.storageManager.update(storageKey, existingSettingFiles); + } + async editSetting(workspaceFolder: WorkspaceFolder, newSetting: Setting, storageKey: StorageKey) { const value = newSetting.value; if (storageKey === StorageKey.Secrets) { diff --git a/src/storageManager.ts b/src/storageManager.ts index f84bcfa..739246c 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -3,8 +3,11 @@ import { ExtensionContext } from "vscode"; export enum StorageKey { WorkspaceHistory = 'workspaceHistory', Secrets = 'secrets', + SecretFiles = 'secretFiles', Variables = 'variables', + VariableFiles = 'variableFiles', Inputs = 'inputs', + InputFiles = 'inputFiles', Runners = 'runners' } diff --git a/src/views/history/history.ts b/src/views/history/history.ts index c4aa34a..b4ea819 100644 --- a/src/views/history/history.ts +++ b/src/views/history/history.ts @@ -40,7 +40,7 @@ export default class HistoryTreeItem extends TreeItem implements GithubLocalActi } this.tooltip = `Name: ${history.name} #${history.count}\n` + `${history.commandArgs.extraHeader.map(header => `${header.key}: ${header.value}`).join('\n')}\n` + - `Path: ${history.commandArgs.fsPath}\n` + + `Path: ${history.commandArgs.path}\n` + `Log File: ${path.parse(history.logPath).base}\n` + `Status: ${history.status}\n` + `Started: ${Utils.getDateString(history.date.start)}\n` + diff --git a/src/views/settings/inputs.ts b/src/views/settings/inputs.ts index 19be59e..590a3ba 100644 --- a/src/views/settings/inputs.ts +++ b/src/views/settings/inputs.ts @@ -1,11 +1,14 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; import { Setting } from "../../settingsManager"; +import { StorageKey } from "../../storageManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import SettingTreeItem from "./setting"; +import SettingFileTreeItem from "./settingFile"; export default class InputsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.inputs'; + storageKey = StorageKey.InputFiles; constructor(public workspaceFolder: WorkspaceFolder, inputs: Setting[]) { super('Inputs', TreeItemCollapsibleState.Collapsed); @@ -18,10 +21,19 @@ export default class InputsTreeItem extends TreeItem implements GithubLocalActio const items: GithubLocalActionsTreeItem[] = []; const settings = await act.settingsManager.getSettings(this.workspaceFolder, false); - for (const input of settings.inputs) { - items.push(SettingTreeItem.getInputTreeItem(this.workspaceFolder, input)); - } - return items.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString())); + const inputTreeItems: GithubLocalActionsTreeItem[] = []; + for (const input of settings.inputs) { + inputTreeItems.push(SettingTreeItem.getInputTreeItem(this.workspaceFolder, input)); + } + items.push(...inputTreeItems.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString()))); + + const inputFileTreeItems: GithubLocalActionsTreeItem[] = []; + for (const inputFile of settings.inputFiles) { + inputFileTreeItems.push(SettingFileTreeItem.getInputTreeItem(this.workspaceFolder, inputFile)); + } + items.push(...inputFileTreeItems.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString()))); + + return items; } } \ No newline at end of file diff --git a/src/views/settings/secrets.ts b/src/views/settings/secrets.ts index fb021b3..28eefda 100644 --- a/src/views/settings/secrets.ts +++ b/src/views/settings/secrets.ts @@ -1,11 +1,14 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; import { Setting } from "../../settingsManager"; +import { StorageKey } from "../../storageManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import SettingTreeItem from "./setting"; +import SettingFileTreeItem from "./settingFile"; export default class SecretsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.secrets'; + storageKey = StorageKey.SecretFiles; constructor(public workspaceFolder: WorkspaceFolder, secrets: Setting[]) { super('Secrets', TreeItemCollapsibleState.Collapsed); @@ -18,10 +21,19 @@ export default class SecretsTreeItem extends TreeItem implements GithubLocalActi const items: GithubLocalActionsTreeItem[] = []; const settings = await act.settingsManager.getSettings(this.workspaceFolder, false); - for (const secret of settings.secrets) { - items.push(SettingTreeItem.getSecretTreeItem(this.workspaceFolder, secret)); - } - return items.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString())); + const secretTreeItems: GithubLocalActionsTreeItem[] = []; + for (const secret of settings.secrets) { + secretTreeItems.push(SettingTreeItem.getSecretTreeItem(this.workspaceFolder, secret)); + } + items.push(...secretTreeItems.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString()))); + + const secretFileTreeItems: GithubLocalActionsTreeItem[] = []; + for (const secretFile of settings.secretFiles) { + secretFileTreeItems.push(SettingFileTreeItem.getSecretTreeItem(this.workspaceFolder, secretFile)); + } + items.push(...secretFileTreeItems.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString()))); + + return items; } } \ No newline at end of file diff --git a/src/views/settings/setting.ts b/src/views/settings/setting.ts index 49a8361..cbdaea6 100644 --- a/src/views/settings/setting.ts +++ b/src/views/settings/setting.ts @@ -36,7 +36,8 @@ export default class SettingTreeItem extends TreeItem implements GithubLocalActi static getVariableTreeItem(workspaceFolder: WorkspaceFolder, variable: Setting): SettingTreeItem { return new SettingTreeItem( workspaceFolder, - variable, StorageKey.Variables, + variable, + StorageKey.Variables, { contextValue: 'githubLocalActions.variable', iconPath: new ThemeIcon('symbol-variable') @@ -47,7 +48,8 @@ export default class SettingTreeItem extends TreeItem implements GithubLocalActi static getInputTreeItem(workspaceFolder: WorkspaceFolder, input: Setting): SettingTreeItem { return new SettingTreeItem( workspaceFolder, - input, StorageKey.Inputs, + input, + StorageKey.Inputs, { contextValue: 'githubLocalActions.input', iconPath: new ThemeIcon('symbol-parameter') @@ -58,7 +60,8 @@ export default class SettingTreeItem extends TreeItem implements GithubLocalActi static getRunnerTreeItem(workspaceFolder: WorkspaceFolder, runner: Setting): SettingTreeItem { return new SettingTreeItem( workspaceFolder, - runner, StorageKey.Runners, + runner, + StorageKey.Runners, { contextValue: 'githubLocalActions.runner', iconPath: new ThemeIcon('vm-connect') diff --git a/src/views/settings/settingFile.ts b/src/views/settings/settingFile.ts new file mode 100644 index 0000000..5e96070 --- /dev/null +++ b/src/views/settings/settingFile.ts @@ -0,0 +1,59 @@ +import { ThemeIcon, TreeItem, TreeItemCheckboxState, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; +import { SettingFile } from "../../settingsManager"; +import { StorageKey } from "../../storageManager"; +import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; + +export default class SettingFileTreeItem extends TreeItem implements GithubLocalActionsTreeItem { + settingFile: SettingFile; + storageKey: StorageKey; + + constructor(public workspaceFolder: WorkspaceFolder, settingFile: SettingFile, storageKey: StorageKey, treeItem: { contextValue: string, iconPath: ThemeIcon }) { + super(settingFile.name, TreeItemCollapsibleState.None); + this.settingFile = settingFile; + this.storageKey = storageKey; + this.description = settingFile.path; + this.contextValue = treeItem.contextValue; + this.iconPath = treeItem.iconPath; + this.checkboxState = settingFile.selected ? TreeItemCheckboxState.Checked : TreeItemCheckboxState.Unchecked; + } + + static getSecretTreeItem(workspaceFolder: WorkspaceFolder, secretFile: SettingFile): SettingFileTreeItem { + return new SettingFileTreeItem( + workspaceFolder, + secretFile, + StorageKey.SecretFiles, + { + contextValue: 'githubLocalActions.secretFile', + iconPath: new ThemeIcon('gist-secret') + } + ); + } + + static getVariableTreeItem(workspaceFolder: WorkspaceFolder, variableFile: SettingFile): SettingFileTreeItem { + return new SettingFileTreeItem( + workspaceFolder, + variableFile, + StorageKey.VariableFiles, + { + contextValue: 'githubLocalActions.variableFile', + iconPath: new ThemeIcon('file') + } + ); + } + + static getInputTreeItem(workspaceFolder: WorkspaceFolder, inputFile: SettingFile): SettingFileTreeItem { + return new SettingFileTreeItem( + workspaceFolder, + inputFile, + StorageKey.InputFiles, + { + contextValue: 'githubLocalActions.inputFile', + iconPath: new ThemeIcon('file') + } + ); + } + + async getChildren(): Promise { + return []; + } +} \ No newline at end of file diff --git a/src/views/settings/settingsTreeDataProvider.ts b/src/views/settings/settingsTreeDataProvider.ts index 4e4beaf..90e3c9c 100644 --- a/src/views/settings/settingsTreeDataProvider.ts +++ b/src/views/settings/settingsTreeDataProvider.ts @@ -1,9 +1,14 @@ +import * as path from "path"; import { CancellationToken, commands, EventEmitter, ExtensionContext, QuickPickItem, QuickPickItemKind, ThemeIcon, TreeCheckboxChangeEvent, TreeDataProvider, TreeItem, TreeItemCheckboxState, window, workspace } from "vscode"; import { act } from "../../extension"; -import { Visibility } from "../../settingsManager"; +import { SettingFile, Visibility } from "../../settingsManager"; import { StorageKey } from "../../storageManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import InputsTreeItem from "./inputs"; +import SecretsTreeItem from "./secrets"; import SettingTreeItem from "./setting"; +import SettingFileTreeItem from "./settingFile"; +import VariablesTreeItem from "./variables"; import WorkspaceFolderSettingsTreeItem from "./workspaceFolderSettings"; export default class SettingsTreeDataProvider implements TreeDataProvider { @@ -15,6 +20,56 @@ export default class SettingsTreeDataProvider implements TreeDataProvider { this.refresh(); + }), + commands.registerCommand('githubLocalActions.addSettingFiles', async (treeItem: SecretsTreeItem | VariablesTreeItem | InputsTreeItem, title: string) => { + const settingFilesUris = await window.showOpenDialog({ + title: title, + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: true, + defaultUri: treeItem.workspaceFolder.uri + }); + + if (settingFilesUris) { + const settingFilesPaths = (await act.settingsManager.getSettingFiles(treeItem.workspaceFolder, treeItem.storageKey)).map(settingFile => settingFile.path); + const existingSettingFileNames: string[] = []; + + for await (const uri of settingFilesUris) { + const settingFileName = path.parse(uri.fsPath).name; + + if (settingFilesPaths.includes(uri.fsPath)) { + existingSettingFileNames.push(settingFileName); + } else { + const newSettingFile: SettingFile = { + name: path.parse(uri.fsPath).name, + path: uri.fsPath, + selected: false + }; + await act.settingsManager.editSettingFile(treeItem.workspaceFolder, newSettingFile, treeItem.storageKey); + } + } + + if (existingSettingFileNames.length > 0) { + window.showErrorMessage(`The following file(s) have already been added: ${existingSettingFileNames.join(', ')}`); + } + this.refresh(); + } + }), + commands.registerCommand('githubLocalActions.addSecretFiles', async (secretsTreeItem: SecretsTreeItem) => { + await commands.executeCommand('githubLocalActions.addSettingFiles', secretsTreeItem, 'Add Secret File'); + }), + commands.registerCommand('githubLocalActions.addVariableFiles', async (variablesTreeItem: VariablesTreeItem) => { + await commands.executeCommand('githubLocalActions.addSettingFiles', variablesTreeItem, 'Add Variable File'); + }), + commands.registerCommand('githubLocalActions.addInputFiles', async (inputsTreeItem: InputsTreeItem) => { + await commands.executeCommand('githubLocalActions.addSettingFiles', inputsTreeItem, 'Add Input File'); + }), + commands.registerCommand('githubLocalActions.openSettingFile', async (settingFileTreeItem: SettingFileTreeItem) => { + const document = await workspace.openTextDocument(settingFileTreeItem.settingFile.path); + await window.showTextDocument(document); + }), + commands.registerCommand('githubLocalActions.removeSettingFile', async (settingFileTreeItem: SettingFileTreeItem) => { + }), commands.registerCommand('githubLocalActions.show', async (settingTreeItem: SettingTreeItem) => { const newSetting = settingTreeItem.setting; @@ -167,11 +222,17 @@ export default class SettingsTreeDataProvider implements TreeDataProvider) { + async onDidChangeCheckboxState(event: TreeCheckboxChangeEvent) { for await (const [treeItem, state] of event.items) { - const newSetting = treeItem.setting; - newSetting.selected = (state === TreeItemCheckboxState.Checked); - await act.settingsManager.editSetting(treeItem.workspaceFolder, newSetting, treeItem.storageKey); + if (treeItem instanceof SettingTreeItem) { + const newSetting = treeItem.setting; + newSetting.selected = (state === TreeItemCheckboxState.Checked); + await act.settingsManager.editSetting(treeItem.workspaceFolder, newSetting, treeItem.storageKey); + } else { + const newSettingFile = treeItem.settingFile; + newSettingFile.selected = (state === TreeItemCheckboxState.Checked); + await act.settingsManager.editSettingFile(treeItem.workspaceFolder, newSettingFile, treeItem.storageKey); + } } this.refresh(); } diff --git a/src/views/settings/variables.ts b/src/views/settings/variables.ts index 6c43350..10316ef 100644 --- a/src/views/settings/variables.ts +++ b/src/views/settings/variables.ts @@ -1,11 +1,14 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; import { Setting } from "../../settingsManager"; +import { StorageKey } from "../../storageManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import SettingTreeItem from "./setting"; +import SettingFileTreeItem from "./settingFile"; export default class VariablesTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.variables'; + storageKey = StorageKey.VariableFiles; constructor(public workspaceFolder: WorkspaceFolder, variables: Setting[]) { super('Variables', TreeItemCollapsibleState.Collapsed); @@ -18,10 +21,19 @@ export default class VariablesTreeItem extends TreeItem implements GithubLocalAc const items: GithubLocalActionsTreeItem[] = []; const settings = await act.settingsManager.getSettings(this.workspaceFolder, false); - for (const variable of settings.variables) { - items.push(SettingTreeItem.getVariableTreeItem(this.workspaceFolder, variable)); - } - return items.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString())); + const variableTreeItems: GithubLocalActionsTreeItem[] = []; + for (const variable of settings.variables) { + variableTreeItems.push(SettingTreeItem.getVariableTreeItem(this.workspaceFolder, variable)); + } + items.push(...variableTreeItems.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString()))); + + const variableFileTreeItems: GithubLocalActionsTreeItem[] = []; + for (const variableFile of settings.variableFiles) { + variableFileTreeItems.push(SettingFileTreeItem.getVariableTreeItem(this.workspaceFolder, variableFile)); + } + items.push(...variableFileTreeItems.sort((a, b) => a.label!.toString().localeCompare(b.label!.toString()))); + + return items; } } \ No newline at end of file