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
5 changes: 5 additions & 0 deletions .changeset/remove-page-designer-assistant.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'b2c-vs-extension': minor
---

Remove the Page Designer Assistant webview and its "Open Page Designer Assistant UI" command from the VS Code extension.
2 changes: 1 addition & 1 deletion docs/vscode-extension/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ A summary by feature:
| **B2C Script Debugger** | WebDAV (for source-mapping). |
| **Log Tailing** | WebDAV (logs are read from `Logs/`). |
| **CAP install** | WebDAV; some apps additionally require OAuth client credentials. |
| **Scaffold**, **Page Designer Assistant** | None — local-only. |
| **Scaffold** | None — local-only. |

### Example `dw.json`

Expand Down
4 changes: 1 addition & 3 deletions packages/b2c-vs-extension/.c8rc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
"src/test/**",
"dist/**",
"scripts/**",
"**/*.d.ts",
"src/template/**",
"src/webview.html"
"**/*.d.ts"
],
"reporter": ["text", "text-summary", "lcov"],
"report-dir": "coverage",
Expand Down
3 changes: 1 addition & 2 deletions packages/b2c-vs-extension/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# B2C DX - VS Code Extension

VS Code extension for B2C Commerce developer experience: sandbox realm explorer, cartridge code sync, WebDAV browser, content libraries, SCAPI API browser, B2C script debugger, scaffold/CAP install, log tailing, and a Page Designer Assistant.
VS Code extension for B2C Commerce developer experience: sandbox realm explorer, cartridge code sync, WebDAV browser, content libraries, SCAPI API browser, B2C script debugger, scaffold/CAP install, and log tailing.

