From abb702df0bb6547067da196963b8f58decf12d21 Mon Sep 17 00:00:00 2001 From: Joakim Gustafsson Date: Thu, 1 Feb 2024 17:38:01 +0100 Subject: [PATCH] Improving result view for complex results --- .../Views/ComplexResult/ResultGraphics.mjs | 62 +++++++++---------- .../Views/Events/EventGraphics.mjs | 4 +- .../Views/Servers/EndpointGraphics.mjs | 4 +- .../ijt-support/Events/EventManager.mjs | 5 +- .../ijt-support/Models/ModelManager.mjs | 14 +++++ .../Models/Results/ResultDataType.mjs | 8 +++ .../Models/Results/TighteningDataType.mjs | 14 ++++- .../ijt-support/Results/ResultManager.mjs | 43 +++++++++++-- 8 files changed, 107 insertions(+), 47 deletions(-) diff --git a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/ComplexResult/ResultGraphics.mjs b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/ComplexResult/ResultGraphics.mjs index 7751b11..83967d4 100644 --- a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/ComplexResult/ResultGraphics.mjs +++ b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/ComplexResult/ResultGraphics.mjs @@ -5,18 +5,13 @@ import BasicScreen from '../GraphicSupport/BasicScreen.mjs' export default class ResultGraphics extends BasicScreen { constructor (resultManager) { super('Result') - this.results = { - 1: [], - 3: [], - 4: [] - } + this.resultManager = resultManager this.displayedIdentity = 0 - this.selectType = '1' - this.selectId = '' + this.selectType = '-1' + this.selectResult = '-1' resultManager.subscribe((result) => { - this.store(result) - this.refresh(result.id) + this.refreshDrawing(result.id) }) this.header = document.createElement('div') @@ -24,20 +19,23 @@ export default class ResultGraphics extends BasicScreen { this.backGround.appendChild(this.header) this.selectResultType = this.createDropdown('Select result type', (selection) => { - this.selectType = selection + this.selectType = parseInt(selection) this.changeResultList(selection) + this.refreshDrawing(this.selectResult) }) this.selectResultType.addOption('Latest', -1) this.selectResultType.addOption('Jobs', 4) this.selectResultType.addOption('Batches', 3) this.selectResultType.addOption('Single tightenings', 1) + this.selectResultType.addOption('Other', 0) this.header.appendChild(this.selectResultType) - this.selectResult = this.createDropdown('Select result', (selection) => { - this.refresh(selection) + this.selectResultDropdown = this.createDropdown('Select result', (selection) => { + this.selectResult = selection + this.refreshDrawing(selection) }) - this.selectResult.addOption('One', 3) - this.header.appendChild(this.selectResult) + this.selectResultDropdown.addOption('Latest', -1) + this.header.appendChild(this.selectResultDropdown) this.display = document.createElement('div') this.display.classList.add('drawResultBox') @@ -45,34 +43,34 @@ export default class ResultGraphics extends BasicScreen { } changeResultList (selectedtype) { - this.selectResult.clearOptions() - this.selectResult.addOption('a', 1) - for (const a of this.results[parseInt(selectedtype)]) { - this.selectResult.addOption(a.name, a.id) - } - } - - resultFromId (id) { - for (const r of this.results[parseInt(this.selectType)]) { - if (id === r.id) { - return r - } + this.selectResultDropdown.clearOptions() + this.selectResultDropdown.addOption('Latest', -1) + for (const a of this.resultManager.getResultOfType(parseInt(selectedtype))) { + this.selectResultDropdown.addOption(a.name + ' [' + a.time + ']', a.id) } } - refresh (id) { - const r = this.resultFromId(id) + refreshDrawing (id) { this.display.innerHTML = '' + + if (this.selectType === -1) { + this.drawResultBoxes(this.resultManager.getLatest(-1), this.display) + return + } + if (this.selectResult === '-1') { + this.drawResultBoxes(this.resultManager.getLatest(this.selectType), this.display) + return + } + const r = this.resultManager.resultFromId(id, this.selectType) if (r) { this.drawResultBoxes(r, this.display) } } - store (result) { - this.results[parseInt(result.classification)].push(result) - } - drawResultBoxes (result, container) { + if (!result) { + return + } // const classification = result.ResultMetaData.Classification const top = document.createElement('div') const bottom = document.createElement('div') diff --git a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/Events/EventGraphics.mjs b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/Events/EventGraphics.mjs index a0f573c..89dcc2b 100644 --- a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/Events/EventGraphics.mjs +++ b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/Events/EventGraphics.mjs @@ -5,10 +5,9 @@ import ControlMessageSplitScreen from '../GraphicSupport/ControlMessageSplitScre * graphical representation of the events */ export default class EventGraphics extends ControlMessageSplitScreen { - constructor (eventManager, modelManager) { + constructor (eventManager) { super('Events', 'Events', 'Event content', 'subscribed') this.eventManager = eventManager - this.modelManager = modelManager this.modelToHTML = new ModelToHTML() eventManager.listenEvent( // We use this function since the actual subscription has been set up once and for all @@ -40,7 +39,6 @@ export default class EventGraphics extends ControlMessageSplitScreen { const content = document.createElement('li') content.classList.add('indent') - // const model = this.modelManager.createModelFromEvent(e) const a = this.modelToHTML.toHTML(e, true, e.SourceName) header.appendChild(a) } diff --git a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/Servers/EndpointGraphics.mjs b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/Servers/EndpointGraphics.mjs index 4ccdb46..f434c0e 100644 --- a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/Servers/EndpointGraphics.mjs +++ b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/Views/Servers/EndpointGraphics.mjs @@ -54,8 +54,8 @@ export default class EndpointGraphics extends BasicScreen { const addressSpaceGraphics = new AddressSpaceGraphics(addressSpace) tabGenerator.generateTab(addressSpaceGraphics, false) - const eventManager = new EventManager(this.connectionManager) - const eventGraphics = new EventGraphics(eventManager, modelManager) + const eventManager = new EventManager(this.connectionManager, modelManager) + const eventGraphics = new EventGraphics(eventManager) tabGenerator.generateTab(eventGraphics, false) const resultManager = new ResultManager(this.connectionManager, eventManager) diff --git a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Events/EventManager.mjs b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Events/EventManager.mjs index cdfd48c..da71814 100644 --- a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Events/EventManager.mjs +++ b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Events/EventManager.mjs @@ -1,13 +1,12 @@ -import { ModelManager } from '../Models/ModelManager.mjs' /** * The purpose of this class is to interpret events * */ export class EventManager { - constructor (connectionManager) { + constructor (connectionManager, modelManager) { this.socketHandler = connectionManager.socketHandler this.callbacks = [] - this.modelManager = new ModelManager() + this.modelManager = modelManager connectionManager.subscribe('subscription', (setToTrue) => { if (setToTrue) { diff --git a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/ModelManager.mjs b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/ModelManager.mjs index 9d76bfd..829c227 100644 --- a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/ModelManager.mjs +++ b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/ModelManager.mjs @@ -26,6 +26,20 @@ import IJTBaseModel from './IJTBaseModel.mjs' /* eslint-disable */ export class ModelManager { + constructor () { + this.resultSubscribeList = [] + } + + resultTypeNotification(result) { + for (const f of this.resultSubscribeList) { + f(result) + } + } + + subscribeSubResults(f) { + this.resultSubscribeList.push(f) + } + /** * The purpose of this method is to create a javascript class from a parameter name * @param {*} parameterName diff --git a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/Results/ResultDataType.mjs b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/Results/ResultDataType.mjs index a6d4bcf..779d72a 100644 --- a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/Results/ResultDataType.mjs +++ b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/Results/ResultDataType.mjs @@ -13,6 +13,7 @@ export default class ResultDataType extends IJTBaseModel { } super(parameters, modelManager, castMapping) + modelManager.resultTypeNotification(this) } get id () { @@ -37,4 +38,11 @@ export default class ResultDataType extends IJTBaseModel { } return false } + + get time () { + if (this.ResultMetaData?.ProcessingTimes?.EndTime) { + return this.ResultMetaData.ProcessingTimes.EndTime + } + return 'No Time' + } } diff --git a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/Results/TighteningDataType.mjs b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/Results/TighteningDataType.mjs index 8cc592b..643ca78 100644 --- a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/Results/TighteningDataType.mjs +++ b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Models/Results/TighteningDataType.mjs @@ -2,9 +2,17 @@ import ResultDataType from './ResultDataType.mjs' // The purpose of this class is to handle the actual subscription or reading of a value and via socketIO send the result to the webpage export default class TighteningDataType extends ResultDataType { constructor (parameters, modelManager) { - const simplifiedParameters = { - ResultMetaData: parameters.Value.ResultMetaData, - ResultContent: parameters.Value.ResultContent + let simplifiedParameters + if (parameters.Value) { + simplifiedParameters = { + ResultMetaData: parameters.Value.ResultMetaData, + ResultContent: parameters.Value.ResultContent + } + } else { + simplifiedParameters = { + ResultMetaData: parameters.ResultMetaData, + ResultContent: parameters.ResultContent + } } const castMapping = { ResultContent: 'JoiningResultDataType' diff --git a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Results/ResultManager.mjs b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Results/ResultManager.mjs index 372d922..26fb989 100644 --- a/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Results/ResultManager.mjs +++ b/OPC_UA_Clients/Release2/IJT_Web_Client/Javascripts/ijt-support/Results/ResultManager.mjs @@ -1,11 +1,21 @@ -import { ModelManager } from '../Models/ModelManager.mjs' - +/** + * The purpose of this class is to store results as they occur and allow to + * query for them, in addition to a specialized subscription focusing on results + */ export class ResultManager { constructor (connectionManager, eventManager) { this.eventManager = eventManager - this.modelManager = new ModelManager() + this.eventManager.modelManager.subscribeSubResults((r) => { + this.addResult(r) + }) this.results = {} this.subscribers = [] + this.results = { + 0: [], + 1: [], + 3: [], + 4: [] + } connectionManager.subscribe('subscription', (setToTrue) => { if (setToTrue) { @@ -17,6 +27,7 @@ export class ResultManager { addResult (result) { this.results[result.id] = result for (const subscriber of this.subscribers) { + this.store(result) subscriber(result) } } @@ -27,7 +38,6 @@ export class ResultManager { return model.constructor.name === 'JoiningSystemResultReadyEventModel' }, (model) => { // Callback - // const model = this.modelManager.createModelFromRead(e) this.addResult(model.Result) }, 'ResultManager subscription of the results' @@ -37,4 +47,29 @@ export class ResultManager { subscribe (func) { this.subscribers.push(func) } + + store (result) { + let classification = 0 + if (result.classification) { + classification = parseInt(result.classification) + } + this.results[classification].push(result) + this.results[-1] = [result] + } + + resultFromId (id, selectType) { + for (const r of this.results[parseInt(selectType)]) { + if (id === r.id) { + return r + } + } + } + + getLatest (resultType) { + return this.results[resultType][this.results[resultType].length - 1] + } + + getResultOfType (resultType) { + return this.results[resultType] + } }