"
+ );
+ }
+ } catch (error) {
+ console.error('Unable to add a context listener', error);
+ }
+}
+
+async function addAppChannel() {
+ try {
+ let appChannelName = document.getElementById('app-channel').value;
+
+ if (!appChannelName) throw new Error('no channel name set');
+
+ let appChannelExists = appChannels.find(appChannel => appChannel.id === appChannelName);
+
+ if (!appChannelExists) {
+ let newAppChannel = await fdc3.getOrCreateChannel(appChannelName);
+ appChannels.push(newAppChannel);
+
+ // add to the list of available app channels
+ let node = document.createElement('li');
+ let textNode = document.createTextNode(appChannelName);
+ node.appendChild(textNode);
+ document.getElementById('app-channel-list').appendChild(node);
+
+ //populate the channel list dropdown with new appChannel
+ populateChannelsDropDown(newAppChannel.id);
+ } else {
+ throw new Error('app channel already exists');
+ }
+ } catch (error) {
+ console.error('could not add an app channel', error);
+ }
+}
+
+async function raiseIntent() {
+ try {
+ // get the channel
+ let intent = document.getElementById('intent').value;
+ let context = JSON.parse(document.getElementById('intent-context').value);
+
+ // TODO: add the target param
+ await fdc3.raiseIntent(intent, context);
+ } catch (err) {
+ console.error('intent did not resolve', err);
+ }
+}
diff --git a/toolbox/fdc3-explained/1.2/styles.css b/toolbox/fdc3-explained/1.2/styles.css
new file mode 100644
index 000000000..8cab74c03
--- /dev/null
+++ b/toolbox/fdc3-explained/1.2/styles.css
@@ -0,0 +1,116 @@
+@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap");
+
+.body {
+ font-family: "Noto Sans JP", sans-serif;
+ margin: 0;
+ padding: 0;
+ background-color: #284b63;
+ color: white;
+}
+
+.main {
+ margin: 10px 0;
+ padding: 0;
+ display: flex;
+ flex-wrap: wrap;
+ place-content: center;
+ flex-direction: column;
+}
+#logo {
+ height: 200px;
+ margin-left: 20px;
+}
+button {
+ min-width: 45px;
+ height: 22px;
+ background: rgb(210 236 255);
+ border: 2px solid rgb(0 0 0 / 0%);
+ border-radius: 5px;
+ box-shadow: #03a9f433 2px 3px 0px 0px;
+ cursor: pointer;
+}
+button:active {
+ outline: transparent;
+ box-shadow: inset #3c3c3c70 2px 3px 3px 0px, #03a9f433 1px 2px 0px 0px;
+ transform: translateY(2px);
+ transition: ease-out 0.1s;
+}
+button:focus {
+ outline: transparent;
+}
+input {
+ background: #e8f7ff;
+ box-shadow: inset -2px -2px 2px 0px rgb(255 255 255 / 12%),
+ inset 2px 3px 6px 2px rgb(0 0 0 / 19%);
+ border-radius: 6px;
+ border: 2px solid transparent;
+}
+input:focus {
+ transition-property: border;
+ transition-duration: 0.8s;
+ border: 2px solid #368cc7;
+ outline: 0;
+}
+textarea {
+ background: #e8f7ff;
+ box-shadow: inset -3px -5px 5px 1px rgb(255 255 255 / 12%),
+ inset 2px 3px 6px 2px rgb(0 0 0 / 19%);
+ border-radius: 6px;
+ border: 2px solid transparent;
+}
+textarea:focus {
+ transition-property: border;
+ transition-duration: 0.8s;
+ border: 2px solid #368cc7;
+ outline: 0;
+}
+table {
+ border: 0;
+ margin: 0 auto;
+ max-width: 1000px;
+ display: flex;
+}
+tr {
+ border: 0;
+}
+td {
+ border: 0;
+}
+textarea {
+ width: 400px;
+ height: 150px;
+}
+
+select {
+ width: 238px;
+ height: 24px;
+ width: 238px;
+ height: 24px;
+ border-radius: 6px;
+ background: #e8f7ff;
+ border: 2px solid rgb(0 0 0 / 0%);
+ box-shadow: #03a9f433 2px 3px 0px 0px;
+}
+
+.ctxInput {
+ width: 241px;
+ height: 24px;
+}
+
+.urlInput {
+ width: 400px;
+ height: 24px;
+}
+
+.header {
+ width: 200px;
+ height: 40px;
+ font-weight: 700;
+}
+
+#context-result {
+ border: 1px solid white;
+ padding: 17px;
+ color: #9fffa2;
+ font-family: monospace;
+}
diff --git a/toolbox/fdc3-explained/README.md b/toolbox/fdc3-explained/README.md
new file mode 100644
index 000000000..b23c2df39
--- /dev/null
+++ b/toolbox/fdc3-explained/README.md
@@ -0,0 +1,21 @@
+#
+
+FDC3 Explained was originally created by Johan Sandersson, an original maintainer of FDC3, and contributed to the project. It shows how easy it is to create very simple HTML and JavaScript that can use the FDC3 APIs to facilitate interoperability.
+
+It is also a useful tool for detecing whether FDC3 is enabled, by running the website inside an FDC3-supporting desktop agent, and for performing basic FDC3 operations to help test interoperability workflows.
+
+## Website
+
+FDC3 Explained can be accessed at the following URL: https://fdc3.finos.org/toolbox/fdc3-explained.
+
+Note that it will only detect and allow use of FDC3 when running in the context of an FDC3 desktop agent.
+
+## Build
+
+The NPM script `copy-explained` in the `website` folder copies the relevant files to the FDC3 website build for deployment.
+
+It is automatically executed during deployments to https://fdc3.finos.org.
+
+## Note
+
+FDC3 Explained does not aim to be an exhaustive reference implementation for each version of the FDC3 Standard, it is merely a convenient testing utility.
diff --git a/toolbox/fdc3-explained/index.html b/toolbox/fdc3-explained/index.html
new file mode 100644
index 000000000..d8c7ebdae
--- /dev/null
+++ b/toolbox/fdc3-explained/index.html
@@ -0,0 +1,82 @@
+
+
+
+ FDC3 Explained
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FDC3 Explained is a community project and reference implementation
+ of various FDC3 functionality. The key goal is to provide a tool for
+ application and container developers to verify their implementations
+ and act as basic but fully functional participant when testing and
+ demonstrating desktop interoperability.
+
+
+
+
+ 1.0
+
+
+ 1.1
+
+
+ 1.2
+
+
+
+
+
+
diff --git a/toolbox/fdc3-explained/logo.svg b/toolbox/fdc3-explained/logo.svg
new file mode 100644
index 000000000..0cf0d70af
--- /dev/null
+++ b/toolbox/fdc3-explained/logo.svg
@@ -0,0 +1,17 @@
+
diff --git a/website/package.json b/website/package.json
index 70764f564..00a9bd6f1 100644
--- a/website/package.json
+++ b/website/package.json
@@ -2,7 +2,7 @@
"scripts": {
"examples": "docusaurus-examples",
"start": "docusaurus-start",
- "prebuild": "yarn run copy-appd && yarn run copy-schemas && yarn run copy-workbench",
+ "prebuild": "yarn run copy-appd && yarn run copy-schemas && yarn run copy-workbench && yarn run copy-explained",
"build": "docusaurus-build",
"prepublish-gh-pages": "yarn run copy-appd && yarn run copy-schemas && yarn run copy-workbench",
"publish-gh-pages": "docusaurus-publish",
@@ -10,6 +10,7 @@
"copy-appd": "cpy ../src/app-directory/specification/appd.yaml static/schemas/next --rename app-directory.yaml",
"build-workbench": "cd ../toolbox/fdc3-workbench && yarn install && yarn build",
"copy-workbench": "yarn del static/toolbox/fdc3-workbench && yarn build-workbench && cd ../toolbox/fdc3-workbench/build && cpy ** ../../../website/static/toolbox/fdc3-workbench --parents",
+ "copy-explained": "yarn del static/toolbox/fdc3-explained && cpy ./fdc3-explained ../website/static/toolbox --parents --cwd=../toolbox",
"version": "yarn run version:docs && yarn run version:schemas && yarn run version:appd",
"version:docs": "docusaurus-version ${VERSION}",
"version:schemas": "cpy static/schemas/next/*.schema.json static/schemas/${VERSION} && replace-in-files --string=/schemas/next --replacement=/schemas/${VERSION} static/schemas/${VERSION}/*.schema.json",