Skip to content

Commit

Permalink
* Allow to save message templates for a feature
Browse files Browse the repository at this point in the history
* Fixed environment layout for ace editor
* Fixed deselection in things table
* Support to load WoT TD for things and features

Signed-off-by: thfries <thomas.fries0@gmail.com>
  • Loading branch information
thfries committed Aug 19, 2022
1 parent f167429 commit 15ee6ce
Show file tree
Hide file tree
Showing 13 changed files with 386 additions and 85 deletions.
18 changes: 18 additions & 0 deletions ui/main.js
Expand Up @@ -10,18 +10,21 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
/* eslint-disable new-cap */

import * as Authorization from './modules/environments/authorization.js';
import * as Environments from './modules/environments/environments.js';
import * as Attributes from './modules/things/attributes.js';
import * as Features from './modules/things/features.js';
import * as FeatureMessages from './modules/things/featureMessages.js';
import * as Fields from './modules/things/fields.js';
import * as SearchFilter from './modules/things/searchFilter.js';
import * as Things from './modules/things/things.js';
import * as Connections from './modules/connections/connections.js';
import * as Policies from './modules/policies/policies.js';
import * as API from './modules/api.js';
import * as Utils from './modules/utils.js';
import {WoTDescription} from './modules/things/wotDescription.js';


