Skip to content

Commit

Permalink
added delte for role assignments
Browse files Browse the repository at this point in the history
  • Loading branch information
gbrueckl committed Jan 21, 2025
1 parent 387f0a7 commit ec0bbfd
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 57 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
- added explicit actions for `Edit using TMDL` and `Edit using PBIR`
- added `Edit Definition` for EventStreams
- added new config setting `fabricStudio.iconStyle` to choose between `mono` and `color`
- changed the default icon style to `mono`
- reworked `Connections` treeview to include the gateways displayname
- added `Role Assignments` for connections
- added Drag&Drop for Gateway and Connection role assignments
- added Drag&Drop to assign a workspace to a capacity by dropping the workspace item on the capacity item
- addede `Delete` action for Role assignments

**v1.3.0**:
- added JSON Viewer for Item Connections
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ The first cell would return the list of all workspaces. The second cell gets the
This approach can also be used to simply copy settings from one Power BI object to another by first running a `GET` on the source object and then a `POST`/`PUT`/`PATCH` on the target referencing the output of the preceding `GET`. Common scenarios would be to copy users/permissions or dataset refresh schedules but there are definitely much more use-cases!

# Custom FileSystemProvider
The extension also provides an easy way to interact with all items hosted in Microsoft Fabric. You need to use a [VSCode Workspace](https://code.visualstudio.com/docs/editor/workspaces) when working with VSCode.
The extension also provides an easy way to interact with all items hosted in Microsoft Fabric and modify their definition. You need to use a [VSCode Workspace](https://code.visualstudio.com/docs/editor/workspaces) for this to work properly.
The easiest way to configure and use the custom FileSystemProvider is to right-click the item (or parent or workspace) in the Workspace Browser and select `Edit Defintion`:
![EditDefinition](./images/EditDefinition.png?raw=true "Edit Definition")
Alternatively you can also add the path to your Fabric Workspace (or item) directly to your workspace settings file using an URI in the format of `fabric://workspaces/<workspace-guid>`:
Expand Down Expand Up @@ -164,6 +164,15 @@ If you have your Fabric workspace connected to a GIT repository, you can from no
Once the GIT repository is managed via VSCode, you can stage, commit, undo your changes from within VSCode:
![SourceControl](./images/SourceControl.png?raw=true "SourceControl")

# Drag & Drop Capabilites
For usability, some items are configured for Drag & Drop.
The following list provides the currently supported souces and targets for Drag & Drop

| Source | Target | Action | Description |
|--------|--------|--------|-------------|
| Role Assignment | Role Assignments | Add RoleAssignment | Adds the dragged role assignment to the parent of `Role Assignments` folder where it is dropped. |
| Workspace | Capacity | Assign to Capacity | Assigns the dragged workspace to the dropped capacity. |

# FAQ

**Q: I have so many workspaces and its hard to find the one I need, what can I do?**
Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@
},
{
"command": "FabricStudio.Item.openNewNotebook",
"title": "Open new Fabric Notebook",
"title": "Open in Fabric API Notebook",
"icon": "$(notebook)",
"category": "FabricStudio"
},
Expand Down Expand Up @@ -573,7 +573,7 @@
},
{
"command": "FabricStudio.Item.openNewNotebook",
"when": "view =~ /(FabricStudioWorkspaces)|(FabricStudioDeploymentPipelines)/",
"when": "view =~ /(FabricStudioWorkspaces)|(FabricStudioDeploymentPipelines)|(FabricStudioConnections)/",
"group": "navigation"
},
{
Expand All @@ -598,6 +598,11 @@
}
],
"view/item/context": [
{
"command": "FabricStudio.Item.openNewNotebook",
"when": "view =~ /(FabricStudioWorkspaces)|(FabricStudioDeploymentPipelines)|(FabricStudioConnections)/",
"group": "navigation"
},
{
"command": "FabricStudio.Item.openInFabric",
"when": "view =~ /(FabricStudioWorkspaces)|(FabricStudioDeploymentPipelines)|(FabricStudioConnections)/ && viewItem =~ /.*,OPEN_IN_BROWSER,.*/",
Expand Down Expand Up @@ -650,7 +655,7 @@
},
{
"command": "FabricStudio.Item.delete",
"when": "view == FabricStudioWorkspaces && viewItem =~ /.*,DELETE,.*/",
"when": "view =~ /(FabricStudioWorkspaces)|(FabricStudioConnections)/ && viewItem =~ /.*,DELETE,.*/",
"group": "3_delete"
},
{
Expand Down
15 changes: 8 additions & 7 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,19 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('FabricStudio.WorkspaceRoleAssignment.delete', (roleAssignment: FabricWorkspaceRoleAssignment = undefined) => roleAssignment.delete());
vscode.commands.registerCommand('FabricStudio.WorkspaceRoleAssignment.update', (roleAssignment: FabricWorkspaceRoleAssignment = undefined) => roleAssignment.update());

vscode.commands.registerCommand('FabricStudio.Item.openInFabric', (treeItem: FabricWorkspaceTreeItem) => treeItem.openInBrowser());
vscode.commands.registerCommand('FabricStudio.Item.copyIdToClipboard', (treeItem: FabricWorkspaceTreeItem) => treeItem.copyIdToClipboard());
vscode.commands.registerCommand('FabricStudio.Item.copyNameToClipboard', (treeItem: FabricWorkspaceTreeItem) => treeItem.copyNameToClipboard());
vscode.commands.registerCommand('FabricStudio.Item.copyPathToClipboard', (treeItem: FabricWorkspaceTreeItem) => treeItem.copyPathToClipboard());
vscode.commands.registerCommand('FabricStudio.Item.copyPropertiesToClipboard', (treeItem: FabricWorkspaceTreeItem) => treeItem.copyPropertiesToClipboard());
vscode.commands.registerCommand('FabricStudio.Item.insertPath', (treeItem: FabricWorkspaceTreeItem) => treeItem.insertCode());
vscode.commands.registerCommand('FabricStudio.Item.openInFabric', (treeItem: FabricApiTreeItem) => treeItem.openInBrowser());
vscode.commands.registerCommand('FabricStudio.Item.copyIdToClipboard', (treeItem: FabricApiTreeItem) => treeItem.copyIdToClipboard());
vscode.commands.registerCommand('FabricStudio.Item.copyNameToClipboard', (treeItem: FabricApiTreeItem) => treeItem.copyNameToClipboard());
vscode.commands.registerCommand('FabricStudio.Item.copyPathToClipboard', (treeItem: FabricApiTreeItem) => treeItem.copyPathToClipboard());
vscode.commands.registerCommand('FabricStudio.Item.copyPropertiesToClipboard', (treeItem: FabricApiTreeItem) => treeItem.copyPropertiesToClipboard());
vscode.commands.registerCommand('FabricStudio.Item.insertPath', (treeItem: FabricApiTreeItem) => treeItem.insertCode());
vscode.commands.registerCommand('FabricStudio.Item.browseInOneLake', (treeItem: FabricWorkspaceTreeItem) => ThisExtension.browseInOneLake(treeItem));
vscode.commands.registerCommand('FabricStudio.Item.editDefinition', (treeItem: FabricWorkspaceTreeItem) => treeItem.editDefinition());
vscode.commands.registerCommand('FabricStudio.Item.editTMDL', (treeItem: FabricWorkspaceTreeItem) => treeItem.editDefinition());
vscode.commands.registerCommand('FabricStudio.Item.editPBIR', (treeItem: FabricWorkspaceTreeItem) => treeItem.editDefinition());
vscode.commands.registerCommand('FabricStudio.Item.showDefintion', async (treeItem: FabricWorkspaceGenericViewer) => treeItem.showDefinition());
vscode.commands.registerCommand('FabricStudio.Item.delete', async (treeItem: FabricWorkspaceTreeItem) => treeItem.delete("yesNo"));
vscode.commands.registerCommand('FabricStudio.Item.delete', async (treeItem: FabricApiTreeItem) =>
treeItem.delete("yesNo"));


vscode.commands.registerCommand('FabricStudio.Lakehouse.copySQLConnectionString', (treeItem: FabricLakehouse) => treeItem.copySQLConnectionString());
Expand Down
4 changes: 4 additions & 0 deletions src/vscode/treeviews/Capacities/FabricCapacity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export class FabricCapacity extends FabricCapacityTreeItem {
}
}

public get canDelete(): boolean {
return false;
}

/* Overwritten properties from FabricCapacityTreeItem */
static async assignWorkspace(workspace: iFabricApiWorkspace, capacity: iFabricApiCapacity): Promise<void> {
// https://learn.microsoft.com/en-us/rest/api/fabric/core/workspaces/assign-to-capacity?tabs=HTTP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,12 @@ export class FabricConnectionRoleAssignment extends FabricConnectionGenericViewe
}

get apiPath(): string {
return Helper.joinPath(this.parent.apiPath, this.itemId);
}
return Helper.joinPath(this.parent.apiPath, this.itemId);
}

