From c27170c81abd0259b98dbeb7497e2134146ad039 Mon Sep 17 00:00:00 2001 From: Chris Millar Date: Wed, 18 Sep 2024 15:00:08 -0600 Subject: [PATCH] GH-244 - Extensible source support * Provides ability to let project spec an `editUrlFormat` object * Supports `{{contentSourceUrl}} {{org}} {{site}} {{pathname}}` placeholders in pattern --- src/extension/app/store/app.js | 27 +++++++++++++++++++++++++-- src/extension/app/store/site.js | 5 +++++ src/extension/types/typedefs.js | 2 ++ test/app/store/app.test.js | 20 ++++++++++++++++++++ test/app/store/site.test.js | 13 +++++++++++++ 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/extension/app/store/app.js b/src/extension/app/store/app.js index e210f147..9ec97f4a 100644 --- a/src/extension/app/store/app.js +++ b/src/extension/app/store/app.js @@ -598,12 +598,14 @@ export class AppStore { * @returns {string} The content source label */ getContentSourceLabel() { - const { contentSourceType } = this.siteStore; + const { contentSourceType, contentSourceEditLabel } = this.siteStore; if (contentSourceType === 'onedrive') { return 'SharePoint'; } else if (contentSourceType === 'google') { return 'Google Drive'; + } else if (contentSourceEditLabel) { + return contentSourceEditLabel; } else { return 'BYOM'; } @@ -1088,6 +1090,27 @@ export class AppStore { } } + getBYOMSourceUrl() { + const { + owner, + repo, + contentSourceUrl, + contentSourceEditPattern, + } = this.siteStore; + if (!contentSourceEditPattern || typeof contentSourceEditPattern !== 'string') return undefined; + + let { pathname } = this.location; + if (pathname.endsWith('/')) pathname += 'index'; + + const url = contentSourceEditPattern + .replace('{{contentSourceUrl}}', contentSourceUrl) + .replace('{{org}}', owner) + .replace('{{site}}', repo) + .replace('{{pathname}}', pathname); + + return url; + } + /** * Switches to (or opens) a given environment. * @param {string} targetEnv One of the following environments: @@ -1128,7 +1151,7 @@ export class AppStore { if (targetEnv === 'edit') { const updatedStatus = await this.fetchStatus(false, true); - envUrl = updatedStatus.edit && updatedStatus.edit.url; + envUrl = updatedStatus.edit?.url || this.getBYOMSourceUrl(); } const [customView] = this.findViews(VIEWS.CUSTOM); diff --git a/src/extension/app/store/site.js b/src/extension/app/store/site.js index 506a1042..4a57acfb 100644 --- a/src/extension/app/store/site.js +++ b/src/extension/app/store/site.js @@ -239,6 +239,8 @@ export class SiteStore { lang, contentSourceUrl, contentSourceType, + editUrlLabel, + editUrlPattern, previewHost, liveHost, outerHost: legacyLiveHost, @@ -273,6 +275,9 @@ export class SiteStore { this.giturl = giturl; this.contentSourceUrl = contentSourceUrl; this.contentSourceType = contentSourceType; + this.contentSourceEditLabel = editUrlLabel; + this.contentSourceEditPattern = editUrlPattern; + this.mountpoints = contentSourceUrl ? [contentSourceUrl] : (mountpoints || []); [this.mountpoint] = this.mountpoints; this.adminVersion = adminVersion; diff --git a/src/extension/types/typedefs.js b/src/extension/types/typedefs.js index c60033b5..3d9839f0 100644 --- a/src/extension/types/typedefs.js +++ b/src/extension/types/typedefs.js @@ -44,6 +44,8 @@ * @prop {string} [liveHost] The host name of a custom live CDN * @prop {string} [host] The production host name to publish content to * @prop {string} [devOrigin] The origin of the local development environment + * @prop {string} [editUrlLabel] The custom label of the edit content source + * @prop {string} [editUrlPattern] The pattern of the edit content source * @prop {string} [adminVersion] The specific version of admin service to use * @prop {boolean} [disabled] Is the project disabled? * @description Represents the sidekick configuration from the user via the options view diff --git a/test/app/store/app.test.js b/test/app/store/app.test.js index 0e5ba349..6ec775a6 100644 --- a/test/app/store/app.test.js +++ b/test/app/store/app.test.js @@ -516,6 +516,20 @@ describe('Test App Store', () => { expect(fetchStatusSpy.calledWith(false, true)).to.be.true; }); + it('switches from preview to BYOM editor', async () => { + instance.siteStore.contentSourceUrl = 'https://aemcloud.com'; + instance.siteStore.contentSourceEditLabel = 'Universal Editor'; + instance.siteStore.contentSourceEditPattern = '{{contentSourceUrl}}{{pathname}}?cmd=open'; + + const fetchStatusStub = sidekickTest.sandbox.stub(instance, 'fetchStatus'); + fetchStatusStub.resolves({}); + + instance.location = new URL(mockStatus.preview.url); + instance.status = mockStatus; + await instance.switchEnv('edit'); + expect(loadPage.calledWith('https://aemcloud.com/index?cmd=open')).to.be.true; + }); + it('switches from live to preview', async () => { instance.location = new URL(mockStatus.live.url); instance.status = mockStatus; @@ -1533,6 +1547,12 @@ describe('Test App Store', () => { expect(instance.getContentSourceLabel()).to.equal('Google Drive'); }); + it('should return "Document Authoring" if a label is provided', () => { + instance.siteStore.contentSourceType = 'markup'; + instance.siteStore.contentSourceEditLabel = 'Document Authoring'; + expect(instance.getContentSourceLabel()).to.equal('Document Authoring'); + }); + it('should return "BYOM" for everything else', () => { instance.siteStore.contentSourceType = 'markup'; expect(instance.getContentSourceLabel()).to.equal('BYOM'); diff --git a/test/app/store/site.test.js b/test/app/store/site.test.js index 19d920d2..91dfee16 100644 --- a/test/app/store/site.test.js +++ b/test/app/store/site.test.js @@ -192,5 +192,18 @@ describe('Test Site Store', () => { expect(appStore.siteStore.owner).to.equal('adobe'); expect(appStore.siteStore.repo).to.equal('aem-boilerplate'); }); + + it('with custom sourceEditUrl', async () => { + /** + * @type {SidekickOptionsConfig | ClientConfig} + */ + const config = { + ...defaultConfig, + editUrlLabel: 'Universal Editor', + editUrlPattern: '{{contentSourceUrl}}{{pathname}}?cmd=open', + }; + await appStore.loadContext(sidekickElement, config); + expect(appStore.siteStore.contentSourceEditLabel).to.equal('Universal Editor'); + }); }); });