let resized = false;
Expand All @@ -45,11 +48,26 @@ document.addEventListener('DOMContentLoaded', async function() {
await Fields.ready();
await SearchFilter.ready();
Features.ready();
await FeatureMessages.ready();
Policies.ready();
Connections.ready();
Authorization.ready();
Environments.ready();

const thingDescription = WoTDescription({
itemsId: 'tabItemsThing',
contentId: 'tabContentThing',
}, false);
Things.addChangeListener(thingDescription.onReferenceChanged);
thingDescription.ready();

const featureDescription = WoTDescription({
itemsId: 'tabItemsFeatures',
contentId: 'tabContentFeatures',
}, true);
Features.addChangeListener(featureDescription.onReferenceChanged);
featureDescription.ready();

// make dropdowns not cutting off
new bootstrap.Dropdown(document.querySelector('.dropdown-toggle'), {
popperConfig: {
Expand Down
6 changes: 4 additions & 2 deletions ui/modules/api.js
Expand Up @@ -247,17 +247,19 @@ export function setAuthHeader(forDevOps) {
* @param {String} method 'POST', 'GET', 'DELETE', etc.
* @param {String} path of the Ditto call (e.g. '/things')
* @param {Object} body payload for the api call
* @param {Object} additionalHeaders object with additional header fields
* @return {Object} result as json object
*/
export async function callDittoREST(method, path, body) {
export async function callDittoREST(method, path, body, additionalHeaders) {
try {
const response = await fetch(Environments.current().api_uri + '/api/2' + path, {
method: method,
headers: {
'Content-Type': 'application/json',
[authHeaderKey]: authHeaderValue,
...additionalHeaders,
},
body: JSON.stringify(body),
...(body) && {body: JSON.stringify(body)},
});
if (!response.ok) {
response.json()
Expand Down
24 changes: 13 additions & 11 deletions ui/modules/environments/environments.html
Expand Up @@ -53,17 +53,19 @@ <h5>Environments</h5>
</div>
</div>
<div class="tab-pane container no-margin" id="tabEnvJson">
<div class="input-group input-group-sm mb-1">
<div class="form-control-sm" style="flex-grow: 1;"></div>
<button class="btn btn-outline-secondary btn-sm button_round_both" id="buttonUpdateJson"
data-bs-toggle="tooltip" title="Save selected environment json">
<i class="bi bi-save"></i>
Save
</button>
</div>
<div class="ace_container" style="height: 100%;">
<div>
<div class="script_editor" id="settingsEditor"></div>
<div class="resizable_flex_column">
<div class="input-group input-group-sm mb-1">
<div class="form-control-sm" style="flex-grow: 1;"></div>
<button class="btn btn-outline-secondary btn-sm button_round_both" id="buttonUpdateJson"
data-bs-toggle="tooltip" title="Save selected environment json">
<i class="bi bi-save"></i>
Save
</button>
</div>
<div class="ace_container" style="flex-grow: 1;">
<div>
<div class="script_editor" id="settingsEditor"></div>
</div>
</div>
</div>
</div>
Expand Down
51 changes: 51 additions & 0 deletions ui/modules/things/featureMessages.html
@@ -0,0 +1,51 @@
<!--
~ Copyright (c) 2022 Contributors to the Eclipse Foundation
~
~ See the NOTICE file(s) distributed with this work for additional
~ information regarding copyright ownership.
~
~ This program and the accompanying materials are made available under the
~ terms of the Eclipse Public License 2.0 which is available at
~ http://www.eclipse.org/legal/epl-2.0
~
~ SPDX-License-Identifier: EPL-2.0
-->
<div class="tab-pane container fade no-margin">
<div class="resizable_flex_column">
<div class="input-group input-group-sm mb-1 mt-1 has-validation">
<label class="input-group-text">Subject and Timeout</label>
<input type="text" class="form-control" id="inputMessageSubject"></input>
<input type="number" class="form-control form-control-sm" id="inputMessageTimeout" value="10"></input>
<button class="btn btn-outline-secondary btn-sm" id="buttonMessageSend">
<i class="bi bi-send"></i>
Send
</button>
<div class="invalid-feedback"></div>
</div>
<div class="input-group input-group-sm mb-1 has-validation">
<label class="input-group-text">Template</label>
<div class="btn-group dropend">
<button id="buttonMessageFavourite" class="btn btn-outline-secondary btn-sm" data-bs-toggle="tooltip"
title="Save favourite for message on this feature">
<i id="favIconMessage" class="bi bi-star"></i>
</button>
<button class="btn btn-outline-secondary btn-sm dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown"></button>
<ul id="ulMessageTemplates" class="dropdown-menu" style="position: fixed; top: auto;">
</ul>
</div>
<input type="text" class="form-control" id="inputMessageTemplate">
<div class="invalid-feedback"></div>
</div>
<div class="input-group input-group-sm" style="flex-grow: 1; display: flex;">
<label class="input-group-text">Payload<br>and<br>Response</label>
<div class="ace_container" style="flex-grow: 1;">
<div class="script_editor" id="acePayload"></div>
</div>
<div class="ace_container" style="flex-grow: 1;">
<div class="script_editor" id="aceResponse"></div>
</div>
</div>

</div>
</div>
163 changes: 163 additions & 0 deletions ui/modules/things/featureMessages.js
@@ -0,0 +1,163 @@
/*
* Copyright (c) 2022 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/

/* eslint-disable require-jsdoc */
import * as API from '../api.js';
import * as Environments from '../environments/environments.js';
import * as Utils from '../utils.js';
import * as Things from './things.js';
import * as Features from './features.js';

const dom = {
inputMessageSubject: null,
inputMessageTimeout: null,
inputMessageTemplate: null,
buttonMessageSend: null,
buttonMessageFavourite: null,
ulMessageTemplates: null,
favIconMessage: null,
theFeatureId: null,
tableValidationFeature: null,
};

let acePayload;
let aceResponse;

/**
* Initializes components. Should be called after DOMContentLoaded event
*/
export async function ready() {
Environments.addChangeListener(onEnvironmentChanged);
Features.addChangeListener(onFeatureChanged);

Utils.addTab(
document.getElementById('tabItemsFeatures'),
document.getElementById('tabContentFeatures'),
'Message to Feature',
await( await fetch('modules/things/featureMessages.html')).text(),
);

Utils.getAllElementsById(dom);

acePayload = Utils.createAceEditor('acePayload', 'ace/mode/json');
aceResponse = Utils.createAceEditor('aceResponse', 'ace/mode/json', true);


dom.buttonMessageSend.onclick = () => {
Utils.assert(dom.theFeatureId.value, 'Please select a Feature', dom.tableValidationFeature);
Utils.assert(dom.inputMessageSubject.value, 'Please give a Subject', dom.inputMessageSubject);
Utils.assert(dom.inputMessageTimeout.value, 'Please give a timeout', dom.inputMessageTimeout);
messageFeature();
};

dom.buttonMessageFavourite.onclick = () => {
const templateName = dom.inputMessageTemplate.value;
const featureId = dom.theFeatureId.value;
Utils.assert(templateName, 'Please give a name for the template', dom.inputMessageTemplate);
Environments.current().messageTemplates[featureId] = Environments.current().messageTemplates[featureId] || {};
if (Object.keys(Environments.current().messageTemplates[featureId]).includes(templateName) &&
dom.favIconMessage.classList.contains('bi-star-fill')) {
dom.favIconMessage.classList.replace('bi-star-fill', 'bi-star');
delete Environments.current().messageTemplates[featureId][templateName];
} else {
dom.favIconMessage.classList.replace('bi-star', 'bi-star-fill');
Environments.current().messageTemplates[featureId][templateName] = {
subject: dom.inputMessageSubject.value,
timeout: dom.inputMessageTimeout.value,
payload: JSON.parse(acePayload.getValue()),
};
acePayload.session.getUndoManager().markClean();
}
Environments.environmentsJsonChanged('messageTemplates');
};

dom.ulMessageTemplates.addEventListener('click', (event) => {
dom.favIconMessage.classList.replace('bi-star', 'bi-star-fill');
const template = Environments.current().messageTemplates[dom.theFeatureId.value][event.target.textContent];
dom.inputMessageTemplate.value = event.target.textContent;
dom.inputMessageSubject.value = template.subject;
dom.inputMessageTimeout.value = template.timeout;
acePayload.setValue(JSON.stringify(template.payload, null, 2), -1);
acePayload.session.getUndoManager().markClean();
});

[dom.inputMessageTemplate, dom.inputMessageSubject, dom.inputMessageTimeout].forEach((e) => {
e.addEventListener('change', () => {
dom.favIconMessage.classList.replace('bi-star-fill', 'bi-star');
});
});

acePayload.on('input', () => {
if (!acePayload.session.getUndoManager().isClean()) {
dom.favIconMessage.classList.replace('bi-star-fill', 'bi-star');
}
});
}

/**
* Calls Ditto to send a message with the parameters of the fields in the UI
*/
function messageFeature() {
const payload = acePayload.getValue();
aceResponse.setValue('');
API.callDittoREST('POST', '/things/' + Things.theThing.thingId +
'/features/' + dom.theFeatureId.value +
'/inbox/messages/' + dom.inputMessageSubject.value +
'?timeout=' + dom.inputMessageTimeout.value,
payload,
).then((data) => {
if (timeout > 0) {
aceResponse.setValue(JSON.stringify(data, null, 2), -1);
};
}).catch((err) => {
aceResponse.setValue('');
});
};

function onEnvironmentChanged(modifiedField) {
Environments.current()['messageTemplates'] = Environments.current()['messageTemplates'] || {};

if (!modifiedField) {
clearAllFields();
}
if (modifiedField === 'messageTemplates') {
refillTemplates();
}
};

function clearAllFields() {
dom.favIconMessage.classList.replace('bi-star-fill', 'bi-star');
dom.inputMessageTemplate.value = null;
dom.inputMessageSubject.value = null;
dom.inputMessageTimeout.value = '10';
acePayload.setValue('{}');
aceResponse.setValue('');
dom.ulMessageTemplates.innerHTML = '';
}

function refillTemplates() {
dom.ulMessageTemplates.innerHTML = '';
Utils.addDropDownEntries(dom.ulMessageTemplates, ['Saved message templates'], true);
if (dom.theFeatureId.value && Environments.current().messageTemplates[dom.theFeatureId.value]) {
Utils.addDropDownEntries(
dom.ulMessageTemplates,
Object.keys(Environments.current().messageTemplates[dom.theFeatureId.value]),
);
}
}

function onFeatureChanged(featureId) {
clearAllFields();
refillTemplates();
};

39 changes: 7 additions & 32 deletions ui/modules/things/features.html
Expand Up @@ -16,22 +16,23 @@ <h5 data-bs-toggle="collapse" data-bs-target="#collapseFeatures">
<div class="collapse show" id="collapseFeatures">
<div class="row resizable_pane" style="height:500px;">
<div class="col-md-4 resizable_flex_column">
<div class="input-group has-validation">
<input class="form-control" id="tableValidationFeature" hidden="true"></input>
<div class="invalid-feedback"></div>
</div>
<div class="table-wrap">
<table class="table table-striped table-hover table-sm">
<tbody id="featuresTable"></tbody>
</table>
</div>
</div>
<div class="col-md-8 resizable_flex_column">
<ul class="nav nav-tabs">
<ul class="nav nav-tabs" id="tabItemsFeatures">
<li class="nav-item">
<a class="nav-link active" data-bs-toggle="tab" data-bs-target="#tabCrudFeature">CRUD Feature</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" data-bs-target="#tabMessage2Feature">Message to Feature</a>
</li>
</ul>
<div class="tab-content" style="flex-grow: 1;">
<div class="tab-content" style="flex-grow: 1;" id="tabContentFeatures">
<div class="tab-pane container active no-margin" id="tabCrudFeature">
<div class="resizable_flex_column">
<div class="input-group input-group-sm mb-1 mt-1">
Expand Down Expand Up @@ -62,33 +63,7 @@ <h5 data-bs-toggle="collapse" data-bs-target="#collapseFeatures">
</div>
</div>
</div>
<div class="tab-pane container fade no-margin" id="tabMessage2Feature">
<div class="resizable_flex_column">
<div class="input-group input-group-sm mb-1 mt-1">
<label class="input-group-text">Subject and Timeout</label>
<input type="text" class="form-control" id="messageFeatureSubject"></input>
<input type="number" class="form-control form-control-sm" id="messageTimeout"
value="10"></input>
<button class="btn btn-outline-secondary btn-sm" id="messageFeature">
<i class="bi bi-send"></i>
Send
</button>
</div>
<div class="input-group input-group-sm mb-1">
<label class="input-group-text">Template</label>
<input type="text" class="form-control" id="inputMessageTemplate">
</div>
<div class="input-group input-group-sm" style="flex-grow: 1; display: flex;">
<label class="input-group-text">Payload<br>and<br>Response</label>
<textarea class="form-control form-control-sm" style="resize:none; flex-grow: 1;"
spellcheck="false" id="messageFeaturePayload">{}</textarea>
<textarea class="form-control form-control-sm" style="resize:none; flex-grow: 1;"
spellcheck="false" id="messageFeatureResponse"></textarea>
</div>

</div>
</div>
</div>
</div>
</div>
</div>
</div>

0 comments on commit 15ee6ce

Please sign in to comment.