Skip to content

Commit

Permalink
UI - policy imports review 2
Browse files Browse the repository at this point in the history
- Update bootstrap-icons for new copy icon
- Fixed color of selected copy icon
- Allow additional actions in table rows
- Clipboard copy value now explicit and not guessed from sibling html
- Policy import allows navigation
- fixed SSE mapping of incoming messages

Signed-off-by: thfries <thomas.fries0@gmail.com>
  • Loading branch information
thfries committed Nov 18, 2023
1 parent 733dd2f commit 876c30b
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 41 deletions.
8 changes: 4 additions & 4 deletions ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
<title>Eclipse Ditto™ explorer</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.8.3/font/bootstrap-icons.min.css"
rel="stylesheet"
integrity="sha512-YzwGgFdO1NQw1CZkPoGyRkEnUTxPSbGWXvGiXrWk8IeSqdyci0dEDYdLLjMxq1zCoU0QBa4kHAFiRhUL3z2bow=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.11.1/font/bootstrap-icons.min.css"
integrity="sha512-oAvZuuYVzkcTc2dH5z1ZJup5OmSQ000qlfRvuoTTiyTBjwX1faoyearj8KdMq0LgsBTHMrRuMek7s+CxF8yE+w=="
crossorigin="anonymous"
referrerpolicy="no-referrer" />
<link rel="icon" type="image/png"
href="https://raw.githubusercontent.com/eclipse/ditto/master/documentation/src/main/resources/images/favicon-16x16.png"
sizes="16x16">
Expand Down
9 changes: 9 additions & 0 deletions ui/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@
--bs-table-hover-color: white;
}

.table-active .bi {
color: white;
}

.table-action-column {
text-align: center;
width: 27.5px;
}

