Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
31 changes: 1 addition & 30 deletions src/renderer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<button class="activity-item" id="mcp-btn" title="MCP Server">
<img id="logs-icon" src="icons/dark/mcp.svg" alt="MCP Icon" class="activity-icon" />
</button>
<button class="activity-item" data-sidebar="consents" title="Consent Review">
<button class="activity-item" id="consent-review-activity-btn" title="Consent Review">
<img id="consent-icon" src="icons/dark/consent-shield.svg" alt="Consent Review Icon" class="activity-icon" />
</button>
<button class="activity-item" id="settings-activity-btn" title="Settings">
Expand Down Expand Up @@ -284,35 +284,6 @@ <h2 class="sidebar-title">MARKETPLACE</h2>
</div>
</div>

<!-- Consent Review Sidebar -->
<div class="sidebar-content" id="sidebar-consents">
<div class="sidebar-header">
<h2 class="sidebar-title">CONSENT REVIEW</h2>
<div class="sidebar-header-actions">
<button id="sidebar-consents-open-tab-btn" class="fluent-button fluent-button-secondary" title="Open full view" aria-label="Open full view">
<img id="consents-open-tab-icon" width="16" height="16" alt="" aria-hidden="true" />
<span>Full View</span>
</button>
</div>
</div>
<div class="sidebar-search-bar">
<div class="sidebar-search-input-wrapper">
<input type="text" id="consents-search-input" class="search-input" placeholder="Search tools..." />
<button type="button" class="search-clear-btn" data-clear-target="consents-search-input" aria-label="Clear consent review search" title="Clear search">&times;</button>
</div>
<div class="filter-btn-group">
<select id="consents-status-filter" class="filter-dropdown-select" aria-label="Filter consent status">
<option value="all">All</option>
<option value="granted">Granted</option>
<option value="revoked">Revoked</option>
</select>
</div>
</div>
<div class="sidebar-body">
<div class="settings-container-sidebar" id="sidebar-consent-review-container"></div>
</div>
</div>

<!-- Links Sidebar -->
<div class="sidebar-content" id="sidebar-links">
<div class="sidebar-header">
Expand Down
124 changes: 41 additions & 83 deletions src/renderer/modules/cspConsentReviewSidebarManagement.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* CSP consent review module
* Renders consent review in sidebar and in full-tab mode.
* Renders consent review in full-tab mode.
*/

import { logError, logInfo } from "../../common/logger";
Expand Down Expand Up @@ -71,11 +71,20 @@ function buildConsentEntries(tools: Tool[], consentsByToolId: { [toolId: string]
});
}

