Skip to content

Commit

Permalink
Updated settings approach to follow the resolver pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
johnman committed Jun 19, 2024
1 parent 9460fdd commit 8c8d7a3
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 85 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { connect, type BaseConnectionOptions } from "@openfin/core-web";
import { getSettings } from "../platform/settings";
import { getSettings } from "../platform/settings/settings";

/**
* Initializes the OpenFin Web Broker connection.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getSettings } from "../platform/settings";
import type { Settings } from "../shapes/setting-shapes";

window.addEventListener("DOMContentLoaded", async () => {
if (window.fdc3) {
Expand All @@ -14,14 +14,6 @@ window.addEventListener("DOMContentLoaded", async () => {
* Initialize the settings.
*/
async function init(): Promise<void> {
const settings = await getSettings();
if (settings === undefined) {
console.error(
"Unable to run the example as we have been unable to load the web manifest and it's settings from the currently running html page. Please ensure that the web manifest is being served and that it contains the custom_settings section."
);
return;
}

// platform settings
const title = document.querySelector<HTMLInputElement>("#title");
const subTitle = document.querySelector<HTMLInputElement>("#subTitle");
Expand Down Expand Up @@ -52,51 +44,76 @@ async function init(): Promise<void> {
sourceDisplayName === null ||
saveButton === null ||
resetButton === null ||
cancelButton === null
cancelButton === null ||
window.fin === undefined
) {
console.error("Unable to use settings as there are missing input fields/buttons.");
return;
}

title.value = settings?.platform?.ui?.title;
subTitle.value = settings?.platform?.ui?.subTitle;
logo.value = settings?.platform?.ui?.logo;
userId.value = settings?.platform.cloudInterop?.connectParams?.userId;
password.value = settings?.platform.cloudInterop?.connectParams?.password;
platformId.value = settings?.platform.cloudInterop?.connectParams?.platformId;
cloudUrl.value = settings?.platform.cloudInterop?.connectParams?.url;
sourceId.value = settings?.platform.cloudInterop?.connectParams.sourceId ?? "";
sourceDisplayName.value = settings?.platform.cloudInterop?.connectParams.sourceDisplayName ?? "";
const settingsResolverChannel = "settings-resolver";
console.log("Settings dialog initialized", settingsResolverChannel);

const settingsResolverService =
await window.fin.InterApplicationBus.Channel.create(settingsResolverChannel);

let appliedSettings: Settings | undefined;

const channel = "platform/settings/dialog";
const appChannel = await window.fdc3.getOrCreateChannel(channel);
console.log("Registering apply-settings handler...");
settingsResolverService.register("apply-settings", async (data) => {
const settings = (data as { customData: { settings: Settings } }).customData.settings;
title.value = settings?.platform?.ui?.title;
subTitle.value = settings?.platform?.ui?.subTitle;
logo.value = settings?.platform?.ui?.logo;
userId.value = settings?.platform.cloudInterop?.connectParams?.userId;
password.value = settings?.platform.cloudInterop?.connectParams?.password;
platformId.value = settings?.platform.cloudInterop?.connectParams?.platformId;
cloudUrl.value = settings?.platform.cloudInterop?.connectParams?.url;
sourceId.value = settings?.platform.cloudInterop?.connectParams.sourceId ?? "";
sourceDisplayName.value = settings?.platform.cloudInterop?.connectParams.sourceDisplayName ?? "";
appliedSettings = settings;
});

saveButton.addEventListener("click", async () => {
settings.platform.ui.title = title.value;
settings.platform.ui.subTitle = subTitle.value;
settings.platform.ui.logo = logo.value;
settings.platform.cloudInterop.connectParams.userId = userId.value;
settings.platform.cloudInterop.connectParams.password = password.value;
settings.platform.cloudInterop.connectParams.platformId = platformId.value;
settings.platform.cloudInterop.connectParams.url = cloudUrl.value;
settings.platform.cloudInterop.connectParams.sourceId = sourceId.value;
settings.platform.cloudInterop.connectParams.sourceDisplayName = sourceDisplayName.value;
if (appliedSettings === undefined) {
console.error("Unable to save settings as they are not defined.");
return;
}
appliedSettings.platform.ui.title = title.value;
appliedSettings.platform.ui.subTitle = subTitle.value;
appliedSettings.platform.ui.logo = logo.value;
appliedSettings.platform.cloudInterop.connectParams.userId = userId.value;
appliedSettings.platform.cloudInterop.connectParams.password = password.value;
appliedSettings.platform.cloudInterop.connectParams.platformId = platformId.value;
appliedSettings.platform.cloudInterop.connectParams.url = cloudUrl.value;
appliedSettings.platform.cloudInterop.connectParams.sourceId = sourceId.value;
appliedSettings.platform.cloudInterop.connectParams.sourceDisplayName = sourceDisplayName.value;

// an example of using an app channel.
await appChannel.broadcast({
type: "platform.settings.dialog.action",
id: { action: "save-reload" },
settings
// eslint-disable-next-line @typescript-eslint/no-floating-promises
settingsResolverService.publish("settings-resolver-response", {
settingsResolverResponse: {
action: "save-reload",
settings: appliedSettings
}
});
});

resetButton.addEventListener("click", async () => {
// an example of using an app channel.
await appChannel.broadcast({ type: "platform.settings.dialog.action", id: { action: "reset-reload" } });
// eslint-disable-next-line @typescript-eslint/no-floating-promises
settingsResolverService.publish("settings-resolver-response", {
settingsResolverResponse: {
action: "reset-reload"
}
});
});

cancelButton.addEventListener("click", async () => {
// an example of using an app channel.
await appChannel.broadcast({ type: "platform.settings.dialog.action", id: { action: "close" } });
// eslint-disable-next-line @typescript-eslint/no-floating-promises
settingsResolverService.publish("settings-resolver-response", {
settingsResolverResponse: {
action: "close"
}
});
});
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { PlatformApp, PlatformAppIdentifier } from "../../shapes/app-shapes";
import type { PlatformLayoutSnapshot } from "../../shapes/layout-shapes";
import { isEmpty, randomUUID } from "../../utils";
import { getSettings } from "../settings";
import { getSettings } from "../settings/settings";

let cachedApps: PlatformApp[] | undefined;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { init as initBrokerConnection } from "@openfin/core-web/iframe-broker";
import { getSettings } from "./settings";
import { getSettings } from "./settings/settings";

/**
* Initializes the OpenFin Web Broker connection.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import type OpenFin from "@openfin/core";
import type { Logger } from "../../shapes/logger-shapes";
import type { SettingsResolverOptions, SettingsResolverResponse } from "../../shapes/setting-shapes";
import { clearSettings, getSettings, saveSettings } from "./settings";

/**
* An helper for updating and resolving settings.
*/
export class SettingsResolverHelper {
private readonly _logger: Logger;

private readonly _settingsResolverOptions?: SettingsResolverOptions;

private readonly _defaultSettingsResolverHeight: number;

private readonly _defaultSettingsResolverWidth: number;

private readonly _dialogElement: HTMLDialogElement | null = null;

private _dialogClient: OpenFin.ChannelClient | null = null;

/**
* Create an instance of the Settings Resolver Helper.
* @param settingsResolverOptions options for the helper
* @param logger the logger to use.
*/
constructor(settingsResolverOptions: SettingsResolverOptions, logger: Logger) {
this._defaultSettingsResolverHeight = 715;
this._defaultSettingsResolverWidth = 665;
this._settingsResolverOptions = {
height: this._defaultSettingsResolverHeight,
width: this._defaultSettingsResolverWidth,
...settingsResolverOptions
};
this._logger = logger;
this._dialogElement = document.createElement("dialog");
this._dialogElement.id = "settings-resolver-dialog";
this._dialogElement.style.height = `${this._settingsResolverOptions.height}px`;
this._dialogElement.style.width = `${this._settingsResolverOptions.width}px`;
this._dialogElement.style.padding = "0px";
this._dialogElement.style.backgroundColor = "var(--brand-background)";
// Create a new iframe element
const settingsResolver = document.createElement("iframe");

// Set the source of the iframe
settingsResolver.src = settingsResolverOptions.url;
settingsResolver.style.height = "99%";
settingsResolver.style.width = "100%";

// Append the iframe to the dialog
this._dialogElement.append(settingsResolver);

// Append the dialog to the body
document.body.append(this._dialogElement);
}

/**
* Launch the settings resolver.
* @returns nothing.
*/
public async showSettings(): Promise<void> {
if (this._dialogElement) {
this._dialogElement.showModal();
}
if (!this._dialogClient && this._dialogClient === null) {
const settingsResolverChannel = "settings-resolver";
console.log("Connecting to settings resolver", settingsResolverChannel);
this._dialogClient = await fin.InterApplicationBus.Channel.connect(settingsResolverChannel);

// eslint-disable-next-line @typescript-eslint/await-thenable
await this._dialogClient.register("settings-resolver-response", async (payload, sender) => {
const response = payload as {
settingsResolverResponse?: SettingsResolverResponse;
errorMessage?: string;
};
if (response.settingsResolverResponse) {
if (
response.settingsResolverResponse.action === "save-reload" &&
response.settingsResolverResponse.settings
) {
await saveSettings(response.settingsResolverResponse.settings);
location.reload();
} else if (response.settingsResolverResponse.action === "reset-reload") {
await clearSettings();
location.reload();
}
} else if (response.errorMessage) {
this._logger.error(response.errorMessage);
}
if (this._dialogElement) {
this._dialogElement.close();
}
});
}
if (this._dialogElement && this._dialogClient) {
const settings = await getSettings();
await this._dialogClient.dispatch("apply-settings", {
customData: {
settings
}
});
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { WebLayoutSnapshot } from "@openfin/core-web";
import type { ManifestSettings, Settings } from "../shapes/setting-shapes";
import type { ManifestSettings, Settings } from "../../shapes/setting-shapes";

/**
* Fetches the settings for the application.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import { connect } from "@openfin/core-web";
import { AppResolverHelper } from "./platform/apps/app-resolver-helper";
import { getConstructorOverride } from "./platform/broker/interop-override";
import { makeOverride } from "./platform/layout/layout-override";
import { clearSettings, getDefaultLayout, getSettings, saveSettings } from "./platform/settings";
import type { PlatformLayoutSnapshot } from "./shapes/layout-shapes";
import { getDefaultLayout, getSettings } from "./platform/settings/settings";
import { SettingsResolverHelper } from "./platform/settings/settings-resolver-helper";
import type { Settings } from "./shapes/setting-shapes";
import { sanitizeString } from "./utils";

/**
* Attach listeners to elements.
* @param fin passing the fin api for use.
*/
async function attachListeners(fin: OpenFin.Fin<OpenFin.EntityType>): Promise<void> {
async function attachListeners(): Promise<void> {
// Get the required settings
const settings = await getSettings();
if (settings !== undefined) {
Expand Down Expand Up @@ -44,45 +43,12 @@ async function attachListeners(fin: OpenFin.Fin<OpenFin.EntityType>): Promise<vo
});
}
if (settingsButton !== null) {
const dialogElement = document.createElement("dialog");
dialogElement.id = "settings-dialog";
dialogElement.style.height = `${settings?.platform?.ui?.settingsResolver?.height ?? 700}px`;
dialogElement.style.width = `${settings?.platform?.ui?.settingsResolver?.width ?? 600}px`;
dialogElement.style.padding = "0px";
dialogElement.style.backgroundColor = "var(--brand-background)";
// Create a new iframe element
const settingsUI = document.createElement("iframe");

// Set the source of the iframe
settingsUI.src = settings.platform.ui.settingsResolver.url;
settingsUI.style.height = "99%";
settingsUI.style.width = "100%";

// Append the iframe to the dialog
dialogElement.append(settingsUI);

// Append the dialog to the body
document.body.append(dialogElement);
const settingsResolverHelper = new SettingsResolverHelper(
settings.platform.ui.settingsResolver,
console
);
settingsButton.addEventListener("click", async () => {
dialogElement.showModal();
});
const platformDialogSettings = await fin.me.interop.joinSessionContextGroup("platform/settings/dialog");
await platformDialogSettings.addContextHandler(async (context) => {
if (context.type === "platform.settings.dialog.action" && context?.id?.action === "close") {
dialogElement.close();
}
if (context.type === "platform.settings.dialog.action" && context?.id?.action === "save-reload") {
const settingsToSave: Settings = (context as unknown as { settings: Settings }).settings;
// get the current layout
const currentLayout = fin.Platform.Layout.getCurrentLayoutManagerSync<PlatformLayoutSnapshot>();
settingsToSave.platform.layout.defaultLayout = await currentLayout?.getLayoutSnapshot();
await saveSettings(settingsToSave);
location.reload();
}
if (context.type === "platform.settings.dialog.action" && context?.id?.action === "reset-reload") {
await clearSettings();
location.reload();
}
await settingsResolverHelper.showSettings();
});
}
}
Expand Down Expand Up @@ -246,7 +212,7 @@ async function init(): Promise<void> {
containerId: settings.platform.layout.layoutContainerId
});
// setup listeners now that everything has been initialized
await attachListeners(fin);
await attachListeners();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ export interface SettingsResolverOptions {
width?: number;
}

/**
* The response from the settings resolver.
*/
export interface SettingsResolverResponse {
/**
* The action to take.
*/
action: "save-reload" | "reset-reload" | "close";

/**
* The the settings if it was to save.
*/
settings?: Settings;
}

/**
* Settings for the client
*/
Expand Down

0 comments on commit 8c8d7a3

Please sign in to comment.