Compare commits
3 commits
main
...
alex/conso
Author | SHA1 | Date | |
---|---|---|---|
|
911ce7d98d | ||
|
6ca2a91f08 | ||
|
acbdbd1bfd |
17 changed files with 212 additions and 261 deletions
48
.github/ISSUE_TEMPLATE/bug.yaml
vendored
48
.github/ISSUE_TEMPLATE/bug.yaml
vendored
|
@ -1,48 +0,0 @@
|
||||||
name: Bug Report
|
|
||||||
description: File a bug report
|
|
||||||
title: "[Bug] "
|
|
||||||
labels: [bug]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
- type: textarea
|
|
||||||
id: repro
|
|
||||||
attributes:
|
|
||||||
label: Reproduction steps
|
|
||||||
description: "How do you trigger this bug? Please walk us through it step by step."
|
|
||||||
value: |
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
...
|
|
||||||
render: bash
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of VS Code are you using?
|
|
||||||
options:
|
|
||||||
- Stable (Default)
|
|
||||||
- Insiders
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: os
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- All
|
|
||||||
- Windows
|
|
||||||
- macOS
|
|
||||||
- Linux
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
40
package.json
40
package.json
|
@ -27,10 +27,7 @@
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"onCommand:vscode-appwrite.Connect",
|
"onCommand:vscode-appwrite.Connect",
|
||||||
"onView:Appwrite",
|
"onView:Appwrite",
|
||||||
"onView:Users",
|
"onView:Projects",
|
||||||
"onView:Database",
|
|
||||||
"onView:Health",
|
|
||||||
"onView:Functions",
|
|
||||||
"onCommand:vscode-appwrite.AddProject",
|
"onCommand:vscode-appwrite.AddProject",
|
||||||
"onCommand:vscode-appwrite.CreateTag"
|
"onCommand:vscode-appwrite.CreateTag"
|
||||||
],
|
],
|
||||||
|
@ -205,11 +202,6 @@
|
||||||
"icon": "$(plus)",
|
"icon": "$(plus)",
|
||||||
"category": "Appwrite"
|
"category": "Appwrite"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "vscode-appwrite.setActiveProject",
|
|
||||||
"title": "Set as active",
|
|
||||||
"category": "Appwrite"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.refreshProjects",
|
"command": "vscode-appwrite.refreshProjects",
|
||||||
"title": "Refresh projects",
|
"title": "Refresh projects",
|
||||||
|
@ -343,29 +335,9 @@
|
||||||
],
|
],
|
||||||
"views": {
|
"views": {
|
||||||
"Appwrite": [
|
"Appwrite": [
|
||||||
{
|
|
||||||
"id": "Users",
|
|
||||||
"name": "Users"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Database",
|
|
||||||
"name": "Database"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Storage",
|
|
||||||
"name": "Storage"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Health",
|
|
||||||
"name": "Health"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "Projects",
|
"id": "Projects",
|
||||||
"name": "Projects"
|
"name": "Projects"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Functions",
|
|
||||||
"name": "Functions (Preview)"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -381,6 +353,11 @@
|
||||||
],
|
],
|
||||||
"menus": {
|
"menus": {
|
||||||
"view/title": [
|
"view/title": [
|
||||||
|
{
|
||||||
|
"command": "vscode-appwrite.addProject",
|
||||||
|
"when": "view == Projects",
|
||||||
|
"group": "navigation"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.OpenUsersDocumentation",
|
"command": "vscode-appwrite.OpenUsersDocumentation",
|
||||||
"when": "view == Users",
|
"when": "view == Users",
|
||||||
|
@ -540,11 +517,6 @@
|
||||||
"when": "viewItem =~ /^(permission)$/",
|
"when": "viewItem =~ /^(permission)$/",
|
||||||
"group": "inline"
|
"group": "inline"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "vscode-appwrite.setActiveProject",
|
|
||||||
"when": "viewItem =~ /^(appwriteProject)$/",
|
|
||||||
"group": "inline"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "vscode-appwrite.removeProject",
|
"command": "vscode-appwrite.removeProject",
|
||||||
"when": "viewItem =~ /(appwriteProject)/"
|
"when": "viewItem =~ /(appwriteProject)/"
|
||||||
|
|
|
@ -42,3 +42,10 @@ export function createAppwriteClient(config?: AppwriteProjectConfiguration): voi
|
||||||
storageClient = undefined;
|
storageClient = undefined;
|
||||||
functionsClient = 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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { setActiveProjectId } from '../../settings';
|
|
||||||
import { ProjectTreeItem } from "../../tree/projects/ProjectTreeItem";
|
|
||||||
|
|
||||||
export async function setActiveProject(treeItem: ProjectTreeItem): Promise<void> {
|
|
||||||
if (treeItem === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(treeItem instanceof ProjectTreeItem)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await setActiveProjectId(treeItem.project.projectId);
|
|
||||||
}
|
|
|
@ -23,26 +23,25 @@ import { openUserInConsole } from "./users/openUserInConsole";
|
||||||
import { refreshUsersList } from "./users/refreshUsersList";
|
import { refreshUsersList } from "./users/refreshUsersList";
|
||||||
import { viewUserPrefs } from "./users/viewUserPrefs";
|
import { viewUserPrefs } from "./users/viewUserPrefs";
|
||||||
import { editPermission } from "./database/permissions/editPermission";
|
import { editPermission } from "./database/permissions/editPermission";
|
||||||
import { setActiveProject } from "./project/setActiveProject";
|
|
||||||
import { removeProject } from "./project/removeProject";
|
import { removeProject } from "./project/removeProject";
|
||||||
import { createTag } from './functions/createTag';
|
import { createTag } from "./functions/createTag";
|
||||||
import { createExecution } from './functions/createExecution';
|
import { createExecution } from "./functions/createExecution";
|
||||||
import { activateTag } from './functions/activateTag';
|
import { activateTag } from "./functions/activateTag";
|
||||||
import { editValue } from './common/editValue';
|
import { editValue } from "./common/editValue";
|
||||||
import { deleteFunction } from './functions/deleteFunction';
|
import { deleteFunction } from "./functions/deleteFunction";
|
||||||
import { createFunction } from './functions/createFunction';
|
import { createFunction } from "./functions/createFunction";
|
||||||
import { createFunctionVar } from './functions/createFunctionVar';
|
import { createFunctionVar } from "./functions/createFunctionVar";
|
||||||
import { deleteFunctionVar } from './functions/deleteFunctionVar';
|
import { deleteFunctionVar } from "./functions/deleteFunctionVar";
|
||||||
import { deleteTag } from './functions/deleteTag';
|
import { deleteTag } from "./functions/deleteTag";
|
||||||
import { viewExecutionErrors } from './functions/viewExecutionErrors';
|
import { viewExecutionErrors } from "./functions/viewExecutionErrors";
|
||||||
import { viewExecutionOutput } from './functions/viewExecutionOutput';
|
import { viewExecutionOutput } from "./functions/viewExecutionOutput";
|
||||||
import { copyExecutionErrors } from './functions/copyExecutionErrors';
|
import { copyExecutionErrors } from "./functions/copyExecutionErrors";
|
||||||
import { copyExecutionOutput } from './functions/copyExecutionOutput';
|
import { copyExecutionOutput } from "./functions/copyExecutionOutput";
|
||||||
import { openExecutionsInBrowser } from './functions/openExecutionsInBrowser';
|
import { openExecutionsInBrowser } from "./functions/openExecutionsInBrowser";
|
||||||
import { openFunctionSettingsInBrowser } from './functions/openFunctionSettingsInBrowser';
|
import { openFunctionSettingsInBrowser } from "./functions/openFunctionSettingsInBrowser";
|
||||||
import { openFunctionTagsInBrowser } from './functions/openFunctionTagsInBrowser';
|
import { openFunctionTagsInBrowser } from "./functions/openFunctionTagsInBrowser";
|
||||||
|
|
||||||
import { viewMore } from './common/viewMore';
|
import { viewMore } from "./common/viewMore";
|
||||||
|
|
||||||
class CommandRegistrar {
|
class CommandRegistrar {
|
||||||
constructor(private readonly context: ExtensionContext) {}
|
constructor(private readonly context: ExtensionContext) {}
|
||||||
|
@ -108,7 +107,6 @@ export function registerCommands(context: ExtensionContext): void {
|
||||||
registerCommand("editPermission", editPermission, "database");
|
registerCommand("editPermission", editPermission, "database");
|
||||||
|
|
||||||
/** Health **/
|
/** Health **/
|
||||||
registerCommand("refreshHealth", undefined, "health");
|
|
||||||
registerCommand("openHealthDocumentation", () => openDocumentation("health"));
|
registerCommand("openHealthDocumentation", () => openDocumentation("health"));
|
||||||
|
|
||||||
/** Storage **/
|
/** Storage **/
|
||||||
|
@ -117,7 +115,6 @@ export function registerCommands(context: ExtensionContext): void {
|
||||||
|
|
||||||
/** Projects **/
|
/** Projects **/
|
||||||
registerCommand("addProject", connectAppwrite, "all");
|
registerCommand("addProject", connectAppwrite, "all");
|
||||||
registerCommand("setActiveProject", setActiveProject, "all");
|
|
||||||
registerCommand("refreshProjects", undefined, "projects");
|
registerCommand("refreshProjects", undefined, "projects");
|
||||||
registerCommand("removeProject", removeProject, "all");
|
registerCommand("removeProject", removeProject, "all");
|
||||||
|
|
||||||
|
|
|
@ -3,28 +3,13 @@ import { createAppwriteClient } from "./client";
|
||||||
import { registerCommands } from "./commands/registerCommands";
|
import { registerCommands } from "./commands/registerCommands";
|
||||||
import { ext } from "./extensionVariables";
|
import { ext } from "./extensionVariables";
|
||||||
import { getActiveProjectConfiguration } from "./settings";
|
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 { ProjectsTreeItemProvider } from "./tree/projects/ProjectsTreeItemProvider";
|
||||||
import { StorageTreeItemProvider } from "./tree/storage/StorageTreeItemProvider";
|
|
||||||
import { UserTreeItemProvider } from "./tree/users/UserTreeItemProvider";
|
|
||||||
import { createAppwriteOutputChannel } from "./ui/AppwriteOutputChannel";
|
import { createAppwriteOutputChannel } from "./ui/AppwriteOutputChannel";
|
||||||
|
|
||||||
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
||||||
const userTreeItemProvider = new UserTreeItemProvider();
|
|
||||||
const healthTreeItemProvider = new HealthTreeItemProvider();
|
|
||||||
const databaseTreeItemProvider = new DatabaseTreeItemProvider();
|
|
||||||
const storageTreeItemProvider = new StorageTreeItemProvider();
|
|
||||||
const projectsTreeItemProvider = new ProjectsTreeItemProvider();
|
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("Projects", projectsTreeItemProvider);
|
||||||
vscode.window.registerTreeDataProvider("Functions", functionsTreeItemProvider);
|
|
||||||
|
|
||||||
const activeProject = await getActiveProjectConfiguration();
|
const activeProject = await getActiveProjectConfiguration();
|
||||||
createAppwriteClient(activeProject);
|
createAppwriteClient(activeProject);
|
||||||
|
@ -33,12 +18,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
|
||||||
ext.outputChannel = createAppwriteOutputChannel("Appwrite", "appwrite");
|
ext.outputChannel = createAppwriteOutputChannel("Appwrite", "appwrite");
|
||||||
|
|
||||||
ext.tree = {
|
ext.tree = {
|
||||||
users: userTreeItemProvider,
|
|
||||||
health: healthTreeItemProvider,
|
|
||||||
database: databaseTreeItemProvider,
|
|
||||||
storage: storageTreeItemProvider,
|
|
||||||
projects: projectsTreeItemProvider,
|
projects: projectsTreeItemProvider,
|
||||||
functions: functionsTreeItemProvider
|
|
||||||
};
|
};
|
||||||
|
|
||||||
registerCommands(context);
|
registerCommands(context);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { ExtensionContext } from "vscode";
|
import { ExtensionContext } from "vscode";
|
||||||
import { DatabaseTreeItemProvider } from './tree/database/DatabaseTreeItemProvider';
|
import { DatabaseTreeItemProvider } from './tree/database/DatabaseTreeItemProvider';
|
||||||
import { FunctionsTreeItemProvider } from './tree/functions/FunctionsTreeItemProvider';
|
import { FunctionsTreeItemProvider } from './tree/functions/FunctionsTreeItemProvider';
|
||||||
import { HealthTreeItemProvider } from './tree/health/HealthTreeItemProvider';
|
|
||||||
import { ProjectsTreeItemProvider } from './tree/projects/ProjectsTreeItemProvider';
|
import { ProjectsTreeItemProvider } from './tree/projects/ProjectsTreeItemProvider';
|
||||||
import { StorageTreeItemProvider } from './tree/storage/StorageTreeItemProvider';
|
import { StorageTreeItemProvider } from './tree/storage/StorageTreeItemProvider';
|
||||||
import { UserTreeItemProvider } from './tree/users/UserTreeItemProvider';
|
import { UserTreeItemProvider } from './tree/users/UserTreeItemProvider';
|
||||||
|
@ -9,7 +8,6 @@ import { AppwriteOutputChannel } from './ui/AppwriteOutputChannel';
|
||||||
|
|
||||||
export type AppwriteTree = {
|
export type AppwriteTree = {
|
||||||
users?: UserTreeItemProvider;
|
users?: UserTreeItemProvider;
|
||||||
health?: HealthTreeItemProvider;
|
|
||||||
database?: DatabaseTreeItemProvider;
|
database?: DatabaseTreeItemProvider;
|
||||||
storage?: StorageTreeItemProvider;
|
storage?: StorageTreeItemProvider;
|
||||||
projects?: ProjectsTreeItemProvider;
|
projects?: ProjectsTreeItemProvider;
|
||||||
|
|
|
@ -30,7 +30,6 @@ export async function addProjectConfiguration(projectConfig: AppwriteProjectConf
|
||||||
const projects = await getAppwriteProjects();
|
const projects = await getAppwriteProjects();
|
||||||
|
|
||||||
await configuration.update("projects", [...projects, projectConfig], true);
|
await configuration.update("projects", [...projects, projectConfig], true);
|
||||||
await setActiveProjectId(projectConfig.projectId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getActiveProjectId(): Promise<string> {
|
export async function getActiveProjectId(): Promise<string> {
|
||||||
|
@ -53,21 +52,9 @@ export async function getActiveProjectConfiguration(): Promise<AppwriteProjectCo
|
||||||
activeConfig = config;
|
activeConfig = config;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (activeConfig === undefined) {
|
|
||||||
activeConfig = configurations[0];
|
|
||||||
setActiveProjectId(configurations[0].projectId);
|
|
||||||
}
|
|
||||||
return activeConfig;
|
return activeConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setActiveProjectId(projectId: string): Promise<void> {
|
|
||||||
const configuration = workspace.getConfiguration("appwrite");
|
|
||||||
await configuration.update("activeProjectId", projectId, true);
|
|
||||||
const active = await getActiveProjectConfiguration();
|
|
||||||
createAppwriteClient(active);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateActiveProjectId(): Promise<void> {
|
export async function updateActiveProjectId(): Promise<void> {
|
||||||
const projects = await getAppwriteProjects();
|
const projects = await getAppwriteProjects();
|
||||||
if (projects.length > 0) {
|
if (projects.length > 0) {
|
||||||
|
|
|
@ -1,13 +1,25 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { client } from "../../client";
|
|
||||||
import AppwriteCall from "../../utils/AppwriteCall";
|
import AppwriteCall from "../../utils/AppwriteCall";
|
||||||
import { Collection, CollectionsList } from "../../appwrite";
|
import { Client, Collection, CollectionsList } from "../../appwrite";
|
||||||
import { CollectionTreeItem } from "./CollectionTreeItem";
|
import { CollectionTreeItem } from "./CollectionTreeItem";
|
||||||
import { AppwriteSDK } from "../../constants";
|
import { AppwriteSDK } from "../../constants";
|
||||||
import { ext } from '../../extensionVariables';
|
import { ext } from '../../extensionVariables';
|
||||||
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
||||||
|
import { ProjectTreeItem } from '../projects/ProjectTreeItem';
|
||||||
|
import { Database } from '../../appwrite/Database';
|
||||||
|
|
||||||
|
export class DatabaseTreeItemProvider extends AppwriteTreeItemBase<ProjectTreeItem> {
|
||||||
|
|
||||||
|
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<vscode.TreeItem> {
|
|
||||||
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | void> = new vscode.EventEmitter<
|
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | void> = new vscode.EventEmitter<
|
||||||
CollectionTreeItem | undefined | void
|
CollectionTreeItem | undefined | void
|
||||||
>();
|
>();
|
||||||
|
@ -29,15 +41,12 @@ export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.
|
||||||
|
|
||||||
async getChildren(parent?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
async getChildren(parent?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
||||||
ext.outputChannel?.appendLine('getChildren for: ' + parent?.label);
|
ext.outputChannel?.appendLine('getChildren for: ' + parent?.label);
|
||||||
if (client === undefined) {
|
|
||||||
return Promise.resolve([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent instanceof AppwriteTreeItemBase) {
|
if (parent instanceof AppwriteTreeItemBase) {
|
||||||
return await parent.getChildren?.() ?? [];
|
return await parent.getChildren?.() ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const databaseSdk = new AppwriteSDK.Database(client);
|
const databaseSdk = new AppwriteSDK.Database(this.sdk);
|
||||||
|
|
||||||
const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections());
|
const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections());
|
||||||
if (collectionsList) {
|
if (collectionsList) {
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { client } from "../../client";
|
import { Client, Function, FunctionsList } from "../../appwrite";
|
||||||
import { Function, FunctionsList } from "../../appwrite";
|
|
||||||
import { AppwriteSDK } from "../../constants";
|
import { AppwriteSDK } from "../../constants";
|
||||||
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||||
import { ext } from "../../extensionVariables";
|
import { ext } from "../../extensionVariables";
|
||||||
import { EventEmitter, TreeItem } from "vscode";
|
import { EventEmitter, TreeItem } from "vscode";
|
||||||
import { FunctionTreeItem } from "./FunctionTreeItem";
|
import { FunctionTreeItem } from "./FunctionTreeItem";
|
||||||
|
import { ProjectTreeItem } from "../projects/ProjectTreeItem";
|
||||||
|
|
||||||
|
export class FunctionsTreeItemProvider extends AppwriteTreeItemBase<ProjectTreeItem> {
|
||||||
|
constructor(parent: ProjectTreeItem, private readonly sdk: Client) {
|
||||||
|
super(parent, "Functions");
|
||||||
|
this.iconPath = new vscode.ThemeIcon('github-action');
|
||||||
|
}
|
||||||
|
|
||||||
export class FunctionsTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
|
||||||
private _onDidChangeTreeData: EventEmitter<TreeItem | undefined | void> = new EventEmitter<TreeItem | undefined | void>();
|
private _onDidChangeTreeData: EventEmitter<TreeItem | undefined | void> = new EventEmitter<TreeItem | undefined | void>();
|
||||||
|
|
||||||
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
@ -25,28 +30,18 @@ export class FunctionsTreeItemProvider implements vscode.TreeDataProvider<vscode
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(parent?: AppwriteTreeItemBase | TreeItem): Promise<vscode.TreeItem[]> {
|
collapsibleState = vscode.TreeItemCollapsibleState.Collapsed;
|
||||||
if (client === undefined) {
|
|
||||||
return Promise.resolve([]);
|
async getChildren(): Promise<vscode.TreeItem[]> {
|
||||||
|
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) {
|
return [{ label: "No functions found" }];
|
||||||
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 [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,31 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { healthClient } from "../../client";
|
|
||||||
import { ext } from "../../extensionVariables";
|
import { ext } from "../../extensionVariables";
|
||||||
import { HealthTreeItem } from "./HealthTreeItem";
|
import { HealthTreeItem } from "./HealthTreeItem";
|
||||||
import * as dayjs from "dayjs";
|
import * as dayjs from "dayjs";
|
||||||
import * as localizedFormat from "dayjs/plugin/localizedFormat";
|
import * as localizedFormat from "dayjs/plugin/localizedFormat";
|
||||||
import { healthTooltips } from "../../appwrite/Health";
|
import { Health, healthTooltips } from "../../appwrite/Health";
|
||||||
import { AppwriteHealth } from "../../appwrite";
|
import { AppwriteHealth, Client } from "../../appwrite";
|
||||||
import { promiseWithTimeout } from "../../utils/promiseWithTimeout";
|
import { promiseWithTimeout } from "../../utils/promiseWithTimeout";
|
||||||
// dayjs.extend(relativeTime);
|
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
|
||||||
|
import { ProjectTreeItem } from '../projects/ProjectTreeItem';
|
||||||
dayjs.extend(localizedFormat);
|
dayjs.extend(localizedFormat);
|
||||||
|
|
||||||
export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
export class HealthParentTreeItem extends AppwriteTreeItemBase<ProjectTreeItem> {
|
||||||
|
|
||||||
|
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<HealthTreeItem | undefined | void> = new vscode.EventEmitter<
|
private _onDidChangeTreeData: vscode.EventEmitter<HealthTreeItem | undefined | void> = new vscode.EventEmitter<
|
||||||
HealthTreeItem | undefined | void
|
HealthTreeItem | undefined | void
|
||||||
>();
|
>();
|
||||||
|
|
||||||
|
label = 'Health';
|
||||||
|
|
||||||
private lastChecked: Date = new Date();
|
private lastChecked: Date = new Date();
|
||||||
|
|
||||||
readonly onDidChangeTreeData: vscode.Event<HealthTreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData: vscode.Event<HealthTreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
@ -27,11 +38,9 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.Tr
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(element?: HealthTreeItem): Promise<vscode.TreeItem[]> {
|
collapsibleState = vscode.TreeItemCollapsibleState.Collapsed;
|
||||||
if (healthClient === undefined) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
async getChildren(element?: HealthTreeItem): Promise<vscode.TreeItem[]> {
|
||||||
// get children for root
|
// get children for root
|
||||||
if (element === undefined) {
|
if (element === undefined) {
|
||||||
try {
|
try {
|
||||||
|
@ -39,7 +48,7 @@ export class HealthTreeItemProvider implements vscode.TreeDataProvider<vscode.Tr
|
||||||
10000,
|
10000,
|
||||||
async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
return await healthClient?.checkup();
|
return await this.healthClient?.checkup();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ext.outputChannel?.append('Error: ' + e.message);
|
ext.outputChannel?.append('Error: ' + e.message);
|
||||||
vscode.window.showErrorMessage('Could not connect to Appwrite project');
|
vscode.window.showErrorMessage('Could not connect to Appwrite project');
|
16
src/tree/projects/AddProjectTreeItem.ts
Normal file
16
src/tree/projects/AddProjectTreeItem.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { ThemeIcon, TreeItem } from "vscode";
|
||||||
|
|
||||||
|
export class AddProjectTreeItem extends TreeItem {
|
||||||
|
iconPath = new ThemeIcon("add");
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super("Add Appwrite project");
|
||||||
|
}
|
||||||
|
|
||||||
|
contextValue = "";
|
||||||
|
|
||||||
|
command = {
|
||||||
|
command: "vscode-appwrite.addProject",
|
||||||
|
title: "Add Appwrite project",
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,15 +1,36 @@
|
||||||
import { ThemeIcon, TreeItem } from "vscode";
|
import { TreeItem, TreeItemCollapsibleState } from "vscode";
|
||||||
|
import { Client } from "../../appwrite";
|
||||||
|
import { createAppwriteSdk } from "../../client";
|
||||||
import { AppwriteProjectConfiguration } from "../../settings";
|
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) {
|
constructor(public readonly project: AppwriteProjectConfiguration, active: boolean) {
|
||||||
super("Project");
|
super(undefined, "Project");
|
||||||
this.iconPath = new ThemeIcon("rocket");
|
|
||||||
const name = project.nickname ?? "Project";
|
const name = project.nickname ?? "Project";
|
||||||
this.label = `${name} ${active ? "(Active)" : ""}`;
|
this.label = `${name}`;
|
||||||
this.contextValue = `appwriteProject${active ? "_active" : ""}`;
|
this.contextValue = `appwriteProject${active ? "_active" : ""}`;
|
||||||
if (!active) {
|
this.description = project.endpoint;
|
||||||
this.command = { command: "vscode-appwrite.setActiveProject", title: "Set active", arguments: [this] };
|
|
||||||
}
|
this.sdk = createAppwriteSdk(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getChildren(): Promise<TreeItem[]> {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { getActiveProjectId, getAppwriteProjects } from "../../settings";
|
import { getActiveProjectId, getAppwriteProjects } from "../../settings";
|
||||||
|
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||||
import { ProjectTreeItem } from "./ProjectTreeItem";
|
import { ProjectTreeItem } from "./ProjectTreeItem";
|
||||||
|
|
||||||
export class ProjectsTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
export class ProjectsTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||||
|
@ -25,12 +26,18 @@ export class ProjectsTreeItemProvider implements vscode.TreeDataProvider<vscode.
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(_element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
async getChildren(element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
||||||
|
if (element instanceof AppwriteTreeItemBase) {
|
||||||
|
return element.getChildren?.() ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
const configs = await getAppwriteProjects();
|
const configs = await getAppwriteProjects();
|
||||||
if (configs === undefined || configs.length === 0) {
|
if (configs === undefined || configs.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const activeProjectId = await getActiveProjectId();
|
const activeProjectId = await getActiveProjectId();
|
||||||
return configs.map((config) => new ProjectTreeItem(config, config.projectId === activeProjectId));
|
const projectTreeItems = configs.map((config) => new ProjectTreeItem(config, config.projectId === activeProjectId));
|
||||||
|
|
||||||
|
return projectTreeItems;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,37 @@
|
||||||
import * as vscode from "vscode";
|
import { Event, EventEmitter, ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||||
import { storageClient } from "../../client";
|
import { Client } from "../../appwrite";
|
||||||
|
import { Storage } from "../../appwrite/Storage";
|
||||||
|
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||||
|
import { ProjectTreeItem } from "../projects/ProjectTreeItem";
|
||||||
import { FileTreeItem } from "./FileTreeItem";
|
import { FileTreeItem } from "./FileTreeItem";
|
||||||
|
|
||||||
export class StorageTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
export class StorageTreeItemProvider extends AppwriteTreeItemBase<ProjectTreeItem> {
|
||||||
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | void> = new vscode.EventEmitter<
|
constructor(parent: ProjectTreeItem, private readonly sdk: Client) {
|
||||||
vscode.TreeItem | undefined | void
|
super(parent, "Storage");
|
||||||
|
this.iconPath = new ThemeIcon('archive');
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onDidChangeTreeData: EventEmitter<TreeItem | undefined | void> = new EventEmitter<
|
||||||
|
TreeItem | undefined | void
|
||||||
>();
|
>();
|
||||||
|
|
||||||
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData: Event<TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||||
|
|
||||||
refresh(): void {
|
refresh(): void {
|
||||||
this._onDidChangeTreeData.fire();
|
this._onDidChangeTreeData.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
getTreeItem(element: vscode.TreeItem): vscode.TreeItem {
|
getTreeItem(element: TreeItem): TreeItem {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(_element?: vscode.TreeItem): Promise<vscode.TreeItem[]> {
|
collapsibleState = TreeItemCollapsibleState.Collapsed;
|
||||||
if (storageClient === undefined) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
async getChildren(_element?: TreeItem): Promise<TreeItem[]> {
|
||||||
|
const storageClient = new Storage(this.sdk);
|
||||||
const files = await storageClient.listFiles();
|
const files = await storageClient.listFiles();
|
||||||
if (files === undefined || files?.files.length === 0) {
|
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 [noStorage];
|
||||||
}
|
}
|
||||||
return files.files.map((file) => new FileTreeItem(file));
|
return files.files.map((file) => new FileTreeItem(file));
|
||||||
|
|
|
@ -1,14 +1,53 @@
|
||||||
import { User } from "../../appwrite";
|
import { User } from "../../appwrite";
|
||||||
import * as vscode from "vscode";
|
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 {
|
export class UserTreeItem extends AppwriteTreeItemBase<UserTreeItemProvider> {
|
||||||
constructor(public readonly user: User) {
|
constructor(parent: UserTreeItemProvider, public readonly user: User) {
|
||||||
super(user.email);
|
super(parent, user.email);
|
||||||
console.log(user);
|
console.log(user);
|
||||||
this.label = `${user.email}`;
|
this.label = `${user.email}`;
|
||||||
this.tooltip = user.emailVerification ? "Verified" : "Unverified";
|
this.tooltip = user.emailVerification ? "Verified" : "Unverified";
|
||||||
this.iconPath = new vscode.ThemeIcon(user.emailVerification ? "verified" : "unverified");
|
this.iconPath = new vscode.ThemeIcon(user.emailVerification ? "verified" : "unverified");
|
||||||
}
|
}
|
||||||
|
async getChildren(): Promise<vscode.TreeItem[]> {
|
||||||
|
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;
|
collapsibleState = vscode.TreeItemCollapsibleState.Collapsed;
|
||||||
contextValue = "user";
|
contextValue = "user";
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { client } from "../../client";
|
|
||||||
import AppwriteCall from "../../utils/AppwriteCall";
|
import AppwriteCall from "../../utils/AppwriteCall";
|
||||||
import { User, UsersList } from "../../appwrite";
|
import { Client, User, UsersList } from "../../appwrite";
|
||||||
import { ThemeIcon } from "vscode";
|
|
||||||
import { UserPrefsTreeItem } from "./properties/UserPrefsTreeItem";
|
|
||||||
import { ChildTreeItem } from "../ChildTreeItem";
|
|
||||||
import { UserTreeItem } from "./UserTreeItem";
|
import { UserTreeItem } from "./UserTreeItem";
|
||||||
|
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
|
||||||
|
import { ProjectTreeItem } from "../projects/ProjectTreeItem";
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const sdk = require("node-appwrite");
|
const sdk = require("node-appwrite");
|
||||||
|
|
||||||
export class UserTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
export class UserTreeItemProvider extends AppwriteTreeItemBase<ProjectTreeItem> {
|
||||||
|
constructor(parent: ProjectTreeItem, private readonly sdk: Client) {
|
||||||
|
super(parent, "Users");
|
||||||
|
this.iconPath = new vscode.ThemeIcon('account');
|
||||||
|
|
||||||
|
}
|
||||||
private _onDidChangeTreeData: vscode.EventEmitter<UserTreeItem | undefined | void> = new vscode.EventEmitter<
|
private _onDidChangeTreeData: vscode.EventEmitter<UserTreeItem | undefined | void> = new vscode.EventEmitter<
|
||||||
UserTreeItem | undefined | void
|
UserTreeItem | undefined | void
|
||||||
>();
|
>();
|
||||||
|
@ -24,48 +27,14 @@ export class UserTreeItemProvider implements vscode.TreeDataProvider<vscode.Tree
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChildren(element?: UserTreeItem): Promise<vscode.TreeItem[]> {
|
collapsibleState = vscode.TreeItemCollapsibleState.Collapsed;
|
||||||
if (client === undefined) {
|
|
||||||
return Promise.resolve([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element instanceof UserTreeItem) {
|
async getChildren(): Promise<vscode.TreeItem[]> {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const usersSdk = new sdk.Users(client);
|
const usersSdk = new sdk.Users(this.sdk);
|
||||||
const usersList = await AppwriteCall<UsersList, UsersList>(usersSdk.list());
|
const usersList = await AppwriteCall<UsersList, UsersList>(usersSdk.list());
|
||||||
if (usersList) {
|
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 = {
|
const headerItem: vscode.TreeItem = {
|
||||||
label: `Total users: ${usersList.sum}`,
|
label: `Total users: ${usersList.sum}`,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue