From acbdbd1bfd56eb8f4f1dd22ce763d060c227f999 Mon Sep 17 00:00:00 2001 From: alexweininger Date: Mon, 19 Jul 2021 21:31:58 -0700 Subject: [PATCH] Combine all providers into one --- package.json | 25 +------- src/client.ts | 7 +++ src/commands/registerCommands.ts | 1 - src/extension.ts | 20 ------- src/extensionVariables.ts | 2 - src/tree/database/DatabaseTreeItemProvider.ts | 23 +++++--- .../functions/FunctionsTreeItemProvider.ts | 43 +++++++------- ...temProvider.ts => HealthParentTreeItem.ts} | 29 ++++++---- src/tree/projects/ProjectTreeItem.ts | 36 +++++++++--- src/tree/projects/ProjectsTreeItemProvider.ts | 7 ++- src/tree/storage/StorageTreeItemProvider.ts | 31 ++++++---- src/tree/users/UserTreeItem.ts | 45 ++++++++++++++- src/tree/users/UserTreeItemProvider.ts | 57 +++++-------------- 13 files changed, 170 insertions(+), 156 deletions(-) rename src/tree/health/{HealthTreeItemProvider.ts => HealthParentTreeItem.ts} (75%) diff --git a/package.json b/package.json index 13b816a..e8a5e6e 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,7 @@ "activationEvents": [ "onCommand:vscode-appwrite.Connect", "onView:Appwrite", - "onView:Users", - "onView:Database", - "onView:Health", - "onView:Functions", + "onView:Projects", "onCommand:vscode-appwrite.AddProject", "onCommand:vscode-appwrite.CreateTag" ], @@ -343,29 +340,9 @@ ], "views": { "Appwrite": [ - { - "id": "Users", - "name": "Users" - }, - { - "id": "Database", - "name": "Database" - }, - { - "id": "Storage", - "name": "Storage" - }, - { - "id": "Health", - "name": "Health" - }, { "id": "Projects", "name": "Projects" - }, - { - "id": "Functions", - "name": "Functions (Preview)" } ] }, diff --git a/src/client.ts b/src/client.ts index 5fe9c13..3ebca7b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -42,3 +42,10 @@ export function createAppwriteClient(config?: AppwriteProjectConfiguration): voi storageClient = undefined; functionsClient = undefined; } + +export function createAppwriteSdk(config: AppwriteProjectConfiguration): Client { + const client = new AppwriteSDK.Client(); + const { endpoint, projectId, secret, selfSigned } = config; + client.setEndpoint(endpoint).setProject(projectId).setKey(secret).setSelfSigned(selfSigned); + return client; +} diff --git a/src/commands/registerCommands.ts b/src/commands/registerCommands.ts index 4bb1f94..f51bb1e 100644 --- a/src/commands/registerCommands.ts +++ b/src/commands/registerCommands.ts @@ -108,7 +108,6 @@ export function registerCommands(context: ExtensionContext): void { registerCommand("editPermission", editPermission, "database"); /** Health **/ - registerCommand("refreshHealth", undefined, "health"); registerCommand("openHealthDocumentation", () => openDocumentation("health")); /** Storage **/ diff --git a/src/extension.ts b/src/extension.ts index 39969a5..b88dffb 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,28 +3,13 @@ import { createAppwriteClient } from "./client"; import { registerCommands } from "./commands/registerCommands"; import { ext } from "./extensionVariables"; import { getActiveProjectConfiguration } from "./settings"; -import { DatabaseTreeItemProvider } from "./tree/database/DatabaseTreeItemProvider"; -import { FunctionsTreeItemProvider } from './tree/functions/FunctionsTreeItemProvider'; -import { HealthTreeItemProvider } from "./tree/health/HealthTreeItemProvider"; import { ProjectsTreeItemProvider } from "./tree/projects/ProjectsTreeItemProvider"; -import { StorageTreeItemProvider } from "./tree/storage/StorageTreeItemProvider"; -import { UserTreeItemProvider } from "./tree/users/UserTreeItemProvider"; import { createAppwriteOutputChannel } from "./ui/AppwriteOutputChannel"; export async function activate(context: vscode.ExtensionContext): Promise { - const userTreeItemProvider = new UserTreeItemProvider(); - const healthTreeItemProvider = new HealthTreeItemProvider(); - const databaseTreeItemProvider = new DatabaseTreeItemProvider(); - const storageTreeItemProvider = new StorageTreeItemProvider(); const projectsTreeItemProvider = new ProjectsTreeItemProvider(); - const functionsTreeItemProvider = new FunctionsTreeItemProvider(); - vscode.window.registerTreeDataProvider("Users", userTreeItemProvider); - vscode.window.registerTreeDataProvider("Health", healthTreeItemProvider); - vscode.window.registerTreeDataProvider("Database", databaseTreeItemProvider); - vscode.window.registerTreeDataProvider("Storage", storageTreeItemProvider); vscode.window.registerTreeDataProvider("Projects", projectsTreeItemProvider); - vscode.window.registerTreeDataProvider("Functions", functionsTreeItemProvider); const activeProject = await getActiveProjectConfiguration(); createAppwriteClient(activeProject); @@ -33,12 +18,7 @@ export async function activate(context: vscode.ExtensionContext): Promise ext.outputChannel = createAppwriteOutputChannel("Appwrite", "appwrite"); ext.tree = { - users: userTreeItemProvider, - health: healthTreeItemProvider, - database: databaseTreeItemProvider, - storage: storageTreeItemProvider, projects: projectsTreeItemProvider, - functions: functionsTreeItemProvider }; registerCommands(context); diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts index bacaaf7..bedda5f 100644 --- a/src/extensionVariables.ts +++ b/src/extensionVariables.ts @@ -1,7 +1,6 @@ import { ExtensionContext } from "vscode"; import { DatabaseTreeItemProvider } from './tree/database/DatabaseTreeItemProvider'; import { FunctionsTreeItemProvider } from './tree/functions/FunctionsTreeItemProvider'; -import { HealthTreeItemProvider } from './tree/health/HealthTreeItemProvider'; import { ProjectsTreeItemProvider } from './tree/projects/ProjectsTreeItemProvider'; import { StorageTreeItemProvider } from './tree/storage/StorageTreeItemProvider'; import { UserTreeItemProvider } from './tree/users/UserTreeItemProvider'; @@ -9,7 +8,6 @@ import { AppwriteOutputChannel } from './ui/AppwriteOutputChannel'; export type AppwriteTree = { users?: UserTreeItemProvider; - health?: HealthTreeItemProvider; database?: DatabaseTreeItemProvider; storage?: StorageTreeItemProvider; projects?: ProjectsTreeItemProvider; diff --git a/src/tree/database/DatabaseTreeItemProvider.ts b/src/tree/database/DatabaseTreeItemProvider.ts index 9d92c16..0908f31 100644 --- a/src/tree/database/DatabaseTreeItemProvider.ts +++ b/src/tree/database/DatabaseTreeItemProvider.ts @@ -1,13 +1,25 @@ import * as vscode from "vscode"; -import { client } from "../../client"; import AppwriteCall from "../../utils/AppwriteCall"; -import { Collection, CollectionsList } from "../../appwrite"; +import { Client, Collection, CollectionsList } from "../../appwrite"; import { CollectionTreeItem } from "./CollectionTreeItem"; import { AppwriteSDK } from "../../constants"; import { ext } from '../../extensionVariables'; import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase'; +import { ProjectTreeItem } from '../projects/ProjectTreeItem'; +import { Database } from '../../appwrite/Database'; + +export class DatabaseTreeItemProvider extends AppwriteTreeItemBase { + + private databaseClient: Database; + + constructor(parent: ProjectTreeItem, private readonly sdk: Client) { + super(parent, 'Database'); + this.databaseClient = new Database(sdk); + this.iconPath = new vscode.ThemeIcon('database'); + } + + collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; -export class DatabaseTreeItemProvider implements vscode.TreeDataProvider { private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter< CollectionTreeItem | undefined | void >(); @@ -29,15 +41,12 @@ export class DatabaseTreeItemProvider implements vscode.TreeDataProvider { ext.outputChannel?.appendLine('getChildren for: ' + parent?.label); - if (client === undefined) { - return Promise.resolve([]); - } if (parent instanceof AppwriteTreeItemBase) { return await parent.getChildren?.() ?? []; } - const databaseSdk = new AppwriteSDK.Database(client); + const databaseSdk = new AppwriteSDK.Database(this.sdk); const collectionsList = await AppwriteCall(databaseSdk.listCollections()); if (collectionsList) { diff --git a/src/tree/functions/FunctionsTreeItemProvider.ts b/src/tree/functions/FunctionsTreeItemProvider.ts index 6713b71..fa96e2c 100644 --- a/src/tree/functions/FunctionsTreeItemProvider.ts +++ b/src/tree/functions/FunctionsTreeItemProvider.ts @@ -1,13 +1,18 @@ import * as vscode from "vscode"; -import { client } from "../../client"; -import { Function, FunctionsList } from "../../appwrite"; +import { Client, Function, FunctionsList } from "../../appwrite"; import { AppwriteSDK } from "../../constants"; import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; import { ext } from "../../extensionVariables"; import { EventEmitter, TreeItem } from "vscode"; import { FunctionTreeItem } from "./FunctionTreeItem"; +import { ProjectTreeItem } from "../projects/ProjectTreeItem"; + +export class FunctionsTreeItemProvider extends AppwriteTreeItemBase { + constructor(parent: ProjectTreeItem, private readonly sdk: Client) { + super(parent, "Functions"); + this.iconPath = new vscode.ThemeIcon('github-action'); + } -export class FunctionsTreeItemProvider implements vscode.TreeDataProvider { private _onDidChangeTreeData: EventEmitter = new EventEmitter(); readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; @@ -25,28 +30,18 @@ export class FunctionsTreeItemProvider implements vscode.TreeDataProvider { - if (client === undefined) { - return Promise.resolve([]); + collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; + + async getChildren(): Promise { + const functionsSdk = new AppwriteSDK.Functions(this.sdk); + + const list: FunctionsList = await functionsSdk.list(); + + if (list) { + const functionTreeItems = list.functions.map((func: Function) => new FunctionTreeItem(func, this)) ?? []; + return functionTreeItems; } - if (parent === undefined) { - const functionsSdk = new AppwriteSDK.Functions(client); - - const list: FunctionsList = await functionsSdk.list(); - - if (list) { - const functionTreeItems = list.functions.map((func: Function) => new FunctionTreeItem(func, this)) ?? []; - return functionTreeItems; - } - - return [{ label: "No functions found" }]; - } - - if (parent instanceof AppwriteTreeItemBase) { - return await parent.getChildren?.() ?? []; - } - - return []; + return [{ label: "No functions found" }]; } } diff --git a/src/tree/health/HealthTreeItemProvider.ts b/src/tree/health/HealthParentTreeItem.ts similarity index 75% rename from src/tree/health/HealthTreeItemProvider.ts rename to src/tree/health/HealthParentTreeItem.ts index 2d508b1..0eb0811 100644 --- a/src/tree/health/HealthTreeItemProvider.ts +++ b/src/tree/health/HealthParentTreeItem.ts @@ -1,20 +1,31 @@ import * as vscode from "vscode"; -import { healthClient } from "../../client"; import { ext } from "../../extensionVariables"; import { HealthTreeItem } from "./HealthTreeItem"; import * as dayjs from "dayjs"; import * as localizedFormat from "dayjs/plugin/localizedFormat"; -import { healthTooltips } from "../../appwrite/Health"; -import { AppwriteHealth } from "../../appwrite"; +import { Health, healthTooltips } from "../../appwrite/Health"; +import { AppwriteHealth, Client } from "../../appwrite"; import { promiseWithTimeout } from "../../utils/promiseWithTimeout"; -// dayjs.extend(relativeTime); +import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase'; +import { ProjectTreeItem } from '../projects/ProjectTreeItem'; dayjs.extend(localizedFormat); -export class HealthTreeItemProvider implements vscode.TreeDataProvider { +export class HealthParentTreeItem extends AppwriteTreeItemBase { + + private readonly healthClient: Health; + + constructor(parent: ProjectTreeItem, sdk: Client) { + super(parent, 'Health'); + this.healthClient = new Health(sdk); + this.iconPath = new vscode.ThemeIcon('pulse'); + } + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter< HealthTreeItem | undefined | void >(); + label = 'Health'; + private lastChecked: Date = new Date(); readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; @@ -27,11 +38,9 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider { - if (healthClient === undefined) { - return []; - } + collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; + async getChildren(element?: HealthTreeItem): Promise { // get children for root if (element === undefined) { try { @@ -39,7 +48,7 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider { try { - return await healthClient?.checkup(); + return await this.healthClient?.checkup(); } catch (e) { ext.outputChannel?.append('Error: ' + e.message); vscode.window.showErrorMessage('Could not connect to Appwrite project'); diff --git a/src/tree/projects/ProjectTreeItem.ts b/src/tree/projects/ProjectTreeItem.ts index 1ea1976..3be2eae 100644 --- a/src/tree/projects/ProjectTreeItem.ts +++ b/src/tree/projects/ProjectTreeItem.ts @@ -1,15 +1,35 @@ -import { ThemeIcon, TreeItem } from "vscode"; +import { TreeItem, TreeItemCollapsibleState } from "vscode"; +import { Client } from "../../appwrite"; +import { createAppwriteSdk } from "../../client"; import { AppwriteProjectConfiguration } from "../../settings"; +import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; +import { DatabaseTreeItemProvider } from "../database/DatabaseTreeItemProvider"; +import { FunctionsTreeItemProvider } from "../functions/FunctionsTreeItemProvider"; +import { HealthParentTreeItem } from "../health/HealthParentTreeItem"; +import { StorageTreeItemProvider } from "../storage/StorageTreeItemProvider"; +import { UserTreeItemProvider } from "../users/UserTreeItemProvider"; + +export class ProjectTreeItem extends AppwriteTreeItemBase { + private readonly sdk: Client; -export class ProjectTreeItem extends TreeItem { constructor(public readonly project: AppwriteProjectConfiguration, active: boolean) { - super("Project"); - this.iconPath = new ThemeIcon("rocket"); + super(undefined, "Project"); const name = project.nickname ?? "Project"; - this.label = `${name} ${active ? "(Active)" : ""}`; + this.label = `${name}`; this.contextValue = `appwriteProject${active ? "_active" : ""}`; - if (!active) { - this.command = { command: "vscode-appwrite.setActiveProject", title: "Set active", arguments: [this] }; - } + + this.sdk = createAppwriteSdk(project); } + + async getChildren(): Promise { + return [ + new DatabaseTreeItemProvider(this, this.sdk), + new FunctionsTreeItemProvider(this, this.sdk), + new UserTreeItemProvider(this, this.sdk), + new StorageTreeItemProvider(this, this.sdk), + new HealthParentTreeItem(this, this.sdk), + ]; + } + + collapsibleState = TreeItemCollapsibleState.Collapsed; } diff --git a/src/tree/projects/ProjectsTreeItemProvider.ts b/src/tree/projects/ProjectsTreeItemProvider.ts index b6922d7..17bdbfe 100644 --- a/src/tree/projects/ProjectsTreeItemProvider.ts +++ b/src/tree/projects/ProjectsTreeItemProvider.ts @@ -1,5 +1,6 @@ import * as vscode from "vscode"; import { getActiveProjectId, getAppwriteProjects } from "../../settings"; +import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; import { ProjectTreeItem } from "./ProjectTreeItem"; export class ProjectsTreeItemProvider implements vscode.TreeDataProvider { @@ -25,7 +26,11 @@ export class ProjectsTreeItemProvider implements vscode.TreeDataProvider { + async getChildren(element?: vscode.TreeItem): Promise { + if (element instanceof AppwriteTreeItemBase) { + return element.getChildren?.() ?? []; + } + const configs = await getAppwriteProjects(); if (configs === undefined || configs.length === 0) { return []; diff --git a/src/tree/storage/StorageTreeItemProvider.ts b/src/tree/storage/StorageTreeItemProvider.ts index 42877c0..29832df 100644 --- a/src/tree/storage/StorageTreeItemProvider.ts +++ b/src/tree/storage/StorageTreeItemProvider.ts @@ -1,30 +1,37 @@ -import * as vscode from "vscode"; -import { storageClient } from "../../client"; +import { Event, EventEmitter, ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import { Client } from "../../appwrite"; +import { Storage } from "../../appwrite/Storage"; +import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; +import { ProjectTreeItem } from "../projects/ProjectTreeItem"; import { FileTreeItem } from "./FileTreeItem"; -export class StorageTreeItemProvider implements vscode.TreeDataProvider { - private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter< - vscode.TreeItem | undefined | void +export class StorageTreeItemProvider extends AppwriteTreeItemBase { + constructor(parent: ProjectTreeItem, private readonly sdk: Client) { + super(parent, "Storage"); + this.iconPath = new ThemeIcon('archive'); + } + + private _onDidChangeTreeData: EventEmitter = new EventEmitter< + TreeItem | undefined | void >(); - readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + readonly onDidChangeTreeData: Event = this._onDidChangeTreeData.event; refresh(): void { this._onDidChangeTreeData.fire(); } - getTreeItem(element: vscode.TreeItem): vscode.TreeItem { + getTreeItem(element: TreeItem): TreeItem { return element; } - async getChildren(_element?: vscode.TreeItem): Promise { - if (storageClient === undefined) { - return []; - } + collapsibleState = TreeItemCollapsibleState.Collapsed; + async getChildren(_element?: TreeItem): Promise { + const storageClient = new Storage(this.sdk); const files = await storageClient.listFiles(); if (files === undefined || files?.files.length === 0) { - const noStorage = new vscode.TreeItem("No files found"); + const noStorage = new TreeItem("No files found"); return [noStorage]; } return files.files.map((file) => new FileTreeItem(file)); diff --git a/src/tree/users/UserTreeItem.ts b/src/tree/users/UserTreeItem.ts index 574dc5f..32da06d 100644 --- a/src/tree/users/UserTreeItem.ts +++ b/src/tree/users/UserTreeItem.ts @@ -1,14 +1,53 @@ import { User } from "../../appwrite"; import * as vscode from "vscode"; +import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; +import { UserTreeItemProvider } from "./UserTreeItemProvider"; +import { ChildTreeItem } from '../ChildTreeItem'; +import { ThemeIcon } from 'vscode'; +import { UserPrefsTreeItem } from './properties/UserPrefsTreeItem'; -export class UserTreeItem extends vscode.TreeItem { - constructor(public readonly user: User) { - super(user.email); +export class UserTreeItem extends AppwriteTreeItemBase { + constructor(parent: UserTreeItemProvider, public readonly user: User) { + super(parent, user.email); console.log(user); this.label = `${user.email}`; this.tooltip = user.emailVerification ? "Verified" : "Unverified"; this.iconPath = new vscode.ThemeIcon(user.emailVerification ? "verified" : "unverified"); } + async getChildren(): Promise { + const regDate = new Date(); + + regDate.setMilliseconds(this.user.registration); + const items: vscode.TreeItem[] = [ + new ChildTreeItem(this, { + contextValue: "user.name", + label: this.user.name || "Unfilled", + iconPath: new ThemeIcon("person"), + description: "Name", + }), + new ChildTreeItem(this, { + contextValue: "user.email", + label: this.user.email, + iconPath: new ThemeIcon("mail"), + description: "Email", + }), + new ChildTreeItem(this, { + contextValue: "user.registration", + label: regDate.toDateString(), + iconPath: new vscode.ThemeIcon("calendar"), + description: "Joined", + }), + new ChildTreeItem(this, { + label: this.user.$id, + description: "User ID", + iconPath: new vscode.ThemeIcon("key"), + contextValue: "user.id", + }), + new UserPrefsTreeItem(this), + ]; + + return items; + } collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; contextValue = "user"; diff --git a/src/tree/users/UserTreeItemProvider.ts b/src/tree/users/UserTreeItemProvider.ts index f2d73ff..e0391c4 100644 --- a/src/tree/users/UserTreeItemProvider.ts +++ b/src/tree/users/UserTreeItemProvider.ts @@ -1,15 +1,18 @@ import * as vscode from "vscode"; -import { client } from "../../client"; import AppwriteCall from "../../utils/AppwriteCall"; -import { User, UsersList } from "../../appwrite"; -import { ThemeIcon } from "vscode"; -import { UserPrefsTreeItem } from "./properties/UserPrefsTreeItem"; -import { ChildTreeItem } from "../ChildTreeItem"; +import { Client, User, UsersList } from "../../appwrite"; import { UserTreeItem } from "./UserTreeItem"; +import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; +import { ProjectTreeItem } from "../projects/ProjectTreeItem"; // eslint-disable-next-line @typescript-eslint/no-var-requires const sdk = require("node-appwrite"); -export class UserTreeItemProvider implements vscode.TreeDataProvider { +export class UserTreeItemProvider extends AppwriteTreeItemBase { + constructor(parent: ProjectTreeItem, private readonly sdk: Client) { + super(parent, "Users"); + this.iconPath = new vscode.ThemeIcon('account'); + + } private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter< UserTreeItem | undefined | void >(); @@ -24,48 +27,14 @@ export class UserTreeItemProvider implements vscode.TreeDataProvider { - if (client === undefined) { - return Promise.resolve([]); - } + collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; - if (element instanceof UserTreeItem) { - const regDate = new Date(); - regDate.setMilliseconds(element.user.registration); - const items: vscode.TreeItem[] = [ - new ChildTreeItem(element, { - contextValue: "user.name", - label: element.user.name || "Unfilled", - iconPath: new ThemeIcon("person"), - description: "Name", - }), - new ChildTreeItem(element, { - contextValue: "user.email", - label: element.user.email, - iconPath: new ThemeIcon("mail"), - description: "Email", - }), - new ChildTreeItem(element, { - contextValue: "user.registration", - label: regDate.toDateString(), - iconPath: new vscode.ThemeIcon("calendar"), - description: "Joined", - }), - new ChildTreeItem(element, { - label: element.user.$id, - description: "User ID", - iconPath: new vscode.ThemeIcon("key"), - contextValue: "user.id", - }), - new UserPrefsTreeItem(element), - ]; - return Promise.resolve(items); - } + async getChildren(): Promise { - const usersSdk = new sdk.Users(client); + const usersSdk = new sdk.Users(this.sdk); const usersList = await AppwriteCall(usersSdk.list()); if (usersList) { - const userTreeItems = usersList.users.map((user: User) => new UserTreeItem(user)) ?? []; + const userTreeItems = usersList.users.map((user: User) => new UserTreeItem(this, user)) ?? []; const headerItem: vscode.TreeItem = { label: `Total users: ${usersList.sum}`, };