Skip to content

Commit

Permalink
Improve form href selection in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
relu91 committed Oct 1, 2021
1 parent 026936a commit 4e8e206
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 28 deletions.
6 changes: 4 additions & 2 deletions src/models/thing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ export default class Thing extends EventEmitter {

if (property.forms) {
property.forms = property.forms.map((form) => {
// TODO: WebThingsIO non-standard keyword
// TODO: webthings proprietary field;
// See https://github.com/WebThingsIO/gateway/issues/2832
if (form.proxy) {
delete form.proxy;
form.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${form.href}`;
Expand Down Expand Up @@ -768,7 +769,8 @@ export default class Thing extends EventEmitter {

if (event.forms) {
event.forms = event.forms.map((form) => {
// TODO: WebThingsIO non-standard keyword
// TODO: webthings proprietary field;
// See https://github.com/WebThingsIO/gateway/issues/2832
if (form.proxy) {
delete form.proxy;
form.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${form.href}`;
Expand Down
3 changes: 2 additions & 1 deletion static/js/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ module.exports.ThingFormat = {
};

module.exports.WoTOperation = {
READ_PROPERTY: 'readyproperty',
READ_PROPERTY: 'readproperty',
WRITE_PROPERTY: 'writeproperty',
INVOKE_ACTION: 'invokeaction',
READ_ALL_PROPERTIES: 'readallproperties',
SUBSCRIBE_ALL_EVENTS: 'subscribeallevents',
Expand Down
5 changes: 3 additions & 2 deletions static/js/models/thing-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const API = require('../api').default;
const App = require('../app');
const Model = require('./model');
const Constants = require('../constants');
const Utils = require('../utils');

class ThingModel extends Model {
constructor(description, ws) {
Expand Down Expand Up @@ -194,7 +195,7 @@ class ThingModel extends Model {

const property = this.propertyDescriptions[name];

const href = property.forms[0].href;
const href = Utils.selectFormHref(property.forms, Constants.WoTOperation.READ_PROPERTY);

return API.putJson(href, value)
.then((json) => {
Expand All @@ -216,7 +217,7 @@ class ThingModel extends Model {
if (typeof this.propertiesHref === 'undefined') {
const urls = Object.values(this.propertyDescriptions).map((v) => {
if (v.forms) {
return v.forms[0].href;
return Utils.selectFormHref(v.forms, Constants.WoTOperation.WRITE_PROPERTY);
}
});
const requests = urls.map((u) => API.getJson(u));
Expand Down
9 changes: 7 additions & 2 deletions static/js/rules/PropertySelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const fluent = require('../fluent');
const RuleUtils = require('./RuleUtils');
const Units = require('../units');
const Utils = require('../utils');
const Constants = require('../constants');

function propertyEqual(a, b) {
if (!a && !b) {
Expand Down Expand Up @@ -373,8 +374,12 @@ class PropertySelect {
continue;
}

property.id = RuleUtils.extractProperty(forms[0].href);
property.thing = RuleUtils.extractThing(forms[0].href);
property.id = RuleUtils.extractProperty(
Utils.selectFormHref(forms, Constants.WoTOperation.READ_PROPERTY)
);
property.thing = RuleUtils.extractThing(
Utils.selectFormHref(forms, Constants.WoTOperation.READ_PROPERTY)
);
delete property.forms;

const name = property.title || Utils.capitalize(property.name);
Expand Down
16 changes: 2 additions & 14 deletions static/js/schema-impl/capability/thing.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,7 @@ class Thing {
}
}

let href;
for (const form of property.forms) {
if (!form.op || form.op === Constants.WoTOperation.READ_PROPERTY) {
href = form.href;
break;
}
}
const href = Utils.selectFormHref(property.forms, Constants.WoTOperation.READ_PROPERTY);

if (!href) {
continue;
Expand Down Expand Up @@ -300,13 +294,7 @@ class Thing {
for (const name in description.actions) {
const action = description.actions[name];

let href;
for (const form of description.actions[name].forms) {
if (!form.op || form.op === Constants.WoTOperation.INVOKE_ACTION) {
href = form.href;
break;
}
}
const href = Utils.selectFormHref(action.forms, Constants.WoTOperation.INVOKE_ACTION);

if (!href) {
continue;
Expand Down
35 changes: 35 additions & 0 deletions static/js/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import * as Fluent from './fluent';
import Constants from './constants';

/**
* @param {String} str
Expand Down Expand Up @@ -264,3 +265,37 @@ export function adjustInputValue(value: number, schema: Record<string, unknown>)

return value;
}

type WoTOperation = keyof typeof Constants.WoTOperation;
type WoTFormOperation = WoTOperation | WoTOperation[] | undefined;
/**
* Finds the gateway api endpoint for a specific operation.
* It uses the assumption that gateway enpoints are pushed to
* the form array as the last element.
*
* @param {Array} forms The list of forms.
* @param {string} operation
* @returns {string | undefined} the href of the select form or undefined if not found.
*/
export function selectFormHref(
forms: Array<{ href: string; op: WoTFormOperation }>,
operation: WoTOperation
): string | undefined {
return [...forms].reverse().find((selectedForm) => {
try {
const { protocol } = new URL(selectedForm.href);
return (
protocol === 'http:' &&
(!selectedForm.op || selectedForm.op === operation || selectedForm.op?.includes(operation))
);
} catch (error) {
if (error instanceof TypeError) {
// URL is relative or not well formatted
return (
!selectedForm.op || selectedForm.op === operation || selectedForm.op?.includes(operation)
);
}
throw error;
}
})?.href;
}
11 changes: 4 additions & 7 deletions static/js/views/things.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,10 @@ const ThingsScreen = {
return;
}

let href;
for (const form of description.actions[actionName].forms) {
if (!form.op || form.op === Constants.WoTOperation.INVOKE_ACTION) {
href = form.href;
break;
}
}
const href = Utils.selectFormHref(
description.actions[actionName],
Constants.WoTOperation.INVOKE_ACTION
);

const icon = Icons.capabilityToIcon(description.selectedCapability);
const iconEl = document.getElementById('thing-title-icon');
Expand Down

0 comments on commit 4e8e206

Please sign in to comment.