Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@
"when": "view == dvEntities",
"group": "navigation@2"
},
{
"command": "dvdt.commands.showToolsPage",
"when": "view == ppToolBox",
"group": "navigation@1",
"icon": "$(table)"
},
{
"command": "dvdt.explorer.webresources.smartMatch",
"when": "view == dvWebResources",
Expand Down Expand Up @@ -505,6 +511,17 @@
"title": "Open Dataverse REST Builder (DRB)",
"category": "%dvdt.commands.category%"
},
{
"command": "dvdt.commands.showToolsPage",
"title": "Show Tools Page",
"category": "%dvdt.commands.category%"
},
{
"command": "dvdt.commands.launchToolByShortName",
"title": "Launch Tool",
"when": "false",
"category": "%dvdt.commands.category%"
},
{
"command": "dvdt.explorer.tools.launchTool",
"title": "Launch tool from ToolBox",
Expand Down
19 changes: 19 additions & 0 deletions resources/views/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ body {
font-size: small;
}

.btn {
padding: 4px 12px;
cursor: pointer;
background-color: var(--vscode-button-background);
color: var(--vscode-button-foreground);
border: none;
border-radius: 2px;
font-size: 0.8rem;
}

.btn:hover {
background-color: var(--vscode-button-hoverBackground);
}

.btn:active {
background-color: var(--vscode-button-hoverBackground);
opacity: 0.8;
}

/**** Lables ****/
label {
font-size: 0.8rem;
Expand Down
14 changes: 14 additions & 0 deletions resources/views/js/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ $(document).ready(function () {
});
});

$("#toolsSearch").on("keyup", function () {
var value = $(this).val().toLowerCase();
$("#toolsTableBody tr").filter(function () {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1);
});
});

if ($matchTable && $matchTable.bootstrapTable) {
$matchTable.bootstrapTable();
$matchTable.bootstrapTable("refreshOptions", {
Expand Down Expand Up @@ -80,6 +87,13 @@ function link(fullPath, wrId) {
});
}

function launchTool(toolShortName) {
vscode.postMessage({
command: "launchTool",
toolShortName: toolShortName,
});
}

function sortTable(tableId, column) {
var table = document.getElementById(tableId);
var tbody = table.querySelector("tbody");
Expand Down
37 changes: 37 additions & 0 deletions resources/views/toolslist.html
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot make it look modern and take the inspiration from XrmToolBox

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! The tools page now features a modern, card-based design inspired by XrmToolBox:

Modern Tools Page

Changes in commit b513cb7:

  • Card-based grid layout with hover effects and smooth animations
  • Visual icons for each tool (πŸ”§ πŸ”Œ πŸ“¦ πŸš€)
  • Rich descriptions for better context
  • Gradient backgrounds and modern styling
  • Enhanced search across name, author, and description
  • Responsive design that adapts to screen size
  • Launch buttons with visual feedback

The design follows XrmToolBox's approach with attractive cards, clear visual hierarchy, and intuitive interactions.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<br /><br />

<input class="vscode-textfield" autofocus id="toolsSearch" placeholder="Search tools..."></input>

<br />

<table class="table table-bordered sortable" id="toolsTable">
<thead>
<th onclick="sortTable('toolsTable',0)">
Tool Name
<div class="sort-icon">
<span class="asc-icon">&#9650;</span>
<span class="desc-icon">&#9660;</span>
</div>
</th>
<th onclick="sortTable('toolsTable',1)">
Short Name
<div class="sort-icon">
<span class="asc-icon">&#9650;</span>
<span class="desc-icon">&#9660;</span>
</div>
</th>
<th onclick="sortTable('toolsTable',2)">
Author
<div class="sort-icon">
<span class="asc-icon">&#9650;</span>
<span class="desc-icon">&#9660;</span>
</div>
</th>
<th>
Action
</th>
</thead>
<tbody id="toolsTableBody">
!!{tools}
</tbody>
</table>
37 changes: 37 additions & 0 deletions src/commands/registerCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,43 @@ export async function registerCommands(vscontext: vscode.ExtensionContext, tr: T
}
},
},
{
command: "dvdt.commands.showToolsPage",
callback: async () => {
try {
const webview = await views.getWebView({ type: "showToolsList", title: "Power Platform ToolBox" });
const { ToolsListView } = await import("../views/ToolsListView");
new ToolsListView(webview, vscontext);
} catch (error) {
errorHandler.log(error, "showToolsPage");
}
},
},
{
command: "dvdt.commands.launchToolByShortName",
callback: async (toolShortName: string) => {
try {
switch (toolShortName) {
case "drb":
drbHelper.openDRB(views);
break;
case "prt":
cliHelper.launchPRT();
break;
case "cmt":
cliHelper.launchCMT();
break;
case "pd":
cliHelper.launchPD();
break;
default:
break;
}
} catch (error) {
errorHandler.log(error, "launchToolByShortName");
}
},
},
{
command: "dvdt.explorer.webresources.linkExistingWebResource",
callback: async (uri: vscode.Uri) => {
Expand Down
52 changes: 52 additions & 0 deletions src/views/ToolsListView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as vscode from "vscode";
import * as path from "path";
import { IToolDetails } from "../utils/Interfaces";
import { readFileSync } from "../utils/FileSystem";
import _ from "lodash";
import { VsCodePanel } from "./base/VsCodePanelBase";
import toolsInJson from "../tools/tools.json";

export class ToolsListView extends VsCodePanel {
private tools: IToolDetails[];

constructor(webview: vscode.WebviewPanel, vscontext: vscode.ExtensionContext) {
super({ panel: webview, extensionUri: vscontext.extensionUri, webViewFileName: "toolslist.html" });
this.tools = toolsInJson.tools;
// Set the webview's initial html content
super.update();

// Set up message listener for launching tools
this.webViewPanel.webview.onDidReceiveMessage(
message => {
switch (message.command) {
case 'launchTool':
vscode.commands.executeCommand('dvdt.commands.launchToolByShortName', message.toolShortName);
return;
}
}
);
}

public getHtmlForWebview(webviewFileName: string): string {
const pathOnDisk = path.join(this.panelOptions.extensionUri.fsPath, "resources", "views", webviewFileName);
const fileHtml = readFileSync(pathOnDisk).toString();
_.templateSettings.interpolate = /!!{([\s\S]+?)}/g;
const compiled = _.template(fileHtml);

const viewModel = {
tools: this.tools.map(tool => {
const escapedToolName = _.escape(tool.toolName);
const escapedShortName = _.escape(tool.toolShortName);
const escapedAuthor = _.escape(tool.toolAuthor);
return `<tr>
<td>${escapedToolName}</td>
<td>${escapedShortName}</td>
<td>${escapedAuthor}</td>
<td><button class="btn" onclick="launchTool('${escapedShortName}')">Launch</button></td>
</tr>`;
}).join(''),
};

return super.render(compiled(viewModel));
}
}