function createCountBadge(label: string, count: number): HTMLElement {
const badge = document.createElement("span");
badge.className = "consent-review-count-badge";
badge.textContent = `${label} ${count}`;
return badge;
function createSummaryStat(label: string, count: number): HTMLElement {
const stat = document.createElement("div");
stat.className = "consent-review-summary-stat";

const value = document.createElement("span");
value.className = "consent-review-summary-value";
value.textContent = String(count);

const labelElement = document.createElement("span");
labelElement.className = "consent-review-summary-label";
labelElement.textContent = label;

stat.append(value, labelElement);
return stat;
}

function createDomainList(title: string, domains: string[]): HTMLElement {
Expand Down Expand Up @@ -153,24 +162,15 @@ function renderContext(context: ConsentReviewContext, entries: ConsentReviewEntr

const filtered = getFilteredEntries(entries, context);

const summaryCard = document.createElement("section");
summaryCard.className = "settings-section-card consent-review-summary-card";
summaryCard.innerHTML = `
<div class="settings-section-header">
<p class="settings-section-eyebrow">Security</p>
<p class="settings-section-description">Review marketplace tool permissions and apply changes in one flow.</p>
</div>
`;

const summaryBody = document.createElement("div");
summaryBody.className = "consent-review-summary-badges";
const summary = document.createElement("section");
summary.className = "consent-review-summary";
summary.setAttribute("aria-label", "Consent summary");
const grantedCount = entries.filter((entry) => entry.granted).length;
const revokedCount = entries.length - grantedCount;
summaryBody.appendChild(createCountBadge("Total", entries.length));
summaryBody.appendChild(createCountBadge("Granted", grantedCount));
summaryBody.appendChild(createCountBadge("Revoked", revokedCount));
summaryCard.appendChild(summaryBody);
container.appendChild(summaryCard);
summary.appendChild(createSummaryStat("Tools", entries.length));
summary.appendChild(createSummaryStat("Granted", grantedCount));
summary.appendChild(createSummaryStat("Revoked", revokedCount));
container.appendChild(summary);

if (filtered.length === 0) {
const emptyCard = document.createElement("section");
Expand All @@ -185,7 +185,7 @@ function renderContext(context: ConsentReviewContext, entries: ConsentReviewEntr

filtered.forEach((entry) => {
const card = document.createElement("section");
card.className = "settings-section-card consent-review-card";
card.className = "settings-vscode-item consent-review-card";

const statusClass = entry.granted ? "granted" : "revoked";
const statusText = entry.granted ? "Granted" : "Revoked";
Expand All @@ -194,21 +194,25 @@ function renderContext(context: ConsentReviewContext, entries: ConsentReviewEntr
const notConsentedDomains = getNotConsentedDomains(entry);

card.innerHTML = `
<div class="consent-review-card-header">
<div class="consent-review-card-title-wrap">
<p class="consent-review-card-title">${entry.toolName}</p>
<p class="consent-review-card-subtitle">${contributorsText}</p>
<div class="consent-review-card-main">
<div class="consent-review-card-header">
<div class="consent-review-card-title-wrap">
<p class="consent-review-card-title">${entry.toolName}</p>
<p class="consent-review-card-subtitle">${contributorsText}</p>
</div>
</div>
<span class="consent-status-badge ${statusClass}">${statusText}</span>
${entry.description ? `<p class="consent-review-card-description">${entry.description}</p>` : ""}
</div>
<div class="consent-review-card-control">
<span class="consent-status ${statusClass}"><span class="consent-status-dot" aria-hidden="true"></span>${statusText}</span>
</div>
${entry.description ? `<p class="consent-review-card-description">${entry.description}</p>` : ""}
`;

const domains = document.createElement("div");
domains.className = "consent-review-domains-grid";
domains.appendChild(createDomainList("Consented", consentedDomains));
domains.appendChild(createDomainList("Not Consented", notConsentedDomains));
card.appendChild(domains);
card.querySelector(".consent-review-card-main")?.appendChild(domains);

const actions = document.createElement("div");
actions.className = "consent-review-card-actions";
Expand All @@ -218,7 +222,7 @@ function renderContext(context: ConsentReviewContext, entries: ConsentReviewEntr
actionButton.textContent = "Make Changes";
actionButton.setAttribute("data-tool-id", entry.toolId);
actions.appendChild(actionButton);
card.appendChild(actions);
card.querySelector(".consent-review-card-control")?.appendChild(actions);

container.appendChild(card);
});
Expand Down Expand Up @@ -334,50 +338,16 @@ function attachContextEventHandlers(context: ConsentReviewContext): void {
bindActionHandling(context);
}

function registerSidebarContext(): ConsentReviewContext | null {
const searchInput = document.getElementById("consents-search-input") as HTMLInputElement | null;
const statusFilter = document.getElementById("consents-status-filter") as HTMLSelectElement | null;
const listContainer = document.getElementById("sidebar-consent-review-container") as HTMLElement | null;

if (!searchInput || !statusFilter || !listContainer) {
return null;
}

const existing = contexts.get("sidebar");
if (existing) {
return existing;
}

const context: ConsentReviewContext = {
key: "sidebar",
searchInput,
statusFilter,
listContainer,
};
contexts.set("sidebar", context);
attachContextEventHandlers(context);

const openTabBtn = document.getElementById("sidebar-consents-open-tab-btn");
if (openTabBtn && openTabBtn.getAttribute("data-bound") !== "true") {
openTabBtn.setAttribute("data-bound", "true");
openTabBtn.addEventListener("click", () => {
openConsentReviewTab().catch((error) => {
logError(error instanceof Error ? error : new Error(String(error)));
});
});
}

return context;
}

function renderConsentTabContent(panel: HTMLElement): void {
panel.className = "settings-tab-container";
panel.innerHTML = `
<div class="settings-tab-content" id="consent-review-tab-scroll-area">
<section class="settings-vscode-section" id="consent-review-section">
<h2 class="settings-vscode-section-title">Consent Review</h2>
<p class="settings-vscode-item-description" style="margin-bottom: 12px;">Review and update permissions for marketplace-installed tools.</p>
<div class="sidebar-search-bar consent-review-tab-toolbar">
<header class="consent-review-page-header">
<h2 class="settings-vscode-section-title">Consent Review</h2>
<p class="consent-review-page-description">Review and update permissions for marketplace-installed tools.</p>
</header>
<div class="consent-review-tab-toolbar">
<div class="sidebar-search-input-wrapper">
<input type="text" id="consent-tab-search-input" class="search-input" placeholder="Search tools..." />
</div>
Expand All @@ -390,7 +360,7 @@ function renderConsentTabContent(panel: HTMLElement): void {
<button id="consent-tab-refresh-btn" class="fluent-button fluent-button-secondary">Refresh</button>
</div>
</div>
<div id="consent-tab-list-container" class="settings-container-sidebar"></div>
<div id="consent-tab-list-container" class="consent-review-list"></div>
</section>
</div>
`;
Expand Down Expand Up @@ -431,15 +401,3 @@ export async function openConsentReviewTab(): Promise<void> {
registerCloseGuard("consent-review", async () => true);
await openLocalPageAsTab("consent-review", "Consent Review", renderConsentTabContent, "");
}

/**
* Loads and renders all CSP consent records in the sidebar panel.
*/
export async function loadSidebarConsentReview(): Promise<void> {
const context = registerSidebarContext();
if (!context) {
return;
}

await refreshContext(context);
}
11 changes: 11 additions & 0 deletions src/renderer/modules/initialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
openAddConnectionModal,
updateFooterConnection,
} from "./connectionManagement";
import { openConsentReviewTab } from "./cspConsentReviewSidebarManagement";
import { initializeGlobalSearch } from "./globalSearchManagement";
import { loadHomepageData, setupHomepageActions } from "./homepageManagement";
import { clearMarketplaceDropdownFilters, handleProtocolInstallToolRequest, loadMarketplace, loadToolsLibrary } from "./marketplaceManagement";
Expand Down Expand Up @@ -270,6 +271,16 @@ function setupActivityBar(): void {
});
}

// Consent review button opens a tab instead of a sidebar panel
const consentReviewActivityBtn = document.getElementById("consent-review-activity-btn");
if (consentReviewActivityBtn) {
consentReviewActivityBtn.addEventListener("click", () => {
openConsentReviewTab().catch((err) => {
logError(err instanceof Error ? err : new Error(String(err)));
});
});
}

// Agent invocation logs button opens a tab
const agentInvocationLogsBtn = document.getElementById("mcp-btn");
if (agentInvocationLogsBtn) {
Expand Down
14 changes: 0 additions & 14 deletions src/renderer/modules/sidebarManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import { logError } from "../../common/logger";
import { loadSidebarCommunityResources } from "./communityResourcesSidebarManagement";
import { loadSidebarConsentReview } from "./cspConsentReviewSidebarManagement";
import { loadSettings } from "./settingsManagement";

// Track current sidebar
Expand Down Expand Up @@ -56,12 +55,6 @@ export function switchSidebar(sidebarId: string): void {
});
}

// Load consent review when re-expanding consent sidebar
if (sidebarId === "consents") {
loadSidebarConsentReview().catch((err) => {
logError(err instanceof Error ? err : new Error(String(err)));
});
}
}
window.api?.send("sidebar-layout-changed");
return;
Expand Down Expand Up @@ -103,12 +96,5 @@ export function switchSidebar(sidebarId: string): void {
});
}

// Load consent review when switching to consent sidebar
if (sidebarId === "consents") {
loadSidebarConsentReview().catch((err) => {
logError(err instanceof Error ? err : new Error(String(err)));
});
}

window.api?.send("sidebar-layout-changed");
}
5 changes: 0 additions & 5 deletions src/renderer/modules/themeManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,6 @@ export function updateConnectionIconsForTheme(): void {
exportIcon.src = isDarkTheme ? "icons/dark/export.svg" : "icons/light/export.svg";
}

const consentsOpenTabIcon = document.getElementById("consents-open-tab-icon") as HTMLImageElement | null;
if (consentsOpenTabIcon) {
consentsOpenTabIcon.src = isDarkTheme ? "icons/dark/expand.svg" : "icons/light/expand.svg";
}

// Update category group export icons
const exportIconPath = isDarkTheme ? "icons/dark/export.svg" : "icons/light/export.svg";
document.querySelectorAll(".connection-group-export-icon").forEach((img) => {
Expand Down
Loading
Loading