get canDelete(): boolean {
return true;
}

/* Overwritten properties from FabricConnectionGenericViewer */
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,9 @@ export class FabricGatewayRoleAssignment extends FabricConnectionGenericViewer {
this._itemDefinition = value;
}

get canDelete(): boolean {
return true;
}

/* Overwritten properties from FabricConnectionGenericViewer */
}
49 changes: 43 additions & 6 deletions src/vscode/treeviews/FabricApiTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ export class FabricApiTreeItem extends vscode.TreeItem {

// tooltip shown when hovering over the item
protected getToolTip(definition: any) {
if(!definition) return undefined;
if (!definition) return undefined;

let tooltip: string = "";
for (const [key, value] of Object.entries(definition)) {
if(!value) continue; // skip empty values
if (!value) continue; // skip empty values
if (typeof value === "string") {
if (value.length > 100 || value.length < 1) {
continue;
Expand All @@ -82,10 +82,10 @@ export class FabricApiTreeItem extends vscode.TreeItem {
"COPY_PROPERTIES",
"INSERT_CODE",
];
if(this.canOpenInBrowser) {
if (this.canOpenInBrowser) {
actions.push("OPEN_IN_BROWSER");
}
if(this.canDelete) {
if (this.canDelete) {
actions.push("DELETE");
}
return `,${actions.join(',')},`;
Expand All @@ -95,12 +95,49 @@ export class FabricApiTreeItem extends vscode.TreeItem {
public get canOpenInBrowser(): boolean {
return true;
}

// can be overwritten in derived classes to disable "Delete"
public get canDelete(): boolean {
return true;
}

public async delete(confirmation: "yesNo" | "name" | undefined = undefined): Promise<void> {
if (confirmation) {
let confirm: string;
switch (confirmation) {
case "yesNo":
confirm = await FabricCommandBuilder.showQuickPick([new FabricQuickPickItem("yes"), new FabricQuickPickItem("no")], `Do you really want to delete ${this.itemType.toLowerCase()} '${this.itemName}'?`, undefined, undefined);
break;
case "name":
confirm = await FabricCommandBuilder.showInputBox("", `Confirm deletion by typeing the ${this.itemType.toLowerCase()} name '${this.itemName}' again.`, undefined, undefined);
break;
}

if (!confirm
|| (confirmation == "name" && confirm != this.itemName)
|| (confirmation == "yesNo" && confirm != "yes")) {
const abortMsg = `Aborted deletion of ${this.itemType.toLowerCase()} '${this.itemName}'!`
ThisExtension.Logger.logWarning(abortMsg);
Helper.showTemporaryInformationMessage(abortMsg, 2000)
return;
}
}

const response = await FabricCommandBuilder.execute<any>(this.apiPath, "DELETE", []);
if (response.error) {
const errorMsg = response.error.message;
vscode.window.showErrorMessage(errorMsg);
}
else {
const successMsg = `Deleted ${this.itemType.toLowerCase()} '${this.itemName}'!`
Helper.showTemporaryInformationMessage(successMsg, 5000);

if (this.parent) {
ThisExtension.refreshTreeView(this.TreeProvider, this.parent);
}
}
}

public async getChildren(element?: FabricApiTreeItem): Promise<FabricApiTreeItem[]> {
await vscode.window.showErrorMessage("getChildren is not implemented! Please overwrite in derived class!");
return undefined;
Expand Down Expand Up @@ -186,7 +223,7 @@ export class FabricApiTreeItem extends vscode.TreeItem {
public openInBrowser(): void {
const tenantParam = FabricApiService.TenantId ? `?ctid=${FabricApiService.TenantId}` : "";
const fullLink = `${this.getBrowserLink()}${tenantParam}`;

Helper.openLink(fullLink);
}

Expand Down
38 changes: 0 additions & 38 deletions src/vscode/treeviews/Workspaces/FabricWorkspaceTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,42 +99,4 @@ export class FabricWorkspaceTreeItem extends FabricApiTreeItem {

await Helper.addToWorkspace(fabricUri.uri, label, true);
}

public async delete(confirmation: "yesNo" | "name" | undefined = undefined): Promise<void> {

if (confirmation) {
let confirm: string;
switch (confirmation) {
case "yesNo":
confirm = await FabricCommandBuilder.showQuickPick([new FabricQuickPickItem("yes"), new FabricQuickPickItem("no")], `Do you really want to delete ${this.itemType.toLowerCase()} '${this.itemName}'?`, undefined, undefined);
break;
case "name":
confirm = await FabricCommandBuilder.showInputBox("", `Confirm deletion by typeing the ${this.itemType.toLowerCase()} name '${this.itemName}' again.`, undefined, undefined);
break;
}

if (!confirm
|| (confirmation == "name" && confirm != this.itemName)
|| (confirmation == "yesNo" && confirm != "yes")) {
const abortMsg = `Deletion of ${this.itemType.toLowerCase()} '${this.itemName}' aborted!`
ThisExtension.Logger.logWarning(abortMsg);
Helper.showTemporaryInformationMessage(abortMsg, 2000)
return;
}
}

const response = await FabricCommandBuilder.execute<any>(this.apiPath, "DELETE", []);
if (response.error) {
const errorMsg = response.error.message;
vscode.window.showErrorMessage(errorMsg);
}
else {
const successMsg = `${this.itemType.toLowerCase()} '${this.itemName}' deleted!`
Helper.showTemporaryInformationMessage(successMsg, 2000);

if (this.parent) {
ThisExtension.refreshTreeView(this.TreeProvider, this.parent);
}
}
}
}

0 comments on commit ec0bbfd

Please sign in to comment.