From f7b3ef0c46e03734e8917679ddc3cfc1d9cc6803 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A1n=20Mach?= <92859870+JMach1@users.noreply.github.com>
Date: Mon, 22 Aug 2022 20:19:50 +0200
Subject: [PATCH] custom widgets df testing fixes (#1917)
* displayName required
* overrides handling - no longer valid override cleanup
* customWidgetList refresh configs in constructor
* listenForSecretsRequests managementApiUrl + ensureUrlArmified
---
.../custom-widget-list/createWidget.html | 2 +-
.../custom-widget-list/createWidget.ts | 2 +
.../custom-widget-list/customWidgetList.ts | 13 +++--
.../loadCustomWidgetConfigs.ts | 50 +++++++++++--------
.../customWidget.design.module.ts | 2 +-
.../customWidget.runtime.module.ts | 2 +-
...equests.ts => listenForSecretsRequests.ts} | 8 ++-
7 files changed, 51 insertions(+), 28 deletions(-)
rename src/components/custom-widget/{ListenForSecretsRequests.ts => listenForSecretsRequests.ts} (86%)
diff --git a/src/components/custom-widget-list/createWidget.html b/src/components/custom-widget-list/createWidget.html
index a585c0375..dfb274a62 100644
--- a/src/components/custom-widget-list/createWidget.html
+++ b/src/components/custom-widget-list/createWidget.html
@@ -9,7 +9,7 @@
data-bind="textInput: displayName, validationElement: displayName, attr: {disabled: !!$component.config}"
maxlength="2000" spellcheck="false" aria-required="true"
/>
-
+
diff --git a/src/components/custom-widget-list/createWidget.ts b/src/components/custom-widget-list/createWidget.ts
index 030828e1e..240df24ca 100644
--- a/src/components/custom-widget-list/createWidget.ts
+++ b/src/components/custom-widget-list/createWidget.ts
@@ -52,6 +52,8 @@ export class CreateWidget {
errorElementClass: "is-invalid",
decorateInputElement: true
});
+
+ this.displayName.extend({ required: { message: `Name is required.` } });
}
@Param()
diff --git a/src/components/custom-widget-list/customWidgetList.ts b/src/components/custom-widget-list/customWidgetList.ts
index 523f9d589..a6fad9673 100644
--- a/src/components/custom-widget-list/customWidgetList.ts
+++ b/src/components/custom-widget-list/customWidgetList.ts
@@ -5,6 +5,7 @@ import { Component } from "@paperbits/common/ko/decorators";
import { MapiBlobStorage } from "../../persistence";
import { TCustomWidgetConfig } from "../custom-widget";
import template from "./customWidgetList.html";
+import { listConfigBlobs } from "./loadCustomWidgetConfigs";
@Component({
@@ -21,9 +22,15 @@ export class ContentWorkshop {
customWidgetConfigsPromise: Promise,
) {
this.customWidgetConfigs = ko.observable();
- customWidgetConfigsPromise.then(configs =>
- this.customWidgetConfigs(configs.sort(ContentWorkshop.sortByName))
- );
+ const refreshConfigs = listConfigBlobs(blobStorage); // in case some configs on the blob storage got deleted/updated/added
+ Promise.all([refreshConfigs, customWidgetConfigsPromise]).then(([configBlobs, configsAll]) => {
+ const configs: Record = {};
+ configBlobs.forEach(config => configs[config.name] = config);
+ configsAll.forEach(config => {
+ if (config.override) configs[config.name] = config
+ });
+ this.customWidgetConfigs(Object.values(configs).sort(ContentWorkshop.sortByName))
+ });
}
private static sortByName(a: TCustomWidgetConfig, b: TCustomWidgetConfig): number {
diff --git a/src/components/custom-widget-list/loadCustomWidgetConfigs.ts b/src/components/custom-widget-list/loadCustomWidgetConfigs.ts
index 67c0e5418..88a0412da 100644
--- a/src/components/custom-widget-list/loadCustomWidgetConfigs.ts
+++ b/src/components/custom-widget-list/loadCustomWidgetConfigs.ts
@@ -5,13 +5,34 @@ import * as Constants from "../../constants";
import { MapiBlobStorage } from "../../persistence";
import { TCustomWidgetConfig } from "../custom-widget";
+export async function listConfigBlobs(blobStorage: MapiBlobStorage): Promise {
+ const configsNames = await blobStorage.listBlobs(`${BLOB_ROOT}/${BLOB_CONFIGS_FOLDER}/`);
+ const configsUint8s = await Promise.all(configsNames.map(blobName => blobStorage.downloadBlob(blobName)));
+ return configsUint8s.map(uint8 => JSON.parse(new TextDecoder().decode(uint8)));
+}
+
+function showToast(viewManager: ViewManager, widgetSource: TCustomWidgetConfig): void {
+ const sessionStorageKey = Constants.overrideToastSessionKeyPrefix + widgetSource.name
+ if (window.sessionStorage.getItem(sessionStorageKey)) return
+
+ let message = `Custom widget "${widgetSource.displayName}" URL is overridden`;
+ if (typeof widgetSource.override === "string") message += ` with ${widgetSource.override}`;
+ const toast = viewManager.addToast(widgetSource.displayName, message, [{
+ title: "Got it",
+ action: async () => {
+ window.sessionStorage.setItem(sessionStorageKey, "true");
+ viewManager.removeToast(toast);
+ }
+ }]);
+}
+
export async function loadCustomWidgetConfigs(
blobStorage: MapiBlobStorage,
viewManager: ViewManager,
): Promise {
- const sourcesSession = Object.keys(window.sessionStorage)
+ const sourcesSessionKeys = Object.keys(window.sessionStorage)
.filter((key: string) => key.startsWith(Constants.overrideConfigSessionKeyPrefix))
- .map(key => window.sessionStorage.getItem(key));
+ const sourcesSession = sourcesSessionKeys.map(key => window.sessionStorage.getItem(key));
const sourcesSearchParams = new URLSearchParams(window.location.search)
.getAll(OVERRIDE_PORT_KEY)
.map(port => new URL("http://localhost:" + (isNaN(parseInt(port)) ? OVERRIDE_DEFAULT_PORT : port)).href);
@@ -28,33 +49,22 @@ export async function loadCustomWidgetConfigs(
}
});
- const configsNames = await blobStorage.listBlobs(`${BLOB_ROOT}/${BLOB_CONFIGS_FOLDER}/`);
- const configsUint8s = await Promise.all(configsNames.map(blobName => blobStorage.downloadBlob(blobName)));
- const configs: TCustomWidgetConfig[] = configsUint8s.map(uint8 => JSON.parse(new TextDecoder().decode(uint8)));
-
const configurations: Record = {};
+ (await listConfigBlobs(blobStorage)).forEach(config => configurations[config.name] = config);
- configs.forEach(config => configurations[config.name] = config);
(await Promise.all(overridesPromises)).forEach(({override, source}) => {
- if (!override) return;
+ if (!override) {
+ const key = sourcesSessionKeys.find(key => window.sessionStorage.getItem(key) === source);
+ if (key) sessionStorage.removeItem(key);
+ return;
+ }
const href = new URL(source).href;
window.sessionStorage.setItem(Constants.overrideConfigSessionKeyPrefix + override.name, href);
const widgetSource = {...override, override: href ?? true};
configurations[override.name] = widgetSource
- const sessionStorageKey = Constants.overrideToastSessionKeyPrefix + override.name
- if (window.sessionStorage.getItem(sessionStorageKey)) return
-
- let message = `Custom widget "${override.displayName}" URL is overridden`;
- if (typeof widgetSource.override === "string") message += ` with ${widgetSource.override}`;
- const toast = viewManager.addToast(override.displayName, message, [{
- title: "Got it",
- action: async () => {
- window.sessionStorage.setItem(sessionStorageKey, "true");
- viewManager.removeToast(toast);
- }
- }]);
+ showToast(viewManager, widgetSource);
});
return Object.values(configurations);
diff --git a/src/components/custom-widget/customWidget.design.module.ts b/src/components/custom-widget/customWidget.design.module.ts
index bffb4d18e..457f7f418 100644
--- a/src/components/custom-widget/customWidget.design.module.ts
+++ b/src/components/custom-widget/customWidget.design.module.ts
@@ -1,7 +1,7 @@
import { IInjectorModule, IInjector } from "@paperbits/common/injection";
import { CustomWidgetEditorViewModel, CustomWidgetViewModel, CustomWidgetViewModelBinder } from "./ko";
import { CustomWidgetModelBinder } from ".";
-import { ListenForSecretsRequests } from "./ListenForSecretsRequests";
+import { ListenForSecretsRequests } from "./listenForSecretsRequests";
export class CustomWidgetDesignModule implements IInjectorModule {
public register(injector: IInjector): void {
diff --git a/src/components/custom-widget/customWidget.runtime.module.ts b/src/components/custom-widget/customWidget.runtime.module.ts
index 2e5ca51d4..a8d30cc56 100644
--- a/src/components/custom-widget/customWidget.runtime.module.ts
+++ b/src/components/custom-widget/customWidget.runtime.module.ts
@@ -1,5 +1,5 @@
import { IInjectorModule, IInjector } from "@paperbits/common/injection";
-import { ListenForSecretsRequests } from "./ListenForSecretsRequests";
+import { ListenForSecretsRequests } from "./listenForSecretsRequests";
export class CustomWidgetRuntimeModule implements IInjectorModule {
public register(injector: IInjector): void {
diff --git a/src/components/custom-widget/ListenForSecretsRequests.ts b/src/components/custom-widget/listenForSecretsRequests.ts
similarity index 86%
rename from src/components/custom-widget/ListenForSecretsRequests.ts
rename to src/components/custom-widget/listenForSecretsRequests.ts
index 7733a3f7b..1da8becf0 100644
--- a/src/components/custom-widget/ListenForSecretsRequests.ts
+++ b/src/components/custom-widget/listenForSecretsRequests.ts
@@ -2,6 +2,7 @@ import { APIM_ASK_FOR_SECRETS_MESSAGE_KEY, Secrets } from "@azure/api-management
import { ISettingsProvider } from "@paperbits/common/configuration";
import { AccessToken, IAuthenticator } from "../../authentication";
import { managementApiVersion, SettingNames } from "../../constants";
+import { Utils } from "../../utils";
export class ListenForSecretsRequests {
constructor(
@@ -20,8 +21,11 @@ export class ListenForSecretsRequests {
: window.document.getElementById(instanceId)
) as HTMLIFrameElement;
- const managementApiUrl = await settingsProvider.getSetting(SettingNames.managementApiUrl)
- const secrets: Secrets = { managementApiUrl, apiVersion: managementApiVersion };
+ const managementApiUrl = await settingsProvider.getSetting(SettingNames.managementApiUrl);
+ const secrets: Secrets = {
+ managementApiUrl: Utils.ensureUrlArmified(managementApiUrl),
+ apiVersion: managementApiVersion
+ };
const token = await authenticator.getAccessTokenAsString();
if (token) {