diff --git a/toolbox/legacy.html b/toolbox/fdc3-explained/1.0/index.html similarity index 85% rename from toolbox/legacy.html rename to toolbox/fdc3-explained/1.0/index.html index 95dc7c494..27368eb89 100644 --- a/toolbox/legacy.html +++ b/toolbox/fdc3-explained/1.0/index.html @@ -5,12 +5,13 @@ FDC3 Explained v.2 - + @@ -34,6 +34,17 @@ FDC3 Not Available + + FDC3 Supported Version: + 1.1 + + + + + +
@@ -43,7 +54,7 @@ App Directory: Not supported yet! - + @@ -71,15 +82,15 @@ Add App Channel: - + Join Channel: Channel: - + - + @@ -94,7 +105,7 @@ - + @@ -126,12 +137,11 @@ - + - diff --git a/toolbox/fdc3-explained/main.js b/toolbox/fdc3-explained/1.1/main.js similarity index 63% rename from toolbox/fdc3-explained/main.js rename to toolbox/fdc3-explained/1.1/main.js index ce0f0c731..ec9cbeb0a 100644 --- a/toolbox/fdc3-explained/main.js +++ b/toolbox/fdc3-explained/1.1/main.js @@ -1,8 +1,22 @@ -// check for FDC3 support -function fdc3OnReady(cb) { - if (window.fdc3) { cb() } - else { window.addEventListener('fdc3Ready', cb) } +import setVersionList from '../versions.js'; + +function fdc3OnReady(callback) { + let fdc3Tries = 10; //lets not check forever... + const checkFDC3Ready = () => { + if (window.fdc3) { + callback.call(this); + } + else { + if (fdc3Tries > 0) { + fdc3Tries--; + window.setTimeout(checkFDC3Ready, 2000); + } + } + }; + checkFDC3Ready(); } + + // Wait for the document to load function documentLoaded(cb) { if (document.readyState === 'loading') { @@ -10,17 +24,21 @@ function documentLoaded(cb) { } else { cb() } } -// document and FDC3 have loaded start the main function -documentLoaded(() => fdc3OnReady(main)) - // use this to keep track of context listener - one per system channel let contextListener = null; -let appChannels = [] +let appChannels = []; + + + +// document and FDC3 have loaded start the main function +documentLoaded(() => fdc3OnReady(main)); + function main() { try { console.log("FDC3 is ready and DOM has rendered") populateHTML() + setUpEventListeners() getPlatform() displayFDC3Support() getContext() @@ -32,27 +50,55 @@ function main() { async function populateHTML() { try { - // populate all the dropdowns for system channels - let channelDropdownList = document.querySelectorAll(".fdc3-channels") - channelDropdownList.forEach(channelDropdown => populateChannels(channelDropdown)) //populate available channels list with system channels let channelList = document.getElementById("system-channel-list"); - const systemChannels = await fdc3.getSystemChannels(); - - systemChannels.forEach(({ displayMetadata, id, type }, key) => { + const populateChannelsList = (name) => { let node = document.createElement("li"); - let textNode = document.createTextNode(displayMetadata.name); + let textNode = document.createTextNode(name); node.appendChild(textNode); channelList.appendChild(node); + } + + const systemChannels = await fdc3.getSystemChannels(); + + // for all of the system channels populate dropdowns & lists + systemChannels.forEach(({ displayMetadata, id, type }) => { + let { name } = displayMetadata; + populateChannelsList(name) + populateChannelsDropDown(name) + }); - // add an event listener for the contextType input box - let contextTypeInput = document.getElementById("context-type"); + // set the versions of FDC3 Explained in the dropdown + setVersionList() + + // as FDC3 is supported we can enable the buttons again except those that are not yet supported features + document.querySelectorAll("button").forEach(button => { + if (!button.className.includes("not-supported")) { + button.disabled = false + } + }) + } catch (error) { + console.error("unable to populate the html for the page ", error); + } + +} + +function setUpEventListeners() { + document.getElementById("add-app-channel__btn").addEventListener("click", addAppChannel); + + document.getElementById("join-channel__btn").addEventListener("click", joinChannel); - // Only get context type when the user hits enter - contextTypeInput.addEventListener("keyup", function (event) { + document.getElementById("leave-channel__btn").addEventListener("click", fdc3.leaveCurrentChannel); + + document.getElementById("broadcast__btn").addEventListener("click", broadcastFDC3Context); + + document.getElementById("raise-intent__btn").addEventListener("click", raiseIntent); + + document.getElementById("context-type").addEventListener("keyup", (event) => { + // we only want to get the context wen the user hits enter if (event.key === "Enter") { event.preventDefault(); @@ -60,11 +106,8 @@ async function populateHTML() { getContext(contextType) } }); - } catch (error) { - console.error("unable to populate the html for the page ", error); - } -} + } function displayFDC3Support() { try { @@ -101,18 +144,21 @@ function getPlatform() { /** *Populate the channel dropdown elements - * @param {HTMLElement} dropdownElement is a dom selector */ -async function populateChannels(dropdownElement) { +function populateChannelsDropDown(newOptionText) { try { - if (!dropdownElement) return new Error("No dropdown element provided") + let dropdownElement = document.querySelector(".fdc3-channels") - const systemChannels = await fdc3.getSystemChannels(); - systemChannels.forEach(({ displayMetadata, id, type }, key) => { dropdownElement[key] = new Option(displayMetadata.name, key) }); + if (newOptionText) { + dropdownElement.add(new Option(newOptionText)) + } + else { + throw new Error("No option provided") + } } catch (error) { - console.error("could not find system channels when populating the dropdown", error); + console.error("could not add a new channel to the channel dropdown list", error); } } @@ -160,7 +206,12 @@ async function addAppChannel() { try { let appChannelName = document.getElementById("app-channel").value; - if (appChannelName) { + 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); @@ -170,8 +221,13 @@ async function addAppChannel() { 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("no channel name set") + throw new Error("app channel already exists") } } catch (error) { console.error("could not add an app channel", error); diff --git a/toolbox/fdc3-explained/styles.css b/toolbox/fdc3-explained/1.1/styles.css similarity index 100% rename from toolbox/fdc3-explained/styles.css rename to toolbox/fdc3-explained/1.1/styles.css diff --git a/toolbox/fdc3-explained/1.2/fdc3_explained_logo.svg b/toolbox/fdc3-explained/1.2/fdc3_explained_logo.svg new file mode 100644 index 000000000..0cf0d70af --- /dev/null +++ b/toolbox/fdc3-explained/1.2/fdc3_explained_logo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/toolbox/fdc3-explained/1.2/index.html b/toolbox/fdc3-explained/1.2/index.html new file mode 100644 index 000000000..41c147be6 --- /dev/null +++ b/toolbox/fdc3-explained/1.2/index.html @@ -0,0 +1,146 @@ + + + + + FDC3 Explained v.2 + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FDC3 Supported Checking
FDC3 Provider Service:FDC3 Not Available
FDC3 Supported Version:1.2 + + +
+
+
App Directory:Not supported yet!
Available Apps: + +
+
+
Available Channels: + System Channels: +
    + App Channels: +
      +
      Add App Channel:
      Join Channel:Channel: + +
      +
      +
      Broadcast Context:
      +
      Get Context:
      Context Type:
      +
      + Context result will appear here. +
      +
      +
      +
      Raise Intent:
      Intent:
      +
      + + + diff --git a/toolbox/fdc3-explained/1.2/main.js b/toolbox/fdc3-explained/1.2/main.js new file mode 100644 index 000000000..b78624074 --- /dev/null +++ b/toolbox/fdc3-explained/1.2/main.js @@ -0,0 +1,237 @@ +import setVersionList from '../versions.js'; + +// check for FDC3 support +function fdc3OnReady(cb) { + if (window.fdc3) { cb() } + else { window.addEventListener('fdc3Ready', cb) } +} +// Wait for the document to load +function documentLoaded(cb) { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', cb) + } else { cb() } +} + +// use this to keep track of context listener - one per system channel +let contextListener = null; +let appChannels = []; + + + +// document and FDC3 have loaded start the main function +documentLoaded(() => fdc3OnReady(main)); + + +function main() { + try { + console.log("FDC3 is ready and DOM has rendered") + populateHTML() + setUpEventListeners() + getPlatform() + displayFDC3Support() + getContext() + } catch (error) { + console.error(error) + } +} + + +async function populateHTML() { + try { + + //populate available channels list with system channels + let channelList = document.getElementById("system-channel-list"); + + const populateChannelsList = (name) => { + let node = document.createElement("li"); + let textNode = document.createTextNode(name); + node.appendChild(textNode); + channelList.appendChild(node); + } + + const systemChannels = await fdc3.getSystemChannels(); + + // for all of the system channels populate dropdowns & lists + systemChannels.forEach(({ displayMetadata, id, type }) => { + let { name } = displayMetadata; + populateChannelsList(name) + populateChannelsDropDown(name) + + }); + + // set the versions of FDC3 Explained in the dropdown + setVersionList() + + // as FDC3 is supported we can enable the buttons again except those that are not yet supported features + document.querySelectorAll("button").forEach(button => { + if (!button.className.includes("not-supported")) { + button.disabled = false + } + }) + } catch (error) { + console.error("unable to populate the html for the page ", error); + } + +} + +function setUpEventListeners() { + document.getElementById("add-app-channel__btn").addEventListener("click", addAppChannel); + + document.getElementById("join-channel__btn").addEventListener("click", joinChannel); + + document.getElementById("leave-channel__btn").addEventListener("click", fdc3.leaveCurrentChannel); + + document.getElementById("broadcast__btn").addEventListener("click", broadcastFDC3Context); + + document.getElementById("raise-intent__btn").addEventListener("click", raiseIntent); + + document.getElementById("context-type").addEventListener("keyup", (event) => { + // we only want to get the context wen the user hits enter + if (event.key === "Enter") { + event.preventDefault(); + + let contextType = event.target.value; + getContext(contextType) + } + }); + +} + +function displayFDC3Support() { + try { + let supportedElement = document.getElementById("fdc3-support") + if (window.fdc3) { supportedElement.innerHTML = "Yes ✅" } else { supportedElement.innerHTML = "No ❌" } + } catch (error) { + console.error("can't find FDC3 support", error) + } + +} + + +function getPlatform() { + + // TODO: add G42 to vendors + if (window.FSBL) { + window.FSBL.getFSBLInfo().then((info) => { + document.getElementById('providerDetails').innerHTML = "Finsemble Version:" + info.FSBLVersion; + }); + } else if (window.fin) { + fin.desktop.Application.getCurrent().getInfo((info) => { + document.getElementById('providerDetails').innerHTML = info.manifest.startup_app.name + }); + } else if (window.fdc3) { + document.getElementById('providerDetails').innerHTML = "FDC3 Desktop Agent Chrome Extension"; + } + else { + // no need to update the DOM there is already a default message just return + return + } + +} + + +/** + *Populate the channel dropdown elements + */ +function populateChannelsDropDown(newOptionText) { + try { + + let dropdownElement = document.querySelector(".fdc3-channels") + + if (newOptionText) { + dropdownElement.add(new Option(newOptionText)) + } + else { + throw new Error("No option provided") + } + + } catch (error) { + console.error("could not add a new channel to the channel dropdown list", error); + } + +} + +function joinChannel() { + try { + let dropdownElement = document.getElementById("join-channel") + let channelName = dropdownElement.options[dropdownElement.selectedIndex].text.toLowerCase(); + fdc3.joinChannel(channelName); + } catch (error) { + console.error("Can't join channel", error) + } + +} + +async function broadcastFDC3Context() { + try { + let contextData = document.getElementById('txtBroadcastData').value; + fdc3.broadcast(JSON.parse(contextData)); + } catch (error) { + console.error("could not broadcast", error) + } + +} + + +async function getContext(contextType) { + try { + let contextResultBox = document.getElementById("context-result"); + if (contextListener) contextListener.unsubscribe(); + + // if context type is passed in then only listen on that specific context + if (contextType) { + contextListener = fdc3.addContextListener(contextType, (context) => contextResultBox.innerText = JSON.stringify(context, null, 2)) + } else { + contextListener = fdc3.addContextListener(context => contextResultBox.innerText = JSON.stringify(context, null, 2)); + } + } 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) + } +} \ No newline at end of file diff --git a/toolbox/fdc3-explained/1.2/styles.css b/toolbox/fdc3-explained/1.2/styles.css new file mode 100644 index 000000000..94bd02a4f --- /dev/null +++ b/toolbox/fdc3-explained/1.2/styles.css @@ -0,0 +1,117 @@ +@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%); + /* box-shadow: rgb(148 184 208 / 26%) 2px -3px 4px 0px, rgb(0 0 0 / 37%) -3px 3px 7px; */ + border-radius: 5px; + box-shadow: #03a9f433 2px 3px 0px 0px; + cursor: pointer; + /* transition: box-shadow 3s ease-in-out; */ +} +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: #55778E; + 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: #55778E; + 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: 100px; +} + +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; +} \ No newline at end of file diff --git a/toolbox/fdc3-explained/versions.js b/toolbox/fdc3-explained/versions.js new file mode 100644 index 000000000..0f98587d0 --- /dev/null +++ b/toolbox/fdc3-explained/versions.js @@ -0,0 +1,15 @@ +export default function () { + + const versions = ["1.0", "1.1", "1.2"]; + + let versionDropdown = document.getElementById("versions") + + // populate the version dropdown with the versions + versions.forEach(version => { + let option = document.createElement("option"); + option.text = version; + option.value = version + versionDropdown.add(option); + }) + +} \ No newline at end of file diff --git a/toolbox/fdc3_explained.html b/toolbox/fdc3_explained.html index 99919dd04..c8ea28094 100644 --- a/toolbox/fdc3_explained.html +++ b/toolbox/fdc3_explained.html @@ -9,13 +9,14 @@ -The FDC3 Explained application has been updated and moved to fdc3-explained/index.html. Please update your apps! +The FDC3 Explained application has been updated and moved to fdc3-explained/index.html. Please update your apps!

      -The old app (pre 1.1) is still available on legacy.html. +The old app (pre 1.1) is still available on legacy.html.