diff --git a/CHANGELOG.md b/CHANGELOG.md index 22c7b68..6052fe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how ## [Unreleased] +## Added +- You can now easily create function tags from multiple places in the extension. + ## [0.1.0] - 2021-5-29 ## Functions! diff --git a/package.json b/package.json index 9055a1b..352d03c 100644 --- a/package.json +++ b/package.json @@ -40,245 +40,300 @@ { "command": "vscode-appwrite.Connect", "title": "Connect to Appwrite", - "category": "" + "category": "Appwrite" }, { "command": "vscode-appwrite.CreateUser", "title": "Create user", - "icon": "$(add)" + "icon": "$(add)", + "category": "Appwrite" }, { "command": "vscode-appwrite.DeleteUser", "title": "Delete user", - "icon": "$(trash)" + "icon": "$(trash)", + "category": "Appwrite" }, { "command": "vscode-appwrite.GetUserLogs", "title": "Get user logs", - "icon": "$(output)" + "icon": "$(output)", + "category": "Appwrite" }, { "command": "vscode-appwrite.openUserInConsole", "title": "View user in Appwrite console", - "icon": "$(link-external)" + "icon": "$(link-external)", + "category": "Appwrite" }, { "command": "vscode-appwrite.viewUserPrefs", "title": "View user preferences", - "icon": "$(json)" + "icon": "$(json)", + "category": "Appwrite" }, { "command": "vscode-appwrite.refreshEntry", "title": "Refresh", - "icon": "$(refresh)" + "icon": "$(refresh)", + "category": "Appwrite" }, { "command": "vscode-appwrite.copyUserId", "title": "Copy user ID", - "icon": "$(clippy)" + "icon": "$(clippy)", + "category": "Appwrite" }, { "command": "vscode-appwrite.copyUserEmail", "title": "Copy user email", - "icon": "$(clippy)" + "icon": "$(clippy)", + "category": "Appwrite" }, { "command": "vscode-appwrite.refreshUsersList", "title": "Refresh users list", - "icon": "$(refresh)" + "icon": "$(refresh)", + "category": "Appwrite" }, { "command": "vscode-appwrite.OpenUsersDocumentation", "title": "Open documentation", - "icon": "$(book)" + "icon": "$(book)", + "category": "Appwrite" }, { "command": "vscode-appwrite.OpenDatabaseDocumentation", "title": "Open documentation", - "icon": "$(book)" + "icon": "$(book)", + "category": "Appwrite" }, { "command": "vscode-appwrite.viewDocumentAsJson", - "title": "View as JSON" + "title": "View as JSON", + "category": "Appwrite" }, { "command": "vscode-appwrite.viewCollectionAsJson", - "title": "View collection as JSON" + "title": "View collection as JSON", + "category": "Appwrite" }, { "command": "vscode-appwrite.refreshCollection", "title": "Refresh", - "icon": "$(refresh)" + "icon": "$(refresh)", + "category": "Appwrite" }, { "command": "vscode-appwrite.createRule", "title": "Create collection rule", - "icon": "$(add)" + "icon": "$(add)", + "category": "Appwrite" }, { "command": "vscode-appwrite.removeRule", - "title": "Remove collection rule" + "title": "Remove collection rule", + "category": "Appwrite" }, { "command": "vscode-appwrite.deleteDocument", - "title": "Delete document" + "title": "Delete document", + "category": "Appwrite" }, { "command": "vscode-appwrite.deleteCollection", - "title": "Delete collection" + "title": "Delete collection", + "category": "Appwrite" }, { "command": "vscode-appwrite.refreshCollectionsList", "title": "Refresh", - "icon": "$(refresh)" + "icon": "$(refresh)", + "category": "Appwrite" }, { "command": "vscode-appwrite.createCollection", "title": "Create collection", - "icon": "$(add)" + "icon": "$(add)", + "category": "Appwrite" }, { "command": "vscode-appwrite.createPermission", "title": "Create permission", - "icon": "$(add)" + "icon": "$(add)", + "category": "Appwrite" }, { "command": "vscode-appwrite.deletePermission", "title": "Delete permission", - "icon": "$(trash)" + "icon": "$(trash)", + "category": "Appwrite" }, { "command": "vscode-appwrite.editPermission", "title": "Edit permission", - "icon": "$(edit)" + "icon": "$(edit)", + "category": "Appwrite" }, { "command": "vscode-appwrite.refreshHealth", "title": "Refresh health", - "icon": "$(refresh)" + "icon": "$(refresh)", + "category": "Appwrite" }, { "command": "vscode-appwrite.openHealthDocumentation", "title": "Open health documentation", - "icon": "$(book)" + "icon": "$(book)", + "category": "Appwrite" }, { "command": "vscode-appwrite.refreshStorage", "title": "Refresh storage", - "icon": "$(refresh)" + "icon": "$(refresh)", + "category": "Appwrite" }, { "command": "vscode-appwrite.openStorageDocumentation", "title": "Open storage documentation", - "icon": "$(book)" + "icon": "$(book)", + "category": "Appwrite" }, { "command": "vscode-appwrite.addProject", "title": "Add Appwrite project", - "icon": "$(plus)" + "icon": "$(plus)", + "category": "Appwrite" }, { "command": "vscode-appwrite.setActiveProject", - "title": "Set as active" + "title": "Set as active", + "category": "Appwrite" }, { "command": "vscode-appwrite.refreshProjects", "title": "Refresh projects", - "icon": "$(refresh)" + "icon": "$(refresh)", + "category": "Appwrite" }, { "command": "vscode-appwrite.refreshFunctions", "title": "Refresh functions", - "icon": "$(refresh)" + "icon": "$(refresh)", + "category": "Appwrite" }, { "command": "vscode-appwrite.removeProject", "title": "Remove project", - "icon": "$(trash)" + "icon": "$(trash)", + "category": "Appwrite" }, { "command": "vscode-appwrite.CreateTag", "title": "Create function tag", - "icon": "$(cloud-upload)" + "icon": "$(cloud-upload)", + "shortTitle": "Create function tag", + "category": "Appwrite" }, { "command": "vscode-appwrite.deleteTag", "title": "Delete tag", - "icon": "$(trash)" + "icon": "$(trash)", + "category": "Appwrite" }, { "command": "vscode-appwrite.CreateExecution", - "title": "Execute" + "title": "Execute", + "category": "Appwrite" }, { "command": "vscode-appwrite.activateTag", - "title": "Activate" + "title": "Activate", + "category": "Appwrite" }, { "command": "vscode-appwrite.editValue", "title": "Edit", - "icon": "$(edit)" + "icon": "$(edit)", + "category": "Appwrite" }, { "command": "vscode-appwrite.deleteFunction", "title": "Delete", - "icon": "$(trash)" + "icon": "$(trash)", + "category": "Appwrite" }, { "command": "vscode-appwrite.openFunctionsDocumentation", "title": "Open functions documentation", - "icon": "$(book)" + "icon": "$(book)", + "category": "Appwrite" }, { "command": "vscode-appwrite.createFunction", "title": "Create function", - "icon": "$(add)" + "icon": "$(add)", + "category": "Appwrite" }, { "command": "vscode-appwrite.createFunctionVar", "title": "Create variable", - "icon": "$(add)" + "icon": "$(add)", + "category": "Appwrite" }, { "command": "vscode-appwrite.deleteFunctionVar", "title": "Delete variable", - "icon": "$(trash)" + "icon": "$(trash)", + "category": "Appwrite" }, { "command": "vscode-appwrite.viewExecutionOutput", "title": "View execution stdout", - "enablement": "viewItem =~ /^((execution|execution_outputOnly))$/" + "enablement": "viewItem =~ /^((execution|execution_outputOnly))$/", + "category": "Appwrite" }, { "command": "vscode-appwrite.viewExecutionErrors", "title": "View execution stderr", - "enablement": "viewItem =~ /^((execution|execution_errorOnly))$/" + "enablement": "viewItem =~ /^((execution|execution_errorOnly))$/", + "category": "Appwrite" }, { "command": "vscode-appwrite.copyExecutionOutput", "title": "Copy execution stdout", - "enablement": "viewItem =~ /^((execution|execution_outputOnly))$/" + "enablement": "viewItem =~ /^((execution|execution_outputOnly))$/", + "category": "Appwrite" }, { "command": "vscode-appwrite.copyExecutionErrors", "title": "Copy execution stderr", - "enablement": "viewItem =~ /^((execution|execution_errorOnly))$/" + "enablement": "viewItem =~ /^((execution|execution_errorOnly))$/", + "category": "Appwrite" }, { "command": "vscode-appwrite.openExecutionsInBrowser", "title": "View executions in browser", "enablement": "viewItem =~ /^(executions)$/", - "icon": "$(link-external)" + "icon": "$(link-external)", + "category": "Appwrite" }, { "command": "vscode-appwrite.openFunctionTagsInBrowser", "title": "Open function tags in browser", - "icon": "$(link-external)" + "icon": "$(link-external)", + "category": "Appwrite" }, { "command": "vscode-appwrite.openFunctionSettingsInBrowser", "title": "Open function settings in browser", - "icon": "$(link-external)" + "icon": "$(link-external)", + "category": "Appwrite" + }, + { + "command": "vscode-appwrite.viewMore", + "title": "View more", + "category": "Appwrite" } ], "views": { @@ -570,6 +625,9 @@ } ], "commandPalette": [ + { + "command": "vscode-appwrite.CreateTag" + }, { "command": "vscode-appwrite.Connect" }, diff --git a/src/appwrite/Functions.ts b/src/appwrite/Functions.ts index 892b69e..1bd8ce9 100644 --- a/src/appwrite/Functions.ts +++ b/src/appwrite/Functions.ts @@ -1,4 +1,4 @@ -import { Client, Execution, ExecutionList, FunctionsClient, Tag, TagList, Vars } from "../appwrite"; +import { Client, Execution, ExecutionList, FunctionsClient, FunctionsList, Tag, TagList, Vars } from "../appwrite"; import { AppwriteSDK } from '../constants'; import AppwriteCall from '../utils/AppwriteCall'; import { ReadStream } from 'node:fs'; @@ -13,7 +13,7 @@ export class Functions { public async create(name: string, execute: string[], env: string, vars?: Vars, events?: string[], schedule?: string, timeout?: number): Promise { return await AppwriteCall(this.functions.create(name, execute, env, vars, events, schedule, timeout)); } - public async list(search?: string, offset?: number, limit?: number, orderType?: 'ASC' | 'DESC'): Promise { + public async list(search?: string, offset?: number, limit?: number, orderType?: 'ASC' | 'DESC'): Promise { return await AppwriteCall(this.functions.list(search, offset, limit, orderType)); } public async get(functionId: string): Promise { @@ -44,7 +44,7 @@ export class Functions { return await AppwriteCall(this.functions.createExecution(functionId, data)); } public async listExecutions(functionId: string, search?: string, limit?: number, offset?: number, orderType?: 'ASC' | 'DESC'): Promise { - return await AppwriteCall(this.functions.listExecutions(functionId, search, offset, limit, orderType)); + return await AppwriteCall(this.functions.listExecutions(functionId, search, limit, offset, orderType)); } public async getExecution(functionId: string, executionId: string): Promise { return await AppwriteCall(this.functions.getExecution(functionId, executionId)); diff --git a/src/commands/common/viewMore.ts b/src/commands/common/viewMore.ts new file mode 100644 index 0000000..736521f --- /dev/null +++ b/src/commands/common/viewMore.ts @@ -0,0 +1,5 @@ +import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase'; + +export async function viewMore(treeItem: AppwriteTreeItemBase): Promise { + await treeItem.viewMore(); +} diff --git a/src/commands/functions/activateTag.ts b/src/commands/functions/activateTag.ts index 534a05a..b34a423 100644 --- a/src/commands/functions/activateTag.ts +++ b/src/commands/functions/activateTag.ts @@ -1,7 +1,8 @@ +import { Tag } from '../../appwrite'; import { functionsClient } from '../../client'; import { TagTreeItem } from '../../tree/functions/tags/TagTreeItem'; -export async function activateTag(tagItem: TagTreeItem): Promise { - const tag = tagItem.tag; +export async function activateTag(tagItem: TagTreeItem | Tag): Promise { + const tag = tagItem instanceof TagTreeItem ? tagItem.tag : tagItem; await functionsClient?.updateTag(tag.functionId, tag.$id); } diff --git a/src/commands/functions/createExecution.ts b/src/commands/functions/createExecution.ts index a372c7f..76e299f 100644 --- a/src/commands/functions/createExecution.ts +++ b/src/commands/functions/createExecution.ts @@ -15,6 +15,7 @@ export async function createExecution(functionTreeItem: FunctionTreeItem): Promi export async function executeFunction(functionId: string): Promise { ext.outputChannel.appendLog(`Creating execution for function with ID: ${functionId}`); let execution = await functionsClient?.createExecution(functionId); + ext.outputChannel.appendLog(JSON.stringify(execution, null, 2)); await ext.tree?.functions?.refresh(); if (execution === undefined) { @@ -22,6 +23,7 @@ export async function executeFunction(functionId: string): Promise { } execution = await waitForExecution(execution); + ext.tree?.functions?.refresh(); if (execution === undefined) { return; @@ -41,12 +43,11 @@ export async function executeFunction(functionId: string): Promise { } async function waitForExecution(execution: Execution | undefined): Promise { - ext.outputChannel.appendLog("Waiting for execution..."); if (execution === undefined) { return; } if (execution.status === "processing" || execution.status === "waiting") { - await sleep(2000); + await sleep(5000); ext.outputChannel.appendLog("Execution still ..."); return await waitForExecution(await functionsClient?.getExecution(execution.functionId, execution.$id)); diff --git a/src/commands/functions/createTag.ts b/src/commands/functions/createTag.ts index 7f32684..b154d33 100644 --- a/src/commands/functions/createTag.ts +++ b/src/commands/functions/createTag.ts @@ -1,42 +1,123 @@ -import { ProgressLocation, Uri, window, workspace } from "vscode"; +import { ProgressLocation, QuickPickItem, Uri, window, workspace } from "vscode"; import { functionsClient } from "../../client"; import { getTarReadStream } from "../../utils/tar"; import { ext } from "../../extensionVariables"; import * as fs from "fs"; import { TagsTreeItem } from "../../tree/functions/tags/TagsTreeItem"; import { selectWorkspaceFolder } from "../../utils/workspace"; -import { ProgressMessage } from '../../utils/types'; -import { Tag } from '../../appwrite'; +import { ProgressMessage } from "../../utils/types"; +import { Tag } from "../../appwrite"; +import { activateTag } from "./activateTag"; -export async function createTag(item: TagsTreeItem | Uri): Promise { +export async function createTag(item?: TagsTreeItem | Uri): Promise { if (item instanceof Uri) { - const tag = await window.withProgress({ location: ProgressLocation.Notification, title: "Creating tag..." }, async (progress, _token) => { - return await createTagFromUri(item, progress); - }); - if (tag) { - await window.showInformationMessage(`Successfully created tag with size ${tag.size}B.`, "Execution function", "View in console"); + const functions = await functionsClient?.list(); + if (functions === undefined) { return; } + const pick = await window.showQuickPick( + functions.functions.map( + (func): QuickPickItem => ({ label: func.name, description: func.env, detail: func.$id }) + ), + { placeHolder: "Select a function to create tag" } + ); + if (pick === undefined || pick.detail === undefined) { + return; + } + const tags = await functionsClient?.listTags(pick.detail); + let value; + if (tags && tags.tags.length > 0) { + value = tags.tags[tags.tags.length - 1].command; + } + const command = await window.showInputBox({ value, prompt: "Command to run your code" }); + if (command === undefined) { + return; + } + const tag = await window.withProgress( + { location: ProgressLocation.Notification, title: "Creating tag..." }, + async (progress, _token) => { + if (pick.detail === undefined) { + return; + } + return await createTagFromUri(pick.detail, command, item, progress); + } + ); + if (tag) { + await tagNotification(tag); + } + return; } if (item instanceof TagsTreeItem) { + const func = item.parent.func; const folder = await selectWorkspaceFolder("Select folder of your function code."); - console.log(folder); - const tag = await window.withProgress({ location: ProgressLocation.Notification, title: "Creating tag..." }, async (progress, _token) => { - return await createTagFromUri(Uri.parse(folder), progress); - }); + if (folder === undefined || folder === "") { + return; + } + const tags = await functionsClient?.listTags(func.$id); + let value; + if (tags && tags.tags.length > 0) { + value = tags.tags[tags.tags.length - 1].command; + } + const command = await window.showInputBox({ value, prompt: "Command to run your code" }); + if (command === undefined) { + return; + } + const tag = await window.withProgress( + { location: ProgressLocation.Notification, title: "Creating tag..." }, + async (progress, _token) => { + return await createTagFromUri(func.$id, command, Uri.parse(folder), progress); + } + ); if (tag) { - await window.showInformationMessage(`Successfully created tag with size ${tag.size}B.`); + await tagNotification(tag); + return; + } + } + + if (item === undefined) { + const functions = await functionsClient?.list(); + if (functions === undefined) { + return; + } + const pick = await window.showQuickPick( + functions.functions.map( + (func): QuickPickItem => ({ label: func.name, description: func.env, detail: func.$id }) + ), + { placeHolder: "Select a function to create tag" } + ); + if (pick === undefined || pick.detail === undefined) { + return; + } + const funcId = pick.detail; + const folder = await selectWorkspaceFolder("Select folder of your function code."); + const tags = await functionsClient?.listTags(funcId); + let value; + if (tags && tags.tags.length > 0) { + value = tags.tags[tags.tags.length - 1].command; + } + const command = await window.showInputBox({ value, prompt: "Command to run your code" }); + if (command === undefined) { + return; + } + const tag = await window.withProgress( + { location: ProgressLocation.Notification, title: "Creating tag..." }, + async (progress, _token) => { + return await createTagFromUri(funcId, command, Uri.parse(folder), progress); + } + ); + + if (tag) { + await tagNotification(tag); return; } } } -async function createTagFromUri(uri: Uri, progress: ProgressMessage): Promise { - - progress.report({message: "Creating tarball", increment: 10}); +async function createTagFromUri(functionId: string, command: string, uri: Uri, progress: ProgressMessage): Promise { + progress.report({ message: "Creating tarball", increment: 10 }); if (functionsClient === undefined) { return; @@ -56,10 +137,28 @@ async function createTagFromUri(uri: Uri, progress: ProgressMessage): Promise { + ext.tree?.functions?.refresh(); + if (tag) { + const action = await window.showInformationMessage( + `Successfully created tag with size ${tag.size}B.`, + "Activate tag", + "View in console" + ); + if (action === "Activate tag") { + await activateTag(tag); + } + if (action === "View in console") { + // + } + return; + } +} diff --git a/src/commands/functions/viewExecutionOutput.ts b/src/commands/functions/viewExecutionOutput.ts index dde8325..28088c5 100644 --- a/src/commands/functions/viewExecutionOutput.ts +++ b/src/commands/functions/viewExecutionOutput.ts @@ -7,11 +7,13 @@ export async function viewExecutionOutput(executionItem: ExecutionTreeItem | Exe return; } + let execution = executionItem as Execution; if (executionItem instanceof ExecutionTreeItem) { execution = executionItem.execution; } + console.log(execution.dateCreated); await openReadOnlyContent({ label: `Execution stdout`, fullId: `${execution.$id}-output.txt` }, execution.stdout, '.txt'); } diff --git a/src/commands/registerCommands.ts b/src/commands/registerCommands.ts index 5b6a27d..4bb1f94 100644 --- a/src/commands/registerCommands.ts +++ b/src/commands/registerCommands.ts @@ -42,6 +42,8 @@ import { openExecutionsInBrowser } from './functions/openExecutionsInBrowser'; import { openFunctionSettingsInBrowser } from './functions/openFunctionSettingsInBrowser'; import { openFunctionTagsInBrowser } from './functions/openFunctionTagsInBrowser'; +import { viewMore } from './common/viewMore'; + class CommandRegistrar { constructor(private readonly context: ExtensionContext) {} @@ -74,6 +76,7 @@ export function registerCommands(context: ExtensionContext): void { /** Common **/ registerCommand("editValue", editValue); + registerCommand("viewMore", viewMore); /** General **/ registerCommand("Connect", connectAppwrite, "all"); diff --git a/src/tree/database/CollectionTreeItem.ts b/src/tree/database/CollectionTreeItem.ts index 79ea8c4..22c3a02 100644 --- a/src/tree/database/CollectionTreeItem.ts +++ b/src/tree/database/CollectionTreeItem.ts @@ -1,13 +1,13 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; import { Collection } from "../../appwrite"; import { databaseClient } from "../../client"; -import { AwTreeItem } from "../common/AwTreeItem"; +import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; import { DatabaseTreeItemProvider } from "./DatabaseTreeItemProvider"; import { DocumentsTreeItem } from "./DocumentsTreeItem"; import { PermissionsTreeItem } from "./settings/PermissionsTreeItem"; import { RulesTreeItem } from "./settings/RulesTreeItem"; -export class CollectionTreeItem extends AwTreeItem { +export class CollectionTreeItem extends AppwriteTreeItemBase { constructor(public collection: Collection, public readonly provider: DatabaseTreeItemProvider) { super(undefined, collection.name); } diff --git a/src/tree/database/DatabaseTreeItemProvider.ts b/src/tree/database/DatabaseTreeItemProvider.ts index 17211c3..9d92c16 100644 --- a/src/tree/database/DatabaseTreeItemProvider.ts +++ b/src/tree/database/DatabaseTreeItemProvider.ts @@ -5,7 +5,7 @@ import { Collection, CollectionsList } from "../../appwrite"; import { CollectionTreeItem } from "./CollectionTreeItem"; import { AppwriteSDK } from "../../constants"; import { ext } from '../../extensionVariables'; -import { AwParentTreeItem } from '../common/AwParentTreeItem'; +import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase'; export class DatabaseTreeItemProvider implements vscode.TreeDataProvider { private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter< @@ -33,8 +33,8 @@ export class DatabaseTreeItemProvider implements vscode.TreeDataProvider { +export class DocumentsTreeItem extends AppwriteTreeItemBase { constructor(parent: CollectionTreeItem) { super(parent, "Documents"); } diff --git a/src/tree/database/settings/PermissionsTreeItem.ts b/src/tree/database/settings/PermissionsTreeItem.ts index bf43212..64788fd 100644 --- a/src/tree/database/settings/PermissionsTreeItem.ts +++ b/src/tree/database/settings/PermissionsTreeItem.ts @@ -1,11 +1,11 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; import { Permissions } from "../../../appwrite"; -import { AwTreeItem } from "../../common/AwTreeItem"; +import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase"; import { CollapsableTreeItem } from "../../CollapsableTreeItem"; import { CollectionTreeItem } from "../CollectionTreeItem"; import { PermissionTreeItem } from "./PermissionTreeItem"; -export class PermissionsTreeItem extends AwTreeItem { +export class PermissionsTreeItem extends AppwriteTreeItemBase { public readonly permissions: Permissions; constructor(parent: CollectionTreeItem) { diff --git a/src/tree/database/settings/RulesTreeItem.ts b/src/tree/database/settings/RulesTreeItem.ts index 4159865..d4722e7 100644 --- a/src/tree/database/settings/RulesTreeItem.ts +++ b/src/tree/database/settings/RulesTreeItem.ts @@ -1,11 +1,11 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; import { Rule } from "../../../appwrite"; -import { AwTreeItem } from "../../common/AwTreeItem"; +import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase"; import { CommandTreeItem } from "../../CommandTreeItem"; import { CollectionTreeItem } from "../CollectionTreeItem"; import { RuleTreeItem } from "./RuleTreeItem"; -export class RulesTreeItem extends AwTreeItem { +export class RulesTreeItem extends AppwriteTreeItemBase { public readonly rules: Rule[]; constructor(parent: CollectionTreeItem) { diff --git a/src/tree/functions/FunctionTreeItem.ts b/src/tree/functions/FunctionTreeItem.ts index 4a7d459..ae5e1ed 100644 --- a/src/tree/functions/FunctionTreeItem.ts +++ b/src/tree/functions/FunctionTreeItem.ts @@ -1,13 +1,13 @@ import { MarkdownString, ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; import { Function } from "../../appwrite"; -import { AwTreeItem } from "../common/AwTreeItem"; +import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; import { msToDate } from '../../utils/date'; import { ExecutionsTreeItem } from './executions/ExecutionsTreeItem'; import { FunctionsTreeItemProvider } from './FunctionsTreeItemProvider'; import { FunctionSettingsTreeItem } from './settings/FunctionSettingsTreeItem'; import { TagsTreeItem } from './tags/TagsTreeItem'; -export class FunctionTreeItem extends AwTreeItem { +export class FunctionTreeItem extends AppwriteTreeItemBase { constructor(public func: Function, public readonly provider: FunctionsTreeItemProvider) { super(undefined, func.name); this.tooltip = new MarkdownString(`ID: ${func.$id} \nLast updated: ${msToDate(func.dateUpdated)} \nCreated: ${msToDate(func.dateCreated)}`); diff --git a/src/tree/functions/FunctionsTreeItemProvider.ts b/src/tree/functions/FunctionsTreeItemProvider.ts index 267d004..6713b71 100644 --- a/src/tree/functions/FunctionsTreeItemProvider.ts +++ b/src/tree/functions/FunctionsTreeItemProvider.ts @@ -2,11 +2,10 @@ import * as vscode from "vscode"; import { client } from "../../client"; import { Function, FunctionsList } from "../../appwrite"; import { AppwriteSDK } from "../../constants"; -import { AwTreeItem } from "../common/AwTreeItem"; +import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; import { ext } from "../../extensionVariables"; import { EventEmitter, TreeItem } from "vscode"; import { FunctionTreeItem } from "./FunctionTreeItem"; -import { AwParentTreeItem } from '../common/AwParentTreeItem'; export class FunctionsTreeItemProvider implements vscode.TreeDataProvider { private _onDidChangeTreeData: EventEmitter = new EventEmitter(); @@ -26,7 +25,7 @@ export class FunctionsTreeItemProvider implements vscode.TreeDataProvider { + async getChildren(parent?: AppwriteTreeItemBase | TreeItem): Promise { if (client === undefined) { return Promise.resolve([]); } @@ -44,8 +43,8 @@ export class FunctionsTreeItemProvider implements vscode.TreeDataProvider = { @@ -26,33 +23,33 @@ export class ExecutionTreeItem extends TreeItem { this.description = execution.trigger; this.contextValue = this.getContextValue(execution); this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting"; - if (this.isAutoRefreshing) { - this.autoRefresh(); - } + // if (this.isAutoRefreshing) { + // this.autoRefresh(); + // } } - async autoRefresh(): Promise { - if (!this.isAutoRefreshing) { - return; - } - this.refreshCount++; - ext.outputChannel.appendLog("Refreshing execution."); - const execution = await functionsClient?.getExecution(this.parent.parent.func.$id, this.execution.$id); + // async autoRefresh(): Promise { + // if (!this.isAutoRefreshing && this.refreshCount < 5) { + // return; + // } + // this.refreshCount++; + // ext.outputChannel.appendLog("Refreshing execution."); + // const execution = await functionsClient?.getExecution(this.parent.parent.func.$id, this.execution.$id); - if (!execution) { - ext.outputChannel.appendLog("Execution is undefined"); - this.isAutoRefreshing = false; - return; - } - this.execution = execution; - this.contextValue = this.getContextValue(execution); - this.iconPath = executionStatusIcons[execution.status]; - this.label = this.getLabel(execution); - this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting"; - ext.tree?.functions?.refreshChild(this); - await sleep(1000); - this.autoRefresh(); - } + // if (!execution) { + // ext.outputChannel.appendLog("Execution is undefined"); + // this.isAutoRefreshing = false; + // return; + // } + // this.execution = execution; + // this.contextValue = this.getContextValue(execution); + // this.iconPath = executionStatusIcons[execution.status]; + // this.label = this.getLabel(execution); + // this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting"; + // ext.tree?.functions?.refreshChild(this); + // await sleep(1000); + // this.autoRefresh(); + // } getLabel(execution: Execution): string { if (execution.status === "completed" || execution.status === "failed") { diff --git a/src/tree/functions/executions/ExecutionsTreeItem.ts b/src/tree/functions/executions/ExecutionsTreeItem.ts index 31ba091..ba65086 100644 --- a/src/tree/functions/executions/ExecutionsTreeItem.ts +++ b/src/tree/functions/executions/ExecutionsTreeItem.ts @@ -1,26 +1,47 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; -import { Execution, ExecutionList } from '../../../appwrite'; +import { Command, ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { Execution, ExecutionList } from "../../../appwrite"; import { functionsClient } from "../../../client"; -import { AwTreeItem } from '../../common/AwTreeItem'; -import { ExecutionTreeItem } from './ExecutionTreeItem'; -import { FunctionTreeItem } from '../FunctionTreeItem'; -import { ext } from '../../../extensionVariables'; +import { ExecutionTreeItem } from "./ExecutionTreeItem"; +import { FunctionTreeItem } from "../FunctionTreeItem"; +import { ext } from "../../../extensionVariables"; +import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase"; -const executionsToShow = 10; - -export class ExecutionsTreeItem extends AwTreeItem { +export class ExecutionsTreeItem extends AppwriteTreeItemBase { constructor(public readonly parent: FunctionTreeItem) { super(parent, "Executions"); } + private executionsToShow = 10; + public async getChildren(): Promise { if (!functionsClient) { return []; } - const executions: ExecutionList | undefined = await functionsClient.listExecutions(this.parent.func.$id, undefined, executionsToShow, undefined, 'DESC'); - const children = executions?.executions.map((execution: Execution) => new ExecutionTreeItem(this, execution)) ?? [new TreeItem('No exeuctions.')]; + const executions: ExecutionList | undefined = await functionsClient.listExecutions( + this.parent.func.$id, + undefined, + this.executionsToShow, + undefined, + "DESC" + ); + const children = executions?.executions.map((execution: Execution) => new ExecutionTreeItem(this, execution)) ?? [ + new TreeItem("No executions."), + ]; + if (children.length === 0) { + children.push(new TreeItem("No executions.")); + } ext.outputChannel.appendLog(`Found ${executions?.sum} executions`); - children.push(new TreeItem('View more')); + if (executions?.sum ?? (0 > this.executionsToShow && this.executionsToShow !== 100)) { + const viewMoreItem: TreeItem = { + command: { + command: "vscode-appwrite.viewMore", + arguments: [this], + title: "View more", + }, + label: "View more...", + }; + children.push(viewMoreItem); + } return children; } @@ -29,4 +50,12 @@ export class ExecutionsTreeItem extends AwTreeItem { contextValue = "executions"; iconPath = new ThemeIcon("history"); + + async viewMore(): Promise { + this.executionsToShow += 10; + if (this.executionsToShow > 100) { + this.executionsToShow = 100; + } + ext.tree?.functions?.refreshChild(this); + } } diff --git a/src/tree/functions/settings/FunctionSettingsTreeItem.ts b/src/tree/functions/settings/FunctionSettingsTreeItem.ts index f374534..654ac2a 100644 --- a/src/tree/functions/settings/FunctionSettingsTreeItem.ts +++ b/src/tree/functions/settings/FunctionSettingsTreeItem.ts @@ -1,7 +1,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; import { Function } from "../../../appwrite"; import { functionsClient } from "../../../client"; -import { AwTreeItem } from "../../common/AwTreeItem"; +import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase'; import { ChildTreeItem } from "../../ChildTreeItem"; import { FunctionTreeItem } from "../FunctionTreeItem"; import { EventsTreeItem } from "./EventsTreeItem"; @@ -10,7 +10,7 @@ import { ScheduleTreeItem } from "./ScheduleTreeItem"; import { TimeoutTreeItem } from "./TimeoutTreeItem"; import { VarsTreeItem } from "./VarsTreeItem"; -export class FunctionSettingsTreeItem extends AwTreeItem { +export class FunctionSettingsTreeItem extends AppwriteTreeItemBase { public readonly func: Function; constructor(public readonly parent: FunctionTreeItem) { diff --git a/src/tree/functions/settings/VarsTreeItem.ts b/src/tree/functions/settings/VarsTreeItem.ts index be05509..165b8dc 100644 --- a/src/tree/functions/settings/VarsTreeItem.ts +++ b/src/tree/functions/settings/VarsTreeItem.ts @@ -1,10 +1,10 @@ import { TreeItem, TreeItemCollapsibleState } from "vscode"; import { Vars } from "../../../appwrite"; -import { AwTreeItem } from "../../common/AwTreeItem"; +import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase'; import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem"; import { VarTreeItem } from "./VarTreeItem"; -export class VarsTreeItem extends AwTreeItem { +export class VarsTreeItem extends AppwriteTreeItemBase { public readonly vars: Vars; constructor(parent: FunctionSettingsTreeItem) { diff --git a/src/tree/functions/tags/TagTreeItem.ts b/src/tree/functions/tags/TagTreeItem.ts index 2a468fa..b34208a 100644 --- a/src/tree/functions/tags/TagTreeItem.ts +++ b/src/tree/functions/tags/TagTreeItem.ts @@ -10,7 +10,7 @@ export class TagTreeItem extends TreeItem { const active = func.tag === tag.$id; this.label = `${msToDate(tag.dateCreated)}${active ? ' (Active)' : ''}`; this.description = tag.$id; - this.iconPath = new ThemeIcon(active ? 'circle-filled' : 'circle-outline'); + this.iconPath = new ThemeIcon(active ? 'circle-large-filled' : 'circle-large-outline'); this.contextValue = `tag${active ? '_active' : ''}`; this.tooltip = new MarkdownString(`ID: ${tag.$id} \nCreated: ${msToDate(tag.dateCreated)} \nCommand: ${tag.command} \nSize: ${tag.size}B`); } diff --git a/src/tree/functions/tags/TagsTreeItem.ts b/src/tree/functions/tags/TagsTreeItem.ts index f093275..e9f7f4a 100644 --- a/src/tree/functions/tags/TagsTreeItem.ts +++ b/src/tree/functions/tags/TagsTreeItem.ts @@ -1,11 +1,10 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; import { functionsClient } from "../../../client"; -import { AwParentTreeItem } from '../../common/AwParentTreeItem'; -import { AwTreeItem } from '../../common/AwTreeItem'; +import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase'; import { FunctionTreeItem } from '../FunctionTreeItem'; import { TagTreeItem } from './TagTreeItem'; -export class TagsTreeItem extends AwParentTreeItem { +export class TagsTreeItem extends AppwriteTreeItemBase { constructor(public readonly parent: FunctionTreeItem) { super(parent, "Tags"); } @@ -15,7 +14,22 @@ export class TagsTreeItem extends AwParentTreeItem { return []; } const tags = await functionsClient.listTags(this.parent.func.$id); - return tags?.tags.sort((a, b) => b.dateCreated - a.dateCreated).map((tag) => new TagTreeItem(this, tag)) ?? [new TreeItem('No tags.')]; + const children = tags?.tags.sort((a, b) => b.dateCreated - a.dateCreated).map((tag) => new TagTreeItem(this, tag)) ?? [new TreeItem('No tags.')]; + + if (children.length === 0) { + const noTagsItem: TreeItem = { + command: { + command: "vscode-appwrite.CreateTag", + title: "Create tag", + arguments: [this], + tooltip: "Create a tag" + }, + label: "Create a tag", + iconPath: new ThemeIcon("cloud-upload"), + }; + children.push(noTagsItem); + } + return children; } collapsibleState = TreeItemCollapsibleState.Collapsed; diff --git a/src/ui/AppwriteTreeItemBase.ts b/src/ui/AppwriteTreeItemBase.ts index 00fd410..a38ead9 100644 --- a/src/ui/AppwriteTreeItemBase.ts +++ b/src/ui/AppwriteTreeItemBase.ts @@ -7,4 +7,7 @@ export abstract class AppwriteTreeItemBase extends TreeItem { abstract getChildren?(): Promise; + viewMore(): Promise { + return Promise.resolve(); + } } diff --git a/src/utils/date.ts b/src/utils/date.ts index dba032f..adad317 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -5,5 +5,5 @@ dayjs.extend(utc); dayjs.extend(timezone); export function msToDate(ms: number): string { - return dayjs(ms * 1000).tz("America/Chicago").format("LTS"); + return dayjs(ms * 1000).tz(dayjs.tz.guess()).format("LTS"); }