td {
text-overflow: ellipsis;
overflow: hidden;
Expand Down
6 changes: 3 additions & 3 deletions ui/modules/connections/connectionsMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ function retrieveConnectionMetrics() {
if (response.connectionMetrics[direction]) {
Object.keys(response.connectionMetrics[direction]).forEach((type) => {
let entry = response.connectionMetrics[direction][type];
Utils.addTableRow(dom.tbodyConnectionMetrics, direction, false, false, type, 'success', entry.success.PT1M, entry.success.PT1H, entry.success.PT24H);
Utils.addTableRow(dom.tbodyConnectionMetrics, direction, false, false, type, 'failure', entry.failure.PT1M, entry.failure.PT1H, entry.failure.PT24H);
Utils.addTableRow(dom.tbodyConnectionMetrics, direction, false, null, type, 'success', entry.success.PT1M, entry.success.PT1H, entry.success.PT24H);
Utils.addTableRow(dom.tbodyConnectionMetrics, direction, false, null, type, 'failure', entry.failure.PT1M, entry.failure.PT1H, entry.failure.PT24H);
});
};
});
Expand Down Expand Up @@ -130,7 +130,7 @@ function fillConnectionLogsTable(entries) {

let filter = connectionLogsFilter ? connectionLogsFilter.match : (a => true);
entries.filter(filter).forEach((entry) => {
Utils.addTableRow(dom.tbodyConnectionLogs, Utils.formatDate(entry.timestamp, true), false, false, entry.type, entry.level);
Utils.addTableRow(dom.tbodyConnectionLogs, Utils.formatDate(entry.timestamp, true), false, null, entry.type, entry.level);
});
dom.tbodyConnectionLogs.scrollTop = dom.tbodyConnectionLogs.scrollHeight - dom.tbodyConnectionLogs.clientHeight;
}
Expand Down
2 changes: 1 addition & 1 deletion ui/modules/policies/policies.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ <h5>Policies</h5>
<h6>Load a policy</h6>
<div class="input-group input-group-sm mb-1 mt-1 has-validation" role="group">
<label class="input-group-text">Policy Id</label>
<input type="text" class="form-control form-control-sm" id="inputPolicyId"></input>
<input type="search" class="form-control form-control-sm" id="inputPolicyId"></input>
<button id="buttonLoadPolicy" class="btn btn-outline-primary btn-sm"
title="Load policy with the given ID">
Load
Expand Down
4 changes: 2 additions & 2 deletions ui/modules/policies/policies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ function refreshWhoAmI() {
API.callDittoREST('GET', '/whoami')
.then((whoamiResult) => {
whoamiResult.subjects.forEach((subject) => {
Utils.addTableRow(dom.tbodyWhoami, subject, false, false,
Utils.addTableRow(dom.tbodyWhoami, subject, false, null,
subject === whoamiResult.defaultSubject ? 'default' : '');
});
})
Expand Down Expand Up @@ -154,7 +154,7 @@ function onEnvironmentChanged(modifiedField: String) {
Environments.current()['recentPolicyIds'] = Environments.current()['recentPolicyIds'] || [];
dom.tbodyRecentPolicies.innerHTML = '';
Environments.current().recentPolicyIds.forEach(entry => {
Utils.addTableRow(dom.tbodyRecentPolicies, entry, thePolicy && thePolicy.policyId === entry, true);
Utils.addTableRow(dom.tbodyRecentPolicies, entry, thePolicy && thePolicy.policyId === entry, entry);
});
}

Expand Down
11 changes: 10 additions & 1 deletion ui/modules/policies/policiesImports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ function onPolicyChanged(policy: Policies.Policy) {
if (policy) {
let policyHasImport = false;
Object.keys(policy.imports).forEach((key) => {
Utils.addTableRow(dom.tbodyPolicyImports, key, key === selectedImport);
const row = Utils.addTableRow(dom.tbodyPolicyImports, key, key === selectedImport);
Utils.addActionToRow(row, 'bi-arrow-up-right-square', getNavigatePolicyAction(key), 'Open policy');
if (key === selectedImport) {
setImport(key);
policyHasImport = true;
Expand All @@ -118,6 +119,14 @@ function onPolicyChanged(policy: Policies.Policy) {
} else {
setImport(null);
}

function getNavigatePolicyAction(policyId: String) {
return (evt: Event) => {
API.callDittoREST('GET', '/policies/' + policyId).then((targetPolicy: Policies.Policy) => {
Policies.setThePolicy(targetPolicy);
})
}
}
}

async function setImport(importedPolicyId: string) {
Expand Down
2 changes: 1 addition & 1 deletion ui/modules/policies/policiesResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ function onEntryChanged(entryLabel: string) {

if (Policies.thePolicy && entryLabel) {
Object.keys(Policies.thePolicy.entries[entryLabel].resources).forEach((key) => {
Utils.addTableRow(dom.tbodyPolicyResources, key, key === selectedResource, false,
Utils.addTableRow(dom.tbodyPolicyResources, key, key === selectedResource, null,
JSON.stringify(Policies.thePolicy.entries[entryLabel].resources[key])
);
if (key === selectedResource) {
Expand Down
2 changes: 1 addition & 1 deletion ui/modules/policies/policiesSubjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function onEntryChanged(entryLabel: string) {

if (Policies.thePolicy && entryLabel) {
Object.keys(Policies.thePolicy.entries[entryLabel].subjects).forEach((key) => {
Utils.addTableRow(dom.tbodyPolicySubjects, key, key === selectedSubject, false,
Utils.addTableRow(dom.tbodyPolicySubjects, key, key === selectedSubject, null,
JSON.stringify(Policies.thePolicy.entries[entryLabel].subjects[key])
);
if (key === selectedSubject) {
Expand Down
2 changes: 1 addition & 1 deletion ui/modules/things/attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ function onThingChanged(thing) {
refreshAttribute(Things.theThing, path);
thingHasAttribute = true;
}
Utils.addTableRow(dom.tbodyAttributes, path, path === dom.crudAttribute.idValue, false,
Utils.addTableRow(dom.tbodyAttributes, path, path === dom.crudAttribute.idValue, null,
attributeToString(Things.theThing.attributes[path]));
count++;
});
Expand Down
18 changes: 9 additions & 9 deletions ui/modules/things/messagesIncoming.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,25 @@ function onMessage(messageData) {
messages.push(messageData);
dom.badgeMessageIncomingCount.textContent = messages.length;

function getColumnValues() {
if (messageData['_context'] && messageData['_context'].value) {
function getColumnValues(): string[] {
if (messageData['features']) {
return [
...messageData['_context'].value.features ? Object.keys(messageData['_context'].value.features) : [],
...messageData['_context'].value.attributes ? Object.keys(messageData['_context'].value.attributes) : []
...messageData['features'] ? Object.keys(messageData.features) : [],
...messageData['attributes'] ? Object.keys(messageData.attributes) : [],
];
} else {
return [
...messageData['features'] ? Object.keys(messageData.features) : [],
...messageData['attributes'] ? Object.keys(messageData.attributes) : []
...messageData['_context'].value.features ? Object.keys(messageData['_context'].value.features) : [],
...messageData['_context'].value.attributes ? Object.keys(messageData['_context'].value.attributes) : [],
]
}
}

Utils.addTableRow(
dom.tbodyMessagesIncoming,
messageData._revision, false, false,
getColumnValues(),
Utils.formatDate(messageData._modified, true),
messageData._revision, false, null,
getColumnValues().join('\n'),
Utils.formatDate(messageData._modified, true)
);
}

Expand Down
12 changes: 6 additions & 6 deletions ui/modules/things/thingsCRUD.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,12 @@ function onThingChanged(thingJson) {
function updateThingDetailsTable() {
dom.tbodyThingDetails.innerHTML = '';
if (thingJson) {
Utils.addTableRow(dom.tbodyThingDetails, 'thingId', false, true, thingJson.thingId);
Utils.addTableRow(dom.tbodyThingDetails, 'policyId', false, true, thingJson.policyId);
Utils.addTableRow(dom.tbodyThingDetails, 'definition', false, true, thingJson.definition ?? '');
Utils.addTableRow(dom.tbodyThingDetails, 'revision', false, true, thingJson._revision);
Utils.addTableRow(dom.tbodyThingDetails, 'created', false, true, thingJson._created);
Utils.addTableRow(dom.tbodyThingDetails, 'modified', false, true, thingJson._modified);
Utils.addTableRow(dom.tbodyThingDetails, 'thingId', false, thingJson.thingId, thingJson.thingId);
Utils.addTableRow(dom.tbodyThingDetails, 'policyId', false, thingJson.policyId, thingJson.policyId);
Utils.addTableRow(dom.tbodyThingDetails, 'definition', false, thingJson.definition ?? ' ', thingJson.definition ?? '');
Utils.addTableRow(dom.tbodyThingDetails, 'revision', false, thingJson._revision, thingJson._revision);
Utils.addTableRow(dom.tbodyThingDetails, 'created', false, thingJson._created, thingJson._created);
Utils.addTableRow(dom.tbodyThingDetails, 'modified', false, thingJson._modified, thingJson._modified);
}
}

Expand Down
35 changes: 23 additions & 12 deletions ui/modules/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,24 @@ export function ready() {
* @param {HTMLTableElement} table tbody element the row is added to
* @param {String} key first column text of the row. Acts as id of the row
* @param {boolean} selected if true, the new row will be marked as selected
* @param {boolean} withClipBoardCopy add a clipboard button at the last column of the row
* @param {boolean} clipBoardValue add a clipboard button at the last column of the row
* @param {array} columnValues texts for additional columns of the row
* @return {HTMLTableRowElement} created row
*/
export const addTableRow = function(table, key, selected, withClipBoardCopy = false, ...columnValues) {
export const addTableRow = function(table: HTMLTableElement, key: string, selected: boolean, clipBoardValue?: string, ...columnValues: string[]) {
const row: HTMLTableRowElement = table.insertRow();
row.id = key;
addCellToRow(row, key, key, 0);
let lastAddedColumn = key;
columnValues.forEach((value) => {
addCellToRow(row, value);
lastAddedColumn = value;
});
if (selected) {
row.classList.add('table-active');
}
if (withClipBoardCopy) {
addClipboardCopyToRow(row);
if (clipBoardValue) {
addActionToRow(row, ICON_CLASS_CLIPBOARD, getRowClipboardAction(ICON_CLASS_CLIPBOARD, ICON_CLASS_CLIPFEEDBACK, clipBoardValue), 'Copy to clipboard');
}
return row;
};
Expand Down Expand Up @@ -98,20 +100,29 @@ export function addCellToRow(row, cellContent, cellTooltip = null, position = -1
* Adds a clipboard copy button to a row. The text of the previous table cell will be copied
* @param {HTMLTableRowElement} row target row
*/
export function addClipboardCopyToRow(row: HTMLTableRowElement) {
export function addActionToRow(row: HTMLTableRowElement, iconClass: string, onClickAction: (evt: Event) => any, toolTip?: string) {
const td = row.insertCell();
td.style.textAlign = 'right';
td.classList.add('table-action-column');
const button = document.createElement('button');
button.classList.add('btn', 'btn-sm');
button.classList.add('btn');
button.style.padding = '0';
button.innerHTML = `<i class="bi bi-clipboard"></i>`;
button.onclick = (evt) => {
const td = (evt.currentTarget as HTMLElement).parentNode.previousSibling as HTMLTableCellElement;
navigator.clipboard.writeText(td.innerText);
};
button.innerHTML = `<i class="bi ${iconClass}"></i>`;
toolTip && (button.title = toolTip);
button.onclick = onClickAction;
td.appendChild(button);
}

export let ICON_CLASS_CLIPBOARD = 'bi-copy';
export let ICON_CLASS_CLIPFEEDBACK = 'bi-check-lg';
export function getRowClipboardAction(iconClassMain: string, iconClassFeedback: string, context: any) {
return (evt: Event) => {
navigator.clipboard.writeText(context);
const icon = (evt.currentTarget as HTMLElement).querySelector('.bi');
icon.classList.replace(iconClassMain, iconClassFeedback);
setTimeout(() => icon.classList.replace(iconClassFeedback, iconClassMain), 500);
};
}

/**
* Adds a header cell to the given table row
* @param {HTMLTableRowElement} row target row
Expand Down

0 comments on commit 876c30b

Please sign in to comment.