**User-facing documentation:** [B2C DX VS Code Extension](https://salesforcecommercecloud.github.io/b2c-developer-tooling/vscode-extension/) — overview, installation, configuration, and feature tour.

Expand All @@ -16,7 +16,6 @@ This README is the source of truth for repo-level developer info (build/watch, l
- B2C Script Debugger (debug type `b2c-script`).
- Scaffold (`New from Scaffold...`) and CAP install.
- Log tailing into a dedicated output channel.
- Page Designer Assistant webview (Storefront Next page generation).

See the [docs site](https://salesforcecommercecloud.github.io/b2c-developer-tooling/vscode-extension/features) for the full tour.

Expand Down
5 changes: 0 additions & 5 deletions packages/b2c-vs-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,6 @@
}
],
"commands": [
{
"command": "b2c-dx.openUI",
"title": "Open Page Designer Assistant UI",
"category": "B2C DX - Page Designer Assistant"
},
{
"command": "b2c-dx.promptAgent",
"title": "Prompt Agent",
Expand Down
140 changes: 1 addition & 139 deletions packages/b2c-vs-extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import {DwJsonSource} from '@salesforce/b2c-tooling-sdk/config';
import {configureLogger} from '@salesforce/b2c-tooling-sdk/logging';

import * as fs from 'fs';
import * as path from 'path';
import * as vscode from 'vscode';
import {B2CExtensionConfig} from './config-provider.js';
Expand All @@ -24,70 +23,7 @@ import {registerDebugger} from './debugger/index.js';
import {registerCodeSync} from './code-sync/index.js';
import {registerScriptTypes} from './script-types/index.js';
import {registerWebDavTree} from './webdav-tree/index.js';
import {disposeTelemetry, initTelemetry, markFeatureUsed, sendEvent, sendException} from './telemetry.js';

function getWebviewContent(context: vscode.ExtensionContext): string {
const htmlPath = path.join(context.extensionPath, 'src', 'webview.html');
return fs.readFileSync(htmlPath, 'utf-8');
}

/** PascalCase for use in template content (class names, types, etc.). e.g. "first page" → "FirstPage" */
function pageNameToPageId(pageName: string): string {
return pageName
.trim()
.split(/\s+/)
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join('');
}

/** camelCase for filename. e.g. "first page" → "firstPage" */
function pageNameToFileNameId(pageName: string): string {
const pascal = pageNameToPageId(pageName || 'Page');
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
}

type RegionForm = {id: string; name: string; description: string; maxComponents: number};

type WebviewMessage =
| {type: 'openExternal'}
| {
type: 'submitForm';
pageType: {name?: string; description?: string; supportedAspectTypes?: string[]};
regions: RegionForm[];
};

function renderTemplate(
template: string,
pageName: string,
pageDescription: string,
supportedAspectTypes: string[],
regions: RegionForm[],
): string {
const pageId = pageNameToPageId(pageName || 'Page');
const quoted = (s: string) => `'${String(s).replace(/'/g, "\\'")}'`;
const aspectsStr = `[${supportedAspectTypes.map((a) => quoted(a)).join(', ')}]`;
const regionsBlock = regions
.map(
(r) =>
`{
id: ${quoted(r.id)},
name: ${quoted(r.name)},
description: ${quoted(r.description)},
maxComponents: ${r.maxComponents},
}`,
)
.join(',\n ');
const firstRegionId = regions[0]?.id ?? '';

return template
.replace(/\$\{pageName\}/g, quoted(pageName || ''))
.replace(/\$\{pageDescription\}/g, quoted(pageDescription || ''))
.replace(/\$\{supportedAspectTypes\}/g, aspectsStr)
.replace('__REGIONS__', regionsBlock)
.replace(/\$\{pageId\}/g, pageId)
.replace(/\$\{pageName\}Data/g, `${pageId}Data`)
.replace(/\$\{regions\[0\]\.id\}/g, firstRegionId);
}
import {disposeTelemetry, initTelemetry, sendEvent, sendException} from './telemetry.js';

function applyLogLevel(log: vscode.OutputChannel): void {
const config = vscode.workspace.getConfiguration('b2c-dx');
Expand Down Expand Up @@ -140,7 +76,6 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.window.showErrorMessage(`B2C DX activation error: ${message}`);
};
context.subscriptions.push(
vscode.commands.registerCommand('b2c-dx.openUI', showActivationError),
vscode.commands.registerCommand('b2c-dx.promptAgent', showActivationError),
vscode.commands.registerCommand('b2c-dx.listWebDav', showActivationError),
);
Expand Down Expand Up @@ -169,78 +104,6 @@ async function activateInner(context: vscode.ExtensionContext, log: vscode.Outpu
const cartridgeService = new CartridgeService(configProvider);
context.subscriptions.push(cartridgeService);

const disposable = vscode.commands.registerCommand('b2c-dx.openUI', () => {
markFeatureUsed('pageDesigner');
vscode.window.showInformationMessage('B2C DX: Opening Page Designer Assistant.');

const panel = vscode.window.createWebviewPanel(
'b2c-dx-page-designer-ui',
'My Extension UI',
vscode.ViewColumn.One,
{enableScripts: true},
);

panel.webview.html = getWebviewContent(context);

panel.webview.onDidReceiveMessage(async (msg: WebviewMessage) => {
if (msg.type === 'openExternal') {
await vscode.env.openExternal(vscode.Uri.parse('https://example.com'));
}
if (msg.type === 'submitForm') {
try {
const {pageType, regions} = msg;
const pageName = pageType?.name ?? '';
const templatePath = path.join(context.extensionPath, 'src', 'template', '_app.pageId.tsx');
const template = fs.readFileSync(templatePath, 'utf-8');
const content = renderTemplate(
template,
pageName,
pageType?.description ?? '',
pageType?.supportedAspectTypes ?? [],
regions ?? [],
);

const fileNameId = pageNameToFileNameId(pageName);
const fileName = `_app.${fileNameId}.tsx`;

let targetUri: vscode.Uri;
if (vscode.workspace.workspaceFolders?.length) {
const rootUri = vscode.Uri.file(configProvider.getWorkingDirectory());
const routesUri = vscode.Uri.joinPath(rootUri, 'routes');
const routesPath = routesUri.fsPath;
const hasRoutesFolder = fs.existsSync(routesPath) && fs.statSync(routesPath).isDirectory();
targetUri = hasRoutesFolder
? vscode.Uri.joinPath(routesUri, fileName)
: vscode.Uri.joinPath(rootUri, fileName);
} else {
const picked = await vscode.window.showSaveDialog({
defaultUri: vscode.Uri.joinPath(context.globalStorageUri, fileName),
saveLabel: 'Create file',
});
if (!picked) {
return;
}
targetUri = picked;
}

vscode.window.showInformationMessage(`Writing file to: ${targetUri.fsPath}`);

await vscode.workspace.fs.writeFile(targetUri, Buffer.from(content, 'utf-8'));
await vscode.window.showInformationMessage(`Saved to: ${targetUri.fsPath}`, 'Open');
const doc = await vscode.workspace.openTextDocument(targetUri);
await vscode.window.showTextDocument(doc, {
viewColumn: panel.viewColumn ?? vscode.ViewColumn.One,
preview: false,
preserveFocus: false,
});
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
vscode.window.showErrorMessage(`Failed to save: ${message}`);
}
}
});
});

const promptAgentDisposable = vscode.commands.registerCommand('b2c-dx.promptAgent', async () => {
const prompt = await vscode.window.showInputBox({
title: 'Prompt Agent',
Expand Down Expand Up @@ -445,7 +308,6 @@ async function activateInner(context: vscode.ExtensionContext, log: vscode.Outpu
});

context.subscriptions.push(
disposable,
promptAgentDisposable,
listWebDavDisposable,
instanceStatusBar,
Expand Down
1 change: 0 additions & 1 deletion packages/b2c-vs-extension/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export type FeatureCategory =
| 'debugger'
| 'scaffold'
| 'cap'
| 'pageDesigner'
| 'logs'
| 'instance';

Expand Down
66 changes: 0 additions & 66 deletions packages/b2c-vs-extension/src/template/_app.pageId.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ suite('extension activation', () => {
});

// This is the workhorse check. The extension's top-level try/catch
// (extension.ts:117-136) registers only three stub commands on failure
// (openUI, promptAgent, listWebDav), so any swallowed activation error
// (extension.ts:117-136) registers only two stub commands on failure
// (promptAgent, listWebDav), so any swallowed activation error
// surfaces here as a flood of missing commands.
test('every contributed command is registered', async () => {
const registered = new Set(await vscode.commands.getCommands(true));
Expand Down
Loading
Loading