From 8a6183e54083cc0960fe123dce851160ca3f1f2f Mon Sep 17 00:00:00 2001 From: Nico De Cleyre <35696168+nicodecleyre@users.noreply.github.com> Date: Thu, 2 Jan 2025 00:45:42 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Adds=20'Set=20Form=20Customizer'?= =?UTF-8?q?=20command=20to=20the=20SharePoint=20Framework=20Toolkit,=20Clo?= =?UTF-8?q?ses=20#348=20(#383)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 🎯 Aim Adds 'Set Form Customizer' command to the SharePoint Framework Toolkit, to set the view, edit or new form with a form customizer ## 📷 Result https://github.com/user-attachments/assets/1ac118ed-ad4b-44bb-946f-94c228aa0d81 ## ✅ What was done - [X] Add action to set the view, edit & new form with a form customizer ## 🔗 Related issue Closes #348 --- package.json | 5 ++ src/constants/Commands.ts | 5 +- src/panels/CommandPanel.ts | 1 + src/services/actions/CliActions.ts | 110 +++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index e5f5aa6..f0fc5c9 100644 --- a/package.json +++ b/package.json @@ -466,6 +466,11 @@ "category": "SharePoint Framework Toolkit", "icon": "$(sync)" }, + { + "command": "spfx-toolkit.setFormCustomizer", + "title": "Set Form Customizer", + "category": "SharePoint Framework Toolkit" + }, { "command": "spfx-toolkit.showMoreActions", "title": "...", diff --git a/src/constants/Commands.ts b/src/constants/Commands.ts index f26f472..9b5869d 100644 --- a/src/constants/Commands.ts +++ b/src/constants/Commands.ts @@ -60,5 +60,8 @@ export const Commands = { enableAppCatalogApp: `${EXTENSION_NAME}.enableAppCatalogApp`, disableAppCatalogApp: `${EXTENSION_NAME}.disableAppCatalogApp`, upgradeAppCatalogApp: `${EXTENSION_NAME}.upgradeAppCatalogApp`, - showMoreActions: `${EXTENSION_NAME}.showMoreActions` + showMoreActions: `${EXTENSION_NAME}.showMoreActions`, + + // Set form customizer + setFormCustomizer: `${EXTENSION_NAME}.setFormCustomizer` }; \ No newline at end of file diff --git a/src/panels/CommandPanel.ts b/src/panels/CommandPanel.ts index a874882..b2635c6 100644 --- a/src/panels/CommandPanel.ts +++ b/src/panels/CommandPanel.ts @@ -310,6 +310,7 @@ export class CommandPanel { actionCommands.push(new ActionTreeItem('Add new component', '', { name: 'add', custom: false }, undefined, Commands.addToProject)); actionCommands.push(new ActionTreeItem('Scaffold CI/CD Workflow', '', { name: 'rocket', custom: false }, undefined, Commands.pipeline)); + actionCommands.push(new ActionTreeItem('Set Form Customizer', '', { name: 'checklist', custom: false }, undefined, Commands.setFormCustomizer)); actionCommands.push(new ActionTreeItem('View samples', '', { name: 'library', custom: false }, undefined, Commands.samplesGallery)); window.registerTreeDataProvider('pnp-view-actions', new ActionTreeDataProvider(actionCommands)); diff --git a/src/services/actions/CliActions.ts b/src/services/actions/CliActions.ts index 9d7c997..6922d9e 100644 --- a/src/services/actions/CliActions.ts +++ b/src/services/actions/CliActions.ts @@ -69,6 +69,9 @@ export class CliActions { subscriptions.push( commands.registerCommand(Commands.upgradeAppCatalogApp, CliActions.upgradeAppCatalogApp) ); + subscriptions.push( + commands.registerCommand(Commands.setFormCustomizer, CliActions.setFormCustomizer) + ); } /** @@ -920,4 +923,111 @@ export class CliActions { Notifications.error(`${fileName}.tour file not found in path ${path.join(wsFolder.uri.fsPath, '.tours')}. Cannot start Code Tour.`); } } + + /** + * Sets the form customizer for a content type on a list. + */ + public static async setFormCustomizer() { + const relativeUrl = await window.showInputBox({ + prompt: 'Enter the relative URL of the site', + ignoreFocusOut: true, + placeHolder: 'e.g., sites/sales', + validateInput: (input) => { + if (!input) { + return 'site URL is required'; + } + + const trimmedInput = input.trim(); + + if (trimmedInput.startsWith('https://')) { + return 'Please provide a relative URL, not an absolute URL.'; + } + if (trimmedInput.startsWith('/')) { + return 'Please provide a relative URL without a leading slash.'; + } + + return undefined; + } + }); + + if (relativeUrl === undefined) { + Notifications.warning('No site URL provided. Setting form customizer aborted.'); + return; + } + + const siteUrl = `${EnvironmentInformation.tenantUrl}/${relativeUrl.trim()}`; + + const listTitle = await window.showInputBox({ + prompt: 'Enter the list title', + ignoreFocusOut: true, + validateInput: (value) => value ? undefined : 'List title is required' + }); + + if (!listTitle) { + Notifications.warning('No list title provided. Setting form customizer aborted.'); + return; + } + + const contentType = await window.showInputBox({ + prompt: 'Enter the Content Type name', + ignoreFocusOut: true, + validateInput: (value) => value ? undefined : 'Content Type name is required' + }); + + if (!contentType) { + Notifications.warning('No content type name provided. Setting form customizer aborted.'); + return; + } + + const editFormClientSideComponentId = await window.showInputBox({ + prompt: 'Enter the Edit form customizer ID (leave empty to skip)', + ignoreFocusOut: true + }); + + const newFormClientSideComponentId = await window.showInputBox({ + prompt: 'Enter the New form customizer ID (leave empty to skip)', + ignoreFocusOut: true + }); + + const displayFormClientSideComponentId = await window.showInputBox({ + prompt: 'Enter the View form customizer ID (leave empty to skip)', + ignoreFocusOut: true + }); + + const commandOptions: any = { + webUrl: siteUrl, + listTitle: listTitle, + name: contentType + }; + + if (editFormClientSideComponentId) { + commandOptions.EditFormClientSideComponentId = editFormClientSideComponentId; + } + + if (newFormClientSideComponentId ) { + commandOptions.NewFormClientSideComponentId = newFormClientSideComponentId ; + } + + if (displayFormClientSideComponentId) { + commandOptions.DisplayFormClientSideComponentId = displayFormClientSideComponentId; + } + + await window.withProgress({ + location: ProgressLocation.Notification, + title: 'Setting form customizer...', + cancellable: true + }, async (progress: Progress<{ message?: string; increment?: number }>) => { + try { + const result = await CliExecuter.execute('spo contenttype set', 'json', commandOptions); + if (result.stderr) { + Notifications.error(result.stderr); + } else { + Notifications.info('Form customizer set successfully.'); + } + } catch (e: any) { + const message = e?.error?.message; + Notifications.error(message); + } + }); + } } \ No newline at end of file