From a5065bd23ea28f069947f4ce887577ca63b4e0b8 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Tue, 23 Jul 2024 21:30:19 +0200 Subject: [PATCH] Fix warnings and errors that can be auto-fixed --- Control/config-default.js | 10 +- Control/index.js | 8 +- .../lib/adapters/EnvironmentInfoAdapter.js | 103 ++++--- .../EnvironmentTransitionResultAdapter.js | 2 +- Control/lib/adapters/RunSummaryAdapter.js | 5 +- Control/lib/adapters/TaskInfoAdapter.js | 3 +- .../external/BookkeepingFilterAdapter.js | 7 +- Control/lib/api.js | 92 +++--- Control/lib/common/cacheKeys.enum.js | 4 +- Control/lib/common/constants.js | 4 +- .../common/environmentTransitionType.enum.js | 2 +- Control/lib/common/kvStore/runtime.enum.js | 6 +- .../common/lock/detectorLockAction.enum.js | 2 +- .../lib/common/lock/detectorLockState.enum.js | 2 +- Control/lib/common/logLevel.enum.js | 6 +- Control/lib/common/role.enum.js | 11 +- .../lib/common/runCalibrationStatus.enum.js | 6 +- Control/lib/common/runDefinition.enum.js | 6 +- Control/lib/common/statusComponents.enum.js | 2 +- Control/lib/config/configProvider.js | 6 +- Control/lib/config/publicConfigProvider.js | 24 +- Control/lib/control-core/ApricotCommands.js | 2 +- Control/lib/control-core/ApricotService.js | 101 ++++--- Control/lib/control-core/ControlService.js | 101 ++++--- Control/lib/control-core/CoreUtils.js | 33 +- Control/lib/control-core/EnvCache.js | 18 +- Control/lib/control-core/GrpcProxy.js | 71 +++-- Control/lib/control-core/RequestHandler.js | 49 ++- Control/lib/controllers/Consul.controller.js | 99 +++--- .../lib/controllers/Environment.controller.js | 62 ++-- Control/lib/controllers/Lock.controller.js | 18 +- Control/lib/controllers/Run.controller.js | 23 +- Control/lib/controllers/Status.controller.js | 35 +-- .../WorkflowTemplate.controller.js | 12 +- Control/lib/dtos/CoreEnvConfig.js | 24 +- Control/lib/dtos/DetectorLock.js | 28 +- Control/lib/dtos/Service.js | 35 +-- Control/lib/dtos/User.js | 34 +-- Control/lib/errors/grpcErrorToNativeError.js | 7 +- .../updateExpressResponseFromNativeError.js | 13 +- .../middleware/lockOwnership.middleware.js | 25 +- .../lib/middleware/minimumRole.middleware.js | 25 +- Control/lib/services/Bookkeeping.service.js | 31 +- Control/lib/services/Broadcast.service.js | 12 +- Control/lib/services/Cache.service.js | 29 +- Control/lib/services/Detector.service.js | 12 +- Control/lib/services/Environment.service.js | 101 ++++--- Control/lib/services/Intervals.service.js | 12 +- Control/lib/services/Lock.service.js | 55 ++-- Control/lib/services/Run.service.js | 53 ++-- Control/lib/services/Status.service.js | 122 ++++---- Control/lib/services/WebSocket.service.js | 10 +- .../lib/services/WorkflowTemplate.service.js | 29 +- .../lib/typedefs/AutoEnvironmentDeployment.js | 39 ++- .../lib/typedefs/CalibrationConfiguration.js | 9 +- Control/lib/typedefs/Detector.js | 9 +- Control/lib/typedefs/DeviceInfo.js | 11 +- Control/lib/typedefs/EnvironmentCreation.js | 1 - Control/lib/typedefs/EnvironmentInfo.js | 33 +- .../typedefs/EnvironmentTransitionResult.js | 9 +- .../lib/typedefs/OdcIntegratedServiceInfo.js | 16 +- Control/lib/typedefs/RunSummary.js | 21 +- Control/lib/typedefs/TaskInfo.js | 17 +- .../lib/typedefs/WorkflowTemplateSource.js | 7 +- Control/lib/utils.js | 33 +- Control/public/Model.js | 50 +-- Control/public/about/About.js | 40 +-- .../panels/servicesInLoadingPanel.js | 9 +- .../panels/servicesResolvedPanel.js | 25 +- .../public/about/components/serviceCard.js | 24 +- Control/public/about/components/serviceRow.js | 14 +- Control/public/about/content.js | 13 +- Control/public/about/header.js | 8 +- Control/public/common/alertPanel.js | 26 +- Control/public/common/appHeader.js | 33 +- .../common/buttons/copyToClipboardIcon.js | 16 +- .../common/buttons/textWithCopyClipboard.js | 9 +- Control/public/common/card/miniCard.js | 44 ++- Control/public/common/card/rowForCard.js | 12 +- Control/public/common/coloredBadge.js | 9 +- .../public/common/constants/serviceStates.js | 4 +- .../public/common/constants/stateColors.js | 4 +- .../common/constants/statusComponents.enum.js | 4 +- Control/public/common/dcs/dcsPropertiesRow.js | 16 +- .../deployEnvironmentButton.component.js | 11 +- Control/public/common/detectorHeader.js | 27 +- .../detectorLock/detectionLockActionButton.js | 27 +- Control/public/common/detectorModal.js | 56 ++-- .../common/enums/DetectorLockAction.enum.js | 2 +- .../common/enums/DetectorLockState.enum.js | 2 +- .../public/common/enums/DetectorState.enum.js | 2 +- .../public/common/enums/HardwareComponent.js | 2 +- Control/public/common/enums/TaskState.js | 5 +- Control/public/common/errorComponent.js | 8 +- Control/public/common/errorPage.js | 8 +- Control/public/common/iframe/iframe.js | 6 +- Control/public/common/loading.js | 31 +- Control/public/common/pageLoading.js | 31 +- Control/public/common/panel/panel.js | 10 +- Control/public/common/panel/panelTitle.js | 6 +- Control/public/common/qcgExternalLink.js | 13 +- Control/public/common/showTableItem.js | 14 +- Control/public/common/sidebar.js | 51 ++-- Control/public/common/userRole.js | 8 +- Control/public/common/utils.js | 69 ++--- Control/public/configuration/ConfigByCru.js | 58 ++-- Control/public/configuration/Configuration.js | 52 ++-- .../components/allLinksCheckBox.js | 79 ++--- .../configuration/components/linkCheckBox.js | 34 +-- .../components/userLogicCheckBox.js | 69 +++-- Control/public/configuration/configPage.js | 216 +++++++------ .../public/configuration/configurationPage.js | 285 +++++++++--------- Control/public/environment/Environment.js | 73 ++--- Control/public/environment/Task.js | 12 +- .../public/environment/components/buttons.js | 32 +- .../components/controlEnvironmentPanel.js | 101 +++---- .../components/environmentActionPanel.js | 16 +- .../components/environmentHeader.js | 16 +- .../components/environmentNavigationTabs.js | 209 ++++++------- .../environmentTasksSummaryTable.js | 49 ++- .../components/expandableEnvRows.js | 103 +++---- .../components/monitoringRunningPlotsPanel.js | 22 +- Control/public/environment/environmentPage.js | 30 +- .../public/environment/environmentsPage.js | 205 +++++++------ Control/public/hardware/hardwarePage.js | 50 ++- Control/public/index.js | 7 +- Control/public/lock/Lock.js | 30 +- Control/public/lock/lockButton.js | 17 +- Control/public/lock/lockPage.js | 108 +++---- .../CalibrationRuns/CalibrationRuns.model.js | 29 +- .../CalibrationRuns/CalibrationRuns.page.js | 16 +- .../components/calibrationActionCard.js | 86 +++--- .../calibrationRefreshContentButton.js | 19 +- .../components/calibrationRunCard.js | 24 +- .../components/calibrationRunCardHeader.js | 13 +- .../components/calibrationRunGroups.js | 36 +-- .../components/calibrationRunsContent.js | 12 +- .../EnvironmentCreation.model.js | 55 ++-- .../EnvironmentCreation.page.js | 38 +-- .../components/workflowMappings.component.js | 42 ++- .../components/workflowTemplate.component.js | 11 +- Control/public/services/DetectorService.js | 75 ++--- Control/public/task/Task.js | 39 +-- Control/public/task/content.js | 158 +++++----- Control/public/task/header.js | 14 +- .../public/typedefs/DetectorAvailability.js | 5 +- Control/public/typedefs/Service.js | 1 - .../utilities/currentPageAndParameters.js | 2 +- Control/public/utilities/jsonDelete.js | 14 +- Control/public/utilities/jsonFetch.js | 19 +- Control/public/utilities/jsonPut.js | 14 +- Control/public/view.js | 57 ++-- Control/public/workflow/Workflow.js | 179 +++++------ Control/public/workflow/WorkflowForm.js | 21 +- Control/public/workflow/constants.js | 20 +- .../workflow/panels/flps/FlpSelection.js | 56 ++-- .../workflow/panels/flps/detectorsPanel.js | 70 ++--- .../workflow/panels/flps/flpSelectionPanel.js | 76 +++-- .../loadConfiguration/loadConfiguration.js | 140 ++++----- .../workflow/panels/revision/revisionPanel.js | 57 ++-- .../panels/variables/WorkflowVariable.js | 65 ++-- .../panels/variables/advancedPanel.js | 96 +++--- .../workflow/panels/variables/basicPanel.js | 249 ++++++++------- .../workflow/panels/variables/components.js | 182 ++++++----- .../workflow/panels/variables/mainPanel.js | 94 +++--- Control/public/workflow/workflowsPage.js | 158 +++++----- 166 files changed, 3300 insertions(+), 3361 deletions(-) diff --git a/Control/config-default.js b/Control/config-default.js index a17a36097..befcc14ff 100644 --- a/Control/config-default.js +++ b/Control/config-default.js @@ -6,7 +6,7 @@ module.exports = { // key: './cert/key.pem', // cert: './cert/cert.pem', tls: false, - limit: '1Mb' + limit: '1Mb', }, grpc: { hostname: 'localhost', @@ -14,7 +14,7 @@ module.exports = { timeout: 20000, // ms, gRPC deadline for service calls maxMessageLength: 50, // MB, gRPC receive message limit label: 'Control', - package: 'o2control' + package: 'o2control', }, apricot: { hostname: 'localhost', @@ -22,10 +22,10 @@ module.exports = { timeout: 20000, // ms, gRPC deadline for service calls maxMessageLength: 50, // MB, gRPC receive message limit label: 'Apricot', - package: 'apricot' + package: 'apricot', }, grafana: { - url: 'http://localhost:3000' + url: 'http://localhost:3000', }, bookkeeping: { url: 'http://localhost:4000', @@ -51,7 +51,7 @@ module.exports = { url: 'localhost:8083', }, qcGui: { - url: 'qcg.cern.ch' + url: 'qcg.cern.ch', }, utils: { refreshTask: 10000, // how often should task list page should refresh its content diff --git a/Control/index.js b/Control/index.js index 05c0d798e..d2528a7da 100644 --- a/Control/index.js +++ b/Control/index.js @@ -10,20 +10,20 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const path = require('path'); -const {HttpServer, WebSocket} = require('@aliceo2/web-ui'); +const { HttpServer, WebSocket } = require('@aliceo2/web-ui'); const config = require('./lib/config/configProvider.js'); -const {buildPublicConfig} = require('./lib/config/publicConfigProvider.js'); +const { buildPublicConfig } = require('./lib/config/publicConfigProvider.js'); const api = require('./lib/api.js'); // ------------------------------------------------------- buildPublicConfig(config); -config.http.iframeCsp = (config?.grafana?.url) ? [ config.grafana.url ] : []; +config.http.iframeCsp = config?.grafana?.url ? [config.grafana.url] : []; const http = new HttpServer(config.http, config.jwt, config.openId); const ws = new WebSocket(http); http.addStaticPath(path.join(__dirname, 'public')); diff --git a/Control/lib/adapters/EnvironmentInfoAdapter.js b/Control/lib/adapters/EnvironmentInfoAdapter.js index 6a276bc35..546ca445f 100644 --- a/Control/lib/adapters/EnvironmentInfoAdapter.js +++ b/Control/lib/adapters/EnvironmentInfoAdapter.js @@ -11,20 +11,21 @@ * or submit itself to any jurisdiction. */ -const {TaskState} = require('./../common/taskState.enum.js'); +const { TaskState } = require('./../common/taskState.enum.js'); + const QC_NODES_NAME_REGEX = /alio2-cr1-q(c|me|ts)[0-9]{2}/; /** * Enum with potential sources of tasks for AliECS environment * @readonly - * @enum {String} + * @enum {string} */ const TASKS_SOURCE = { EPN: 'EPN', FLP: 'FLP', TRG: 'TRG', QC: 'QC', -} +}; /** * EnvironmentInfoAdapter - Given an AliECS Environment, construct an EnvironmentInfo object for GUI purposes @@ -38,10 +39,10 @@ class EnvironmentInfoAdapter { /** * Converts the given proto object (o2control.proto) to an entity overview object. - * * @param {EnvironmentInfoProto} protoObject - object to convert - * @param {Array} detectorsAll - list of all detectors in the current AliECS deployment - * @param {Map>} hostsByDetector - object with list of hosts grouped by detector + * @param environment + * @param {Array} detectorsAll - list of all detectors in the current AliECS deployment + * @param {Map>} hostsByDetector - object with list of hosts grouped by detector * @returns {EnvironmentInfo} entity of environment with needed information */ static toOverviewEntity(environment, detectorsAll, hostsByDetector) { @@ -93,31 +94,29 @@ class EnvironmentInfoAdapter { /** * Method to build an environment info with tasks from specified source * @param {EnvironmentInfoProto} environment - environment as from AliECS - * @param {String} taskSource - source of tasks - * @param {Array} detectorsAll - list of all detectors in the current AliECS deployment - * @param {Map>} hostsByDetectors - object with list of hosts grouped by detector + * @param {string} taskSource - source of tasks + * @param {Array} detectorsAll - list of all detectors in the current AliECS deployment + * @param {Map>} hostsByDetectors - object with list of hosts grouped by detector */ static toEntity(environment, taskSource = '', detectorsAll, hostsByDetectors) { taskSource = taskSource.toLocaleUpperCase(); const environmentInfo = EnvironmentInfoAdapter.toOverviewEntity(environment, detectorsAll, hostsByDetectors); if (taskSource === TASKS_SOURCE.EPN) { - const {integratedServicesData: {odc = '{}'}} = environment; - const {devices = []} = JSON.parse(odc); + const { integratedServicesData: { odc = '{}' } } = environment; + const { devices = [] } = JSON.parse(odc); - environmentInfo.tasks = Array.from( - Object.values(devices).map((device) => { - device.epnState = device.state; - device.state = device.ecsState; - delete device.ecsState; - return device; - }) - ); + environmentInfo.tasks = Array.from(Object.values(devices).map((device) => { + device.epnState = device.state; + device.state = device.ecsState; + delete device.ecsState; + return device; + })); } else if (taskSource === TASKS_SOURCE.FLP) { - const {tasks = [], includedDetectors} = environment; + const { tasks = [], includedDetectors } = environment; environmentInfo.tasks = []; for (const task of tasks) { - const {deploymentInfo: {hostname = ''} = {}} = task; + const { deploymentInfo: { hostname = '' } = {} } = task; const keyDetector = Object.keys(Object.fromEntries(hostsByDetectors)) .filter((detector) => hostsByDetectors.get(detector).includes(hostname))[0]; if (!hostname.match(QC_NODES_NAME_REGEX) && includedDetectors.includes(keyDetector)) { @@ -125,19 +124,19 @@ class EnvironmentInfoAdapter { } } } else if (taskSource === TASKS_SOURCE.QC) { - const {tasks = []} = environment; + const { tasks = [] } = environment; environmentInfo.tasks = []; for (const task of tasks) { - const {deploymentInfo: {hostname = ''} = {}} = task; + const { deploymentInfo: { hostname = '' } = {} } = task; if (hostname.match(QC_NODES_NAME_REGEX)) { environmentInfo.tasks.push(task); } } } else if (taskSource === TASKS_SOURCE.TRG) { - const {tasks = [], includedDetectors} = environment; + const { tasks = [], includedDetectors } = environment; environmentInfo.tasks = []; for (const task of tasks) { - const {deploymentInfo: {hostname = ''} = {}} = task; + const { deploymentInfo: { hostname = '' } = {} } = task; const keyDetector = Object.keys(Object.fromEntries(hostsByDetectors)) .filter((detector) => hostsByDetectors.get(detector).includes(hostname))[0]; if (!hostname.match(QC_NODES_NAME_REGEX) && !includedDetectors.includes(keyDetector)) { @@ -151,7 +150,7 @@ class EnvironmentInfoAdapter { /** * Given an environment, group its tasks by the 3 main categories: FLP, QC Nodes and CTP Readout * @param {EnvironmentInfo} environment - DTO representing an environment - * @param {Map>} hostsByDetectors - hosts grouped by the detectors + * @param {Map>} hostsByDetectors - hosts grouped by the detectors * @returns {object{tasks: Array, hosts: Set}} - Object with groups of tasks and set of unique hosts */ static _getHardwareCountersPerComponent(environment, hostsByDetectors) { @@ -171,11 +170,11 @@ class EnvironmentInfoAdapter { const trgStates = {}; const trgStatuses = {}; - const {tasks = [], includedDetectors = []} = environment; + const { tasks = [], includedDetectors = [] } = environment; for (const task of tasks) { - const {critical = false, status = 'NOT-KNOWN', deploymentInfo: {hostname = ''} = {}} = task; - let {state = TaskState.UNKNOWN} = task; + const { critical = false, status = 'NOT-KNOWN', deploymentInfo: { hostname = '' } = {} } = task; + let { state = TaskState.UNKNOWN } = task; if (state === TaskState.ERROR && critical) { state = TaskState.ERROR_CRITICAL; @@ -183,19 +182,19 @@ class EnvironmentInfoAdapter { if (hostname.match(QC_NODES_NAME_REGEX)) { qcTasksTotal++; - qcStates[state] = (qcStates[state] + 1) || 1; - qcStatuses[status] = (qcStatuses[status] + 1) || 1; + qcStates[state] = qcStates[state] + 1 || 1; + qcStatuses[status] = qcStatuses[status] + 1 || 1; qcHosts.add(hostname); } else { - const {userVars: {ctp_readout_enabled = 'false'} = {}} = environment; + const { userVars: { ctp_readout_enabled = 'false' } = {} } = environment; const isReadoutEnabled = ctp_readout_enabled === 'true'; const keyDetector = Object.keys(Object.fromEntries(hostsByDetectors)) .filter((detector) => hostsByDetectors.get(detector).includes(hostname))[0]; if (includedDetectors.includes(keyDetector)) { flpTasksTotal++; - flpStates[state] = (flpStates[state] + 1) || 1; - flpStatuses[status] = (flpStatuses[status] + 1) || 1; + flpStates[state] = flpStates[state] + 1 || 1; + flpStatuses[status] = flpStatuses[status] + 1 || 1; if (!flpDetectors[keyDetector]) { flpDetectors[keyDetector] = { total: 0, @@ -204,14 +203,14 @@ class EnvironmentInfoAdapter { }; } flpDetectors[keyDetector].total++; - flpDetectors[keyDetector].states[state] = (flpDetectors[keyDetector].states[state] + 1) || 1; - flpDetectors[keyDetector].statuses[status] = (flpDetectors[keyDetector].statuses[status] + 1) || 1; + flpDetectors[keyDetector].states[state] = flpDetectors[keyDetector].states[state] + 1 || 1; + flpDetectors[keyDetector].statuses[status] = flpDetectors[keyDetector].statuses[status] + 1 || 1; flpHosts.add(hostname); } else if (isReadoutEnabled) { trgTasksTotal++; - trgStates[state] = (trgStates[state] + 1) || 1; - trgStatuses[status] = (trgStatuses[status] + 1) || 1; + trgStates[state] = trgStates[state] + 1 || 1; + trgStatuses[status] = trgStatuses[status] + 1 || 1; trgHosts.add(hostname); } } @@ -234,42 +233,44 @@ class EnvironmentInfoAdapter { }, hosts: flpHosts.size, detectorCounters: flpDetectors, - }, trg: { + }, + trg: { tasks: { total: trgTasksTotal, states: trgStates, statuses: trgStatuses, }, hosts: trgHosts.size, - } + }, }; } /** * Prepare an ODC object with hardware information based - * @param {Map} integratedServicesData - object with details of the integrated services + * @param {Map} integratedServicesData - object with details of the integrated services + * @param odc */ static _getOdcCounters(odc = {}) { try { /** * @type {Array} devices */ - const {devices = [], ddsSessionId = '', ddsSessionStatus = '', state = ''} = JSON.parse(odc); + const { devices = [], ddsSessionId = '', ddsSessionStatus = '', state = '' } = JSON.parse(odc); const states = {}; const hosts = new Set(); Object.values(devices).forEach((device) => { - const {ecsState, host} = device; + const { ecsState, host } = device; hosts.add(host); - states[ecsState] = (states[ecsState] + 1) || 1; + states[ecsState] = states[ecsState] + 1 || 1; }); return { tasks: { total: Object.keys(devices).length, - states + states, }, hosts: hosts.size, - info: {ddsSessionId, ddsSessionStatus, state} + info: { ddsSessionId, ddsSessionStatus, state }, }; } catch (error) { return { @@ -278,7 +279,7 @@ class EnvironmentInfoAdapter { states: {}, }, hosts: 0, - info: {ddsSessionId: '-', ddsSessionStatus: '-', state: '-'} + info: { ddsSessionId: '-', ddsSessionStatus: '-', state: '-' }, }; } } @@ -289,18 +290,20 @@ class EnvironmentInfoAdapter { * * remove any variables that are a detector variable but are not part of the included detector * @param {JSON} objectToFilterFrom - object from which var * @param {string} label - * @return {JSON} + * @param includedDetectors + * @param detectors + * @returns {JSON} */ static _filterOutDetectorsVariables(objectToFilterFrom, includedDetectors, detectors) { const data = JSON.parse(JSON.stringify(objectToFilterFrom)); for (const key of Object.keys(data)) { const prefixUpper = key.split('_')[0].toLocaleUpperCase(); const isVariableDetector = - detectors.findIndex((det) => det.toLocaleUpperCase() === prefixUpper) !== -1 + detectors.findIndex((det) => det.toLocaleUpperCase() === prefixUpper) !== -1; const isVariableIncludedDetector = includedDetectors.findIndex((det) => det.toLocaleUpperCase() === prefixUpper) !== -1; if (isVariableDetector && !isVariableIncludedDetector) { - delete data[key] + delete data[key]; } } return data; diff --git a/Control/lib/adapters/EnvironmentTransitionResultAdapter.js b/Control/lib/adapters/EnvironmentTransitionResultAdapter.js index 4a84c08b4..d7f286f75 100644 --- a/Control/lib/adapters/EnvironmentTransitionResultAdapter.js +++ b/Control/lib/adapters/EnvironmentTransitionResultAdapter.js @@ -25,7 +25,7 @@ class EnvironmentTransitionResultAdapter { * Converts the given object to an entity object. * @static * @param {ControlEnvironmentReply} transitionResult - as from AliECS - * @return {EnvironmentTransitionResult} information on the transition result of the environment + * @returns {EnvironmentTransitionResult} information on the transition result of the environment */ static toEntity(transitionResult) { const { diff --git a/Control/lib/adapters/RunSummaryAdapter.js b/Control/lib/adapters/RunSummaryAdapter.js index 9e8cfb419..9def64821 100644 --- a/Control/lib/adapters/RunSummaryAdapter.js +++ b/Control/lib/adapters/RunSummaryAdapter.js @@ -23,8 +23,7 @@ class RunSummaryAdapter { /** * Converts the given object to an entity object. - * - * @param {Object} run - Run Entity as per Bookkeeping https://github.com/AliceO2Group/Bookkeeping/blob/main/lib/domain/entities/Run.js + * @param {object} run - Run Entity as per Bookkeeping https://github.com/AliceO2Group/Bookkeeping/blob/main/lib/domain/entities/Run.js * @returns {RunSummary} entity of a task with needed information */ static toEntity(run) { @@ -40,7 +39,7 @@ class RunSummaryAdapter { endTime, } = run; - let {detectors = []} = run; + let { detectors = [] } = run; if (typeof detectors === 'string') { detectors = detectors.split(','); } diff --git a/Control/lib/adapters/TaskInfoAdapter.js b/Control/lib/adapters/TaskInfoAdapter.js index 18150f260..19820a333 100644 --- a/Control/lib/adapters/TaskInfoAdapter.js +++ b/Control/lib/adapters/TaskInfoAdapter.js @@ -22,7 +22,6 @@ class TaskInfoAdapter { /** * Converts the given proto object (o2control.proto) to an entity object. - * * @param {TaskInfoProto} task - object to convert * @returns {TaskInfo} entity of a task with needed information */ @@ -62,7 +61,7 @@ class TaskInfoAdapter { * @returns {string} short name of the task */ static getShortName(taskName) { - const regex = new RegExp(`tasks/.*@`); + const regex = new RegExp('tasks/.*@'); const matchedTaskName = taskName.match(regex); if (matchedTaskName) { taskName = matchedTaskName[0].replace('tasks/', '').replace('@', ''); diff --git a/Control/lib/adapters/external/BookkeepingFilterAdapter.js b/Control/lib/adapters/external/BookkeepingFilterAdapter.js index 620cbe1fc..d03899c6c 100644 --- a/Control/lib/adapters/external/BookkeepingFilterAdapter.js +++ b/Control/lib/adapters/external/BookkeepingFilterAdapter.js @@ -16,9 +16,8 @@ * BookkeepingFilterAdapter - Class that allows adapting given objects to string filters as accepted by Bookkeeping HTTP API */ class BookkeepingFilterAdapter { - /** - * @constructor + * @class * BookkeepingFilterAdapter */ constructor() { } @@ -32,7 +31,7 @@ class BookkeepingFilterAdapter { * @return {String} - as understood by Bookkeeping HTTP API */ static toString(filterMap) { - const {detectors, runTypes, definitions, calibrationStatuses, limit = 1} = filterMap; + const { detectors, runTypes, definitions, calibrationStatuses, limit = 1 } = filterMap; let filter = `page[limit]=${limit}`; if (detectors) { @@ -80,7 +79,7 @@ class BookkeepingFilterAdapter { } else if (Array.isArray(value) && value.length > 0) { return value.join(','); } else if (typeof value === 'number') { - return new String(value) + return new String(value); } return null; } diff --git a/Control/lib/api.js b/Control/lib/api.js index 6773da5c5..180e5d2d4 100644 --- a/Control/lib/api.js +++ b/Control/lib/api.js @@ -10,38 +10,38 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const log = new (require('@aliceo2/web-ui').Log)(`${process.env.npm_config_log_label ?? 'cog'}/api`); const config = require('./config/configProvider.js'); // middleware -const {minimumRoleMiddleware} = require('./middleware/minimumRole.middleware.js'); -const {lockOwnershipMiddleware} = require('./middleware/lockOwnership.middleware.js'); +const { minimumRoleMiddleware } = require('./middleware/minimumRole.middleware.js'); +const { lockOwnershipMiddleware } = require('./middleware/lockOwnership.middleware.js'); // controllers -const {ConsulController} = require('./controllers/Consul.controller.js'); -const {EnvironmentController} = require('./controllers/Environment.controller.js'); -const {LockController} = require('./controllers/Lock.controller.js'); -const {RunController} = require('./controllers/Run.controller.js'); -const {StatusController} = require('./controllers/Status.controller.js'); -const {WebSocketService} = require('./services/WebSocket.service.js'); -const {WorkflowTemplateController} = require('./controllers/WorkflowTemplate.controller.js'); +const { ConsulController } = require('./controllers/Consul.controller.js'); +const { EnvironmentController } = require('./controllers/Environment.controller.js'); +const { LockController } = require('./controllers/Lock.controller.js'); +const { RunController } = require('./controllers/Run.controller.js'); +const { StatusController } = require('./controllers/Status.controller.js'); +const { WebSocketService } = require('./services/WebSocket.service.js'); +const { WorkflowTemplateController } = require('./controllers/WorkflowTemplate.controller.js'); // local services -const {BookkeepingService} = require('./services/Bookkeeping.service.js'); -const {BroadcastService} = require('./services/Broadcast.service.js'); -const {CacheService} = require('./services/Cache.service.js'); -const {DetectorService} = require('./services/Detector.service.js'); -const {EnvironmentService} = require('./services/Environment.service.js'); -const {Intervals} = require('./services/Intervals.service.js'); -const {LockService} = require('./services/Lock.service.js'); -const {RunService} = require('./services/Run.service.js'); -const {StatusService} = require('./services/Status.service.js'); -const {WorkflowTemplateService} = require('./services/WorkflowTemplate.service.js'); +const { BookkeepingService } = require('./services/Bookkeeping.service.js'); +const { BroadcastService } = require('./services/Broadcast.service.js'); +const { CacheService } = require('./services/Cache.service.js'); +const { DetectorService } = require('./services/Detector.service.js'); +const { EnvironmentService } = require('./services/Environment.service.js'); +const { Intervals } = require('./services/Intervals.service.js'); +const { LockService } = require('./services/Lock.service.js'); +const { RunService } = require('./services/Run.service.js'); +const { StatusService } = require('./services/Status.service.js'); +const { WorkflowTemplateService } = require('./services/WorkflowTemplate.service.js'); // web-ui services -const {NotificationService, ConsulService} = require('@aliceo2/web-ui'); +const { NotificationService, ConsulService } = require('@aliceo2/web-ui'); // AliECS Core const AliecsRequestHandler = require('./control-core/RequestHandler.js'); @@ -51,10 +51,11 @@ const EnvCache = require('./control-core/EnvCache.js'); const GrpcProxy = require('./control-core/GrpcProxy.js'); const path = require('path'); + const O2_CONTROL_PROTO_PATH = path.join(__dirname, './../protobuf/o2control.proto'); const O2_APRICOT_PROTO_PATH = path.join(__dirname, './../protobuf/o2apricot.proto'); -const {Role} = require('./common/role.enum.js'); +const { Role } = require('./common/role.enum.js'); if (!config.grpc) { throw new Error('Control gRPC Configuration is missing'); @@ -67,7 +68,6 @@ if (!config.grafana) { } module.exports.setup = (http, ws) => { - let consulService; if (config.consul) { consulService = new ConsulService(config.consul); @@ -112,9 +112,7 @@ module.exports.setup = (http, ws) => { notificationService.proxyWebNotificationToWs(ws); } - const statusService = new StatusService( - config, ctrlService, consulService, apricotService, notificationService, wsService - ); + const statusService = new StatusService(config, ctrlService, consulService, apricotService, notificationService, wsService); const statusController = new StatusController(statusService); const intervals = new Intervals(); @@ -122,13 +120,9 @@ module.exports.setup = (http, ws) => { initializeData(apricotService, lockService); initializeIntervals(intervals, statusService, runService, bkpService); - const coreMiddleware = [ - ctrlService.isConnectionReady.bind(ctrlService), - ]; + const coreMiddleware = [ctrlService.isConnectionReady.bind(ctrlService)]; - ctrlProxy.methods.forEach( - (method) => http.post(`/${method}`, coreMiddleware, (req, res) => ctrlService.executeCommand(req, res)) - ); + ctrlProxy.methods.forEach((method) => http.post(`/${method}`, coreMiddleware, (req, res) => ctrlService.executeCommand(req, res))); http.post('/core/request', coreMiddleware, (req, res) => aliecsReqHandler.add(req, res)); http.get('/core/requests', coreMiddleware, (req, res) => aliecsReqHandler.getAll(req, res)); http.post('/core/removeRequest/:id', coreMiddleware, (req, res) => aliecsReqHandler.remove(req, res)); @@ -137,29 +131,26 @@ module.exports.setup = (http, ws) => { http.get('/workflow/template/mappings', workflowController.getWorkflowMapping.bind(workflowController)); http.get('/workflow/configuration', workflowController.getWorkflowConfiguration.bind(workflowController)); - http.get('/runs/calibration/config', [ - minimumRoleMiddleware(Role.GLOBAL) - ], runController.refreshCalibrationRunsConfigurationHandler.bind(runController)); + http.get('/runs/calibration/config', [minimumRoleMiddleware(Role.GLOBAL)], runController.refreshCalibrationRunsConfigurationHandler.bind(runController)); http.get('/runs/calibration', runController.getCalibrationRunsHandler.bind(runController)); - http.get('/environment/:id/:source?', coreMiddleware, envCtrl.getEnvironmentHandler.bind(envCtrl), {public: true}); + http.get('/environment/:id/:source?', coreMiddleware, envCtrl.getEnvironmentHandler.bind(envCtrl), { public: true }); http.post('/environment/auto', coreMiddleware, envCtrl.newAutoEnvironmentHandler.bind(envCtrl)); http.put('/environment/:id', coreMiddleware, envCtrl.transitionEnvironmentHandler.bind(envCtrl)); - http.delete('/environment/:id', + http.delete( + '/environment/:id', coreMiddleware, minimumRoleMiddleware(Role.DETECTOR), lockOwnershipMiddleware(lockService, envService), - envCtrl.destroyEnvironmentHandler.bind(envCtrl) + envCtrl.destroyEnvironmentHandler.bind(envCtrl), ); - http.get('/core/environments', coreMiddleware, (req, res) => envCache.get(req, res), {public: true}); + http.get('/core/environments', coreMiddleware, (req, res) => envCache.get(req, res), { public: true }); http.post('/core/environments/configuration/save', (req, res) => apricotService.saveCoreEnvConfig(req, res)); http.post('/core/environments/configuration/update', (req, res) => apricotService.updateCoreEnvConfig(req, res)); - apricotProxy.methods.forEach( - (method) => http.post(`/${method}`, (req, res) => apricotService.executeCommand(req, res)) - ); + apricotProxy.methods.forEach((method) => http.post(`/${method}`, (req, res) => apricotService.executeCommand(req, res))); http.get('/core/detectors', (req, res) => apricotService.getDetectorList(req, res)); http.get('/core/hostsByDetectors', (req, res) => apricotService.getHostsByDetectorList(req, res)); @@ -169,21 +160,21 @@ module.exports.setup = (http, ws) => { // Lock Service http.get('/locks', lockController.getLocksStateHandler.bind(lockController)); http.put('/locks/:action/:detectorId', lockController.actionLockHandler.bind(lockController)); - http.put('/locks/force/:action/:detectorId', + http.put( + '/locks/force/:action/:detectorId', minimumRoleMiddleware(Role.GLOBAL), - lockController.actionForceLockHandler.bind(lockController)); + lockController.actionForceLockHandler.bind(lockController), + ); // Status Service http.get('/status/consul', statusController.getConsulStatus.bind(statusController)); http.get('/status/grafana', statusController.getGrafanaStatus.bind(statusController)); http.get('/status/notification', statusController.getNotificationSystemStatus.bind(statusController)); - http.get('/status/gui', statusController.getGuiStatus.bind(statusController), {public: true}); + http.get('/status/gui', statusController.getGuiStatus.bind(statusController), { public: true }); http.get('/status/apricot', statusController.getApricotStatus.bind(statusController)); http.get('/status/core', coreMiddleware[0], statusController.getAliECSStatus.bind(statusController)); http.get('/status/system', statusController.getSystemCompatibility.bind(statusController)); - http.get('/status/core/services', coreMiddleware[0], - statusController.getAliECSIntegratedServicesStatus.bind(statusController) - ); + http.get('/status/core/services', coreMiddleware[0], statusController.getAliECSIntegratedServicesStatus.bind(statusController)); // Consul const validateService = consulController.validateService.bind(consulController); @@ -200,7 +191,7 @@ module.exports.setup = (http, ws) => { * @param {StatusService} statusService - service used for retrieving status on dependent services * @param {RunService} runService - service for retrieving and building information on runs * @param {BookkeepingService} bkpService - service for retrieving information on runs from Bookkeeping - * @return {void} + * @returns {void} */ function initializeIntervals(intervalsService, statusService, runService, bkpService) { const SERVICES_REFRESH_RATE = 10000; @@ -214,11 +205,10 @@ function initializeIntervals(intervalsService, statusService, runService, bkpSer intervalsService.register(statusService.retrieveNotificationSystemStatus.bind(statusService), SERVICES_REFRESH_RATE); intervalsService.register(statusService.retrieveAliECSIntegratedInfo.bind(statusService), SERVICES_REFRESH_RATE); - if (config.bookkeeping) { intervalsService.register( runService.retrieveCalibrationRunsGroupedByDetector.bind(runService), - CALIBRATION_RUNS_REFRESH_RATE + CALIBRATION_RUNS_REFRESH_RATE, ); } } diff --git a/Control/lib/common/cacheKeys.enum.js b/Control/lib/common/cacheKeys.enum.js index bc0ab1135..bb927371d 100644 --- a/Control/lib/common/cacheKeys.enum.js +++ b/Control/lib/common/cacheKeys.enum.js @@ -10,12 +10,12 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** * Keys that are used to set/get information to/from the CacheService */ -const CacheKeys = Object.freeze({ +const CacheKeys = Object.freeze({ CALIBRATION_RUNS_BY_DETECTOR: 'CALIBRATION_RUNS_BY_DETECTOR', CALIBRATION_RUNS_REQUESTS: 'CALIBRATION_RUNS_REQUESTS', }); diff --git a/Control/lib/common/constants.js b/Control/lib/common/constants.js index 2d5aa72ff..cfed0d8ca 100644 --- a/Control/lib/common/constants.js +++ b/Control/lib/common/constants.js @@ -10,10 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const SERVICES = { STATUS: 'STATUS', -} +}; exports.SERVICES = SERVICES; diff --git a/Control/lib/common/environmentTransitionType.enum.js b/Control/lib/common/environmentTransitionType.enum.js index bb96ed11b..e08255161 100644 --- a/Control/lib/common/environmentTransitionType.enum.js +++ b/Control/lib/common/environmentTransitionType.enum.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** * Available environment transitions as per: https://github.com/AliceO2Group/Control/blob/master/core/protos/o2control.proto#L228 diff --git a/Control/lib/common/kvStore/runtime.enum.js b/Control/lib/common/kvStore/runtime.enum.js index 293d76811..f8e5c272d 100644 --- a/Control/lib/common/kvStore/runtime.enum.js +++ b/Control/lib/common/kvStore/runtime.enum.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const RUNTIME_COMPONENT = Object.freeze({ PDP_VERSION: 'aliecs/defaults', @@ -22,7 +22,7 @@ const RUNTIME_KEY = Object.freeze({ FLP_VERSION: 'flp_suite_version', PDP_VERSION: 'pdp_o2pdpsuite_version', CALIBRATION_MAPPING: 'calibration-mappings', - RUN_TYPE_TO_HOST_MAPPING: 'runType-to-host-mapping' + RUN_TYPE_TO_HOST_MAPPING: 'runType-to-host-mapping', }); -module.exports = {RUNTIME_COMPONENT, RUNTIME_KEY}; +module.exports = { RUNTIME_COMPONENT, RUNTIME_KEY }; diff --git a/Control/lib/common/lock/detectorLockAction.enum.js b/Control/lib/common/lock/detectorLockAction.enum.js index f1b4991be..083493af2 100644 --- a/Control/lib/common/lock/detectorLockAction.enum.js +++ b/Control/lib/common/lock/detectorLockAction.enum.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** * Available lock actions for users diff --git a/Control/lib/common/lock/detectorLockState.enum.js b/Control/lib/common/lock/detectorLockState.enum.js index 2da12144c..e43f370b3 100644 --- a/Control/lib/common/lock/detectorLockState.enum.js +++ b/Control/lib/common/lock/detectorLockState.enum.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** * Available lock states diff --git a/Control/lib/common/logLevel.enum.js b/Control/lib/common/logLevel.enum.js index c9e6c1cd9..9437bb510 100644 --- a/Control/lib/common/logLevel.enum.js +++ b/Control/lib/common/logLevel.enum.js @@ -10,16 +10,16 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** - * Levels are defined as per InfoLogger API: https://github.com/AliceO2Group/InfoLogger/blob/master/doc/README.md#api-for-developers + * Levels are defined as per InfoLogger API: https://github.com/AliceO2Group/InfoLogger/blob/master/doc/README.md#api-for-developers */ const LOG_LEVEL = Object.freeze({ OPERATIONS: 5, SUPPORT: 10, DEVELOPER: 20, - TRACE: 99 + TRACE: 99, }); exports.LOG_LEVEL = LOG_LEVEL; diff --git a/Control/lib/common/role.enum.js b/Control/lib/common/role.enum.js index 04561fb6b..617d8d2b8 100644 --- a/Control/lib/common/role.enum.js +++ b/Control/lib/common/role.enum.js @@ -10,21 +10,21 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const Role = Object.freeze({ ADMIN: 1, GLOBAL: 10, DETECTOR: 30, // roles for this level will be in format of `det-` e.g. `det-its` DEFAULT_ROLE: 50, - GUEST: 100 + GUEST: 100, }); /** * Method to check if the provided access as per WebUI server is stronger than the minimum required role - * @param {String} roleName - admin, global, det-, guest + * @param {string} roleName - admin, global, det-, guest * @param {Role} minimumRole - minimum role that user should have - * @return {Boolean} + * @returns {boolean} */ const isRoleSufficient = (roleName, minimumRole) => { const roleInUpperCase = roleName.toLocaleUpperCase(); @@ -40,7 +40,8 @@ const isRoleSufficient = (roleName, minimumRole) => { role = Role[roleInUpperCase]; } return role <= minimumRole; -} +}; exports.Role = Role; + exports.isRoleSufficient = isRoleSufficient; diff --git a/Control/lib/common/runCalibrationStatus.enum.js b/Control/lib/common/runCalibrationStatus.enum.js index edc958928..1fca8e5a2 100644 --- a/Control/lib/common/runCalibrationStatus.enum.js +++ b/Control/lib/common/runCalibrationStatus.enum.js @@ -10,15 +10,15 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** - * Run Definitions as per Bookkeeping's implementation: https://github.com/AliceO2Group/Bookkeeping/blob/main/docs/RUN_DEFINITIONS.md + * Run Definitions as per Bookkeeping's implementation: https://github.com/AliceO2Group/Bookkeeping/blob/main/docs/RUN_DEFINITIONS.md */ const RunCalibrationStatus = Object.freeze({ SUCCESS: 'SUCCESS', NO_STATUS: 'NO STATUS', - FAILED: 'FAILED' + FAILED: 'FAILED', }); exports.RunCalibrationStatus = RunCalibrationStatus; diff --git a/Control/lib/common/runDefinition.enum.js b/Control/lib/common/runDefinition.enum.js index 1948b1f41..7fbc3b2db 100644 --- a/Control/lib/common/runDefinition.enum.js +++ b/Control/lib/common/runDefinition.enum.js @@ -10,13 +10,13 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** - * Run Definitions as per Bookkeeping's implementation: https://github.com/AliceO2Group/Bookkeeping/blob/main/docs/RUN_DEFINITIONS.md + * Run Definitions as per Bookkeeping's implementation: https://github.com/AliceO2Group/Bookkeeping/blob/main/docs/RUN_DEFINITIONS.md */ const RunDefinitions = Object.freeze({ - CALIBRATION: 'CALIBRATION' + CALIBRATION: 'CALIBRATION', }); exports.RunDefinitions = RunDefinitions; diff --git a/Control/lib/common/statusComponents.enum.js b/Control/lib/common/statusComponents.enum.js index 7c2cc06b8..efa1d5cd0 100644 --- a/Control/lib/common/statusComponents.enum.js +++ b/Control/lib/common/statusComponents.enum.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const STATUS_COMPONENTS_KEYS = Object.freeze({ CONSUL_KEY: 'CONSUL', diff --git a/Control/lib/config/configProvider.js b/Control/lib/config/configProvider.js index 9be7fda11..d97589ffa 100644 --- a/Control/lib/config/configProvider.js +++ b/Control/lib/config/configProvider.js @@ -10,9 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ + +const { Log } = require('@aliceo2/web-ui'); -const {Log} = require('@aliceo2/web-ui'); const log = new Log(`${process.env.npm_config_log_label ?? 'cog'}/config`); const fs = require('fs'); @@ -39,6 +40,7 @@ try { } const config = require(configFile); + Log.configure(config.logging); log.info(`Read config file "${configFile}"`); diff --git a/Control/lib/config/publicConfigProvider.js b/Control/lib/config/publicConfigProvider.js index e85edafa9..4601c2312 100644 --- a/Control/lib/config/publicConfigProvider.js +++ b/Control/lib/config/publicConfigProvider.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const fs = require('fs'); const path = require('path'); @@ -18,7 +18,7 @@ const path = require('path'); /** * Removes (if exists) and creates a new config file which is to be sent to the client side for fixed configurations * The configuration file is based on `config.js` file - * @param {JSON} config + * @param {JSON} config */ function buildPublicConfig(config) { const publicConfigPath = path.join(__dirname, './../../public/config.js'); @@ -35,7 +35,7 @@ function buildPublicConfig(config) { CONSUL: getConsulConfig(config), REFRESH_TASK: config?.utils?.refreshTask || 10000, }; - let codeStr = `/* eslint-disable quote-props */\n` + const codeStr = '/* eslint-disable quote-props */\n' + `const publicConfig = ${JSON.stringify(publicConfig, null, 2)}; \nexport {publicConfig as COG};\n`; fs.writeFileSync(publicConfigPath, codeStr); } @@ -69,7 +69,7 @@ function getConsulConfig(config) { /** * Create a JSON containing static grafana information * @param {JSON} config - server configuration - * @return {JSON} + * @returns {JSON} */ function _getGrafanaConfig(config) { if (config?.grafana?.url) { @@ -82,10 +82,10 @@ function _getGrafanaConfig(config) { flpStats: `${hostPort}/${ecsDashboard}?panelId=16${theme}`, epnStats: `${hostPort}/${ecsDashboard}?panelId=22${theme}`, readoutPlot: `${hostPort}/${ecsDashboard}?panelId=20${theme}`, - } + }, }; } else { - return {status: false}; + return { status: false }; } } @@ -97,7 +97,7 @@ function _getGrafanaConfig(config) { */ function _getInfoLoggerURL(config) { const ilg = config?.infoLoggerGui; - return (ilg?.url) ? `${ilg.url}` : ''; + return ilg?.url ? `${ilg.url}` : ''; } /** @@ -106,7 +106,7 @@ function _getInfoLoggerURL(config) { */ function _getInfoLoggerEpnUrl(config) { const ilg = config?.infoLoggerEpnGui; - return (ilg?.url) ? `${ilg.url}` : ''; + return ilg?.url ? `${ilg.url}` : ''; } /** @@ -117,7 +117,7 @@ function _getInfoLoggerEpnUrl(config) { */ function _getQcgURL(config) { const qcg = config?.qcGui; - return (qcg?.url) ? `${qcg.url}` : ''; + return qcg?.url ? `${qcg.url}` : ''; } /** @@ -127,10 +127,10 @@ function _getQcgURL(config) { * @returns {string} */ function _getBookkeepingURL(config = {}) { - const {bookkeeping = {}} = config; - return bookkeeping.url ? new URL(bookkeeping.url) : null + const { bookkeeping = {} } = config; + return bookkeeping.url ? new URL(bookkeeping.url) : null; } module.exports = { - buildPublicConfig, _getGrafanaConfig, _getInfoLoggerURL, _getQcgURL, _getBookkeepingURL, getConsulConfig + buildPublicConfig, _getGrafanaConfig, _getInfoLoggerURL, _getQcgURL, _getBookkeepingURL, getConsulConfig, }; diff --git a/Control/lib/control-core/ApricotCommands.js b/Control/lib/control-core/ApricotCommands.js index a691d3a2f..b73c4bda8 100644 --- a/Control/lib/control-core/ApricotCommands.js +++ b/Control/lib/control-core/ApricotCommands.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const APRICOT_COMMANDS = Object.freeze({ ListRuntimeEntries: 'ListRuntimeEntries', diff --git a/Control/lib/control-core/ApricotService.js b/Control/lib/control-core/ApricotService.js index 7ede4c415..0d5114534 100644 --- a/Control/lib/control-core/ApricotService.js +++ b/Control/lib/control-core/ApricotService.js @@ -10,17 +10,20 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const assert = require('assert'); + const log = new (require('@aliceo2/web-ui').Log)(`${process.env.npm_config_log_label ?? 'cog'}/apricotservice`); -const {errorHandler, errorLogger} = require('./../utils.js'); +const { errorHandler, errorLogger } = require('./../utils.js'); const CoreEnvConfig = require('../dtos/CoreEnvConfig.js'); const CoreUtils = require('./CoreUtils.js'); + const COMPONENT = 'COG-v1'; -const {User} = require('./../dtos/User.js'); -const {APRICOT_COMMANDS: {ListRuntimeEntries, GetRuntimeEntry}} = require('./ApricotCommands.js'); -const {LOG_LEVEL} = require('../common/logLevel.enum.js'); +const { User } = require('./../dtos/User.js'); +const { APRICOT_COMMANDS: { ListRuntimeEntries, GetRuntimeEntry } } = require('./ApricotCommands.js'); +const { LOG_LEVEL } = require('../common/logLevel.enum.js'); + const LOG_FACILITY = 'cog/apricotservice'; /** @@ -48,18 +51,16 @@ class ApricotService { log.infoMessage(`Initial data retrieved from AliECS/Apricot: ${this.detectors} detectors`, { level: 99, system: 'GUI', - facility: 'cog/api' + facility: 'cog/api', }); - await Promise.allSettled( - this.detectors.map(async (detector) => { - try { - const {hosts} = await this.apricotProxy['GetHostInventory']({detector}); - this.hostsByDetector.set(detector, hosts); - } catch (error) { - log.error(`Unable to retrieve list of hosts for detector: ${detector}`); - } - }) - ); + await Promise.allSettled(this.detectors.map(async (detector) => { + try { + const { hosts } = await this.apricotProxy['GetHostInventory']({ detector }); + this.hostsByDetector.set(detector, hosts); + } catch (error) { + log.error(`Unable to retrieve list of hosts for detector: ${detector}`); + } + })); } catch (error) { log.error('Unable to list detectors'); } @@ -67,21 +68,21 @@ class ApricotService { /** * Use Apricot defined `o2apricot.proto` `GetRuntimeEntry` to retrieve the value stored in a specified key - * + * * Corner cases for Apricot returns: * * if key(component) does not exist, Apricot wrongly returns code 2 instead of 5 in the gRPC error; * * if key exists but there is no content, Apricot returns '{}' * * if key exists and there is content, Apricot returns content within payload attribute '{payload}' - * @param {String} component - component for which it should query - * @param {String} key - key for which value should be retrieved - * @returns {Promise} - value stored by apricot + * @param {string} component - component for which it should query + * @param {string} key - key for which value should be retrieved + * @returns {Promise} - value stored by apricot */ async getRuntimeEntryByComponent(component, key) { try { - const {payload = '{}'} = await this.apricotProxy[GetRuntimeEntry]({component, key}); + const { payload = '{}' } = await this.apricotProxy[GetRuntimeEntry]({ component, key }); return payload; } catch (error) { - const {code, details = ''} = error; + const { code, details = '' } = error; if (code === 2 && details.includes('nil')) { error.code = 5; } @@ -93,6 +94,7 @@ class ApricotService { * Retrieve an in-memory detectors list * If list does not exist, make a request to Apricot * @param {Request} req + * @param _ * @param {Response} res */ async getDetectorList(_, res) { @@ -104,13 +106,14 @@ class ApricotService { return; } } - res.status(200).json({detectors: this.detectors}); + res.status(200).json({ detectors: this.detectors }); } /** * Return an in-memory map of hosts grouped by their detector * If map is empty, make a request to Apricot * @param {Request} req + * @param _ * @param {Response} res */ async getHostsByDetectorList(_, res) { @@ -118,36 +121,34 @@ class ApricotService { try { this.detectors = (await this.apricotProxy['ListDetectors']()).detectors; - await Promise.allSettled( - this.detectors.map(async (detector) => { - try { - const {hosts} = await this.apricotProxy['GetHostInventory']({detector}); - this.hostsByDetector.set(detector, hosts); - } catch (error) { - log.error(`Unable to retrieve list of hosts for detector: ${detector}`); - log.error(error); - } - }) - ); + await Promise.allSettled(this.detectors.map(async (detector) => { + try { + const { hosts } = await this.apricotProxy['GetHostInventory']({ detector }); + this.hostsByDetector.set(detector, hosts); + } catch (error) { + log.error(`Unable to retrieve list of hosts for detector: ${detector}`); + log.error(error); + } + })); } catch (error) { errorHandler(error, res, 503, 'apricotservice'); return; } } - res.status(200).json({hosts: Object.fromEntries(this.hostsByDetector)}); + res.status(200).json({ hosts: Object.fromEntries(this.hostsByDetector) }); } /** - * Request a list of detectors from Apricot to confirm + * Request a list of detectors from Apricot to confirm * connection and O2Apricot are up - * @return {Promise} + * @returns {Promise} */ async getStatus() { try { if (this.apricotProxy?.isConnectionReady) { await this.apricotProxy['ListDetectors'](); } else { - throw new Error('Unable to check status of Apricot') + throw new Error('Unable to check status of Apricot'); } } catch (error) { log.error(error); @@ -189,21 +190,21 @@ class ApricotService { async saveCoreEnvConfig(req, res) { try { const data = req.body; - const {username, personid} = req.session; - data.user = {username, personid}; + const { username, personid } = req.session; + data.user = { username, personid }; const envConf = CoreEnvConfig.fromJSON(data); - const {payload: configurations} = await this.apricotProxy[ListRuntimeEntries]({component: COMPONENT}); + const { payload: configurations } = await this.apricotProxy[ListRuntimeEntries]({ component: COMPONENT }); if (configurations.includes(envConf.id)) { errorHandler(`A configuration with name '${envConf.id}' already exists. ` + 'Please load existing configuration and use \'Update\'', res, 409, 'apricotservice'); } else { log.infoMessage( `${req.session.username} request to save new core environment configuration "${envConf.id}"`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY} + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY }, ); - await this.apricotProxy['SetRuntimeEntry']({component: COMPONENT, key: envConf.id, value: envConf.toString()}); - res.status(201).json({message: `Configuration successfully saved as ${envConf.id}`}); + await this.apricotProxy['SetRuntimeEntry']({ component: COMPONENT, key: envConf.id, value: envConf.toString() }); + res.status(201).json({ message: `Configuration successfully saved as ${envConf.id}` }); } } catch (error) { errorHandler(error, res, 503, 'apricotservice'); @@ -222,22 +223,22 @@ class ApricotService { async updateCoreEnvConfig(req, res) { try { const data = req.body; - const {username, name, personid, access} = req.session; + const { username, name, personid, access } = req.session; const user = new User(username, name, personid, access); - data.user = {username, personid}; + data.user = { username, personid }; const envConf = CoreEnvConfig.fromJSON(data); const envConfigToSave = await this._getUpdatedConfigIfExists(envConf, user); log.infoMessage( `${req.session.username} requested to update new core environment configuration "${envConf.id}"`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY} + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY }, ); await this.apricotProxy['SetRuntimeEntry']({ component: COMPONENT, key: envConfigToSave.id, - value: envConfigToSave.toString() + value: envConfigToSave.toString(), }); - res.status(200).json({message: `Successfully updated configuration: ${envConf.id}`}); + res.status(200).json({ message: `Successfully updated configuration: ${envConf.id}` }); } catch (error) { errorHandler(error, res, 503, 'apricotservice'); } @@ -260,7 +261,7 @@ class ApricotService { async _getUpdatedConfigIfExists(envConfig, user) { let existingConfig = ''; try { - const {payload: envConfigAsString} = await this.apricotProxy['GetRuntimeEntry']({ + const { payload: envConfigAsString } = await this.apricotProxy['GetRuntimeEntry']({ component: COMPONENT, key: envConfig.id, }); diff --git a/Control/lib/control-core/ControlService.js b/Control/lib/control-core/ControlService.js index 9a9d4a31c..6790a7fc3 100644 --- a/Control/lib/control-core/ControlService.js +++ b/Control/lib/control-core/ControlService.js @@ -10,15 +10,16 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const assert = require('assert'); const path = require('path'); -const {WebSocketMessage, Log} = require('@aliceo2/web-ui'); +const { WebSocketMessage, Log } = require('@aliceo2/web-ui'); + const log = new Log(`${process.env.npm_config_log_label ?? 'cog'}/controlservice`); -const {errorHandler, errorLogger} = require('./../utils.js'); +const { errorHandler, errorLogger } = require('./../utils.js'); const CoreUtils = require('./CoreUtils.js'); -const {LOG_LEVEL} = require('../common/logLevel.enum.js'); +const { LOG_LEVEL } = require('../common/logLevel.enum.js'); /** * Gateway for all AliECS - Core calls @@ -30,6 +31,8 @@ class ControlService { * @param {WebSocket} webSocket * @param {ConsulController} consulController * * @param {JSON} coreConfig + * @param coreConfig + * @param O2_CONTROL_PROTO_PATH */ constructor(ctrlProx, consulController, coreConfig, O2_CONTROL_PROTO_PATH) { assert(ctrlProx, 'Missing GrpcProxy dependency for AliECS'); @@ -43,7 +46,7 @@ class ControlService { /** * Set websocket after server initialization - * @param {WebSocket} webSocket + * @param {WebSocket} webSocket */ setWS(webSocket) { this.webSocket = webSocket; @@ -57,13 +60,13 @@ class ControlService { initiateHeartBeat() { return setInterval(async () => { try { - await this.ctrlProx['GetEnvironments']({}, {deadline: Date.now() + 9000}); + await this.ctrlProx['GetEnvironments']({}, { deadline: Date.now() + 9000 }); } catch (err) { const stateCode = this.ctrlProx.client.getChannel().getConnectivityState(); log.errorMessage(`Unable to reach AliECS (state: ${stateCode}), attempting reconnection`, { level: 20, system: 'GUI', - facility: 'cog/controlservice' + facility: 'cog/controlservice', }); } }, 10000); @@ -78,27 +81,33 @@ class ControlService { * Current supported auto environments: * * resources-cleanup: will execute for all existing hosts * * o2-roc-config: will execute only for passed hosts - * * + * * * @param {Request} req * @param {Response} res */ async createAutoEnvironment(req, res) { - let {channelId, vars, operation} = req.body; + let { channelId, vars, operation } = req.body; const method = 'NewAutoEnvironment'; if (!channelId) { res.status(502).json({ - ended: true, success: false, id: channelId, - message: 'Channel ID should be provided' + ended: true, + success: false, + id: channelId, + message: 'Channel ID should be provided', }); } else if (vars?.hosts?.length === 0) { res.status(502).json({ - ended: true, success: false, id: channelId, - message: 'List of Hosts should be provided' + ended: true, + success: false, + id: channelId, + message: 'List of Hosts should be provided', }); } else if (!operation) { res.status(502).json({ - ended: true, success: false, id: channelId, - message: 'Operation should be provided' + ended: true, + success: false, + id: channelId, + message: 'Operation should be provided', }); } else { try { @@ -107,14 +116,14 @@ class ControlService { vars.hosts = await this.consulController.getFLPsList(); } vars.hosts = JSON.stringify(vars.hosts); - const {repos: repositories} = await this.ctrlProx['ListRepos'](); - const {name: repositoryName, defaultRevision} = repositories.find((repository) => repository.default); + const { repos: repositories } = await this.ctrlProx['ListRepos'](); + const { name: repositoryName, defaultRevision } = repositories.find((repository) => repository.default); if (!defaultRevision) { throw new Error(`Unable to find a default revision for repository: ${repositoryName}`); } // Setup Stream Channel - const streamChannel = this.ctrlProx.client['Subscribe']({id: channelId}); + const streamChannel = this.ctrlProx.client['Subscribe']({ id: channelId }); streamChannel.on('data', (data) => this.onData(channelId, operation, data)); streamChannel.on('error', (err) => this.onError(channelId, operation, err)); // onEnd gets called no matter what @@ -127,20 +136,24 @@ class ControlService { workflowTemplate: path.join(repositoryName, `workflows/${operation}@${defaultRevision}`), }; log.infoMessage(`Request of user: ${req.session.username} to "${operation}" for ${channelId}`, { - level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: 'cog/controlservice' + level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: 'cog/controlservice', }); await this.ctrlProx[method](coreConf); res.status(200).json({ - ended: false, success: true, id: channelId, - info: {message: `Request for "${operation}" was successfully sent and is now in progress`} + ended: false, + success: true, + id: channelId, + info: { message: `Request for "${operation}" was successfully sent and is now in progress` }, }); } catch (error) { // Failed to getFLPs, ListRepos or NewAutoEnvironment errorLogger(error); res.status(502).json({ - ended: true, success: false, id: channelId, + ended: true, + success: false, + id: channelId, message: error.message || error || `Error while attempting to run ${operation} ...`, - info: {message: error.message || error || `Error while attempting to run ${operation} ...`} + info: { message: error.message || error || `Error while attempting to run ${operation} ...` }, }); } } @@ -163,7 +176,7 @@ class ControlService { * @param {string} method - AliECS method name * @param {object} body - request body * @param {JSON} options - optional parameters that are to be set to the gRPC call (e.g deadline) - * @return {Promise} + * @returns {Promise} */ executeCommandNoResponse(method, body = {}, options = undefined) { return this.ctrlProx[method](body, options); @@ -171,7 +184,7 @@ class ControlService { /** * Method to execute specified command return results - * @return {Promise} + * @returns {Promise} */ async getAliECSInfo() { const method = CoreUtils.parseMethodNameString('GetFrameworkInfo'); @@ -182,7 +195,7 @@ class ControlService { /** * Request information about the integrated services from AliECS Core - * @return {Promise} + * @returns {Promise} */ async getIntegratedServicesInfo() { const method = CoreUtils.parseMethodNameString('GetIntegratedServices'); @@ -193,9 +206,10 @@ class ControlService { /** * Middleware method to check if AliECS connection is up and running * @param {Request} req + * @param _ * @param {Response} res * @param {Next} next - * @return {boolean} + * @returns {boolean} */ isConnectionReady(_, res, next) { if (!this.ctrlProx?.isConnectionReady) { @@ -213,6 +227,7 @@ class ControlService { * Middleware method to log the action and id of the user * @param {Request} req * @param {Response} res + * @param _ * @param {Next} next */ logAction(req, _, next) { @@ -222,7 +237,7 @@ class ControlService { if (method.startsWith('New') || method.startsWith('CleanupTasks')) { const operation = req.body.operation ? ` (${req.body.operation})` : ''; log.infoMessage(`${username}(${personid}) => ${method} ${operation}`, { - level: 1, facility: 'cog/controlservice' + level: 1, facility: 'cog/controlservice', }); } else if (method.startsWith('Control') || method.startsWith('Destroy')) { const type = req.body.type ? ` (${req.body.type})` : ''; @@ -231,7 +246,7 @@ class ControlService { delete req.body.runNumber; log.infoMessage(`${username}(${personid}) => ${method} ${type}`, { - level: 1, facility: 'cog/controlservice', partition, run + level: 1, facility: 'cog/controlservice', partition, run, }); } next(); @@ -253,8 +268,11 @@ class ControlService { const msg = new WebSocketMessage(); msg.command = command; msg.payload = { - ended: false, success: false, id: channelId, type: 'TASK', - info: {host: data.taskEvent.hostname, id: data.taskEvent.taskid}, + ended: false, + success: false, + id: channelId, + type: 'TASK', + info: { host: data.taskEvent.hostname, id: data.taskEvent.taskid }, }; this.webSocket.broadcast(msg); } @@ -265,13 +283,18 @@ class ControlService { if (!data.environmentEvent.error) { msg.payload = { ended: data.environmentEvent.state === 'DONE' ? true : false, - success: true, id: channelId, type: 'ENV', - info: {message: data.environmentEvent.message || 'Executing ...'} + success: true, + id: channelId, + type: 'ENV', + info: { message: data.environmentEvent.message || 'Executing ...' }, }; } else { msg.payload = { - ended: true, success: false, id: channelId, type: 'ENV', - info: {message: data.environmentEvent.error || `Failed operation: ${command} ...`} + ended: true, + success: false, + id: channelId, + type: 'ENV', + info: { message: data.environmentEvent.error || `Failed operation: ${command} ...` }, }; } this.webSocket.broadcast(msg); @@ -281,13 +304,17 @@ class ControlService { /** * Deal with incoming error message from AliECS Core Stream * @param {string} channelId - to distinguish to which client should this message be sent + * @param command + * @param error */ onError(channelId, command, error) { const msg = new WebSocketMessage(); msg.command = command; msg.payload = { - ended: true, success: false, id: channelId, - info: {message: `"${command}" action failed due to ${error.toString()}`} + ended: true, + success: false, + id: channelId, + info: { message: `"${command}" action failed due to ${error.toString()}` }, }; errorLogger(error); this.webSocket.broadcast(msg); diff --git a/Control/lib/control-core/CoreUtils.js b/Control/lib/control-core/CoreUtils.js index 277699f8a..1f7a67e39 100644 --- a/Control/lib/control-core/CoreUtils.js +++ b/Control/lib/control-core/CoreUtils.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** * Shared methods used within Core Services/Controllers @@ -24,7 +24,7 @@ class CoreUtils { /** * Given a core response with framework info, filter out * data which should not be displayed to the user - * @param {JSON} info + * @param {JSON} info */ static parseFrameworkInfo(info) { delete info.detectorsInInstance; @@ -36,11 +36,11 @@ class CoreUtils { /** * Method to remove `/` if exists from method name * @param {string} method - * @return {string} + * @returns {string} */ static parseMethodNameString(method) { if (method === '/core/request') { - return 'NewEnvironment' + return 'NewEnvironment'; } else if (method?.startsWith('/execute/')) { return 'NewAutoEnvironment'; } @@ -50,7 +50,7 @@ class CoreUtils { /** * Parse the JSON of the version and return it as a string * @param {JSON} versionJSON - * @return {string} + * @returns {string} */ static parseAliEcsVersion(versionJSON) { let version = ''; @@ -58,10 +58,10 @@ class CoreUtils { version += versionJSON.productName; } if (versionJSON.versionStr) { - version += ' ' + versionJSON.versionStr; + version += ` ${versionJSON.versionStr}`; } if (versionJSON.build) { - version += ' (revision ' + versionJSON.build + ')'; + version += ` (revision ${versionJSON.build})`; } return version; } @@ -69,24 +69,24 @@ class CoreUtils { /** * Given a payload with properties, extract the runType one * @param {EnvironmentCreation} environmentPayload - object with properties required to create an environment - * @return {String} runType of the environment creation. + * @returns {string} runType of the environment creation. */ static getRunType(environmentPayload) { - const {vars} = environmentPayload; - return vars['run_type'] ?? null; + const { vars } = environmentPayload; + return vars['run_type'] ?? null; } /** * Checks for mandatory fields and parses variables to: * - replace new lines with spaces * @param {EnvironmentCreation} payload - configuration for creating an environment in raw format - * @param {Array} hostsToIgnore - list of hosts that should be removed from payload - * @return {EnvironmentCreation} - validated and parsed configuration + * @param {Array} hostsToIgnore - list of hosts that should be removed from payload + * @returns {EnvironmentCreation} - validated and parsed configuration */ static parseEnvironmentCreationPayload(payload, hostsToIgnore = []) { - const {workflowTemplate, vars} = payload; + const { workflowTemplate, vars } = payload; if (!workflowTemplate || !vars) { - throw new Error(`Missing mandatory parameter 'workflowTemplate' or 'vars'`) + throw new Error(`Missing mandatory parameter 'workflowTemplate' or 'vars'`); } payload = CoreUtils._removeHostsFromSelection(payload, hostsToIgnore); Object.keys(vars).forEach((key) => vars[key] = vars[key].trim().replace(/\r?\n/g, ' ')); @@ -96,7 +96,8 @@ class CoreUtils { /** * Temporal removal of bad FLP host if run_type is as per specified * @param {EnvironmentCreation} payload - configuration for creating an environment in raw format - * @returns {EnvironmentCreation} - validated and parsed configuration + * @param hostsToIgnore + * @returns {EnvironmentCreation} - validated and parsed configuration */ static _removeHostsFromSelection(payload, hostsToIgnore = []) { try { @@ -114,7 +115,7 @@ class CoreUtils { }); payload.vars.hosts = JSON.stringify(hostsList); } catch (error) { - console.error(error) + console.error(error); } return payload; diff --git a/Control/lib/control-core/EnvCache.js b/Control/lib/control-core/EnvCache.js index 02d0ee5ec..dadcba4ec 100644 --- a/Control/lib/control-core/EnvCache.js +++ b/Control/lib/control-core/EnvCache.js @@ -10,9 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ + +const { WebSocketMessage, Log } = require('@aliceo2/web-ui'); -const {WebSocketMessage, Log} = require('@aliceo2/web-ui'); const log = new Log(`${process.env.npm_config_log_label ?? 'cog'}/envcache`); const assert = require('assert'); @@ -20,7 +21,6 @@ const assert = require('assert'); * Caches AliECS core GetEnvironments response */ class EnvCache { - /** * @param {object} ctrlService - Handle to Control service * @param {EnvironmentService} environmentService - service to be used to retrieve information on environments @@ -65,8 +65,8 @@ class EnvCache { } /** - * @param {Object} obj Object to compare cache with - * @return {bool} Whether object and cache are deep equal + * @param {object} obj Object to compare cache with + * @returns {bool} Whether object and cache are deep equal */ _cacheInSync(obj) { try { @@ -83,9 +83,9 @@ class EnvCache { async refresh() { try { const deadline = Date.now() + this.timeout; - const envs = await this.ctrlService.executeCommandNoResponse('GetEnvironments', {}, {deadline}); + const envs = await this.ctrlService.executeCommandNoResponse('GetEnvironments', {}, { deadline }); - for (let [index, currentEnv] of envs.environments.entries()) { + for (const [index, currentEnv] of envs.environments.entries()) { try { const environment = await this._environmentService.getEnvironment(currentEnv.id); envs.environments[index] = environment; @@ -104,7 +104,8 @@ class EnvCache { /** * Method to update cache if there are any changes * @param {Object{Environments}} - environments' data that is to be stored in cache - * @return {void} + * @param envs + * @returns {void} */ _updateCache(envs) { if (!this._cacheInSync(envs)) { @@ -115,4 +116,5 @@ class EnvCache { this.cacheEvictionLast = new Date(); } } + module.exports = EnvCache; diff --git a/Control/lib/control-core/GrpcProxy.js b/Control/lib/control-core/GrpcProxy.js index 20f5577a9..0f3044320 100644 --- a/Control/lib/control-core/GrpcProxy.js +++ b/Control/lib/control-core/GrpcProxy.js @@ -10,15 +10,16 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ // Doc: https://grpc.io/docs/languages/node/ const protoLoader = require('@grpc/proto-loader'); const grpcLibrary = require('@grpc/grpc-js'); const path = require('path'); -const {grpcErrorToNativeError} = require('./../errors/grpcErrorToNativeError.js'); -const {Status} = require(path.join(__dirname, './../../protobuf/status_pb.js')); -const {EnvironmentInfo} = require(path.join(__dirname, './../../protobuf/environmentinfo_pb.js')); +const { grpcErrorToNativeError } = require('./../errors/grpcErrorToNativeError.js'); +const { Status } = require(path.join(__dirname, './../../protobuf/status_pb.js')); +const { EnvironmentInfo } = require(path.join(__dirname, './../../protobuf/environmentinfo_pb.js')); + const log = new (require('@aliceo2/web-ui').Log)(`${process.env.npm_config_log_label ?? 'cog'}/grpcproxy`); /** @@ -28,22 +29,22 @@ class GrpcProxy { /** * Create gRPC client and sets the methods identified in the provided path of protofile * https://grpc.io/grpc/node/grpc.Client.html - * @param {Object} config - Contains configuration fields for gRPC client + * @param {object} config - Contains configuration fields for gRPC client * @param {string} path - path to protofile location */ constructor(config, path) { if (this._isConfigurationValid(config, path)) { - const packageDefinition = protoLoader.loadSync(path, {longs: String, keepCase: false, arrays: true}); + const packageDefinition = protoLoader.loadSync(path, { longs: String, keepCase: false, arrays: true }); const octlProto = grpcLibrary.loadPackageDefinition(packageDefinition); const protoService = octlProto[this._package][this._label]; const address = `${config.hostname}:${config.port}`; const credentials = grpcLibrary.credentials.createInsecure(); - const options = {'grpc.max_receive_message_length': 1024 * 1024 * this._maxMessageLength}; // MB + const options = { 'grpc.max_receive_message_length': 1024 * 1024 * this._maxMessageLength }; // MB this.client = new protoService(address, credentials, options); this.client.waitForReady( Date.now() + this._connectionTimeout, - (error) => this._logConnectionResponse(error, address) + (error) => this._logConnectionResponse(error, address), ); // set all the available gRPC methods in object and build a separate array with names only @@ -63,41 +64,39 @@ class GrpcProxy { * Definition of each call that can be made based on the proto file definition * @param {JSON} args - arguments to be passed to gRPC Server * @param {JSON} options - metadata for gRPC call such as deadline - * @returns + * @returns */ - this[methodName] = (args = {}, options = {deadline: Date.now() + this._timeout}) => { - return new Promise((resolve, reject) => { - this.client[methodName](args, options, (error, response) => { - if (error) { - try { - if (methodName === 'NewEnvironment' && error.metadata?.internalRepr?.has('grpc-status-details-bin')) { - const buffer = error.metadata.get('grpc-status-details-bin')[0]; - Status.deserializeBinary(buffer).getDetailsList().map((detail) => { - if (detail.getTypeName() == 'o2control.EnvironmentInfo') { - const deserialized = detail.unpack(EnvironmentInfo.deserializeBinary, detail.getTypeName()); - error.envId = deserialized.array[0]; - } - }); - } - reject(error); - } catch (exception) { - log.debug('Failed new env details error' + exception); - reject(exception); + this[methodName] = (args = {}, options = { deadline: Date.now() + this._timeout }) => new Promise((resolve, reject) => { + this.client[methodName](args, options, (error, response) => { + if (error) { + try { + if (methodName === 'NewEnvironment' && error.metadata?.internalRepr?.has('grpc-status-details-bin')) { + const buffer = error.metadata.get('grpc-status-details-bin')[0]; + Status.deserializeBinary(buffer).getDetailsList().map((detail) => { + if (detail.getTypeName() == 'o2control.EnvironmentInfo') { + const deserialized = detail.unpack(EnvironmentInfo.deserializeBinary, detail.getTypeName()); + error.envId = deserialized.array[0]; + } + }); } - reject(grpcErrorToNativeError(error)); - return; + reject(error); + } catch (exception) { + log.debug(`Failed new env details error${exception}`); + reject(exception); } - resolve(response); - }); + reject(grpcErrorToNativeError(error)); + return; + } + resolve(response); }); - }; + }); return methodName; } /** * Checks if configuration provided for gRPC Connection is valid * @param {JSON} config - * @param {String} path - location of gRPC file containing API + * @param {string} path - location of gRPC file containing API */ _isConfigurationValid(config, path) { let isValid = true; @@ -134,7 +133,7 @@ class GrpcProxy { } /** - * + * * @param {Error} error - error following attempt to connect to gRPC server * @param {string} address - address on which connection was attempted */ @@ -158,7 +157,7 @@ class GrpcProxy { /** * Get the status of the connection to gRPC - * @return {boolean} + * @returns {boolean} */ get isConnectionReady() { return this._isConnectionReady; @@ -174,7 +173,7 @@ class GrpcProxy { /** * Get the error of the connection if present. - * @return {Error} + * @returns {Error} */ get connectionError() { return this._connectionError; diff --git a/Control/lib/control-core/RequestHandler.js b/Control/lib/control-core/RequestHandler.js index a66d9ff6e..1a5227d4d 100644 --- a/Control/lib/control-core/RequestHandler.js +++ b/Control/lib/control-core/RequestHandler.js @@ -10,22 +10,22 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ -const {WebSocketMessage, Log} = require('@aliceo2/web-ui'); -const {errorLogger} = require('./../utils.js'); + */ +const { WebSocketMessage, Log } = require('@aliceo2/web-ui'); +const { errorLogger } = require('./../utils.js'); const CoreUtils = require('./CoreUtils.js'); const { - RUNTIME_COMPONENT: {COG}, - RUNTIME_KEY: {RUN_TYPE_TO_HOST_MAPPING} + RUNTIME_COMPONENT: { COG }, + RUNTIME_KEY: { RUN_TYPE_TO_HOST_MAPPING }, } = require('../common/kvStore/runtime.enum.js'); -const {LOG_LEVEL} = require('../common/logLevel.enum.js'); +const { LOG_LEVEL } = require('../common/logLevel.enum.js'); + const LOG_FACILITY = 'cog/controlrequests'; /** * Handles AliECS create env requests */ class RequestHandler { - /** * @param {object} ctrlService - Handle to Control service * @param {ApricotService} apricotService - service to use to interact with A.P.R.I.C.O.T @@ -66,7 +66,7 @@ class RequestHandler { logMessage += `and detectors: ${req.body.detectors}`; } - this._logger.infoMessage(logMessage, {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY}); + this._logger.infoMessage(logMessage, { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY }); this.requestList[index] = { id: index, @@ -75,19 +75,19 @@ class RequestHandler { date: new Date(), owner: req.session.name, personid: req.session.personid, - failed: false + failed: false, }; - res.json({ok: 1}); + res.json({ ok: 1 }); this.broadcast(); - const {selectedConfiguration} = req.body; + const { selectedConfiguration } = req.body; if (selectedConfiguration) { // workaround for reloading configuration before deployment from global page try { - const {variables} = await this._workflowService.retrieveWorkflowSavedConfiguration(selectedConfiguration); + const { variables } = await this._workflowService.retrieveWorkflowSavedConfiguration(selectedConfiguration); variables.hosts = req.body.vars.hosts; - const {epn_enabled, odc_n_epns} = req.body.vars; + const { epn_enabled, odc_n_epns } = req.body.vars; if (epn_enabled === 'true') { variables.odc_n_epns = odc_n_epns; } @@ -121,7 +121,7 @@ class RequestHandler { } catch (error) { if (error.envId) { this._logger.errorMessage(`Creation of environment failed with: ${error.details}.`, { - level: LOG_LEVEL.ERROR, system: 'GUI', facility: LOG_FACILITY, partition: error.envId + level: LOG_LEVEL.ERROR, system: 'GUI', facility: LOG_FACILITY, partition: error.envId, }); let logMessage = `Environment was requested by user: ${req.session.username} with`; if (req.body.workflowTemplate) { @@ -131,7 +131,7 @@ class RequestHandler { logMessage += `and detectors: ${req.body.detectors}.`; } this._logger.errorMessage(logMessage, { - level: LOG_LEVEL.ERROR, system: 'GUI', facility: LOG_FACILITY, partition: error.envId + level: LOG_LEVEL.ERROR, system: 'GUI', facility: LOG_FACILITY, partition: error.envId, }); } else { let logMessage = `Creation of environment failed with: ${error.details}. `; @@ -163,12 +163,12 @@ class RequestHandler { * Remove request from "cache". * @param {Request} req * @param {Response} res - * @returns {Object} + * @returns {object} */ remove(req, res) { const index = req.params.id; this._logger.infoMessage(`User ${req.session.username} acknowledged and removed failed request`, { - level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY + level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, }); delete this.requestList[index]; return this.getAll(req, res); @@ -178,26 +178,24 @@ class RequestHandler { * Broadcast list of request */ broadcast() { - this.webSocket?.broadcast(new WebSocketMessage().setCommand('requests').setPayload( - this._getAll() - )); + this.webSocket?.broadcast(new WebSocketMessage().setCommand('requests').setPayload(this._getAll())); } /** - * @returns {Object} Returns request as array and current date + * @returns {object} Returns request as array and current date */ _getAll() { return { now: new Date(), - requests: Object.values(this.requestList) - } + requests: Object.values(this.requestList), + }; } /** * Get all the requests from the "cache" * @param {Request} req * @param {Response} res - * @returns {Object} + * @returns {object} */ getAll(req, res) { return res.json(this._getAll()); @@ -210,10 +208,11 @@ class RequestHandler { /** * Setter for updating workflowService to use * @param {WorkflowService} - service to be used for retrieving workflow configuration - * @return {void} + * @returns {void} */ set workflowService(service) { this._workflowService = service; } } + module.exports = RequestHandler; diff --git a/Control/lib/controllers/Consul.controller.js b/Control/lib/controllers/Consul.controller.js index a55fb811b..28d61d852 100644 --- a/Control/lib/controllers/Consul.controller.js +++ b/Control/lib/controllers/Consul.controller.js @@ -10,12 +10,12 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const log = new (require('@aliceo2/web-ui').Log)(`${process.env.npm_config_log_label ?? 'cog'}/consul`); -const {errorHandler, errorLogger} = require('../utils.js'); -const {getConsulConfig} = require('../config/publicConfigProvider.js'); -const {LOG_LEVEL} = require('../common/logLevel.enum.js'); +const { errorHandler, errorLogger } = require('../utils.js'); +const { getConsulConfig } = require('../config/publicConfigProvider.js'); +const { LOG_LEVEL } = require('../common/logLevel.enum.js'); /** * Gateway for all Consul Consumer calls @@ -29,7 +29,7 @@ class ConsulController { */ constructor(consulService, config) { this.consulService = consulService; - this.config = getConsulConfig({consul: config}); + this.config = getConsulConfig({ consul: config }); this.flpHardwarePath = this.config.flpHardwarePath; this.detHardwarePath = this.config.detHardwarePath; this.readoutCardPath = this.config.readoutCardPath; @@ -43,8 +43,8 @@ class ConsulController { * * If yes, allow request to continue * * If not, send response accordingly * @param {Request} req - * @param {Response} res - * @param {Next} next + * @param {Response} res + * @param {Next} next */ validateService(req, res, next) { if (this.consulService) { @@ -64,13 +64,13 @@ class ConsulController { } /** - * Method to request all CRUs available in consul KV store under the - * hardware key - * @param {Request} req - * @param {Response} res - */ + * Method to request all CRUs available in consul KV store under the + * hardware key + * @param {Request} req + * @param {Response} res + */ async getCRUs(req, res) { - const regex = new RegExp(`.*/.*/cards`); + const regex = new RegExp('.*/.*/cards'); this.consulService.getOnlyRawValuesByKeyPrefix(this.flpHardwarePath).then((data) => { const crusByHost = {}; Object.keys(data) @@ -107,7 +107,7 @@ class ConsulController { const flpList = data.filter((key) => key.match(regex)) .map((key) => key.split('/')[3]); res.status(200); - res.json({flps: [...new Set(flpList)]}); + res.json({ flps: [...new Set(flpList)] }); }) .catch((error) => { if (error.message.includes('404')) { @@ -128,7 +128,7 @@ class ConsulController { */ async getCRUsWithConfiguration(req, res) { try { - let cardsByHost = await this._getCardsByHost(); + const cardsByHost = await this._getCardsByHost(); const crusByHost = this._mapCrusWithId(cardsByHost); const crusWithConfigByHost = await this._getCrusConfigById(crusByHost); res.status(200).json(crusWithConfigByHost); @@ -167,26 +167,24 @@ class ConsulController { async getCRUsAlias(req, res) { try { const aliases = {}; - let detectorsKey = await this.consulService.getKeysByPrefix(this.detHardwarePath); - await Promise.all( - detectorsKey.filter((key) => key.includes('aliases')) - .map(async (key) => { - try { - let alias = await this.consulService.getOnlyRawValuesByKeyPrefix(key); - alias = JSON.parse(alias[key]); + const detectorsKey = await this.consulService.getKeysByPrefix(this.detHardwarePath); + await Promise.all(detectorsKey.filter((key) => key.includes('aliases')) + .map(async (key) => { + try { + let alias = await this.consulService.getOnlyRawValuesByKeyPrefix(key); + alias = JSON.parse(alias[key]); - const host = key.split('/')[5]; - aliases[host] = { - alias: alias.flp.alias, - cards: alias.cards, - }; - } catch (error) { - errorLogger(`Bad format to get aliases for key: ${key}`, 'consul'); - errorLogger(error, 'consul') - } - return; - }) - ); + const host = key.split('/')[5]; + aliases[host] = { + alias: alias.flp.alias, + cards: alias.cards, + }; + } catch (error) { + errorLogger(`Bad format to get aliases for key: ${key}`, 'consul'); + errorLogger(error, 'consul'); + } + return; + })); res.json(aliases); } catch (error) { errorHandler(error, res, 502); @@ -211,10 +209,10 @@ class ConsulController { const keyValues = this._mapToKVPairs(crusByHost, latestCrusWithConfigByHost); try { log.infoMessage(`Request of user: ${req.session.username} to update CRU configuration`, { - level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: 'cog/consul' + level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: 'cog/consul', }); await this.consulService.putListOfKeyValues(keyValues); - res.status(200).json({info: {message: 'CRUs Configuration saved'}}); + res.status(200).json({ info: { message: 'CRUs Configuration saved' } }); } catch (error) { errorHandler(error, res, 502); } @@ -222,7 +220,7 @@ class ConsulController { /** * Get a list of FLPs loaded from Consul - * @return {Array} + * @returns {Array} */ async getFLPsList() { if (this.consulService) { @@ -249,7 +247,7 @@ class ConsulController { * on the readoutPath prefix and group them in a JSON * by host and cruid (cru__) * @param {JSON} crus - * @return {Promise.} + * @returns {Promise.} */ async _getCrusConfigById(crus) { const crusByEndpoint = await this.consulService.getOnlyRawValuesByKeyPrefix(this.readoutCardPath); @@ -274,7 +272,7 @@ class ConsulController { /** * Get a JSON of cards grouped by their host by querying Consul through the flpHardwarePath * @example - * { + * { * "host_one": { * "0": { * "key": "value" @@ -284,10 +282,10 @@ class ConsulController { * } * } * } - * @return {Promise.} + * @returns {Promise.} */ async _getCardsByHost() { - const regex = new RegExp(`.*cards`); + const regex = new RegExp('.*cards'); const data = await this.consulService.getOnlyRawValuesByKeyPrefix(this.flpHardwarePath); const cardsByHost = {}; Object.keys(data) @@ -306,7 +304,8 @@ class ConsulController { * * cru.userLogicEnabled * * link0 - link11 * @param {JSON} crusByHost - * @return {Array} + * @param latestCrusByHost + * @returns {Array} */ _mapToKVPairs(crusByHost, latestCrusByHost) { const kvPairs = []; @@ -322,15 +321,15 @@ class ConsulController { .filter((key) => key.match('link[0-9]{1,2}')) // select only fields from links0 to links11 .forEach((key) => { if (cruConfig[key] && cruConfig[key].enabled) { - latestConfig[key].enabled = cruConfig[key].enabled + latestConfig[key].enabled = cruConfig[key].enabled; } }); const serial = cruId.split('_')[1]; const endpoint = cruId.split('_')[2]; - const pair = {} + const pair = {}; pair[`${this.readoutCardPath}/${host}/cru/${serial}/${endpoint}`] = JSON.stringify(latestConfig, null, 2); kvPairs.push(pair); - }) + }); }); return kvPairs; } @@ -339,10 +338,10 @@ class ConsulController { * Filter out any cards with type != CRU and replace the incremental index on each CRU * by their unique ID used in CRUs configuration * @param {JSON} cards - * @return {JSON} + * @returns {JSON} */ _mapCrusWithId(cards) { - const crusWithIdByHost = {} + const crusWithIdByHost = {}; Object.keys(cards).forEach((hostName) => { const hostCru = {}; Object.keys(cards[hostName]) @@ -350,7 +349,7 @@ class ConsulController { .sort((a, b) => this._sortCRUsBySerialEndpoint(cards[hostName][a], cards[hostName][b])) .forEach((cruIndex) => { const cruInfo = cards[hostName][cruIndex]; - hostCru[`cru_${cruInfo.serial}_${cruInfo.endpoint}`] = {info: cruInfo, config: {}}; + hostCru[`cru_${cruInfo.serial}_${cruInfo.endpoint}`] = { info: cruInfo, config: {} }; crusWithIdByHost[hostName] = hostCru; }); }); @@ -363,7 +362,9 @@ class ConsulController { * @param {JSON} cards * @param {number} a * @param {number} b - * @return {number} 1 / -1 + * @param cruA + * @param cruB + * @returns {number} 1 / -1 */ _sortCRUsBySerialEndpoint(cruA, cruB) { const cruIdA = `cru_${cruA.serial}_${cruA.endpoint}`; diff --git a/Control/lib/controllers/Environment.controller.js b/Control/lib/controllers/Environment.controller.js index 3faec5451..fe8f2fcbd 100644 --- a/Control/lib/controllers/Environment.controller.js +++ b/Control/lib/controllers/Environment.controller.js @@ -10,16 +10,17 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ -const {Log} = require('@aliceo2/web-ui'); + */ +const { Log } = require('@aliceo2/web-ui'); + const LOG_FACILITY = 'cog/env-ctrl'; -const {EnvironmentTransitionType} = require('./../common/environmentTransitionType.enum.js'); -const {grpcErrorToNativeError} = require('./../errors/grpcErrorToNativeError.js'); -const {InvalidInputError} = require('./../errors/InvalidInputError.js'); -const {UnauthorizedAccessError} = require('./../errors/UnauthorizedAccessError.js'); -const {updateExpressResponseFromNativeError} = require('./../errors/updateExpressResponseFromNativeError.js'); -const {User} = require('./../dtos/User.js'); -const {LOG_LEVEL} = require('../common/logLevel.enum.js'); +const { EnvironmentTransitionType } = require('./../common/environmentTransitionType.enum.js'); +const { grpcErrorToNativeError } = require('./../errors/grpcErrorToNativeError.js'); +const { InvalidInputError } = require('./../errors/InvalidInputError.js'); +const { UnauthorizedAccessError } = require('./../errors/UnauthorizedAccessError.js'); +const { updateExpressResponseFromNativeError } = require('./../errors/updateExpressResponseFromNativeError.js'); +const { User } = require('./../dtos/User.js'); +const { LOG_LEVEL } = require('../common/logLevel.enum.js'); /** * Controller for dealing with all API requests on environments from AliECS: @@ -63,7 +64,7 @@ class EnvironmentController { * @returns {void} */ async getEnvironmentHandler(req, res) { - const {id, source} = req.params; + const { id, source } = req.params; if (!id) { updateExpressResponseFromNativeError(res, new InvalidInputError('Missing environment ID parameter')); return; @@ -84,10 +85,10 @@ class EnvironmentController { * @returns {void} */ async transitionEnvironmentHandler(req, res) { - const {personid, username, name} = req.session; + const { personid, username, name } = req.session; const user = new User(username, name, personid); - const {id} = req.params; - const {type: transitionType, runNumber = ''} = req.body; + const { id } = req.params; + const { type: transitionType, runNumber = '' } = req.body; if (!id) { updateExpressResponseFromNativeError(res, new InvalidInputError('Missing environment ID parameter')); } else if (!(transitionType in EnvironmentTransitionType)) { @@ -95,8 +96,9 @@ class EnvironmentController { } else { const transitionRequestedAt = Date.now(); let response = null; - this._logger.infoMessage(`Request to transition environment by ${req.session.username} to ${transitionType}`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, partition: id, run: runNumber} + this._logger.infoMessage( + `Request to transition environment by ${req.session.username} to ${transitionType}`, + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, partition: id, run: runNumber }, ); try { response = await this._envService.transitionEnvironment(id, transitionType, user); @@ -104,7 +106,7 @@ class EnvironmentController { } catch (error) { this._logger.errorMessage( `Request to transition environment by ${req.session.username} to ${transitionType} failed due to ${error}`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, partition: id, run: runNumber} + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, partition: id, run: runNumber }, ); updateExpressResponseFromNativeError(res, error); } @@ -120,23 +122,24 @@ class EnvironmentController { * @returns {void} */ async destroyEnvironmentHandler(req, res) { - const {id} = req.params ?? {}; - const {runNumber = '', keepTasks = false, allowInRunningState = false, force = false} = req.body ?? {}; + const { id } = req.params ?? {}; + const { runNumber = '', keepTasks = false, allowInRunningState = false, force = false } = req.body ?? {}; if (!id) { updateExpressResponseFromNativeError(res, new InvalidInputError('Missing environment ID parameter')); } else { const destroyRequestedAt = Date.now(); - this._logger.infoMessage(`Request to destroy environment by ${req.session.username} by force: ${force}`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, partition: id, run: runNumber} + this._logger.infoMessage( + `Request to destroy environment by ${req.session.username} by force: ${force}`, + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, partition: id, run: runNumber }, ); try { - const response = await this._envService.destroyEnvironment(id, {keepTasks, allowInRunningState, force}); + const response = await this._envService.destroyEnvironment(id, { keepTasks, allowInRunningState, force }); res.status(200).json(response); } catch (error) { this._logger.errorMessage( `Request to destroy environment by ${req.session.username} failed due to ${error}`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, partition: id, run: runNumber} + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY, partition: id, run: runNumber }, ); updateExpressResponseFromNativeError(res, error); } @@ -151,9 +154,9 @@ class EnvironmentController { * @returns {void} */ async newAutoEnvironmentHandler(req, res) { - const {personid, name, username} = req.session; + const { personid, name, username } = req.session; const user = new User(username, name, personid); - const {detector, runType, configurationName} = req.body; + const { detector, runType, configurationName } = req.body; if (!this._lockService.isLockOwnedByUser(detector, user)) { updateExpressResponseFromNativeError(res, new UnauthorizedAccessError('Lock not taken')); @@ -194,7 +197,7 @@ class EnvironmentController { // Retrieve latest default workflow to use let workflowTemplatePath; try { - const {template, repository, revision} = await this._workflowService.getDefaultTemplateSource(); + const { template, repository, revision } = await this._workflowService.getDefaultTemplateSource(); workflowTemplatePath = `${repository}/workflows/${template}@${revision}`; } catch (error) { this._logger.debug(`Unable to retrieve default workflow template due to ${error}`); @@ -203,19 +206,20 @@ class EnvironmentController { } // Attempt to deploy environment try { - this._logger.infoMessage(`Request by username(${username}) to deploy configuration ${configurationName}`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY} + this._logger.infoMessage( + `Request by username(${username}) to deploy configuration ${configurationName}`, + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY }, ); const environment = await this._envService.newAutoEnvironment(workflowTemplatePath, variables, detector, runType); res.status(200).json(environment); } catch (error) { this._logger.errorMessage( `Unable to deploy request by username(${username}) for ${configurationName} due to error`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY} + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY }, ); updateExpressResponseFromNativeError(res, error); } } } -module.exports = {EnvironmentController}; +module.exports = { EnvironmentController }; diff --git a/Control/lib/controllers/Lock.controller.js b/Control/lib/controllers/Lock.controller.js index 2bc3481f3..18b24e680 100644 --- a/Control/lib/controllers/Lock.controller.js +++ b/Control/lib/controllers/Lock.controller.js @@ -10,13 +10,13 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {InvalidInputError} = require('./../errors/InvalidInputError.js'); -const {DetectorLockAction} = require('./../common/lock/detectorLockAction.enum.js'); -const {Log} = require('@aliceo2/web-ui'); -const {updateExpressResponseFromNativeError} = require('./../errors/updateExpressResponseFromNativeError.js'); -const {User} = require('./../dtos/User.js'); +const { InvalidInputError } = require('./../errors/InvalidInputError.js'); +const { DetectorLockAction } = require('./../common/lock/detectorLockAction.enum.js'); +const { Log } = require('@aliceo2/web-ui'); +const { updateExpressResponseFromNativeError } = require('./../errors/updateExpressResponseFromNativeError.js'); +const { User } = require('./../dtos/User.js'); const ERROR_LOG_LEVEL = 99; const LOG_FACILITY = 'cog/log-ctrl'; @@ -60,8 +60,8 @@ class LockController { * @returns {void} */ async actionLockHandler(req, res) { - const {action, detectorId, shouldForce = false} = req.params; - const {personid, name, username, access} = req.session; + const { action, detectorId, shouldForce = false } = req.params; + const { personid, name, username, access } = req.session; try { if (!detectorId) { throw new InvalidInputError('Missing detectorId'); @@ -98,7 +98,7 @@ class LockController { res.status(200).json(this._lockService.locksByDetectorToJSON()); } } catch (error) { - this._logger.errorMessage(error, {level: ERROR_LOG_LEVEL, facility: LOG_FACILITY}); + this._logger.errorMessage(error, { level: ERROR_LOG_LEVEL, facility: LOG_FACILITY }); updateExpressResponseFromNativeError(res, error); } } diff --git a/Control/lib/controllers/Run.controller.js b/Control/lib/controllers/Run.controller.js index 714bd31ae..f20574bdd 100644 --- a/Control/lib/controllers/Run.controller.js +++ b/Control/lib/controllers/Run.controller.js @@ -10,12 +10,13 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ -const {Log} = require('@aliceo2/web-ui'); + */ +const { Log } = require('@aliceo2/web-ui'); + const LOG_FACILITY = 'run-ctrl'; -const {updateExpressResponseFromNativeError} = require('./../errors/updateExpressResponseFromNativeError.js'); -const {CacheKeys} = require('./../common/cacheKeys.enum.js'); -const {LOG_LEVEL} = require('./../common/logLevel.enum.js'); +const { updateExpressResponseFromNativeError } = require('./../errors/updateExpressResponseFromNativeError.js'); +const { CacheKeys } = require('./../common/cacheKeys.enum.js'); +const { LOG_LEVEL } = require('./../common/logLevel.enum.js'); /** * Controller for dealing with all API requests on retrieving information on runs @@ -43,6 +44,7 @@ class RunController { /** * API - GET endpoint for retrieving calibration runs * @param {Request} req - HTTP Request object + * @param _ * @param {Response} res - HTTP Response object * @returns {void} */ @@ -68,23 +70,24 @@ class RunController { * API - GET endpoint to request a re-init of the run service which will update calibration configurations * The handler also must check that the user making the request is allowed for such operation * @param {Request} _ - HTTP Request object + * @param req * @param {Response} res - HTTP Response object * @returns {void} */ async refreshCalibrationRunsConfigurationHandler(req, res) { try { - let logMessage = `Refresh calibration configuration requested by user(${req.session.username})`; - this._logger.infoMessage(logMessage, {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY}); + const logMessage = `Refresh calibration configuration requested by user(${req.session.username})`; + this._logger.infoMessage(logMessage, { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: LOG_FACILITY }); await this._runService.retrieveStaticConfigurations(); - res.status(200).json({ok: true}); + res.status(200).json({ ok: true }); } catch (error) { const logMessage = `Error refreshing calibration configuration by ${req.session.username} due to: ${error}`; - this._logger.errorMessage(logMessage, {level: LOG_LEVEL.OPERATIONS, facility: LOG_FACILITY}) + this._logger.errorMessage(logMessage, { level: LOG_LEVEL.OPERATIONS, facility: LOG_FACILITY }); updateExpressResponseFromNativeError(res, error); } } } -module.exports = {RunController}; +module.exports = { RunController }; diff --git a/Control/lib/controllers/Status.controller.js b/Control/lib/controllers/Status.controller.js index 80d2ad007..28c107c30 100644 --- a/Control/lib/controllers/Status.controller.js +++ b/Control/lib/controllers/Status.controller.js @@ -10,8 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ -const {Log} = require('@aliceo2/web-ui'); + */ +const { Log } = require('@aliceo2/web-ui'); + const LOG_LEVEL = 99; const LOG_FACILITY = 'cog/status-ctrl'; @@ -50,8 +51,8 @@ class StatusController { res.status(200).json(componentStatus); } catch (error) { const message = 'Unable to retrieve status of CONSUL'; - this.log.errorMessage(message, {level: LOG_LEVEL, facility: LOG_FACILITY}); - res.status(502).json({message}); + this.log.errorMessage(message, { level: LOG_LEVEL, facility: LOG_FACILITY }); + res.status(502).json({ message }); } } @@ -67,8 +68,8 @@ class StatusController { res.status(200).json(componentStatus); } catch (error) { const message = 'Unable to retrieve status of GRAFANA'; - this.log.errorMessage(message, {level: LOG_LEVEL, facility: LOG_FACILITY}); - res.status(502).json({message}); + this.log.errorMessage(message, { level: LOG_LEVEL, facility: LOG_FACILITY }); + res.status(502).json({ message }); } } @@ -83,8 +84,8 @@ class StatusController { res.status(200).json(componentStatus); } catch (error) { const message = 'Unable to retrieve status of NOTIFICATION SYSTEM'; - this.log.errorMessage(message, {level: LOG_LEVEL, facility: LOG_FACILITY}); - res.status(502).json({message}); + this.log.errorMessage(message, { level: LOG_LEVEL, facility: LOG_FACILITY }); + res.status(502).json({ message }); } } @@ -98,8 +99,8 @@ class StatusController { res.status(200).json(this._statusService.getGuiStatus()); } catch (error) { const message = 'Unable to retrieve status of AliECS GUI'; - this.log.errorMessage(message, {level: LOG_LEVEL, facility: LOG_FACILITY}); - res.status(502).json({message}); + this.log.errorMessage(message, { level: LOG_LEVEL, facility: LOG_FACILITY }); + res.status(502).json({ message }); } } @@ -114,8 +115,8 @@ class StatusController { res.status(200).json(componentStatus); } catch (error) { const message = 'Unable to retrieve status of AliECS CORE'; - this.log.errorMessage(message, {level: LOG_LEVEL, facility: LOG_FACILITY}); - res.status(502).json({message}); + this.log.errorMessage(message, { level: LOG_LEVEL, facility: LOG_FACILITY }); + res.status(502).json({ message }); } } @@ -130,8 +131,8 @@ class StatusController { res.status(200).json(componentStatus); } catch (error) { const message = 'Unable to retrieve status of APRICOT'; - this.log.errorMessage(message, {level: LOG_LEVEL, facility: LOG_FACILITY}); - res.status(502).json({message}); + this.log.errorMessage(message, { level: LOG_LEVEL, facility: LOG_FACILITY }); + res.status(502).json({ message }); } } @@ -146,8 +147,8 @@ class StatusController { res.status(200).json(componentStatus); } catch (error) { const message = 'Unable to retrieve status of AliECS Integrated Services'; - this.log.errorMessage(message, {level: LOG_LEVEL, facility: LOG_FACILITY}); - res.status(502).json({message}); + this.log.errorMessage(message, { level: LOG_LEVEL, facility: LOG_FACILITY }); + res.status(502).json({ message }); } } @@ -163,7 +164,7 @@ class StatusController { } catch (error) { console.error(error); const message = 'Unable to retrieve FLP and PDP versions'; - res.status(502).json({message}); + res.status(502).json({ message }); } } } diff --git a/Control/lib/controllers/WorkflowTemplate.controller.js b/Control/lib/controllers/WorkflowTemplate.controller.js index 79550dbf0..25f982de2 100644 --- a/Control/lib/controllers/WorkflowTemplate.controller.js +++ b/Control/lib/controllers/WorkflowTemplate.controller.js @@ -10,8 +10,8 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ -const {updateExpressResponseFromNativeError} = require('./../errors/updateExpressResponseFromNativeError.js'); + */ +const { updateExpressResponseFromNativeError } = require('./../errors/updateExpressResponseFromNativeError.js'); /** * Controller for dealing with all API requests on workflow templates from AliECS: @@ -22,7 +22,6 @@ class WorkflowTemplateController { * @param {WorkflowTemplateService} workflowService - service to use to query AliECS with regards to workflow templates */ constructor(workflowService) { - /** * @type {WorkflowTemplateService} */ @@ -32,6 +31,7 @@ class WorkflowTemplateController { /** * API - GET endpoint for retrieving source of the default workflow template used by AliECS * @param {Request} req - HTTP Request object + * @param _ * @param {Response} res - HTTP Response object with EnvironmentDetails * @returns {void} */ @@ -67,9 +67,9 @@ class WorkflowTemplateController { */ async getWorkflowConfiguration(req, res) { try { - const {name} = req.query; + const { name } = req.query; if (!name) { - res.status(400).json({message: 'No name for the configuration provided'}); + res.status(400).json({ message: 'No name for the configuration provided' }); return; } const mappings = await this._workflowService.retrieveWorkflowSavedConfiguration(name); @@ -80,4 +80,4 @@ class WorkflowTemplateController { } } -module.exports = {WorkflowTemplateController}; +module.exports = { WorkflowTemplateController }; diff --git a/Control/lib/dtos/CoreEnvConfig.js b/Control/lib/dtos/CoreEnvConfig.js index db877dcfa..d6c998dc4 100644 --- a/Control/lib/dtos/CoreEnvConfig.js +++ b/Control/lib/dtos/CoreEnvConfig.js @@ -10,10 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ 'use strict'; -const {User} = require('./User.js'); +const { User } = require('./User.js'); /** * CoreEnvConfig DTO @@ -62,7 +62,7 @@ class CoreEnvConfig { const envConfig = new CoreEnvConfig(); envConfig._user = { username: data?.user?.username ?? 'anonymous', - personid: data?.user?.personid ?? 0 + personid: data?.user?.personid ?? 0, }; envConfig._created = data.created ?? Date.now(); envConfig._edited = data.edited ?? Date.now(); @@ -80,7 +80,7 @@ class CoreEnvConfig { /** * Method to parse a string into a JSON and attempt to create an environment configuration with it; * If successful, it will written an CoreEnvConfig - * @param {String} data - string version of a JSON + * @param {string} data - string version of a JSON * @returns {CoreEnvConfig} */ static fromString(data) { @@ -90,7 +90,7 @@ class CoreEnvConfig { /** * Returns a string version of the current CoreEnvConfig with new lines and spaces (2) - * @returns {String} + * @returns {string} */ toString() { const envConfig = { @@ -101,11 +101,11 @@ class CoreEnvConfig { edited: this._edited, workflow: this._workflow, revision: this._revision, - repository: this._repository, + repository: this._repository, variables: this._variables, detectors: this._detectors, - } - return JSON.stringify(envConfig, null, 2) + }; + return JSON.stringify(envConfig, null, 2); } /** @@ -123,8 +123,8 @@ class CoreEnvConfig { * Build the ID of the configuration to be saved from the name: * * Replace any existing `/` from it with `_` so that Apricot is able to understand Consul storage * * Replace any spaces from it with `_` - * @param {String} name - * @returns {String} + * @param {string} name + * @returns {string} */ static _getNameAsId(name) { return `${name.trim().replace(/ /g, '_')}`.replace(/\//g, '_'); @@ -147,7 +147,7 @@ class CoreEnvConfig { /** * Return the id of an environment configuration - * @returns {String} + * @returns {string} */ get id() { return this._id; @@ -155,7 +155,7 @@ class CoreEnvConfig { /** * Return the person id that has created the configuration - * @returns {String} + * @returns {string} */ get personId() { return this._user.personid; diff --git a/Control/lib/dtos/DetectorLock.js b/Control/lib/dtos/DetectorLock.js index 3014884a1..47928dcd0 100644 --- a/Control/lib/dtos/DetectorLock.js +++ b/Control/lib/dtos/DetectorLock.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {DetectorLockState} = require('../common/lock/detectorLockState.enum.js'); +const { DetectorLockState } = require('../common/lock/detectorLockState.enum.js'); /** * DetectorLock representation as used for ECS GUI purposes @@ -20,13 +20,12 @@ const {DetectorLockState} = require('../common/lock/detectorLockState.enum.js'); class DetectorLock { /** * Initializing a lock with a free state - * @param {String} name - name of the detector + * @param {string} name - name of the detector */ constructor(name) { - /** * Name of the detector the lock represents - * @type {String} + * @type {string} */ this._name = name; @@ -44,16 +43,17 @@ class DetectorLock { /** * Method to assign a user to a lock * @param {User} - user that is to own the lock - * @return {void} + * @param user + * @returns {void} */ assignOwner(user) { - this._state = DetectorLockState.TAKEN + this._state = DetectorLockState.TAKEN; this._owner = user; } /** * Method to allow the removal of a user of a lock - * @return {void} + * @returns {void} */ release() { this._state = DetectorLockState.FREE; @@ -63,7 +63,7 @@ class DetectorLock { /** * Given a user, check if the lock is currently assigned by the respective user * @param {User} user - to check ownership of - * @return {Boolean} + * @returns {boolean} */ isOwnedBy(user) { return this._owner && this._owner.isSameUser(user); @@ -71,7 +71,7 @@ class DetectorLock { /** * Method to return if the lock is currently taken - * @return {Boolean} - if state of detector lock is taken + * @returns {boolean} - if state of detector lock is taken */ isTaken() { return this._state === DetectorLockState.TAKEN; @@ -79,7 +79,7 @@ class DetectorLock { /** * Method to return if the lock is currently free - * @return {Boolean} - if state of detector lock is free + * @returns {boolean} - if state of detector lock is free */ isFree() { return this._state === DetectorLockState.FREE; @@ -87,7 +87,7 @@ class DetectorLock { /** * Return a user object currently owning the lock - * @return {User} + * @returns {User} */ get owner() { return this._owner; @@ -95,14 +95,14 @@ class DetectorLock { /** * Return a JSON representation of the lock that is to be passed via HTTP - * @return {JSON{DetectorLock}} + * @returns {JSON{DetectorLock}} */ toJSON() { return { name: this._name, state: this._state, owner: this._owner?.toJSON(), - } + }; } } diff --git a/Control/lib/dtos/Service.js b/Control/lib/dtos/Service.js index 87f3114fa..dad10aab3 100644 --- a/Control/lib/dtos/Service.js +++ b/Control/lib/dtos/Service.js @@ -10,14 +10,13 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ 'use strict'; const KNOWN_FIELDS = ['data', 'hostname', 'port', 'connectionState', 'enabled', 'endpoint']; /** * Service DTO representation - * * @property {string} name * @property {string} endpoint * @property {string} [version] @@ -42,16 +41,16 @@ class Service { const name = Service._getNameOfService(service); const endpoint = Service._getEndpoint(service); const data = Service._getDataOfService(service); - + const serviceToReturn = { - ...name && {name}, - ...endpoint && {endpoint}, - ...service.version && {version: service.version}, - ...service.connectionState && {connectionState: service.connectionState}, - extras: {...data}, - } + ...name && { name }, + ...endpoint && { endpoint }, + ...service.version && { version: service.version }, + ...service.connectionState && { connectionState: service.connectionState }, + extras: { ...data }, + }; Object.keys(service) - .filter((name) => !(KNOWN_FIELDS.includes(name))) + .filter((name) => !KNOWN_FIELDS.includes(name)) .filter((name) => !serviceToReturn[name]) .forEach((key) => serviceToReturn.extras[key] = service[key]); return serviceToReturn; @@ -59,7 +58,7 @@ class Service { /** * Given a general service object, build the endpoint of it or return undefined if not possible - * @param {object} service + * @param {object} service * @returns {string|undefined} */ static _getEndpoint(service) { @@ -67,28 +66,30 @@ class Service { return service.endpoint; } else if (service.hostname) { const protocol = service.protocol ? `${service.protocol}://` : ''; - const hostname = service.hostname; + const { hostname } = service; const port = service.port ?? ''; return `${protocol}${hostname}:${port}`; - } + } return undefined; } /** * Given a general service object, return its trimmed value if there is or undefined - * @param {object} service + * @param {object} service + * @param service.name * @returns {string|undefined} */ - static _getNameOfService({name}) { + static _getNameOfService({ name }) { return name && name?.trim() !== '' ? name : undefined; } /** * Given a general service object, look for AliECS Integrated services particularities such as "data" field of type string and return it parsed as JSON - * @param {object} service + * @param {object} service + * @param service.data * @returns {JSON|undefined} */ - static _getDataOfService({data}) { + static _getDataOfService({ data }) { if (data && typeof data === 'string') { try { const dataJson = JSON.parse(data); diff --git a/Control/lib/dtos/User.js b/Control/lib/dtos/User.js index 76155f330..395190c45 100644 --- a/Control/lib/dtos/User.js +++ b/Control/lib/dtos/User.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ 'use strict'; /** @@ -19,29 +19,29 @@ class User { /** * Initializing an environment configuration - * @param {String} username - username of the user - * @param {String} fullName - full name to be displayed for the user - * @param {Number} personid - id of the user - * @param {Array|String} access - list of access roles of the user + * @param {string} username - username of the user + * @param {string} fullName - full name to be displayed for the user + * @param {number} personid - id of the user + * @param {Array | string} access - list of access roles of the user */ constructor(username, fullName, personid, access = []) { /** - * @type {String} + * @type {string} */ this._username = username; /** - * @type {String} + * @type {string} */ this._fullName = fullName; /** - * @type {Number} + * @type {number} */ this._personid = personid; /** - * @type {Array} + * @type {Array} */ this._accessList = []; if (typeof access === 'string') { @@ -54,9 +54,9 @@ class User { /** * Checks if the given user is considered admin * @param {User} user - user type object as defined by webui/framework - * @returns {Boolean} + * @returns {boolean} */ - static isAdmin({access = ''}) { + static isAdmin({ access = '' }) { let accessList = []; if (typeof access === 'string') { accessList = access.split(','); @@ -69,7 +69,7 @@ class User { /** * Check if provided details of a user are the same as the current instance one; * @param {User} user - to compare to - * @return {Boolean} + * @returns {boolean} */ isSameUser(user) { return this._username === user.username && this._personid === this.personid; @@ -77,7 +77,7 @@ class User { /** * Returns the username - * @returns {String} + * @returns {string} */ get username() { return this._username; @@ -85,7 +85,7 @@ class User { /** * Returns the full name of the user - * @returns {String} + * @returns {string} */ get fullName() { return this._fullName; @@ -93,7 +93,7 @@ class User { /** * Returns the personid of the user - * @returns {Number} + * @returns {number} */ get personid() { return this._personid; @@ -101,7 +101,7 @@ class User { /** * Returns the access granted to this user - * @returns {Array} + * @returns {Array} */ get access() { return this._accessList; @@ -109,7 +109,7 @@ class User { /** * Returns the JSON representation of the user that is to be sent via HTTP - * @return {JSON{User}} + * @returns {JSON{User}} */ toJSON() { return { diff --git a/Control/lib/errors/grpcErrorToNativeError.js b/Control/lib/errors/grpcErrorToNativeError.js index 3bb0a24c3..60baf4257 100644 --- a/Control/lib/errors/grpcErrorToNativeError.js +++ b/Control/lib/errors/grpcErrorToNativeError.js @@ -11,14 +11,13 @@ * or submit itself to any jurisdiction. */ -const {NotFoundError} = require('./NotFoundError.js'); -const {InvalidInputError} = require('./InvalidInputError.js'); -const {TimeoutError} = require('./TimeoutError.js'); +const { NotFoundError } = require('./NotFoundError.js'); +const { InvalidInputError } = require('./InvalidInputError.js'); +const { TimeoutError } = require('./TimeoutError.js'); /** * Convert a gRPC error to native error * Code List source: https://grpc.github.io/grpc/core/md_doc_statuscodes.html - * * @param {gRPCError} error - error object from gRPC Client library * @returns {Error} */ diff --git a/Control/lib/errors/updateExpressResponseFromNativeError.js b/Control/lib/errors/updateExpressResponseFromNativeError.js index ede5666c1..b7ad033af 100644 --- a/Control/lib/errors/updateExpressResponseFromNativeError.js +++ b/Control/lib/errors/updateExpressResponseFromNativeError.js @@ -11,22 +11,21 @@ * or submit itself to any jurisdiction. */ -const {UnauthorizedAccessError} = require('./UnauthorizedAccessError.js'); -const {InvalidInputError} = require('./InvalidInputError.js'); -const {NotFoundError} = require('./NotFoundError.js'); -const {TimeoutError} = require('./TimeoutError.js'); +const { UnauthorizedAccessError } = require('./UnauthorizedAccessError.js'); +const { InvalidInputError } = require('./InvalidInputError.js'); +const { NotFoundError } = require('./NotFoundError.js'); +const { TimeoutError } = require('./TimeoutError.js'); /** * Update (in place) the given Express response considering a given error * If the error is specific, the response status may be set to a specific error code - * * @param {Response} response - express response to be used * @param {Error} error - the error instance to handle * @returns {void} */ const updateExpressResponseFromNativeError = (response, error) => { let status = 500; - const {message, constructor} = error; + const { message, constructor } = error; switch (constructor) { case InvalidInputError: status = 400; @@ -41,7 +40,7 @@ const updateExpressResponseFromNativeError = (response, error) => { status = 408; break; } - response.status(status).json({message}); + response.status(status).json({ message }); }; exports.updateExpressResponseFromNativeError = updateExpressResponseFromNativeError; diff --git a/Control/lib/middleware/lockOwnership.middleware.js b/Control/lib/middleware/lockOwnership.middleware.js index 20d8571d8..c0dbd4e8b 100644 --- a/Control/lib/middleware/lockOwnership.middleware.js +++ b/Control/lib/middleware/lockOwnership.middleware.js @@ -11,28 +11,28 @@ * or submit itself to any jurisdiction. */ -const {User} = require('../dtos/User'); -const {grpcErrorToNativeError} = require('../errors/grpcErrorToNativeError'); -const {updateExpressResponseFromNativeError} = require('../errors/updateExpressResponseFromNativeError'); +const { User } = require('../dtos/User'); +const { grpcErrorToNativeError } = require('../errors/grpcErrorToNativeError'); +const { updateExpressResponseFromNativeError } = require('../errors/updateExpressResponseFromNativeError'); /** * Middleware function to check that the user has ownership of the locks for the given detectors - * * @param {LockService} lockService - service to be used to check ownership of locks * @param {EnvironmentService} environmentService - service to be used to retrieve environment information - * @return {function(req, res, next): void} - middleware function + * @returns {function(req, res, next): void} - middleware function */ -const lockOwnershipMiddleware = (lockService, environmentService) => { +const lockOwnershipMiddleware = (lockService, environmentService) => + /** * Middleware function to check that the user has ownership of the locks for the given detectors * @param {Request} req - HTTP Request object * @param {Response} res - HTTP Response object * @param {Next} next - HTTP Next object to use if checks pass - * @return {void} continue if checks pass, 403 if checks fail + * @returns {void} continue if checks pass, 403 if checks fail */ - return async (req, res, next) => { - const {name, username, personid, access} = req.session; - const {id = ''} = req.body ?? {}; + async (req, res, next) => { + const { name, username, personid, access } = req.session; + const { id = '' } = req.body ?? {}; let detectors = []; try { @@ -45,7 +45,7 @@ const lockOwnershipMiddleware = (lockService, environmentService) => { } try { if (!lockService.hasLocks(new User(username, name, personid, access), detectors)) { - res.status(403).json({message: `Action not allowed for user ${name} due to missing ownership of lock(s)`}); + res.status(403).json({ message: `Action not allowed for user ${name} due to missing ownership of lock(s)` }); } else { next(); } @@ -54,6 +54,5 @@ const lockOwnershipMiddleware = (lockService, environmentService) => { updateExpressResponseFromNativeError(res, error); } }; -}; -exports.lockOwnershipMiddleware = lockOwnershipMiddleware +exports.lockOwnershipMiddleware = lockOwnershipMiddleware; diff --git a/Control/lib/middleware/minimumRole.middleware.js b/Control/lib/middleware/minimumRole.middleware.js index bee85d2d7..f2498cf88 100644 --- a/Control/lib/middleware/minimumRole.middleware.js +++ b/Control/lib/middleware/minimumRole.middleware.js @@ -10,26 +10,27 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {isRoleSufficient} = require('../common/role.enum.js'); -const {UnauthorizedAccessError} = require('../errors/UnauthorizedAccessError.js'); -const {updateExpressResponseFromNativeError} = require('../errors/updateExpressResponseFromNativeError.js'); +const { isRoleSufficient } = require('../common/role.enum.js'); +const { UnauthorizedAccessError } = require('../errors/UnauthorizedAccessError.js'); +const { updateExpressResponseFromNativeError } = require('../errors/updateExpressResponseFromNativeError.js'); /** * Method to receive a minimum role that needs to be met by owner of request and to return a middleware function * @param {Role} minimumRole - minimum role that should be fulfilled by the requestor - * @return {function(req, res, next): void} - middleware function + * @returns {function(req, res, next): void} - middleware function */ -const minimumRoleMiddleware = (minimumRole) => { +const minimumRoleMiddleware = (minimumRole) => + /** * Returned middleware method * @param {Request} req - HTTP Request object * @param {Next} next - HTTP Next object to use if checks pass * @param {Response} res - HTTP Response object - * @return {void} + * @returns {void} */ - return (req, res, next) => { + (req, res, next) => { try { const { access } = req?.session ?? ''; @@ -41,8 +42,9 @@ const minimumRoleMiddleware = (minimumRole) => { } const isAllowed = accessList.some((role) => isRoleSufficient(role, minimumRole)); if (!isAllowed) { - updateExpressResponseFromNativeError(res, - new UnauthorizedAccessError('Not enough permissions for this operation') + updateExpressResponseFromNativeError( + res, + new UnauthorizedAccessError('Not enough permissions for this operation'), ); return; } @@ -51,7 +53,6 @@ const minimumRoleMiddleware = (minimumRole) => { console.error(error); updateExpressResponseFromNativeError(res, error); } - } -}; + }; exports.minimumRoleMiddleware = minimumRoleMiddleware; diff --git a/Control/lib/services/Bookkeeping.service.js b/Control/lib/services/Bookkeeping.service.js index 763a8d082..70362e4e2 100644 --- a/Control/lib/services/Bookkeeping.service.js +++ b/Control/lib/services/Bookkeeping.service.js @@ -10,12 +10,12 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {Log} = require('@aliceo2/web-ui'); -const {httpGetJson} = require('./../utils.js'); +const { Log } = require('@aliceo2/web-ui'); +const { httpGetJson } = require('./../utils.js'); const RunSummaryAdapter = require('./../adapters/RunSummaryAdapter.js'); -const {BookkeepingFilterAdapter} = require('./../adapters/external/BookkeepingFilterAdapter.js'); +const { BookkeepingFilterAdapter } = require('./../adapters/external/BookkeepingFilterAdapter.js'); const DEFAULT_REFRESH_RATE = 30000; @@ -25,11 +25,14 @@ const DEFAULT_REFRESH_RATE = 30000; class BookkeepingService { /** * Constructor for configuring the service to retrieve data via Bookkeeping HTTP API - * @param {Object} config = {url: string, token: string} - configuration for using BKP service + * @param {object} config = {url: string, token: string} - configuration for using BKP service + * @param config.url + * @param config.token + * @param config.refreshRate */ - constructor({url, token, refreshRate}) { + constructor({ url, token, refreshRate }) { this._url = url ?? null; - const {protocol, hostname, port} = url ? new URL(this._url) : {}; + const { protocol, hostname, port } = url ? new URL(this._url) : {}; this._hostname = hostname; this._port = port; this._protocol = protocol; @@ -42,13 +45,13 @@ class BookkeepingService { /** * Given a definition, a type of a run and a detector, fetch from Bookkeeping the last RUN matching the parameters - * @param {Object} filter - definition of the run to query - * @return {RunSummary|{}} - run object from Bookkeeping + * @param {Object} filter - definition of the run to query + * @returns {RunSummary|{}} - run object from Bookkeeping */ async getRun(filter) { const filterAsString = BookkeepingFilterAdapter.toString(filter); try { - const {data} = await httpGetJson(this._hostname, this._port, `/api/runs?${filterAsString}&token=${this._token}`, { + const { data } = await httpGetJson(this._hostname, this._port, `/api/runs?${filterAsString}&token=${this._token}`, { protocol: this._protocol, rejectUnauthorized: false, }); @@ -63,12 +66,12 @@ class BookkeepingService { /** * Method to fetch run types from Bookkeeping and build a map of types to IDs as needed for filtering in RUNs API - * @returns {Object} - map of runtypes to their ID + * @returns {Object} - map of runtypes to their ID */ async getRunTypes() { try { const runTypesMap = {}; - const {data} = await httpGetJson(this._hostname, this._port, `/api/runTypes?token=${this._token}`, { + const { data } = await httpGetJson(this._hostname, this._port, `/api/runTypes?token=${this._token}`, { protocol: this._protocol, rejectUnauthorized: false, }); @@ -88,11 +91,11 @@ class BookkeepingService { /** * Getter for retrieving the rate of refreshing data from Bookkeeping - * @return {Number} + * @returns {number} */ get refreshRate() { return this._refreshRate; } } -module.exports = {BookkeepingService}; +module.exports = { BookkeepingService }; diff --git a/Control/lib/services/Broadcast.service.js b/Control/lib/services/Broadcast.service.js index 1273324aa..c6a7ca20e 100644 --- a/Control/lib/services/Broadcast.service.js +++ b/Control/lib/services/Broadcast.service.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {WebSocketMessage} = require('@aliceo2/web-ui'); +const { WebSocketMessage } = require('@aliceo2/web-ui'); /** * @class @@ -20,7 +20,7 @@ const {WebSocketMessage} = require('@aliceo2/web-ui'); */ class BroadcastService { /** - * @constructor + * @class * Constructor for initializing the service with AliceO2/websocket service instance to use * @param {WebSocket} wsService - which is to be used for broadcasting */ @@ -33,9 +33,9 @@ class BroadcastService { /** * Method to receive command and payload to build a WebSocket message and broadcast it to all listening clients - * @param {String} command - command to be added to websocket message - * @param {Object} payload - payload to be sent to the clients - * @return {void} + * @param {string} command - command to be added to websocket message + * @param {object} payload - payload to be sent to the clients + * @returns {void} */ broadcast(command, payload) { if (payload) { diff --git a/Control/lib/services/Cache.service.js b/Control/lib/services/Cache.service.js index 8b4a39d27..4222e9fd0 100644 --- a/Control/lib/services/Cache.service.js +++ b/Control/lib/services/Cache.service.js @@ -10,10 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {Log} = require('@aliceo2/web-ui'); -const {deepStrictEqual, AssertionError} = require('assert'); +const { Log } = require('@aliceo2/web-ui'); +const { deepStrictEqual, AssertionError } = require('assert'); /** * @class @@ -21,16 +21,15 @@ const {deepStrictEqual, AssertionError} = require('assert'); */ class CacheService { /** - * @constructor + * @class * Constructor for initializing the service with: * - empty maps for needed information * - optional service for broadcasting information * @param {BroadcastService} broadcastService - which is to be used for broadcasting */ constructor(broadcastService) { - /** - * @type {Object} + * @type {Object} */ this._memory = {}; @@ -43,13 +42,14 @@ class CacheService { } /** - * Method to receive a function for retrieval of information and a key under which the information should be updated - * @param {String} key - key under which the information should be stored - * @param {String} value - command to be used for broadcasting message - * @param {Object} broadcastConfig - object containing broadcast information; if present information will be broadcasted - * @return {void} + * Method to receive a function for retrieval of information and a key under which the information should be updated + * @param {string} key - key under which the information should be stored + * @param {string} value - command to be used for broadcasting message + * @param {object} broadcastConfig - object containing broadcast information; if present information will be broadcasted + * @param broadcastConfig.command + * @returns {void} */ - async updateByKeyAndBroadcast(key, value, {command} = {}) { + async updateByKeyAndBroadcast(key, value, { command } = {}) { if (value) { try { deepStrictEqual(value, this._memory[key]); @@ -69,7 +69,8 @@ class CacheService { /** * Getter for retrieving a copy of the information stored in-memory under a certain key * @param {key} - key under which information is stored - * @return {Object} + * @param key + * @returns {object} */ getByKey(key) { if (this._memory[key]) { @@ -79,4 +80,4 @@ class CacheService { } } -module.exports = {CacheService}; +module.exports = { CacheService }; diff --git a/Control/lib/services/Detector.service.js b/Control/lib/services/Detector.service.js index 783e9cba3..d7dc81434 100644 --- a/Control/lib/services/Detector.service.js +++ b/Control/lib/services/Detector.service.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** * @class @@ -18,7 +18,7 @@ */ class DetectorService { /** - * @constructor + * @class * Constructor for initializing the service with gRPC core service * @param {CoreProxy} coreGrpc - interface to interact with gRPC AliECS core service */ @@ -31,15 +31,15 @@ class DetectorService { /** * Method to retrieve which detectors are currently active and compare to received input - * @param {Array} detectors - list of strings with detector name - * @return {boolean} + * @param {Array} detectors - list of strings with detector name + * @returns {boolean} * @throws {gRPCError} */ async areDetectorsAvailable(detectors) { - const {detectors: activeDetectors} = await this._coreGrpc['GetActiveDetectors'](); + const { detectors: activeDetectors } = await this._coreGrpc['GetActiveDetectors'](); const areDetectorsNonActive = detectors.every((detector) => !activeDetectors.includes(detector)); return areDetectorsNonActive; } } -module.exports = {DetectorService}; +module.exports = { DetectorService }; diff --git a/Control/lib/services/Environment.service.js b/Control/lib/services/Environment.service.js index a661addfd..7c19edb53 100644 --- a/Control/lib/services/Environment.service.js +++ b/Control/lib/services/Environment.service.js @@ -10,13 +10,13 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {NotFoundError} = require('@aliceo2/web-ui'); -const {CacheKeys} = require('./../common/cacheKeys.enum.js'); +const { NotFoundError } = require('@aliceo2/web-ui'); +const { CacheKeys } = require('./../common/cacheKeys.enum.js'); const EnvironmentInfoAdapter = require('./../adapters/EnvironmentInfoAdapter.js'); -const {EnvironmentTransitionResultAdapter} = require('./../adapters/EnvironmentTransitionResultAdapter.js'); -const {grpcErrorToNativeError} = require('./../errors/grpcErrorToNativeError.js'); +const { EnvironmentTransitionResultAdapter } = require('./../adapters/EnvironmentTransitionResultAdapter.js'); +const { grpcErrorToNativeError } = require('./../errors/grpcErrorToNativeError.js'); /** * EnvironmentService class to be used to retrieve data from AliEcs Core via the gRPC Control client @@ -24,9 +24,10 @@ const {grpcErrorToNativeError} = require('./../errors/grpcErrorToNativeError.js' class EnvironmentService { /** * Constructor for inserting dependencies needed to retrieve environment data - * @param {GrpcProxy} coreGrpc - * @param {ApricotProxy} apricotGrpc + * @param {GrpcProxy} coreGrpc + * @param {ApricotProxy} apricotGrpc * @param {CacheService} cacheService - to use for updating information on environments + * @param broadcastService */ constructor(coreGrpc, apricotGrpc, cacheService, broadcastService) { /** @@ -38,6 +39,7 @@ class EnvironmentService { * @type {ApricotProxy} */ this._apricotGrpc = apricotGrpc; + /** * @type {CacheService} */ @@ -54,17 +56,17 @@ class EnvironmentService { * Parses the environment and prepares the information for GUI purposes * @param {string} id - environment id as defined by AliECS Core * @param {string} taskSource - Source of where to request tasks from: FLP, EPN, QC, TRG - * @return {EnvironmentInfo} + * @returns {EnvironmentInfo} * @throws {Error} */ async getEnvironment(id, taskSource) { let grpcPayload = {}; try { - grpcPayload = await this._coreGrpc.GetEnvironment({id}); + grpcPayload = await this._coreGrpc.GetEnvironment({ id }); } catch (error) { throw grpcErrorToNativeError(error); } - if (!grpcPayload.environment) { + if (!grpcPayload.environment) { throw new NotFoundError(`Environment (id: ${id}) not found`); } const detectorsAll = this._apricotGrpc.detectors ?? []; @@ -74,10 +76,11 @@ class EnvironmentService { /** * Given an environment ID and a transition type, use the gRPC client to perform the transition - * @param {String} id - environment id as defined by AliECS Core + * @param {string} id - environment id as defined by AliECS Core * @param {EnvironmentTransitionType} transitionType - allowed transitions for an environment * @param {User} requestUser - user that requested the transition - * @return {EnvironmentTransitionResult} - result of the environment transition + * @param user + * @returns {EnvironmentTransitionResult} - result of the environment transition */ async transitionEnvironment(id, transitionType, user = {}) { try { @@ -85,7 +88,7 @@ class EnvironmentService { name: user.username ?? 'unknown', externalId: user.personId ?? 0, }; - const transitionedEnvironment = await this._coreGrpc.ControlEnvironment({id, type: transitionType, requestUser}); + const transitionedEnvironment = await this._coreGrpc.ControlEnvironment({ id, type: transitionType, requestUser }); return EnvironmentTransitionResultAdapter.toEntity(transitionedEnvironment); } catch (error) { throw grpcErrorToNativeError(error); @@ -94,14 +97,14 @@ class EnvironmentService { /** * Given an environment ID and optional parameters, use the gRPC client to send a request to destroy an environment - * @param {String} id - environment id as defined by AliECS Core - * @param {{keepTasks: Boolean, allowInRunningState: Boolean, force: Boolean}} - options for destroying the environment - * @return {Promise.<{String}, Error>} - if operation was a success or not + * @param {string} id - environment id as defined by AliECS Core + * @param {{keepTasks: boolean, allowInRunningState: boolean, force: boolean}} - options for destroying the environment + * @returns {Promise.<{String}, Error>} - if operation was a success or not */ - async destroyEnvironment(id, {keepTasks = false, allowInRunningState = false, force = false} = {}) { + async destroyEnvironment(id, { keepTasks = false, allowInRunningState = false, force = false } = {}) { try { - await this._coreGrpc.DestroyEnvironment({id, keepTasks, allowInRunningState, force}); - return {id}; + await this._coreGrpc.DestroyEnvironment({ id, keepTasks, allowInRunningState, force }); + return { id }; } catch (grpcError) { throw grpcErrorToNativeError(grpcError); } @@ -110,14 +113,14 @@ class EnvironmentService { /** * Given the workflowTemplate and variables configuration, it will generate a unique string and send all to AliECS to create a * new auto transitioning environment - * @param {String} workflowTemplate - name in format `repository/revision/template` - * @param {Object} vars - KV string pairs to define environment configuration - * @param {String} detector - on which the environment is deployed - * @param {String} runType - for which the environment is deployed - * @return {AutoEnvironmentDeployment} - if environment request was successfully sent + * @param {string} workflowTemplate - name in format `repository/revision/template` + * @param {Object} vars - KV string pairs to define environment configuration + * @param {string} detector - on which the environment is deployed + * @param {string} runType - for which the environment is deployed + * @returns {AutoEnvironmentDeployment} - if environment request was successfully sent */ async newAutoEnvironment(workflowTemplate, vars, detector, runType) { - const channelIdString = (Math.floor(Math.random() * (999999 - 100000) + 100000)).toString(); + const channelIdString = Math.floor(Math.random() * (999999 - 100000) + 100000).toString(); const autoEnvironment = { channelIdString, inProgress: true, @@ -130,8 +133,8 @@ class EnvironmentService { id: '-', message: 'request was sent to AliECS', at: Date.now(), - } - } + }, + }, ], }; let calibrationRunsRequests = this._cacheService.getByKey(CacheKeys.CALIBRATION_RUNS_REQUESTS); @@ -143,21 +146,19 @@ class EnvironmentService { } if (!calibrationRunsRequests[detector[runType]]) { calibrationRunsRequests[detector][runType] = autoEnvironment; - } this._cacheService.updateByKeyAndBroadcast(CacheKeys.CALIBRATION_RUNS_REQUESTS, calibrationRunsRequests); this._broadcastService.broadcast(CacheKeys.CALIBRATION_RUNS_REQUESTS, calibrationRunsRequests[detector][runType]); - const subscribeChannel = this._coreGrpc.client.Subscribe({id: channelIdString}); + const subscribeChannel = this._coreGrpc.client.Subscribe({ id: channelIdString }); subscribeChannel.on('data', (data) => this._onData(data, detector, runType)); subscribeChannel.on('error', (error) => this._onError(error, detector, runType)); subscribeChannel.on('end', () => this._onEnd(detector, runType)); - this._coreGrpc.NewAutoEnvironment({ vars, workflowTemplate, - id: channelIdString + id: channelIdString, }); return autoEnvironment; @@ -166,13 +167,13 @@ class EnvironmentService { /** * Method to parse incoming messages from stream channel * @param {Event} event - AliECS Event (proto) - * @param {String} detector - detector name for which the event was triggered - * @param {String} runType - run type for which the event was triggered - * @return {void} + * @param {string} detector - detector name for which the event was triggered + * @param {string} runType - run type for which the event was triggered + * @returns {void} */ _onData(event, detector, runType) { const events = []; - const {taskEvent, environmentEvent, timestamp = Date.now()} = event; + const { taskEvent, environmentEvent, timestamp = Date.now() } = event; if (taskEvent && (taskEvent.state === 'ERROR' || taskEvent.status === 'TASK_FAILED')) { events.push({ type: 'TASK', @@ -180,7 +181,7 @@ class EnvironmentService { ...taskEvent, at: Number(timestamp), message: 'Please ensure environment is killed before retrying', - } + }, }); } else if (environmentEvent) { events.push({ @@ -188,7 +189,7 @@ class EnvironmentService { payload: { ...environmentEvent, at: Number(timestamp), - } + }, }); } if (events.length > 0) { @@ -202,9 +203,9 @@ class EnvironmentService { /** * Method to be used in case of AliECS environment creation request error * @param {Error} error - error encountered during the creation of environment - * @param {String} detector - detector name for which the event was triggered - * @param {String} runType - run type for which the event was triggered - * @return {void} + * @param {string} detector - detector name for which the event was triggered + * @param {string} runType - run type for which the event was triggered + * @returns {void} */ _onError(error, detector, runType) { const calibrationRunsRequests = this._cacheService.getByKey(CacheKeys.CALIBRATION_RUNS_REQUESTS); @@ -212,15 +213,15 @@ class EnvironmentService { type: 'ERROR', payload: { error, - at: Date.now() - } + at: Date.now(), + }, }); calibrationRunsRequests[detector][runType].events.push({ type: 'ERROR', payload: { error: 'Please ensure environment is killed before retrying', - at: Date.now() - } + at: Date.now(), + }, }); this._cacheService.updateByKeyAndBroadcast(CacheKeys.CALIBRATION_RUNS_REQUESTS, calibrationRunsRequests); this._broadcastService.broadcast(CacheKeys.CALIBRATION_RUNS_REQUESTS, calibrationRunsRequests[detector][runType]); @@ -228,9 +229,9 @@ class EnvironmentService { /** * Method to be used for when environment successfully finished transitioning - * @param {String} detector - detector name for which the event was triggered - * @param {String} runType - run type for which the event was triggered - * @return {void} + * @param {string} detector - detector name for which the event was triggered + * @param {string} runType - run type for which the event was triggered + * @returns {void} */ _onEnd(detector, runType) { const calibrationRunsRequests = this._cacheService.getByKey(CacheKeys.CALIBRATION_RUNS_REQUESTS); @@ -238,8 +239,8 @@ class EnvironmentService { type: 'ENVIRONMENT', payload: { at: Date.now(), - message: 'Stream has now ended' - } + message: 'Stream has now ended', + }, }); calibrationRunsRequests[detector][runType].inProgress = false; this._cacheService.updateByKeyAndBroadcast(CacheKeys.CALIBRATION_RUNS_REQUESTS, calibrationRunsRequests); @@ -247,4 +248,4 @@ class EnvironmentService { } } -module.exports = {EnvironmentService}; +module.exports = { EnvironmentService }; diff --git a/Control/lib/services/Intervals.service.js b/Control/lib/services/Intervals.service.js index 165d5c339..d9f4b5e62 100644 --- a/Control/lib/services/Intervals.service.js +++ b/Control/lib/services/Intervals.service.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const DEFAULT_INTERVAL_RATE = 60 * 1000; @@ -20,7 +20,7 @@ const DEFAULT_INTERVAL_RATE = 60 * 1000; */ class Intervals { /** - * @constructor + * @class * Constructor for initializing a list of intervals */ constructor() { @@ -32,9 +32,9 @@ class Intervals { /** * Method to allow other services to register events that should trigger based on an interval rate - * @param {function} callback - function that should be called based on interval rate + * @param {Function} callback - function that should be called based on interval rate * @param {number} intervalRate = 60 * 1000 - (ms) on how often the callback should be called - * @return {Symbol} - unique key for registered callback + * @returns {symbol} - unique key for registered callback */ register(callback, intervalRate = DEFAULT_INTERVAL_RATE) { const key = Symbol(Math.random()); @@ -44,8 +44,8 @@ class Intervals { /** * Method to allow services to deregister and clear an interval - * @param {Symbol} key - key under which the interval was registered - * @return {void} + * @param {symbol} key - key under which the interval was registered + * @returns {void} */ deregister(key) { clearInterval(this._intervals[key]); diff --git a/Control/lib/services/Lock.service.js b/Control/lib/services/Lock.service.js index dacc6600c..12d502f54 100644 --- a/Control/lib/services/Lock.service.js +++ b/Control/lib/services/Lock.service.js @@ -10,11 +10,11 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {DetectorLock} = require('./../dtos/DetectorLock.js'); -const {NotFoundError} = require('../errors/NotFoundError.js'); -const {UnauthorizedAccessError} = require('./../errors/UnauthorizedAccessError'); +const { DetectorLock } = require('./../dtos/DetectorLock.js'); +const { NotFoundError } = require('../errors/NotFoundError.js'); +const { UnauthorizedAccessError } = require('./../errors/UnauthorizedAccessError'); const PADLOCK_UPDATE = 'padlock-update'; @@ -26,7 +26,7 @@ const PADLOCK_UPDATE = 'padlock-update'; */ class LockService { /** - * @constructor + * @class * Constructor for configuring the initial state of stored information * @param {BroadcastService} broadcastService - service to use to broadcast lock state changes */ @@ -37,15 +37,15 @@ class LockService { this._broadcastService = broadcastService; /** - * @type {Object} + * @type {Object} */ this._locksByDetector = {}; } /** * Initialize Lock service based on the provided list of detectors - * @param {Array} detectors = [] - list of detectors to be used for the lock mechanism - * @return {void} + * @param {Array} detectors = [] - list of detectors to be used for the lock mechanism + * @returns {void} */ setLockStatesForDetectors(detectors = []) { for (const detectorName of detectors) { @@ -55,7 +55,7 @@ class LockService { /** * Return the states of all detector locks currently used by the system grouped by the detector name - * @returns {Object} + * @returns {Object} */ get locksByDetector() { return this._locksByDetector; @@ -63,7 +63,7 @@ class LockService { /** * Return the states of all detector locks currently used by the system grouped by the detector name as JSONs for HTTP responses - * @return {JSON{Object}} + * @returns {JSON{Object}} */ locksByDetectorToJSON() { const locksJson = {}; @@ -72,13 +72,12 @@ class LockService { return locksJson; } - /** + /** * Method to try to acquire lock for a specified detector by a user - * @param {String} detectorName - detector as defined by AliECS + * @param {string} detectorName - detector as defined by AliECS * @param {User} user - user trying to acquiring the lock - * @param {Boolean} shouldForce - specified if lock should be taken even if held by another user - * - * @return {Object} - updated state of all detector locks + * @param {boolean} shouldForce - specified if lock should be taken even if held by another user + * @returns {Object} - updated state of all detector locks * @throws {UnauthorizedAccessError} */ takeLock(detectorName, user, shouldForce = false) { @@ -88,9 +87,7 @@ class LockService { throw new NotFoundError(`Detector ${detectorName} not found in the list of detectors`); } else if (lock.isTaken()) { if (!lock.isOwnedBy(user) && !shouldForce) { - throw new UnauthorizedAccessError( - `Unauthorized TAKE action for lock of detector ${detectorName} by user ${user.fullName}` - ); + throw new UnauthorizedAccessError(`Unauthorized TAKE action for lock of detector ${detectorName} by user ${user.fullName}`); } if (lock.isOwnedBy(user)) { return this._locksByDetector; @@ -102,25 +99,22 @@ class LockService { return this._locksByDetector; } - /** + /** * Method to try to release lock for a specified detector by a user - * @param {String} detectorName - detector name as defined by AliECS + * @param {string} detectorName - detector name as defined by AliECS * @param {User} user - user that wishes to release the lock - * @param {Boolean} shouldForce - lock should be taken even if held by another user - * - * @return {Object} + * @param {boolean} shouldForce - lock should be taken even if held by another user + * @returns {Object} * @throws {UnauthorizedAccessError} */ releaseLock(detectorName, user, shouldForce = false) { - const lock = this._locksByDetector[detectorName] + const lock = this._locksByDetector[detectorName]; if (!lock) { throw new NotFoundError(`Detector ${detectorName} not found in the list of detectors`); } else if (lock.isFree()) { return this._locksByDetector; } else if (!lock.isOwnedBy(user) && !shouldForce) { - throw new UnauthorizedAccessError( - `Unauthorized RELEASE action for lock of detector ${detectorName} by user ${user.fullName}` - ); + throw new UnauthorizedAccessError(`Unauthorized RELEASE action for lock of detector ${detectorName} by user ${user.fullName}`); } this._locksByDetector[detectorName].release(); @@ -130,8 +124,9 @@ class LockService { /** * Checks if the given user has the lock for the provided list of detectors - * @param {String} userName - of user to check lock ownership - * @param {Number} userId - person id of the user + * @param {string} userName - of user to check lock ownership + * @param {number} userId - person id of the user + * @param user * @param {Array} detectors - list of detectors to check lock is owned by the user * @returns {boolean} */ @@ -141,7 +136,7 @@ class LockService { /** * Method to check if lock is taken by specific user - * @param {String} detector - detector for which check should be done + * @param {string} detector - detector for which check should be done * @param {User} user - user to check if owns the lock */ isLockOwnedByUser(detector, user) { diff --git a/Control/lib/services/Run.service.js b/Control/lib/services/Run.service.js index cf2e34310..e1e337ca4 100644 --- a/Control/lib/services/Run.service.js +++ b/Control/lib/services/Run.service.js @@ -10,16 +10,16 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -const {Log} = require('@aliceo2/web-ui'); +const { Log } = require('@aliceo2/web-ui'); -const {CacheKeys} = require('../common/cacheKeys.enum.js'); -const {grpcErrorToNativeError} = require('./../errors/grpcErrorToNativeError.js'); -const {LOG_LEVEL} = require('./../common/logLevel.enum.js'); -const {RunCalibrationStatus} = require('./../common/runCalibrationStatus.enum.js'); -const {RunDefinitions} = require('./../common/runDefinition.enum.js') -const {RUNTIME_COMPONENT: {COG}, RUNTIME_KEY: {CALIBRATION_MAPPING}} = require('./../common/kvStore/runtime.enum.js'); +const { CacheKeys } = require('../common/cacheKeys.enum.js'); +const { grpcErrorToNativeError } = require('./../errors/grpcErrorToNativeError.js'); +const { LOG_LEVEL } = require('./../common/logLevel.enum.js'); +const { RunCalibrationStatus } = require('./../common/runCalibrationStatus.enum.js'); +const { RunDefinitions } = require('./../common/runDefinition.enum.js'); +const { RUNTIME_COMPONENT: { COG }, RUNTIME_KEY: { CALIBRATION_MAPPING } } = require('./../common/kvStore/runtime.enum.js'); /** * @class @@ -30,7 +30,7 @@ const {RUNTIME_COMPONENT: {COG}, RUNTIME_KEY: {CALIBRATION_MAPPING}} = require(' */ class RunService { /** - * @constructor + * @class * Constructor for configuring the service to retrieve data via passed services * @param {BookkeepingService} bkpService - service for retrieving RUNs information * @param {ApricotService} apricotService - service for retrieving information through AliECS Apricot gRPC connection, mainly KV Store data @@ -53,13 +53,13 @@ class RunService { this._cacheService = cacheService; /** - * @type {Object} + * @type {Object} */ this._runTypes = {}; /** * Contains an object with list of run types that should be fetched for each detector - * @type {Object>} + * @type {Object>} */ this._calibrationConfigurationPerDetectorMap = {}; @@ -68,7 +68,7 @@ class RunService { /** * Method to initialize the service with data such as runTypes and calibration mappings - * @return {void} + * @returns {void} */ async retrieveStaticConfigurations() { this._calibrationConfigurationPerDetectorMap = await this._retrieveCalibrationConfigurationsForDetectors(); @@ -78,7 +78,7 @@ class RunService { /** * Based on already loaded calibration configuration mapping from KV store, retrieve runs with those characteristics from Bookkeeping - * @return {Promise.Error>} - list of calibration runs grouped by detector + * @returns {Promise.Error>} - list of calibration runs grouped by detector */ async retrieveCalibrationRunsGroupedByDetector() { const calibrationRunsPerDetector = {}; @@ -90,13 +90,13 @@ class RunService { const lastCalibrationRun = await this._bkpService.getRun({ definitions: RunDefinitions.CALIBRATION, runTypes: runTypeId, - detectors: detector + detectors: detector, }); const lastSuccessfulCalibrationRun = await this._bkpService.getRun({ definitions: RunDefinitions.CALIBRATION, runTypes: runTypeId, detectors: detector, - calibrationStatuses: RunCalibrationStatus.SUCCESS + calibrationStatuses: RunCalibrationStatus.SUCCESS, }); calibrationRunsPerDetector[detector][calibrationConfiguration.runType] = { configuration: calibrationConfiguration, @@ -108,7 +108,7 @@ class RunService { // done in a separate loop to avoid race condition generated by waiting on Bookkeeping for (const detector in this._calibrationConfigurationPerDetectorMap) { const calibrationConfigurationList = this._calibrationConfigurationPerDetectorMap[detector] ?? []; - for (const {runType} of calibrationConfigurationList) { + for (const { runType } of calibrationConfigurationList) { const ongoingRequests = this._cacheService?.getByKey(CacheKeys.CALIBRATION_RUNS_REQUESTS); const ongoingCalibrationRun = ongoingRequests?.[detector]?.[runType] ?? null; calibrationRunsPerDetector[detector][runType].ongoingCalibrationRun = ongoingCalibrationRun; @@ -117,7 +117,7 @@ class RunService { this._cacheService?.updateByKeyAndBroadcast( CacheKeys.CALIBRATION_RUNS_BY_DETECTOR, calibrationRunsPerDetector, - {command: CacheKeys.CALIBRATION_RUNS_BY_DETECTOR} + { command: CacheKeys.CALIBRATION_RUNS_BY_DETECTOR }, ); return calibrationRunsPerDetector; } @@ -128,9 +128,8 @@ class RunService { /** * Load calibration mapping for each detector as per the KV store - * @return {Promise} - map of calibration configurations - * - * @example + * @returns {Promise} - map of calibration configurations + * @example * { "XYZ": [ { "runType": "PEDESTAL", "configuration": "cpv-pedestal-20220412", "label": "CPV PEDESTAL", description: "To be ran second for CPV" }]} */ async _retrieveCalibrationConfigurationsForDetectors() { @@ -139,9 +138,10 @@ class RunService { return JSON.parse(calibrationMappings); } catch (error) { const err = grpcErrorToNativeError(error); - this._logger.errorMessage(`Unable to load calibration mapping due to: ${err}`, - {level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: 'calibration-service'} - ) + this._logger.errorMessage( + `Unable to load calibration mapping due to: ${err}`, + { level: LOG_LEVEL.OPERATIONS, system: 'GUI', facility: 'calibration-service' }, + ); } return {}; } @@ -152,7 +152,7 @@ class RunService { /** * Return the KV object for runType with its id - * @return {Object} - mapping of run types to their bookkeeping ID + * @returns {Object} - mapping of run types to their bookkeeping ID */ get runTypes() { return this._runTypes; @@ -160,12 +160,11 @@ class RunService { /** * Return the object containing a KV object with detector and its corresponding run types needed for calibration runs - * @return {Object>} + * @returns {Object>} */ get runTypesPerDetectorStoredMapping() { return this._calibrationConfigurationPerDetectorMap; } - } -module.exports = {RunService}; +module.exports = { RunService }; diff --git a/Control/lib/services/Status.service.js b/Control/lib/services/Status.service.js index e7e0f2f09..7153cbd38 100644 --- a/Control/lib/services/Status.service.js +++ b/Control/lib/services/Status.service.js @@ -10,15 +10,15 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const projPackage = require('./../../package.json'); -const {httpGetJson} = require('./../utils.js'); -const {Service} = require('./../dtos/Service.js'); -const {SERVICES: {STATUS}} = require('./../common/constants.js'); -const {Log} = require('@aliceo2/web-ui'); -const {STATUS_COMPONENTS_KEYS} = require('./../common/statusComponents.enum.js'); -const {RUNTIME_COMPONENT, RUNTIME_KEY} = require('./../common/kvStore/runtime.enum.js'); +const { httpGetJson } = require('./../utils.js'); +const { Service } = require('./../dtos/Service.js'); +const { SERVICES: { STATUS } } = require('./../common/constants.js'); +const { Log } = require('@aliceo2/web-ui'); +const { STATUS_COMPONENTS_KEYS } = require('./../common/statusComponents.enum.js'); +const { RUNTIME_COMPONENT, RUNTIME_KEY } = require('./../common/kvStore/runtime.enum.js'); const NOT_CONFIGURED_MESSAGE = 'This service was not configured'; @@ -26,7 +26,6 @@ const NOT_CONFIGURED_MESSAGE = 'This service was not configured'; * Gateway for all Status Consumer calls */ class StatusService { - /** * Setup StatusService * @param {JSON} config - server configuration @@ -52,7 +51,7 @@ class StatusService { /** * @type {ControlService | undefined} */ - this._ctrlService = ctrlService + this._ctrlService = ctrlService; /** * @type {ApricotService | undefined} @@ -67,16 +66,16 @@ class StatusService { /** * Retrieve status of the ServiceDiscovery system (Consul) - * @returns {Promise} - return of JSON with requested information + * @returns {Promise} - return of JSON with requested information */ async retrieveConsulStatus() { - let status = {ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: true}; + let status = { ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: true }; if (this._consulService) { try { await this._consulService.getConsulLeaderStatus(); - status = {ok: true, configured: true, isCritical: true}; + status = { ok: true, configured: true, isCritical: true }; } catch (error) { - status = {ok: false, configured: true, isCritical: true, message: error.toString()}; + status = { ok: false, configured: true, isCritical: true, message: error.toString() }; } } this._updateStatusMaps(STATUS_COMPONENTS_KEYS.CONSUL_KEY, status); @@ -92,8 +91,8 @@ class StatusService { return { status, name: 'Consul - KV Store', - ...status.configured && Service.fromObjectAsJson(this.config?.consul) - } + ...status.configured && Service.fromObjectAsJson(this.config?.consul), + }; } /** @@ -103,9 +102,9 @@ class StatusService { */ async retrieveAliEcsCoreInfo() { let configuration = {}; - let status = {ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: true}; + let status = { ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: true }; if (this._ctrlService?.coreConfig) { - const {hostname, port, timeout, maxMessageLength} = this._ctrlService.coreConfig; + const { hostname, port, timeout, maxMessageLength } = this._ctrlService.coreConfig; configuration = { endpoint: `${hostname}:${port}`, timeout, @@ -114,12 +113,12 @@ class StatusService { try { const coreInfo = await this._ctrlService.getAliECSInfo(); Object.assign(configuration, coreInfo); - status = {ok: true, configured: true, isCritical: true}; + status = { ok: true, configured: true, isCritical: true }; } catch (error) { - status = {ok: false, configured: true, isCritical: true, message: error.toString()}; + status = { ok: false, configured: true, isCritical: true, message: error.toString() }; } } - const aliecs = Object.assign({status, name: 'AliECS Core'}, Service.fromObjectAsJson(configuration)); + const aliecs = { status, name: 'AliECS Core', ...Service.fromObjectAsJson(configuration) }; this._updateStatusMaps(STATUS_COMPONENTS_KEYS.ALIECS_CORE_KEY, status); return aliecs; } @@ -135,36 +134,36 @@ class StatusService { let integServices = {}; if (this._ctrlService) { try { - const {services} = await this._ctrlService.getIntegratedServicesInfo(); + const { services } = await this._ctrlService.getIntegratedServicesInfo(); Object.entries(services) .filter(([key]) => key !== 'testplugin') .forEach(([key, value]) => { const status = { ok: value?.connectionState !== 'TRANSIENT_FAILURE' && value?.connectionState !== 'SHUTDOWN', configured: Boolean(value?.enabled), - isCritical: true + isCritical: true, }; delete value.enabled; value.name = value.name ?? key; integServices[key] = { status, - ...Service.fromObjectAsJson(value) + ...Service.fromObjectAsJson(value), }; - this._updateStatusMaps(STATUS_COMPONENTS_KEYS.ALIECS_SERVICES_KEY, {status: {ok: true, configured: true}}); + this._updateStatusMaps(STATUS_COMPONENTS_KEYS.ALIECS_SERVICES_KEY, { status: { ok: true, configured: true } }); this._updateStatusMaps(`INTEG_SERVICE-${key.toLocaleUpperCase()}`, integServices[key]); }); } catch (error) { - const status = {ok: false, configured: true, message: error.toString(), isCritical: true}; + const status = { ok: false, configured: true, message: error.toString(), isCritical: true }; this._updateStatusMaps(STATUS_COMPONENTS_KEYS.ALIECS_SERVICES_KEY); integServices = { - ALL: {status} + ALL: { status }, }; } } else { - const status = {ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: true}; + const status = { ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: true }; this._updateStatusMaps(STATUS_COMPONENTS_KEYS.ALIECS_SERVICES_KEY, status); integServices = { - ALL: {status} + ALL: { status }, }; } return integServices; @@ -172,16 +171,16 @@ class StatusService { /** * Retrieve status of Apricot Service - * @returns {Promise} - return of JSON with requested information + * @returns {Promise} - return of JSON with requested information */ async retrieveApricotStatus() { - let status = {ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: true}; + let status = { ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: true }; if (this._apricotService) { try { await this._apricotService.getStatus(); - status = {ok: true, configured: true, isCritical: true}; + status = { ok: true, configured: true, isCritical: true }; } catch (error) { - status = {ok: false, configured: true, isCritical: true, message: error.toString()} + status = { ok: false, configured: true, isCritical: true, message: error.toString() }; } } this._updateStatusMaps(STATUS_COMPONENTS_KEYS.APRICOT_KEY, status); @@ -197,19 +196,19 @@ class StatusService { return { status, name: 'Apricot', - ...status.configured && Service.fromObjectAsJson(this.config.apricot) + ...status.configured && Service.fromObjectAsJson(this.config.apricot), }; } /** - * Retrieve status of Monitoring System (Grafana) - * @returns {Promise} - return of JSON with requested information + * Retrieve status of Monitoring System (Grafana) + * @returns {Promise} - return of JSON with requested information */ async retrieveGrafanaStatus() { - let status = {ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: false}; + let status = { ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: false }; if (this.config?.grafana?.url) { try { - const {protocol, hostname, port} = new URL(this.config.grafana.url); + const { protocol, hostname, port } = new URL(this.config.grafana.url); await httpGetJson(hostname, port, '/api/health', { statusCodeMin: 200, statusCodeMax: 301, @@ -217,9 +216,9 @@ class StatusService { rejectMessage: 'Invalid status code: ', rejectUnauthorized: false, }); - status = {ok: true, configured: true, isCritical: false}; + status = { ok: true, configured: true, isCritical: false }; } catch (error) { - status = {ok: false, configured: true, isCritical: false, message: error.toString()}; + status = { ok: false, configured: true, isCritical: false, message: error.toString() }; } } this._updateStatusMaps(STATUS_COMPONENTS_KEYS.GRAFANA_KEY, status); @@ -228,14 +227,14 @@ class StatusService { /** * Build a response containing the information and status of the Grafana Service - * @return {Promise} + * @returns {Promise} */ async getGrafanaAsComponent() { const status = await this.retrieveGrafanaStatus(); return { status, name: 'Grafana - Monitoring', - ...status.configured && Service.fromObjectAsJson({endpoint: this.config.grafana.url}) + ...status.configured && Service.fromObjectAsJson({ endpoint: this.config.grafana.url }), }; } @@ -243,29 +242,30 @@ class StatusService { * Retrieve status of the notification system (Kafka) */ async retrieveNotificationSystemStatus() { - let status = {ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: false}; + let status = { ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: false }; if (this._notificationService && this._notificationService.isConfigured()) { try { await this._notificationService.health(); - status = {configured: true, ok: true, isCritical: false}; + status = { configured: true, ok: true, isCritical: false }; } catch (error) { - status = {configured: true, ok: false, isCritical: false, message: error.name}; + status = { configured: true, ok: false, isCritical: false, message: error.name }; } } this._updateStatusMaps(STATUS_COMPONENTS_KEYS.NOTIFICATION_SYSTEM_KEY, status); return status; } + /** * Build a response containing the information and status of the Notification Service * @param {object} notification - configuration of Notification Service, including Kafka brokers - * @return {Promise} + * @returns {Promise} */ async getNotificationSystemAsComponent() { const status = await this.retrieveNotificationSystemStatus(); return { status, name: 'Kafka - Notification', - ...status.configured && Service.fromObjectAsJson(this.config?.kafka) + ...status.configured && Service.fromObjectAsJson(this.config?.kafka), }; } @@ -278,23 +278,23 @@ class StatusService { name: 'AliECS GUI', version: projPackage?.version ?? '-', status: { - ok: true, configured: true, isCritical: true + ok: true, configured: true, isCritical: true, }, - clients: this?._wsService?._ws?.server?.clients?.size ?? 0 + clients: this?._wsService?._ws?.server?.clients?.size ?? 0, }; } /** * Method to retrieve versions of FLP & PDP and check their compatibility - * @returns {object, PDP: string>} - + * @returns {object, PDP: string>} - */ async getCompatibilityStateAsComponent() { - const {status, extras} = await this.retrieveSystemCompatibility(); + const { status, extras } = await this.retrieveSystemCompatibility(); return { status, name: 'General System Components', - ...status.configured && Service.fromObjectAsJson({...extras, showExtras: true}) - } + ...status.configured && Service.fromObjectAsJson({ ...extras, showExtras: true }), + }; } /** @@ -302,36 +302,34 @@ class StatusService { * @returns {object} - containing status of the system and extra information on the 2 components versions */ async retrieveSystemCompatibility() { - let status = {ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: false}; + let status = { ok: false, configured: false, message: NOT_CONFIGURED_MESSAGE, isCritical: false }; let flpVersion = ''; try { flpVersion = await this._apricotService.getRuntimeEntryByComponent('', RUNTIME_KEY.FLP_VERSION); } catch (error) { - this._logger.warnMessage(error, {level: 26, system: 'GUI', facility: 'cog/status'}); + this._logger.warnMessage(error, { level: 26, system: 'GUI', facility: 'cog/status' }); } let pdpVersion = ''; try { - pdpVersion = await this._apricotService.getRuntimeEntryByComponent( - RUNTIME_COMPONENT.PDP_VERSION, RUNTIME_KEY.PDP_VERSION - ); + pdpVersion = await this._apricotService.getRuntimeEntryByComponent(RUNTIME_COMPONENT.PDP_VERSION, RUNTIME_KEY.PDP_VERSION); } catch (error) { - this._logger.warnMessage(error, {level: 26, system: 'GUI', facility: 'cog/status'}); + this._logger.warnMessage(error, { level: 26, system: 'GUI', facility: 'cog/status' }); } if (flpVersion && pdpVersion) { const flpVersionLabel = `flp-suite-v${flpVersion}`; const isMatch = pdpVersion.toLocaleUpperCase().includes(flpVersionLabel.toLocaleUpperCase()); - status = {ok: isMatch, configured: true, isCritical: true}; + status = { ok: isMatch, configured: true, isCritical: true }; } else if (flpVersion || pdpVersion) { - status = {ok: true, configured: true, isCritical: true}; + status = { ok: true, configured: true, isCritical: true }; } this._updateStatusMaps(STATUS_COMPONENTS_KEYS.GENERAL_SYSTEM_KEY, status); return { status, - extras: {flpVersion, pdpVersion} + extras: { flpVersion, pdpVersion }, }; } @@ -339,7 +337,7 @@ class StatusService { * Update the maps with relation to statuses: * - statusMap should always save the new status; * - statusMapUpdate should only save it if the value has changed and delete the pair if it exists and is the same value - * @param {string} key - + * @param {string} key - * @param {object} value - JSON component with status */ _updateStatusMaps(key, value) { diff --git a/Control/lib/services/WebSocket.service.js b/Control/lib/services/WebSocket.service.js index bf59dfd0c..6c0a7f084 100644 --- a/Control/lib/services/WebSocket.service.js +++ b/Control/lib/services/WebSocket.service.js @@ -10,10 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ -const {WebSocketMessage} = require('@aliceo2/web-ui'); -const {deepStrictEqual} = require('assert'); -const {SERVICES} = require('../common/constants.js'); + */ +const { WebSocketMessage } = require('@aliceo2/web-ui'); +const { deepStrictEqual } = require('assert'); +const { SERVICES } = require('../common/constants.js'); /** * Service for dealing with broadcasting information about the on framework such as: @@ -40,7 +40,7 @@ class WebSocketService { * Method to receive updates with regards to the AliECS GUI services; If the update is different than the one sent last time, * then a broadcast message will be sent * @param {SERVICES} serviceKey - refers to service which is updating data - * @param {string} key - component from service that receives an update + * @param {string} key - component from service that receives an update * @param {Map} value - JSON representation of the status */ updateData(serviceKey, key, value) { diff --git a/Control/lib/services/WorkflowTemplate.service.js b/Control/lib/services/WorkflowTemplate.service.js index f29b8c647..122012a39 100644 --- a/Control/lib/services/WorkflowTemplate.service.js +++ b/Control/lib/services/WorkflowTemplate.service.js @@ -10,10 +10,11 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ + +const { grpcErrorToNativeError } = require('../errors/grpcErrorToNativeError.js'); +const { NotFoundError } = require('./../errors/NotFoundError.js'); -const {grpcErrorToNativeError} = require('../errors/grpcErrorToNativeError.js'); -const {NotFoundError} = require('./../errors/NotFoundError.js'); const RUNTIME_COMPONENT = 'COG'; const RUNTIME_CONFIGURATION = 'COG-v1'; const RUNTIME_KEY = 'workflow-mappings'; @@ -38,34 +39,34 @@ class WorkflowTemplateService { * @throws */ async getDefaultTemplateSource() { - const {repos: repositories} = await this._coreGrpc['ListRepos'](); + const { repos: repositories } = await this._coreGrpc['ListRepos'](); const defaultRepository = repositories.find((repository) => repository.default); if (!defaultRepository) { - throw new NotFoundError(`Unable to find a default repository`); + throw new NotFoundError('Unable to find a default repository'); } - const {name: repository, defaultRevision: revision} = defaultRepository; + const { name: repository, defaultRevision: revision } = defaultRepository; if (!revision) { - throw new NotFoundError(`Unable to find a default revision`); + throw new NotFoundError('Unable to find a default revision'); } return { repository, revision, - template: 'readout-dataflow' + template: 'readout-dataflow', }; } /** * Retrieve a list of mappings for simplified creation of environments based on workflow saved configurations - * @return {Array<{label: String, configuration: String}>} - list of mappings to be displayed + * @returns {Array<{label: string, configuration: string}>} - list of mappings to be displayed */ async retrieveWorkflowMappings() { try { const mappingsString = await this._apricotGrpc.getRuntimeEntryByComponent(RUNTIME_COMPONENT, RUNTIME_KEY); const mappings = JSON.parse(mappingsString); if (Array.isArray(mappings)) { - return mappings.sort(({label: labelA}, {label: labelB}) => labelA < labelB ? -1 : 1); + return mappings.sort(({ label: labelA }, { label: labelB }) => labelA < labelB ? -1 : 1); } return []; @@ -76,18 +77,18 @@ class WorkflowTemplateService { /** * Using apricot service, retrieve the content of a saved configuration by name - * @param {String} name - configuration that needs to be retrieved - * @return {Object} - object with saved configuration + * @param {string} name - configuration that needs to be retrieved + * @returns {object} - object with saved configuration */ async retrieveWorkflowSavedConfiguration(name) { try { const configurationString = await this._apricotGrpc.getRuntimeEntryByComponent(RUNTIME_CONFIGURATION, name); const configuration = JSON.parse(configurationString); - return configuration + return configuration; } catch (error) { throw grpcErrorToNativeError(error); } } } -module.exports = {WorkflowTemplateService}; +module.exports = { WorkflowTemplateService }; diff --git a/Control/lib/typedefs/AutoEnvironmentDeployment.js b/Control/lib/typedefs/AutoEnvironmentDeployment.js index 69baa8fae..c6f0823fe 100644 --- a/Control/lib/typedefs/AutoEnvironmentDeployment.js +++ b/Control/lib/typedefs/AutoEnvironmentDeployment.js @@ -15,37 +15,34 @@ * @typedef AutoEnvironmentDeployment * * AutoEnvironmentDeployment type definition for auto transitioning environments which send updates to the GUI via streams - * - * @property {String} channelIdString - id of the channel on which updates are sent by AliECS - * @property {String} detector - * @property {String} runType - * @property {Boolean} inProgress - whether the deployment is still in progress + * @property {string} channelIdString - id of the channel on which updates are sent by AliECS + * @property {string} detector + * @property {string} runType + * @property {boolean} inProgress - whether the deployment is still in progress * @property {Array} events */ /** * @typedef TaskEvent - * + * * Event as sent by AliECS which describes the latest state of a task - * - * @property {String} name - * @property {String} taskid - * @property {String} state - * @property {String} status - * @property {String} hostname - * @property {String} className - * @property {Number} at - date and time at which the event took place + * @property {string} name + * @property {string} taskid + * @property {string} state + * @property {string} status + * @property {string} hostname + * @property {string} className + * @property {number} at - date and time at which the event took place */ /** * @typedef EnvironmentEvent - * + * * Event as sent by AliECS which describes the latest state of an environment - * - * @property {String} environmentId + * @property {string} environmentId * @property {'DEPLOYED'|'STANDBY'|'CONFIGURED'|'RUNNING'|'ERROR'|'MIXED'|'SHUTDOWN'} state - * @property {Number} currentRunNumber - * @property {String} [error] - only in case of ERROR state - * @property {String} [message] - * @property {Number} at - date and time at which the event took place + * @property {number} currentRunNumber + * @property {string} [error] - only in case of ERROR state + * @property {string} [message] + * @property {number} at - date and time at which the event took place */ diff --git a/Control/lib/typedefs/CalibrationConfiguration.js b/Control/lib/typedefs/CalibrationConfiguration.js index 1c1edc06a..79297161d 100644 --- a/Control/lib/typedefs/CalibrationConfiguration.js +++ b/Control/lib/typedefs/CalibrationConfiguration.js @@ -16,9 +16,8 @@ * * CalibrationConfiguration is an object which contains details on what a calibration run should be * based on and displayed to the user - * - * @property {String} runType - * @property {String} configuration - name of the configuration to be used from the existing saved ones in KV store runtime - * @property {String} label - label to be displayed to the user for this calibration - * @property {String} description - description to be displayed if specifics are needed for that calibration + * @property {string} runType + * @property {string} configuration - name of the configuration to be used from the existing saved ones in KV store runtime + * @property {string} label - label to be displayed to the user for this calibration + * @property {string} description - description to be displayed if specifics are needed for that calibration */ diff --git a/Control/lib/typedefs/Detector.js b/Control/lib/typedefs/Detector.js index 8939d07b8..f0c2fba61 100644 --- a/Control/lib/typedefs/Detector.js +++ b/Control/lib/typedefs/Detector.js @@ -15,11 +15,10 @@ * @typedef Detector * * Detector definition as received from ECS directly from DCS - * - * @property {String} [name] - optional name of the detector + * @property {string} [name] - optional name of the detector * @property {DetectorState} state - state of detector - * @property {Number} timestamp - timestamp of the last updated state + * @property {number} timestamp - timestamp of the last updated state * @property {Array[String]} allowedRunTypes - * @property {String} pfrAvailability - no enum provided but usually a string in the form of DetectorState - * @property {String} sorAvailability - no enum provided but usually a string in the form of DetectorState + * @property {string} pfrAvailability - no enum provided but usually a string in the form of DetectorState + * @property {string} sorAvailability - no enum provided but usually a string in the form of DetectorState */ diff --git a/Control/lib/typedefs/DeviceInfo.js b/Control/lib/typedefs/DeviceInfo.js index d2b783e66..49f49ff0c 100644 --- a/Control/lib/typedefs/DeviceInfo.js +++ b/Control/lib/typedefs/DeviceInfo.js @@ -16,10 +16,9 @@ * * DeviceInfo type definition as parsed and sent to the client by the GUI server * The parsing is done based on the object received from ECS in `o2control.proto` in integratedServicesData from EPN - * - * @property {String} taskId - * @property {String} state - * @property {String} path - * @property {String} host - * @property {boolean} ignored + * @property {string} taskId + * @property {string} state + * @property {string} path + * @property {string} host + * @property {boolean} ignored */ diff --git a/Control/lib/typedefs/EnvironmentCreation.js b/Control/lib/typedefs/EnvironmentCreation.js index 1ee7a953e..a4d9acbb4 100644 --- a/Control/lib/typedefs/EnvironmentCreation.js +++ b/Control/lib/typedefs/EnvironmentCreation.js @@ -15,7 +15,6 @@ * @typedef EnvironmentCreation * * EnvironmentCreation type definition as being received from UI - * * @property {string} workflowTemplate * @property {object} vars * @property {Array} [detectors] diff --git a/Control/lib/typedefs/EnvironmentInfo.js b/Control/lib/typedefs/EnvironmentInfo.js index 3b29b20fd..349d4aa46 100644 --- a/Control/lib/typedefs/EnvironmentInfo.js +++ b/Control/lib/typedefs/EnvironmentInfo.js @@ -16,22 +16,21 @@ * * EnvironmentInfo type definition as parsed and sent to the client by the GUI server * The parsing is done based on the object received from ECS in `o2control.proto` definition - * - * @property {String} id - * @property {Number} currentRunNumber - * @property {Number} createdWhen - timestamp in ms - * @property {String} state - STANDBY, DEPLOYED, CONFIGURED, RUNNING, ERROR, MIXED, SHUTDOWN - * @property {String} currentTransition - DEPLOY, CONFIGURE, RESET, START_ACTIVITY, STOP_ACTIVITY, EXIT, GO_ERROR, RECOVER AS PER https://github.com/AliceO2Group/Control/blob/master/core/environment/environment.go#L143 - * @property {String} rootRole - workflow selected by user - * @property {String} description - * @property {Number} numberOfFlps - * @property {Number} numberOfHosts - * @property {Number} numberOfTasks - number of tasks running on FLPs - * @property {Map<[qc, epn, flp, trg], Object>} hardware - a map of counters per component of their tasks (FLP, EPN, QC, TRIGGER, ALL) - * @property {Array} includedDetectors - list of detectors part of the environment - * @property {Map} defaults - map of variables that are set as defaults and their values - * @property {Map} vars - map of all variables that are set and their values - * @property {Map} userVars - map of user set variables and their values - * @property {Map} [integratedServicesData] - map of integrated services such as Bookkeeping, ODC, CCDB, etc. + * @property {string} id + * @property {number} currentRunNumber + * @property {number} createdWhen - timestamp in ms + * @property {string} state - STANDBY, DEPLOYED, CONFIGURED, RUNNING, ERROR, MIXED, SHUTDOWN + * @property {string} currentTransition - DEPLOY, CONFIGURE, RESET, START_ACTIVITY, STOP_ACTIVITY, EXIT, GO_ERROR, RECOVER AS PER https://github.com/AliceO2Group/Control/blob/master/core/environment/environment.go#L143 + * @property {string} rootRole - workflow selected by user + * @property {string} description + * @property {number} numberOfFlps + * @property {number} numberOfHosts + * @property {number} numberOfTasks - number of tasks running on FLPs + * @property {Map<[qc, epn, flp, trg], object>} hardware - a map of counters per component of their tasks (FLP, EPN, QC, TRIGGER, ALL) + * @property {Array} includedDetectors - list of detectors part of the environment + * @property {Map} defaults - map of variables that are set as defaults and their values + * @property {Map} vars - map of all variables that are set and their values + * @property {Map} userVars - map of user set variables and their values + * @property {Map} [integratedServicesData] - map of integrated services such as Bookkeeping, ODC, CCDB, etc. * @property {Array} [tasks] - a list of minimum tasks information */ diff --git a/Control/lib/typedefs/EnvironmentTransitionResult.js b/Control/lib/typedefs/EnvironmentTransitionResult.js index 6ee4e77e7..38fdf3ed5 100644 --- a/Control/lib/typedefs/EnvironmentTransitionResult.js +++ b/Control/lib/typedefs/EnvironmentTransitionResult.js @@ -13,10 +13,9 @@ /** * @type {EnvironmentTransitionResult} - * + * * Object describing the reply from AliECS Core with regards to the state of an environment following a transition - * - * @param {String} id - environment id on which the transition was performed - * @param {String} state - current state of environment - * @param {Number} [currentRunNumber] - run number if the environment is in RUNNING state + * @param {string} id - environment id on which the transition was performed + * @param {string} state - current state of environment + * @param {number} [currentRunNumber] - run number if the environment is in RUNNING state */ diff --git a/Control/lib/typedefs/OdcIntegratedServiceInfo.js b/Control/lib/typedefs/OdcIntegratedServiceInfo.js index 0cd7972ae..d7634787c 100644 --- a/Control/lib/typedefs/OdcIntegratedServiceInfo.js +++ b/Control/lib/typedefs/OdcIntegratedServiceInfo.js @@ -4,8 +4,9 @@ 'ddsSessionId', 'ddsSessionStatus', 'devices', - 'hosts' -] + 'hosts', +]; + /** * @license * Copyright CERN and copyright holders of ALICE O2. This software is @@ -24,11 +25,10 @@ * * OdcIntegratedServiceInfo type definition as parsed and sent to the client by the GUI server * The parsing is done based on the object received from ECS in integratedServicesData object - * - * @property {Number} currentRunNumber - * @property {String} state - * @property {String} ddsSessionId - * @property {String} ddsSessionStatus + * @property {number} currentRunNumber + * @property {string} state + * @property {string} ddsSessionId + * @property {string} ddsSessionStatus * @property {Array} devices - * @property {Array} hosts + * @property {Array} hosts */ diff --git a/Control/lib/typedefs/RunSummary.js b/Control/lib/typedefs/RunSummary.js index f08cbe9d2..16b0ffd61 100644 --- a/Control/lib/typedefs/RunSummary.js +++ b/Control/lib/typedefs/RunSummary.js @@ -15,15 +15,14 @@ * @typedef RunSummary * * RunSummary is an object which contains just a summary of an entire run entity: https://github.com/AliceO2Group/Bookkeeping/blob/main/lib/domain/entities/Run.js - * - * @property {Number} runNumber - * @property {Number} id - * @property {String} environmentId - * @property {String} definition - * @property {String} calibrationStatus - * @property {String} runType - * @property {Number} runDuration - * @property {Number} startTime - * @property {Number} endTime - * @property {Array} detectors + * @property {number} runNumber + * @property {number} id + * @property {string} environmentId + * @property {string} definition + * @property {string} calibrationStatus + * @property {string} runType + * @property {number} runDuration + * @property {number} startTime + * @property {number} endTime + * @property {Array} detectors */ diff --git a/Control/lib/typedefs/TaskInfo.js b/Control/lib/typedefs/TaskInfo.js index fd413078d..f37f5a65a 100644 --- a/Control/lib/typedefs/TaskInfo.js +++ b/Control/lib/typedefs/TaskInfo.js @@ -16,15 +16,14 @@ * * TaskInfo type definition as parsed and sent to the client by the GUI server * The parsing is done based on the object received from ECS in `o2control.proto` definition - * - * @property {String} taskId - * @property {String} name + * @property {string} taskId + * @property {string} name * @property {boolean} locked - * @property {String} status - * @property {String} state - * @property {String} className - * @property {String} pid - * @property {String} sandboxStdout - * @property {boolean} claimable + * @property {string} status + * @property {string} state + * @property {string} className + * @property {string} pid + * @property {string} sandboxStdout + * @property {boolean} claimable * @property {boolean} critical */ diff --git a/Control/lib/typedefs/WorkflowTemplateSource.js b/Control/lib/typedefs/WorkflowTemplateSource.js index b46b798cb..061402d00 100644 --- a/Control/lib/typedefs/WorkflowTemplateSource.js +++ b/Control/lib/typedefs/WorkflowTemplateSource.js @@ -15,8 +15,7 @@ * @typedef WorkflowTemplateSource * * WorkflowTemplate type definition as parsed and sent to the client by the GUI server - * - * @property {String} template - * @property {String} repository - * @property {String} revision + * @property {string} template + * @property {string} repository + * @property {string} revision */ diff --git a/Control/lib/utils.js b/Control/lib/utils.js index 9cda39e8f..855a5206a 100644 --- a/Control/lib/utils.js +++ b/Control/lib/utils.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const log = new (require('@aliceo2/web-ui').Log)(`${process.env.npm_config_log_label ?? 'cog'}/utils`); const http = require('http'); @@ -21,16 +21,18 @@ const https = require('https'); * @param {string} err - Message error * @param {Response} res - Response object to send to * @param {number} status - status code 4xx 5xx, 500 will print to debug + * @param facility */ function errorHandler(err, res, status = 500, facility = 'utils') { errorLogger(err, facility); res.status(status); - res.send({message: err.message || err}); + res.send({ message: err.message || err }); } /** * Global Error Logger for AliECS GUI - * @param {Error} err + * @param {Error} err + * @param facility */ function errorLogger(err, facility = 'utils') { log.facility = `${process.env.npm_config_log_label ?? 'cog'}/${facility}`; @@ -41,13 +43,14 @@ function errorLogger(err, facility = 'utils') { } /** - * Util to get JSON data (parsed) following a GET request - * @param {string} host - hostname of the server - * @param {number} port - port of the server - * @param {string} path - path of the server request - * @param {JSON} options - specific request options (e.g range of accepted status code) - * @return {Promise.} JSON response - */ + * Util to get JSON data (parsed) following a GET request + * @param {string} host - hostname of the server + * @param hostname + * @param {number} port - port of the server + * @param {string} path - path of the server request + * @param {JSON} options - specific request options (e.g range of accepted status code) + * @returns {Promise.} JSON response + */ function httpGetJson(hostname, port, path, options = undefined) { options = { statusCodeMin: 200, @@ -55,7 +58,7 @@ function httpGetJson(hostname, port, path, options = undefined) { rejectMessage: 'Non-2xx status code: ', protocol: 'http:', rejectUnauthorized: true, - ...options ?? {} + ...options ?? {}, }; return new Promise((resolve, reject) => { const requestOptions = { @@ -65,9 +68,10 @@ function httpGetJson(hostname, port, path, options = undefined) { method: 'GET', rejectUnauthorized: Boolean(options.rejectUnauthorized), headers: { - Accept: 'application/json' - } + Accept: 'application/json', + }, }; + /** * Generic handler for GET HTTP requests, buffers response, checks status code and parses JSON * @param {Response} response @@ -100,5 +104,4 @@ function httpGetJson(hostname, port, path, options = undefined) { }); } - -module.exports = {errorHandler, errorLogger, httpGetJson}; +module.exports = { errorHandler, errorLogger, httpGetJson }; diff --git a/Control/public/Model.js b/Control/public/Model.js index 06788e54f..c10926f45 100644 --- a/Control/public/Model.js +++ b/Control/public/Model.js @@ -10,11 +10,11 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ // Import frontend framework -import {Observable, WebSocketClient, QueryRouter, Loader, sessionService, RemoteData} from '/js/src/index.js'; -import {Notification as O2Notification} from '/js/src/index.js'; +import { Observable, WebSocketClient, QueryRouter, Loader, sessionService, RemoteData } from '/js/src/index.js'; +import { Notification as O2Notification } from '/js/src/index.js'; import Lock from './lock/Lock.js'; import Environment from './environment/Environment.js'; import About from './about/About.js'; @@ -22,14 +22,14 @@ import Workflow from './workflow/Workflow.js'; import Task from './task/Task.js'; import Config from './configuration/ConfigByCru.js'; import DetectorService from './services/DetectorService.js'; -import {PREFIX, ROLES} from './../workflow/constants.js'; -import {SERVICE_STATES} from './common/constants/serviceStates.js'; -import {di} from './utilities/di.js'; +import { PREFIX, ROLES } from './../workflow/constants.js'; +import { SERVICE_STATES } from './common/constants/serviceStates.js'; +import { di } from './utilities/di.js'; -import {EnvironmentCreationModel} from './pages/EnvironmentCreation/EnvironmentCreation.model.js'; -import {CalibrationRunsModel} from './pages/CalibrationRuns/CalibrationRuns.model.js'; +import { EnvironmentCreationModel } from './pages/EnvironmentCreation/EnvironmentCreation.model.js'; +import { CalibrationRunsModel } from './pages/CalibrationRuns/CalibrationRuns.model.js'; -import {STATUS_COMPONENTS_KEYS} from './common/constants/statusComponents.enum.js'; +import { STATUS_COMPONENTS_KEYS } from './common/constants/statusComponents.enum.js'; /** * Root of model tree @@ -62,7 +62,7 @@ export default class Model extends Observable { this.detectors = new DetectorService(this); this.services = { - detectors: this.detectors + detectors: this.detectors, }; this.configuration = new Config(this); @@ -106,9 +106,9 @@ export default class Model extends Observable { this.init(); } - /** + /** * Returns user role - * @returns {object} User's role + * @returns {object} User's role */ getRole() { if (this.session.access.includes('admin')) { @@ -121,7 +121,7 @@ export default class Model extends Observable { return ROLES.Guest; } - /** + /** * Evaluate whether action is allowed for given role * @param {ROLES} role - target role * @param {bool} [strict=false] - The target role must equal current role @@ -191,7 +191,7 @@ export default class Model extends Observable { break; case 'CALIBRATION_RUNS_REQUESTS': if (message.payload && this.calibrationRunsModel.calibrationRuns.isSuccess()) { - const {detector, runType} = message.payload; + const { detector, runType } = message.payload; this.calibrationRunsModel.calibrationRuns.payload[detector][runType].ongoingCalibrationRun = RemoteData.success(message.payload); this.calibrationRunsModel.notify(); @@ -212,9 +212,9 @@ export default class Model extends Observable { // Release client-side this.lock.padlockState = {}; - this.notification.show(`Connection to server has been lost. Retrying to connect in 10 seconds...`, 'danger', 10000); + this.notification.show('Connection to server has been lost. Retrying to connect in 10 seconds...', 'danger', 10000); this.about.setWsInfo(SERVICE_STATES.IN_ERROR, { - status: {ok: false, configured: true, message: 'Cannot establish connection to server'} + status: { ok: false, configured: true, message: 'Cannot establish connection to server' }, }); const wsReconnectInterval = setInterval(() => { @@ -225,9 +225,9 @@ export default class Model extends Observable { this.ws.addListener('close', this.handleWSClose.bind(this)); clearInterval(wsReconnectInterval); this.about.setWsInfo(SERVICE_STATES.IN_SUCCESS, { - status: {ok: true, configured: true}, message: 'WebSocket connection is alive' + status: { ok: true, configured: true }, message: 'WebSocket connection is alive', }); - this.notification.show(`Connection to server has been restored`, 'success', 3000); + this.notification.show('Connection to server has been restored', 'success', 3000); } catch (error) { console.error(error); } @@ -254,7 +254,7 @@ export default class Model extends Observable { if (!this.router.params.panel) { this.router.go(`?page=environment&id=${this.router.params.id}&panel=general`, true, true); } - this.environment.getEnvironment({id: this.router.params.id}, true, this.router.params.panel); + this.environment.getEnvironment({ id: this.router.params.id }, true, this.router.params.panel); break; case 'newEnvironmentAdvanced': this.workflow.initWorkflowPage(); @@ -305,7 +305,7 @@ export default class Model extends Observable { /** * Update detector selection view - * @param {String} detector + * @param {string} detector * @returns {vnode} */ setDetectorView(detector) { @@ -331,14 +331,14 @@ export default class Model extends Observable { /** * Display a browser notification(Notification - Web API) - * @param {String} message + * @param {string} message */ showNativeNotification(message) { - const notification = new Notification(message.title, {body: message.body, icon: '/o2_icon.png'}); - notification.onclick = function(event) { + const notification = new Notification(message.title, { body: message.body, icon: '/o2_icon.png' }); + notification.onclick = function (event) { event.preventDefault(); window.open(message.url, '_blank'); - } + }; } /** @@ -358,6 +358,6 @@ export default class Model extends Observable { checkBrowserNotificationPermissions() { return (Notification.permission === 'denied' || Notification.permission === 'default') && - window.location.protocol === "https:"; + window.location.protocol === 'https:'; } } diff --git a/Control/public/about/About.js b/Control/public/about/About.js index 5a47733c0..7a0636fef 100644 --- a/Control/public/about/About.js +++ b/Control/public/about/About.js @@ -10,10 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {Observable, RemoteData} from '/js/src/index.js'; -import {SERVICE_STATES} from './../common/constants/serviceStates.js'; +import { Observable, RemoteData } from '/js/src/index.js'; +import { SERVICE_STATES } from './../common/constants/serviceStates.js'; const INTEGRATED_SERVICE_LABEL = 'INTEG_SERVICE'; @@ -53,7 +53,7 @@ export default class About extends Observable { */ async retrieveInfo() { for (const key in this.servicesPath) { - this.retrieveServiceStatus(key, this.servicesPath[key]) + this.retrieveServiceStatus(key, this.servicesPath[key]); } // this.retrieveWsInfo(); } @@ -69,15 +69,15 @@ export default class About extends Observable { */ async retrieveServiceStatus(key, path) { this._removeServiceFromMap(key); - this.services[SERVICE_STATES.IN_LOADING][key] = RemoteData.loading(); // adds general loading state of integrated services + this.services[SERVICE_STATES.IN_LOADING][key] = RemoteData.loading(); // adds general loading state of integrated services this.notify(); - const {result, ok} = await this.model.loader.get(`/api/status/${path}`); + const { result, ok } = await this.model.loader.get(`/api/status/${path}`); delete this.services[SERVICE_STATES.IN_LOADING][key]; if (!ok) { this.services[SERVICE_STATES.IN_ERROR][key] = RemoteData.failure({ - name: key, status: {configured: true, ok: false, message: result.message} + name: key, status: { configured: true, ok: false, message: result.message }, }); } else { this._addServicesToMap(key, result); @@ -96,12 +96,10 @@ export default class About extends Observable { this.services[SERVICE_STATES.IN_LOADING].ws = RemoteData.loading(); this.notify(); if (this.model.ws.connection.readyState === WebSocket.OPEN) { - this.setWsInfo( - SERVICE_STATES.IN_SUCCESS, {status: {ok: true, configured: true}, message: 'WebSocket connection is alive'} - ); + this.setWsInfo(SERVICE_STATES.IN_SUCCESS, { status: { ok: true, configured: true }, message: 'WebSocket connection is alive' }); } else { this.setWsInfo(SERVICE_STATES.IN_ERROR, { - status: {ok: false, configured: true, message: 'Cannot establish connection to the server'} + status: { ok: false, configured: true, message: 'Cannot establish connection to the server' }, }); } delete this.services[SERVICE_STATES.IN_LOADING].ws; @@ -111,18 +109,18 @@ export default class About extends Observable { /** * Method to allow the update of WS connection while not being on the about page * @param {string} category - * @param {object} info + * @param {object} info * @returns {void} */ setWsInfo(category, info) { - this.services[category].ws = RemoteData.success({name: 'GUI Stream', ...info}); + this.services[category].ws = RemoteData.success({ name: 'GUI Stream', ...info }); this.notify(); } /** * Given a status of a service, return the category to which it belongs - * @param {boolean} isConfigured - * @param {boolean} isOk + * @param {boolean} isConfigured + * @param {boolean} isOk * @returns {string} - constant SERVICE_STATES */ _getCategoryOnStatus(isConfigured, isOk) { @@ -137,7 +135,9 @@ export default class About extends Observable { /** * Given a component key and an updated status, remove the service from the current grouped lists * and add it to the corresponding new list based on its new status - * @return {void} + * @param component + * @param status + * @returns {void} */ updateComponentStatus(component, status) { const service = this._removeServiceFromMap(component) ?? {}; @@ -158,7 +158,7 @@ export default class About extends Observable { Object.keys(this.services[category]) .filter((name) => name.startsWith(INTEGRATED_SERVICE_LABEL)) .forEach((name) => delete this.services[category][name]); - } else if (this.services[category][serviceKey]){ + } else if (this.services[category][serviceKey]) { const toReturn = JSON.parse(JSON.stringify(this.services[category][serviceKey].payload ?? {})); delete this.services[category][serviceKey]; return toReturn; @@ -169,7 +169,7 @@ export default class About extends Observable { /** * Given a Map of services, add it to the list of queried services * @param {string} key - key of the service - * @param {Service|Map} services - map of services to be added + * @param {Service | Map} services - map of services to be added * @returns {void} */ _addServicesToMap(key, services) { @@ -183,11 +183,11 @@ export default class About extends Observable { /** * Add a service to the current list of statuses enquired - * @param {string} key + * @param {string} key * @param {Service} service - to be added */ _addServiceToMap(key, service) { - const {status: {ok, configured}} = service; + const { status: { ok, configured } } = service; const category = this._getCategoryOnStatus(configured, ok); this.services[category][key] = RemoteData.success(service); } diff --git a/Control/public/about/components/panels/servicesInLoadingPanel.js b/Control/public/about/components/panels/servicesInLoadingPanel.js index 0bfc992ee..653b9e59a 100644 --- a/Control/public/about/components/panels/servicesInLoadingPanel.js +++ b/Control/public/about/components/panels/servicesInLoadingPanel.js @@ -10,24 +10,23 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; import loading from '../../../common/loading.js'; /** * Build a reusable panel which displays a list of names of service that are currently waiting for their status * @param {Array} names + * @param services * @returns {vnode} */ export const servicesInLoadingPanel = (services) => { if (Object.keys(services).length > 0) { - const namesAsString = Object.keys(services).join(', '); return h('.w-100.flex-row.items-center.p2.shadow-level1', [ loading(2), h('.ph2', `Loading status for: ${namesAsString}`), ]); } - -} +}; diff --git a/Control/public/about/components/panels/servicesResolvedPanel.js b/Control/public/about/components/panels/servicesResolvedPanel.js index 616a46038..dac81f3b6 100644 --- a/Control/public/about/components/panels/servicesResolvedPanel.js +++ b/Control/public/about/components/panels/servicesResolvedPanel.js @@ -1,4 +1,3 @@ - /** * @license * Copyright 2019-2020 CERN and copyright holders of ALICE O2. @@ -11,29 +10,31 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; -import {serviceCard} from './../serviceCard.js'; +import { h } from '/js/src/index.js'; +import { serviceCard } from './../serviceCard.js'; /** * Build a reusable panel to display a wrapped list of service panels with their respective information - * @param {Map} services + * @param {Map} services + * @param servicesMap * @param {'success'|'error'|undefined} category - 'success', 'error' * @returns {vnode} */ export const servicesResolvedPanel = (servicesMap, category = undefined) => { const services = Object.values(servicesMap); if (services.length > 0) { - const label = `Services that are ${category ? 'in ' + category.toLocaleUpperCase() + ' state' : 'not enabled'}:`; - const classes = category === 'error' ? 'danger' : (category ?? ''); - return h('.w-100.flex-column.p2.shadow-level1', - h('h4', {class: classes}, label), + const label = `Services that are ${category ? `in ${category.toLocaleUpperCase()} state` : 'not enabled'}:`; + const classes = category === 'error' ? 'danger' : category ?? ''; + return h( + '.w-100.flex-column.p2.shadow-level1', + h('h4', { class: classes }, label), h('.flex-wrap.g1', [ services - .sort(({payload: {name: nameA}}, {payload: {name: nameB}}) => nameA > nameB ? 1 : -1) - .map(({payload}) => serviceCard(payload)) - ]) + .sort(({ payload: { name: nameA } }, { payload: { name: nameB } }) => nameA > nameB ? 1 : -1) + .map(({ payload }) => serviceCard(payload)), + ]), ); } }; diff --git a/Control/public/about/components/serviceCard.js b/Control/public/about/components/serviceCard.js index 308115730..8ebfc8bd9 100644 --- a/Control/public/about/components/serviceCard.js +++ b/Control/public/about/components/serviceCard.js @@ -10,10 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; -import {serviceRow as itemRow} from './serviceRow.js'; +import { h } from '/js/src/index.js'; +import { serviceRow as itemRow } from './serviceRow.js'; /** * Builds a panel corresponding to the information of Service in AliECS GUI @@ -22,28 +22,28 @@ import {serviceRow as itemRow} from './serviceRow.js'; */ export const serviceCard = (service) => { const { - status: {ok, configured, message} = {}, endpoint, version, extras = {}, name = 'UNDEFINED', connectionState + status: { ok, configured, message } = {}, endpoint, version, extras = {}, name = 'UNDEFINED', connectionState, } = service; const isDown = configured && !ok; - + const showExtras = extras?.showExtras && Object.keys(extras).length > 0; const extrasToDisplay = JSON.parse(JSON.stringify(extras)); delete extrasToDisplay.showExtras; - const titleClass = (configured && ok) ? 'success' : (configured && !ok) ? 'bg-danger white' : ''; + const titleClass = configured && ok ? 'success' : configured && !ok ? 'bg-danger white' : ''; - return h('.w-33.flex-column', {id: name}, [ - h('.panel-title.p2.flex-row', {class: titleClass}, [ + return h('.w-33.flex-column', { id: name }, [ + h('.panel-title.p2.flex-row', { class: titleClass }, [ h('h4', name), - version && h('i.text-right.flex-grow', {style: 'justify-content: flex-end'}, version) + version && h('i.text-right.flex-grow', { style: 'justify-content: flex-end' }, version), ]), configured && h('.panel.flex-column.g2', [ [ isDown && itemRow('Error', message), itemRow('Endpoint', endpoint), itemRow('Connection State', connectionState), - showExtras && h('pre', {style: 'max-height: 10em'}, JSON.stringify(extrasToDisplay, null, 2)) - ] - ]) + showExtras && h('pre', { style: 'max-height: 10em' }, JSON.stringify(extrasToDisplay, null, 2)), + ], + ]), ]); }; diff --git a/Control/public/about/components/serviceRow.js b/Control/public/about/components/serviceRow.js index 8da2d88d0..7190a3213 100644 --- a/Control/public/about/components/serviceRow.js +++ b/Control/public/about/components/serviceRow.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Builds a line composed of 2 elements: name and value @@ -20,9 +20,7 @@ import {h} from '/js/src/index.js'; * @param {string} value - value of the field * @returns {vnode} - only if value is !undefined */ -export const serviceRow = (name, value) => { - return value && h('.w-100.flex-row', [ - h('h6.w-40.p1', name), - h('span.w-60.ph1', value) - ]); -}; +export const serviceRow = (name, value) => value && h('.w-100.flex-row', [ + h('h6.w-40.p1', name), + h('span.w-60.ph1', value), +]); diff --git a/Control/public/about/content.js b/Control/public/about/content.js index a45330361..c14b63e56 100644 --- a/Control/public/about/content.js +++ b/Control/public/about/content.js @@ -10,13 +10,13 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; -import {servicesResolvedPanel} from './components/panels/servicesResolvedPanel.js'; -import {servicesInLoadingPanel} from './components/panels/servicesInLoadingPanel.js'; +import { h } from '/js/src/index.js'; +import { servicesResolvedPanel } from './components/panels/servicesResolvedPanel.js'; +import { servicesInLoadingPanel } from './components/panels/servicesInLoadingPanel.js'; import { SERVICE_STATES } from '../common/constants/serviceStates.js'; -const {IN_ERROR, IN_LOADING, IN_SUCCESS, NOT_ENABLED} = SERVICE_STATES; +const { IN_ERROR, IN_LOADING, IN_SUCCESS, NOT_ENABLED } = SERVICE_STATES; /** * @file Content for About Page @@ -28,7 +28,8 @@ const {IN_ERROR, IN_LOADING, IN_SUCCESS, NOT_ENABLED} = SERVICE_STATES; * @param {Model} model * @returns {vnode} */ -export const content = ({about: {services} = {}}) => h('.scroll-y.absolute-fill.flex-column.p2.g2', +export const content = ({ about: { services } = {} }) => h( + '.scroll-y.absolute-fill.flex-column.p2.g2', servicesInLoadingPanel(services[IN_LOADING]), servicesResolvedPanel(services[IN_ERROR], 'error'), servicesResolvedPanel(services[IN_SUCCESS], 'success'), diff --git a/Control/public/about/header.js b/Control/public/about/header.js index 452b28e72..5aa83c562 100644 --- a/Control/public/about/header.js +++ b/Control/public/about/header.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * @file Header for About Page @@ -23,6 +23,4 @@ import {h} from '/js/src/index.js'; * @param {Model} model - root object of the framework * @returns {vnode} */ -export const header = (model) => [ - h('.w-100 text-center', h('h4', 'About')), -]; +export const header = (model) => [h('.w-100 text-center', h('h4', 'About'))]; diff --git a/Control/public/common/alertPanel.js b/Control/public/common/alertPanel.js index 67271ff0b..d19df9a33 100644 --- a/Control/public/common/alertPanel.js +++ b/Control/public/common/alertPanel.js @@ -10,38 +10,36 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {SERVICE_STATES} from './constants/serviceStates.js'; -import {h, iconCircleX} from '/js/src/index.js'; +import { SERVICE_STATES } from './constants/serviceStates.js'; +import { h, iconCircleX } from '/js/src/index.js'; /** * Component to display an icon with an alert if something goes wrong: * - iconCircleX for critical alerts - * - + * - * @param {number} servicesByCategory - * @return {vnode} + * @param model + * @returns {vnode} */ const alertPanel = (servicesByCategory, model) => { let numberOfCriticalErrors = 0; for (const service of Object.values(servicesByCategory[SERVICE_STATES.IN_ERROR])) { - const {status = {}} = service.payload; + const { status = {} } = service.payload; if (status.isCritical && !service.ok) { numberOfCriticalErrors++; } } if (numberOfCriticalErrors > 0) { - return h('a.mh2.flex-row.flex-end', { href: '?page=about', - onclick: (e) => model.router.handleLinkEvent(e) - }, - h('.g2.danger.items-center.flex-row.actionable-icon', [ + onclick: (e) => model.router.handleLinkEvent(e), + }, h('.g2.danger.items-center.flex-row.actionable-icon', [ h('span', iconCircleX()), - h('h3', `Errors`), - ]) - ) + h('h3', 'Errors'), + ])); } }; -export {alertPanel}; +export { alertPanel }; diff --git a/Control/public/common/appHeader.js b/Control/public/common/appHeader.js index e92f043f1..02d2c7d59 100644 --- a/Control/public/common/appHeader.js +++ b/Control/public/common/appHeader.js @@ -10,42 +10,45 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h, iconPerson} from '/js/src/index.js'; +import { h, iconPerson } from '/js/src/index.js'; /** * Application header (left part): lockpad button and application name - * @param {Object} model - * @return {vnode} + * @param {object} model + * @returns {vnode} */ -export default (model) => h('.text-left', +export default (model) => h( + '.text-left', { - style: 'width: 15em' + style: 'width: 15em', }, [ loginButton(model), ' ', - h('span.f4 gray', 'Control') - ]); + h('span.f4 gray', 'Control'), + ], +); /** * Login button on top left * One click shows username and logout link if any - * @param {Object} model - * @return {vnode} + * @param {object} model + * @returns {vnode} */ -const loginButton = (model) => h('.dropdown', {class: model.accountMenuEnabled ? 'dropdown-open' : ''}, [ - h('button.btn', {onclick: () => model.toggleAccountMenu()}, iconPerson()), +const loginButton = (model) => h('.dropdown', { class: model.accountMenuEnabled ? 'dropdown-open' : '' }, [ + h('button.btn', { onclick: () => model.toggleAccountMenu() }, iconPerson()), h('.dropdown-menu', [ h('p.m3.mv2.text-ellipsis', `Welcome ${model.session.name}`, h('sup', model.session.role)), model.session.personid === 0 // anonymous user has id 0 && h('p.m3.gray-darker', 'You are connected as anonymous, no authentification needed for this application.'), model.checkBrowserNotificationPermissions() && - h('a.menu-item', {onclick: () => { - model.toggleAccountMenu(); model.requestBrowserNotificationPermissions()} + h('a.menu-item', { onclick: () => { + model.toggleAccountMenu(); model.requestBrowserNotificationPermissions(); + }, }, 'Enable notifications'), model.session.personid !== 0 && - h('a.menu-item', {onclick: () => alert(`Not implemented`)}, 'Logout') + h('a.menu-item', { onclick: () => alert('Not implemented') }, 'Logout'), ]), ]); diff --git a/Control/public/common/buttons/copyToClipboardIcon.js b/Control/public/common/buttons/copyToClipboardIcon.js index 9288334af..59ac64289 100644 --- a/Control/public/common/buttons/copyToClipboardIcon.js +++ b/Control/public/common/buttons/copyToClipboardIcon.js @@ -10,10 +10,10 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h, iconClipboard} from '/js/src/index.js'; -import {di} from './../../utilities/di.js'; +import { h, iconClipboard } from '/js/src/index.js'; +import { di } from './../../utilities/di.js'; /** * Copy passed value to the user's clipboard @@ -27,8 +27,8 @@ export const copyToClipboardIcon = (value) => { onclick: () => { navigator.clipboard.writeText(value); di.notification.show('Successfully copied to clipboard', 'success', 1500); - } - }, iconClipboard()) + }, + }, iconClipboard()); } return; }; @@ -36,8 +36,6 @@ export const copyToClipboardIcon = (value) => { /** * Method to check if connection is secure to enable certain improvements * e.g navigator.clipboard, notifications, service workers - * @return {boolean} + * @returns {boolean} */ -const isContextSecure = () => { - return window.isSecureContext; -} +const isContextSecure = () => window.isSecureContext; diff --git a/Control/public/common/buttons/textWithCopyClipboard.js b/Control/public/common/buttons/textWithCopyClipboard.js index 511156ff0..65ef9739b 100644 --- a/Control/public/common/buttons/textWithCopyClipboard.js +++ b/Control/public/common/buttons/textWithCopyClipboard.js @@ -10,15 +10,16 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; import { copyToClipboardIcon } from './copyToClipboardIcon.js'; /** * Build a component which displays some text and provides a copy to clipboard actionable icon - * @param {String|vnode} text - text to be displayed - * @return {vnode} + * @param {string | vnode} text - text to be displayed + * @param type + * @returns {vnode} */ export const textWithCopyClipboard = (text, type) => h('.flex-row.gc2', [ diff --git a/Control/public/common/card/miniCard.js b/Control/public/common/card/miniCard.js index 402e2e162..0c5046be1 100644 --- a/Control/public/common/card/miniCard.js +++ b/Control/public/common/card/miniCard.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Builds a miniCard frame and adds inside the passed children @@ -21,18 +21,16 @@ import {h} from '/js/src/index.js'; * @param {Array} [classes] - object containing style parameters * @returns {vnode} */ -export const miniCard = (title, children = [], classes = ['p2', 'g2']) => { - return h(`.miniCard.flex-column.shadow-level1.br2`, { - class: classes.join(' '), - }, [ - !title - ? undefined - : typeof title === 'string' - ? miniCardTitle(title) - : title, - children, - ]); -} +export const miniCard = (title, children = [], classes = ['p2', 'g2']) => h('.miniCard.flex-column.shadow-level1.br2', { + class: classes.join(' '), +}, [ + !title + ? undefined + : typeof title === 'string' + ? miniCardTitle(title) + : title, + children, +]); /** * Builds a title group for a mini-card @@ -40,13 +38,11 @@ export const miniCard = (title, children = [], classes = ['p2', 'g2']) => { * @param {string} [sub] - optional sub-title to be added at the end of the title group * @returns {vnode} */ -export const miniCardTitle = (main, sub = '') => { - return h(`.w-100.flex-row`, [ - h(`h4`, { - style: 'text-decoration: underline; flex-grow: 6;' - }, main), - sub && h('.text-right', { - style: 'font-style: italic; flex-grow: 4;' - }, sub) - ]); -} +export const miniCardTitle = (main, sub = '') => h('.w-100.flex-row', [ + h('h4', { + style: 'text-decoration: underline; flex-grow: 6;', + }, main), + sub && h('.text-right', { + style: 'font-style: italic; flex-grow: 4;', + }, sub), +]); diff --git a/Control/public/common/card/rowForCard.js b/Control/public/common/card/rowForCard.js index 782bf9a80..873eba036 100644 --- a/Control/public/common/card/rowForCard.js +++ b/Control/public/common/card/rowForCard.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Returns a row to be used for panels @@ -21,8 +21,8 @@ import {h} from '/js/src/index.js'; * @param {{Array, Array}} [valueClasses] - list of classes as list to be used to customise the values * @returns {vnode} */ -export const rowForCard = (key, value, {keyClasses = [], valueClasses = []} = {}) => - h(`.flex-row.justify-between.gc4`, [ - h('', {classList: keyClasses.join(' ')}, key), - h('', {classList: valueClasses.join(' ')}, value) +export const rowForCard = (key, value, { keyClasses = [], valueClasses = [] } = {}) => + h('.flex-row.justify-between.gc4', [ + h('', { classList: keyClasses.join(' ') }, key), + h('', { classList: valueClasses.join(' ') }, value), ]); diff --git a/Control/public/common/coloredBadge.js b/Control/public/common/coloredBadge.js index c5fbccce4..23dad5e65 100644 --- a/Control/public/common/coloredBadge.js +++ b/Control/public/common/coloredBadge.js @@ -11,14 +11,13 @@ * or submit itself to any jurisdiction. */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Return a colored cell based on a given value and mapping associated - * - * @param {String} value - the value to be displayed in the cell - * @param {Object} colorMap - map storing color based on value - * @return {vnode} - the colored cell + * @param {string} value - the value to be displayed in the cell + * @param {Object} colorMap - map storing color based on value + * @returns {vnode} - the colored cell */ export const coloredBadge = (value = '', colorMap = {}) => { const valueAsKey = value.split(' ').join('_'); diff --git a/Control/public/common/constants/serviceStates.js b/Control/public/common/constants/serviceStates.js index 0847036c2..bec4041d8 100644 --- a/Control/public/common/constants/serviceStates.js +++ b/Control/public/common/constants/serviceStates.js @@ -10,11 +10,11 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ export const SERVICE_STATES = { IN_ERROR: 'IN_ERROR', IN_SUCCESS: 'IN_SUCCESS', IN_LOADING: 'IN_LOADING', - NOT_ENABLED: 'NOT_ENABLED' + NOT_ENABLED: 'NOT_ENABLED', }; diff --git a/Control/public/common/constants/stateColors.js b/Control/public/common/constants/stateColors.js index 6248d5bda..c31000e13 100644 --- a/Control/public/common/constants/stateColors.js +++ b/Control/public/common/constants/stateColors.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ export const ALIECS_STATE_COLOR = { RUNNING: 'success', @@ -22,7 +22,7 @@ export const ALIECS_STATE_COLOR = { STANDBY: 'gray-darker', DEPLOYED: 'gray-darker', PENDING: 'gray-darker', - DONE: 'primary' + DONE: 'primary', }; export const ODC_STATE_COLOR = { diff --git a/Control/public/common/constants/statusComponents.enum.js b/Control/public/common/constants/statusComponents.enum.js index dc5ddd1c5..d88d0f86a 100644 --- a/Control/public/common/constants/statusComponents.enum.js +++ b/Control/public/common/constants/statusComponents.enum.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ const STATUS_COMPONENTS_KEYS = Object.freeze({ CONSUL_KEY: 'CONSUL', @@ -23,4 +23,4 @@ const STATUS_COMPONENTS_KEYS = Object.freeze({ APRICOT_KEY: 'APRICOT', }); -export {STATUS_COMPONENTS_KEYS}; +export { STATUS_COMPONENTS_KEYS }; diff --git a/Control/public/common/dcs/dcsPropertiesRow.js b/Control/public/common/dcs/dcsPropertiesRow.js index 1f12198da..a16409153 100644 --- a/Control/public/common/dcs/dcsPropertiesRow.js +++ b/Control/public/common/dcs/dcsPropertiesRow.js @@ -10,20 +10,20 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h, iconCheck, iconX} from '/js/src/index.js'; -import {DetectorState} from './../enums/DetectorState.enum.js'; +import { h, iconCheck, iconX } from '/js/src/index.js'; +import { DetectorState } from './../enums/DetectorState.enum.js'; /** * Construct a visual element under the form of a row that displays the state of properties of a detector as per DCS * - PFR - Prepare For Run * - SOR - Start Of Run * @param {Detector} detector - information of a detector from DCS - * @return {vnode} + * @returns {vnode} */ export const dcsPropertiesRow = (detector = {}) => { - const {pfrAvailability, sorAvailability} = detector; + const { pfrAvailability, sorAvailability } = detector; return h('.flex-row.g2', [ pfrAvailability && dcsProperty(pfrAvailability, 'PFR'), sorAvailability && dcsProperty(sorAvailability, 'SOR'), @@ -34,7 +34,7 @@ export const dcsPropertiesRow = (detector = {}) => { * Construct a visual element that it will help the user in understanding the property of DCS and what actions can be taken * @param {DetectorState} state - state of the DCS property that we wish to display * @param {String['PFR', 'SOR']} name - dcs component that we display availability for - * @return {vnode} + * @returns {vnode} */ export const dcsProperty = (state = '', name) => { let stateClass = ''; @@ -49,8 +49,8 @@ export const dcsProperty = (state = '', name) => { } if (state !== DetectorState.UNDEFINED) { return h('.flex-row.g1', [ - h(``, {class: stateClass}, icon), - name + h('', { class: stateClass }, icon), + name, ]); } return ''; diff --git a/Control/public/common/deployEnvironmentButton.component.js b/Control/public/common/deployEnvironmentButton.component.js index 2d881b38f..d96b3c257 100644 --- a/Control/public/common/deployEnvironmentButton.component.js +++ b/Control/public/common/deployEnvironmentButton.component.js @@ -11,13 +11,12 @@ * or submit itself to any jurisdiction. */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Builds a component with a set of buttons to allow users to create environments based on mapped workflow templates - * - * @param {Boolean} isLoading - if the button should be displayed as loading - * @param {Boolean} isReady - if environment creation is ready to be deployed + * @param {boolean} isLoading - if the button should be displayed as loading + * @param {boolean} isReady - if environment creation is ready to be deployed * @param {void} onclick - deploying action of the environment * @returns {vnode} */ @@ -27,6 +26,6 @@ export const deployEnvironmentButton = (isLoading = false, isReady = false, oncl class: isLoading ? 'loading' : '', disabled: !isReady || isLoading, onclick, - title: 'Deploy environment' - },'Deploy') + title: 'Deploy environment', + }, 'Deploy'), ]); diff --git a/Control/public/common/detectorHeader.js b/Control/public/common/detectorHeader.js index b256da41d..97bcc470b 100644 --- a/Control/public/common/detectorHeader.js +++ b/Control/public/common/detectorHeader.js @@ -10,30 +10,27 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h, iconPencil} from '/js/src/index.js'; +import { h, iconPencil } from '/js/src/index.js'; /** * Component which will display selected detectors to filter data based on * To be used in most of the pages to display the selection - * @param {Object} model - * @return {vnode} + * @param {object} model + * @returns {vnode} */ const detectorHeader = (model) => { - const selected = model.detectors.selected; + const { selected } = model.detectors; if (selected) { return h('.w-100.bg-gray-light.pv2', { - style: 'height: 40px' - },[ - h('h4.f5.flex-row', {style: 'justify-content: center;'}, - h('.ph2', `Detector View: ${selected}`), - h('a.f6.actionable-icon.ph2', { - onclick: () => model.resetDetectorView('') - }, iconPencil()), - ) - ]) + style: 'height: 40px', + }, [ + h('h4.f5.flex-row', { style: 'justify-content: center;' }, h('.ph2', `Detector View: ${selected}`), h('a.f6.actionable-icon.ph2', { + onclick: () => model.resetDetectorView(''), + }, iconPencil())), + ]); } }; -export {detectorHeader}; +export { detectorHeader }; diff --git a/Control/public/common/detectorLock/detectionLockActionButton.js b/Control/public/common/detectorLock/detectionLockActionButton.js index 603752f6b..ed93a502e 100644 --- a/Control/public/common/detectorLock/detectionLockActionButton.js +++ b/Control/public/common/detectorLock/detectionLockActionButton.js @@ -10,25 +10,22 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; -import {DetectorLockState} from './../enums/DetectorLockState.enum.js'; +import { h } from '/js/src/index.js'; +import { DetectorLockState } from './../enums/DetectorLockState.enum.js'; /** * Button with action to force take/release lock for a detector - * @param {Lock} lockModel - model of the lock service - * @param {String} detector - detector name + * @param {Lock} lockModel - model of the lock service + * @param {string} detector - detector name * @param {DetectorLockState} lockState - lock state of the detector * @param {DetectorLockAction} action - action to be performed - * @param {String} label - button label to be displayed to the user - * @return {vnode} + * @param shouldForce + * @param {string} label - button label to be displayed to the user + * @returns {vnode} */ -export const detectorLockActionButton = ( - lockModel, detector, lockState, action, shouldForce = false, label = `${action}` -) => { - return h('button.btn.btn-sm.btn-danger', { - disabled: lockState?.state === DetectorLockState.FREE, - onclick: () => lockModel.actionOnLock(detector, action, shouldForce) - }, label); -}; +export const detectorLockActionButton = (lockModel, detector, lockState, action, shouldForce = false, label = `${action}`) => h('button.btn.btn-sm.btn-danger', { + disabled: lockState?.state === DetectorLockState.FREE, + onclick: () => lockModel.actionOnLock(detector, action, shouldForce), +}, label); diff --git a/Control/public/common/detectorModal.js b/Control/public/common/detectorModal.js index 3bdb1b144..24b024622 100644 --- a/Control/public/common/detectorModal.js +++ b/Control/public/common/detectorModal.js @@ -10,62 +10,60 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h, iconCircleX} from '/js/src/index.js'; +import { h, iconCircleX } from '/js/src/index.js'; import loading from './loading.js'; -import {ROLES} from './../workflow/constants.js'; -import {isUserAllowedRole} from './userRole.js'; +import { ROLES } from './../workflow/constants.js'; +import { isUserAllowedRole } from './userRole.js'; /** * Component which will display a modal allowing the users to select their detector view * No matter the page location, modal will be displayed if user did not make a selection - * @param {Object} model - * @return {vnode} + * @param {object} model + * @returns {vnode} */ const detectorsModal = (model) => - !model.detectors.selected && isUserAllowedRole(ROLES.Detector) && h('.o2-modal', + !model.detectors.selected && isUserAllowedRole(ROLES.Detector) && h( + '.o2-modal', h('.o2-modal-content', [ h('.p2.text-center', [ h('h4', 'Select your detector view'), - h('label', {style: 'font-style: italic;'}, 'Displayed data will be filtered based on your selection') + h('label', { style: 'font-style: italic;' }, 'Displayed data will be filtered based on your selection'), ]), - h('.w-100.flex-row', {style: 'flex-wrap: wrap; justify-content:center'}, [ + h('.w-100.flex-row', { style: 'flex-wrap: wrap; justify-content:center' }, [ model.detectors.listRemote.match({ NotAsked: () => null, Loading: () => h('.w-100.text-center', loading(2)), Success: (data) => detectorsList(model, data), - Failure: (_) => h('.w-100.text-center.danger', [ - iconCircleX(), ' Unable to load list of detectors.' - ]) - }) + Failure: (_) => h('.w-100.text-center.danger', [iconCircleX(), ' Unable to load list of detectors.']), + }), ]), - h('.w-100.pv3.f3.flex-row', {style: 'justify-content:center;'}, - h('.w-50.flex-column.dropdown#flp_selection_info_icon', [ - isUserAllowedRole(ROLES.Global) && - h(`button.btn.btn-default.w-100`, { - id: `GLOBALViewButton`, + h('.w-100.pv3.f3.flex-row', { style: 'justify-content:center;' }, h('.w-50.flex-column.dropdown#flp_selection_info_icon', [ + isUserAllowedRole(ROLES.Global) && + h('button.btn.btn-default.w-100', { + id: 'GLOBALViewButton', onclick: () => model.setDetectorView('GLOBAL'), - }, 'GLOBAL') - ]) - ) - ]) + }, 'GLOBAL'), + ])), + ]), ); /** * Build a wrapped list of detector buttons - * @param {Object} model - * @param {List} list + * @param {object} model + * @param {List} list * @returns {vnode} */ const detectorsList = (model, list) => list - .filter(detector => model.detectors.authed.includes(detector) || isUserAllowedRole(ROLES.Global)) - .map((detector) => h('.w-25.pv3.text-center.f3', + .filter((detector) => model.detectors.authed.includes(detector) || isUserAllowedRole(ROLES.Global)) + .map((detector) => h( + '.w-25.pv3.text-center.f3', h('button.btn.btn-default.w-70', { id: `${detector}ViewButton`, - onclick: () => model.setDetectorView(detector) - }, detector) + onclick: () => model.setDetectorView(detector), + }, detector), )); -export {detectorsModal}; +export { detectorsModal }; diff --git a/Control/public/common/enums/DetectorLockAction.enum.js b/Control/public/common/enums/DetectorLockAction.enum.js index adbba138e..9aa645392 100644 --- a/Control/public/common/enums/DetectorLockAction.enum.js +++ b/Control/public/common/enums/DetectorLockAction.enum.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** * Available lock actions for users diff --git a/Control/public/common/enums/DetectorLockState.enum.js b/Control/public/common/enums/DetectorLockState.enum.js index ea1d9e4dd..2e36405bf 100644 --- a/Control/public/common/enums/DetectorLockState.enum.js +++ b/Control/public/common/enums/DetectorLockState.enum.js @@ -10,7 +10,7 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /** * Available lock states diff --git a/Control/public/common/enums/DetectorState.enum.js b/Control/public/common/enums/DetectorState.enum.js index 06970d12e..ff3448993 100644 --- a/Control/public/common/enums/DetectorState.enum.js +++ b/Control/public/common/enums/DetectorState.enum.js @@ -14,7 +14,7 @@ /** * States of a detector as considered by DCS * @link https://github.com/AliceO2Group/Control/blob/c5fdca8e25f6f724231d15e34bb1bde7b2c267ab/core/integration/dcs/protos/dcs.proto#L251 - * @return {Object} + * @returns {object} */ export const DetectorState = Object.freeze({ UNDEFINED: 'UNDEFINED', // GUI initial set state diff --git a/Control/public/common/enums/HardwareComponent.js b/Control/public/common/enums/HardwareComponent.js index 188f11d6e..9b8409a9f 100644 --- a/Control/public/common/enums/HardwareComponent.js +++ b/Control/public/common/enums/HardwareComponent.js @@ -20,7 +20,7 @@ export const HardwareComponent = Object.freeze({ /** * List of possible hardware components sorted alphabetically with FLP first - * @return {Array} list of hardware components + * @returns {Array} list of hardware components */ export const HARDWARE_COMPONENTS = Object.keys(HardwareComponent) .sort((a, b) => { diff --git a/Control/public/common/enums/TaskState.js b/Control/public/common/enums/TaskState.js index 68e1097f0..8be8dd74a 100644 --- a/Control/public/common/enums/TaskState.js +++ b/Control/public/common/enums/TaskState.js @@ -25,11 +25,10 @@ export const TaskState = Object.freeze({ /** * List of possible states for a task sorted alphabetically with ERROR first and RUNNING second and CONFIGURED third - * @return {Array} list of task states + * @returns {Array} list of task states */ export const TASK_STATES = Object.values(TaskState) .sort((a, b) => { - if (a === TaskState.ERROR_CRITICAL) { return -1; } else if (b === TaskState.ERROR_CRITICAL) { @@ -58,7 +57,7 @@ export const TASK_STATES = Object.values(TaskState) /** * Given a hardware component task state, return the class associated with the state * @param {TaskState} state - task state to get the class for - * @return {String} - CSS class to be used in the HTML + * @returns {string} - CSS class to be used in the HTML */ export function getTaskStateClassAssociation(state) { switch (state) { diff --git a/Control/public/common/errorComponent.js b/Control/public/common/errorComponent.js index d91208b65..c65e06a8c 100644 --- a/Control/public/common/errorComponent.js +++ b/Control/public/common/errorComponent.js @@ -10,15 +10,15 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; -import {iconCircleX} from '/js/src/icons.js'; +import { h } from '/js/src/index.js'; +import { iconCircleX } from '/js/src/icons.js'; /** * Display an iconCircleX and a red error message * @param {string} message - * @return {vnode} + * @returns {vnode} */ export default (message) => h('.danger', iconCircleX(), ' ', message); diff --git a/Control/public/common/errorPage.js b/Control/public/common/errorPage.js index b895490ca..47903138b 100644 --- a/Control/public/common/errorPage.js +++ b/Control/public/common/errorPage.js @@ -10,16 +10,16 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h, iconCircleX} from '/js/src/index.js'; +import { h, iconCircleX } from '/js/src/index.js'; /** * Generic page error with label, used on page load failed or access denied * @param {string} error - * @return {vnode} + * @returns {vnode} */ export default (error) => h('.flex-column items-center justify-center', [ h('span.errorPage', iconCircleX()), - h('span.text-center.danger.measure-narrow', {style: 'white-space: pre-line'},error) + h('span.text-center.danger.measure-narrow', { style: 'white-space: pre-line' }, error), ]); diff --git a/Control/public/common/iframe/iframe.js b/Control/public/common/iframe/iframe.js index 8a0bcd61a..d1890f5f8 100644 --- a/Control/public/common/iframe/iframe.js +++ b/Control/public/common/iframe/iframe.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Builds an iframe with specified source and no borders @@ -20,4 +20,4 @@ import {h} from '/js/src/index.js'; * @param {string} [style] - optional style parameters * @returns {vnode} */ -export const iframe = (src, style = 'border:0;') => h('iframe', {src, style}); +export const iframe = (src, style = 'border:0;') => h('iframe', { src, style }); diff --git a/Control/public/common/loading.js b/Control/public/common/loading.js index ab14c2324..11b1c5c86 100644 --- a/Control/public/common/loading.js +++ b/Control/public/common/loading.js @@ -10,28 +10,33 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Generic page loading placeholder * @param {number} size - * @return {vnode} + * @returns {vnode} */ -export default (size) => h('span', +export default (size) => h( + 'span', { - style: size ? `font-size: ${size}em` : 'font-size: 10em' + style: size ? `font-size: ${size}em` : 'font-size: 10em', }, - h('.atom-spinner', - h('.spinner-inner', + h( + '.atom-spinner', + h( + '.spinner-inner', [ h('.spinner-line'), h('.spinner-line'), h('.spinner-line'), - h('.spinner-circle', - h('div', '●') - ) - ] - ) - )); + h( + '.spinner-circle', + h('div', '●'), + ), + ], + ), + ), +); diff --git a/Control/public/common/pageLoading.js b/Control/public/common/pageLoading.js index 2f3b00982..94b7321ea 100644 --- a/Control/public/common/pageLoading.js +++ b/Control/public/common/pageLoading.js @@ -10,30 +10,35 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Generic page loading placeholder * @param {number} size - * @return {vnode} + * @param margin + * @returns {vnode} */ export default (size = 10, margin = '2em') => - h('span.pageLoading', + h( + 'span.pageLoading', { - style: `font-size: ${size}em;margin:${margin}` + style: `font-size: ${size}em;margin:${margin}`, }, - h('.atom-spinner', - h('.spinner-inner', + h( + '.atom-spinner', + h( + '.spinner-inner', [ h('.spinner-line'), h('.spinner-line'), h('.spinner-line'), - h('.spinner-circle', - h('div', '●') - ) - ] - ) - ) + h( + '.spinner-circle', + h('div', '●'), + ), + ], + ), + ), ); diff --git a/Control/public/common/panel/panel.js b/Control/public/common/panel/panel.js index 5b3cfbecb..85b10d8c9 100644 --- a/Control/public/common/panel/panel.js +++ b/Control/public/common/panel/panel.js @@ -10,14 +10,14 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; -import {panelTitle} from './panelTitle.js'; +import { h } from '/js/src/index.js'; +import { panelTitle } from './panelTitle.js'; /** * Returns a div element with properties for a panel title - * @param {String|vnode} title - title to be placed for panel + * @param {string | vnode} title - title to be placed for panel * @param {vnode} content - content to be placed within the panel * @returns {vnode} */ @@ -25,4 +25,4 @@ export const panel = (title, content) => h('.w-100.panel', [ panelTitle(title), content, - ]) + ]); diff --git a/Control/public/common/panel/panelTitle.js b/Control/public/common/panel/panelTitle.js index e12949fe9..cdd7b299b 100644 --- a/Control/public/common/panel/panelTitle.js +++ b/Control/public/common/panel/panelTitle.js @@ -10,13 +10,13 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; /** * Returns a div element with properties for a panel title - * @param {String|vnode} title - title to be placed for panel + * @param {string | vnode} title - title to be placed for panel * @returns {vnode} */ export const panelTitle = (title) => h('h5.panel-title.text-center.p2', title); diff --git a/Control/public/common/qcgExternalLink.js b/Control/public/common/qcgExternalLink.js index 5ee9ccdb1..7a4c9886a 100644 --- a/Control/public/common/qcgExternalLink.js +++ b/Control/public/common/qcgExternalLink.js @@ -10,19 +10,19 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h, iconExternalLink} from '/js/src/index.js'; +import { h, iconExternalLink } from '/js/src/index.js'; /* global COG */ /** * Component for building an external link in a new tab to QCG component based on a given run object * @param {Run} run - object with run information needed for building a link - * @return {vnode} + * @returns {vnode} */ export const qcgExternalLink = (run) => { - const {runNumber, detectors, definition, runType} = run; + const { runNumber, detectors, definition, runType } = run; const qcgLinkQueryParameters = ['page=layoutShow']; if (definition) { @@ -46,8 +46,7 @@ export const qcgExternalLink = (run) => { }, h('.flex-row.gc1', [ 'QCG', h('span.f6', iconExternalLink()), - ]) - ); + ])); } return; -} +}; diff --git a/Control/public/common/showTableItem.js b/Control/public/common/showTableItem.js index af6353268..3396277db 100644 --- a/Control/public/common/showTableItem.js +++ b/Control/public/common/showTableItem.js @@ -10,22 +10,22 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; -import {parseObject} from './utils.js'; +import { h } from '/js/src/index.js'; +import { parseObject } from './utils.js'; /** * Generic table to show properties of an object * This can be forked to show more specific data (format date, colors, more buttons...) - * @param {Object} item - object to be shown - * @return {vnode} table view + * @param {object} item - object to be shown + * @returns {vnode} table view */ -export default (item) => h('table.table.shadow-level2', {style: 'white-space: pre-wrap;'}, [ +export default (item) => h('table.table.shadow-level2', { style: 'white-space: pre-wrap;' }, [ h('tbody', Object.keys(item).map((columnName) => h('tr', [ h('th', columnName), typeof item[columnName] === 'object' ? h('td', parseObject(item[columnName], columnName)) : - h('td', item[columnName]) + h('td', item[columnName]), ]))), ]); diff --git a/Control/public/common/sidebar.js b/Control/public/common/sidebar.js index 09797140f..926fe9701 100644 --- a/Control/public/common/sidebar.js +++ b/Control/public/common/sidebar.js @@ -10,46 +10,52 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {h} from '/js/src/index.js'; +import { h } from '/js/src/index.js'; import { iconGridTwoUp, iconGridThreeUp, iconExcerpt, iconPlus, iconMediaSkipBackward, iconMediaSkipForward, iconCog, - iconCalculator, iconLockLocked, iconWrench + iconCalculator, iconLockLocked, iconWrench, } from '/js/src/icons.js'; /** * Sidebar is the main navigation menu to choose pages though QueryRouter instance - * @param {Object} model - * @return {vnode} + * @param {object} model + * @returns {vnode} */ export default (model) => h('.absolute-fill scroll-y.flex-column', [ - h('h5.menu-title-large.mh1', - model.sideBarMenu ? 'Environments' : 'ENVS'), + h( + 'h5.menu-title-large.mh1', + model.sideBarMenu ? 'Environments' : 'ENVS', + ), menuItem(model, 'Global Runs', 'newEnvironment', iconPlus()), menuItem(model, 'Calibration Runs', 'calibrationRuns', iconWrench()), menuItem(model, 'Active Environments', 'environments', iconGridTwoUp()), menuItem(model, 'Create', 'newEnvironmentAdvanced', iconPlus()), menuItem(model, 'Task list', 'taskList', iconGridThreeUp()), - h('h5.menu-title-large.mh1', - model.sideBarMenu ? 'Hardware' : 'HDW'), + h( + 'h5.menu-title-large.mh1', + model.sideBarMenu ? 'Hardware' : 'HDW', + ), menuItem(model, 'Links', 'configuration', iconCog()), menuItem(model, 'FLPs', 'hardware', iconCalculator()), - h('h5.menu-title-large.mh1', - model.sideBarMenu ? 'Admin' : 'ADM'), + h( + 'h5.menu-title-large.mh1', + model.sideBarMenu ? 'Admin' : 'ADM', + ), menuItem(model, 'Locks', 'locks', iconLockLocked()), - h('', {style: 'flex-grow:1'}), // empty item to fill in space + h('', { style: 'flex-grow:1' }), // empty item to fill in space menuItem(model, 'About', 'about', iconExcerpt()), collapseSidebarMenuItem(model), ]); /** * Create a menu-item - * @param {Object} model + * @param {object} model * @param {string} title * @param {string} pageParam - where onclick() should navigate to * @param {icon} icon - * @return {vnode} + * @returns {vnode} */ const menuItem = (model, title, pageParam, icon) => h('a.menu-item', { @@ -57,29 +63,28 @@ const menuItem = (model, title, pageParam, icon) => style: 'display: flex', href: `?page=${pageParam}`, onclick: (e) => model.router.handleLinkEvent(e), - class: model.router.params.page === pageParam ? 'selected' : '' + class: model.router.params.page === pageParam ? 'selected' : '', }, [ h('span', icon), - model.sideBarMenu && itemMenuText(title) + model.sideBarMenu && itemMenuText(title), ]); /** -* Show link to status page -* @param {Object} model -* @return {vnode} -*/ + * Show link to status page + * @param {object} model + * @returns {vnode} + */ const collapseSidebarMenuItem = (model) => h('a.menu-item', { title: 'Toggle Sidebar', onclick: () => model.toggleSideBarMenu(), }, model.sideBarMenu ? [iconMediaSkipBackward(), itemMenuText('Collapse Sidebar')] - : iconMediaSkipForward(), - ); + : iconMediaSkipForward()); /** * Display text with item properties * @param {string} text - * @return {vnode} + * @returns {vnode} */ const itemMenuText = (text) => h('span.ph2', text); diff --git a/Control/public/common/userRole.js b/Control/public/common/userRole.js index e4894d803..e31d9f45f 100644 --- a/Control/public/common/userRole.js +++ b/Control/public/common/userRole.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {di} from './../utilities/di.js'; +import { di } from './../utilities/di.js'; /** * @file User role helper functions @@ -22,11 +22,11 @@ import {di} from './../utilities/di.js'; * Check if the user has needed role * @param {Role} role - role to check that user has * @param {boolean} strict - if true, the role must be exactly the same, otherwise it can be lower - * @return {boolean} - true if user has the role + * @returns {boolean} - true if user has the role */ export const isUserAllowedRole = (role, strict = false) => { if (strict) { - return di.session.role === role + return di.session.role === role; } else { return di.session.role <= role; } diff --git a/Control/public/common/utils.js b/Control/public/common/utils.js index 19968883f..a4995ca38 100644 --- a/Control/public/common/utils.js +++ b/Control/public/common/utils.js @@ -10,25 +10,25 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {ODC_STATE_COLOR} from './constants/stateColors.js'; +import { ODC_STATE_COLOR } from './constants/stateColors.js'; /** * Method to display specific JSON fields in a particular way - * @param {Object} item + * @param {object} item * @param {string} key - * @return {string} + * @returns {string} */ const parseObject = (item, key) => { switch (key) { case 'trg_enabled': return item['trg_enabled'] === 'false' ? 'OFF' - : (item['trg_global_run_enabled'] === "true" ? 'CTP' : 'LTU'); + : item['trg_global_run_enabled'] === 'true' ? 'CTP' : 'LTU'; case 'dcs_enabled': case 'ctp_readout_enabled': case 'dd_enabled': - return item[key] && item[key] === 'true' ? 'ON' : 'OFF' + return item[key] && item[key] === 'true' ? 'ON' : 'OFF'; case 'odc_topology': return _parseTopology(item); case 'tasks': @@ -42,83 +42,84 @@ const parseObject = (item, key) => { ? new Date(Number.parseInt(item)).toLocaleString() : '-'; case 'odc_n_epns': - return (item['epn_enabled'] && item['epn_enabled'] == 'true') ? item['odc_n_epns'] : 'OFF'; + return item['epn_enabled'] && item['epn_enabled'] == 'true' ? item['odc_n_epns'] : 'OFF'; default: return JSON.stringify(item); } -} +}; /** - * Create a map of tasks grouped by their FLP name - * @param {object} tasks - raw data - * @return {JSON} {:{list: , stdout: }} - */ + * Create a map of tasks grouped by their FLP name + * @param {object} tasks - raw data + * @returns {JSON} {:{list: , stdout: }} + */ const getTasksByFlp = (tasks) => { - var taskMap = {}; + const taskMap = {}; tasks.forEach((task) => { - const hostname = task.deploymentInfo.hostname; + const { hostname } = task.deploymentInfo; if (!taskMap.hasOwnProperty(hostname)) { - taskMap[hostname] = {list: [], stdout: ''}; + taskMap[hostname] = { list: [], stdout: '' }; } task.name = getTaskShortName(task.name); taskMap[hostname].list.push(task); taskMap[hostname].stdout = task.sandboxStdout; }); return taskMap; -} +}; /** - * Create a map of tasks grouped by their EPN host - * @param {object} tasks - raw data - * @return {JSON} {:{list: , stdout: }} - */ + * Create a map of tasks grouped by their EPN host + * @param {object} tasks - raw data + * @returns {JSON} {:{list: , stdout: }} + */ const getTasksByEpn = (tasks) => { - var taskMap = {}; + const taskMap = {}; tasks.forEach((task) => { const hostname = task.host; if (!taskMap.hasOwnProperty(hostname)) { - taskMap[hostname] = {list: []}; + taskMap[hostname] = { list: [] }; } taskMap[hostname].list.push(task); }); return taskMap; -} +}; /** * Method to check if a task name is the long version. * If yes, return the short version * @param {string} taskName - * @return {string} + * @returns {string} */ const getTaskShortName = (taskName) => { - const regex = new RegExp(`tasks/.*@`); + const regex = new RegExp('tasks/.*@'); const matchedTaskName = taskName.match(regex); if (matchedTaskName) { taskName = matchedTaskName[0].replace('tasks/', '').replace('@', ''); } return taskName; -} +}; /** * Look through the AliECS Integrated services and return the status and style associated to it of ODC for a given environment * ODC status should be displayed as `-` if EPN is set to OFF - * @param {string} envId + * @param {string} envId * @param {Model} model * @param {JSON} userVars - payload from AliECS with variables set by the user + * @param environment * @returns {vnode} */ const parseOdcStatusPerEnv = (environment) => { try { if (environment?.hardware?.epn?.info) { - const {state} = environment.hardware.epn.info; + const { state } = environment.hardware.epn.info; const styleClass = ODC_STATE_COLOR[state] ?? ''; - return {state, styleClass}; + return { state, styleClass }; } } catch (error) { console.error(error); } - return {state: '-', styleClass: ''}; -} + return { state: '-', styleClass: '' }; +}; /** * Helpers @@ -128,7 +129,7 @@ const parseOdcStatusPerEnv = (environment) => { * Given a JSON containing userVars, it will apply the logic described in OCTRL-574 * to display desired value for topology * @param {JSON} item - * @returns {String} + * @returns {string} */ const _parseTopology = (item) => { if (!item['epn_enabled'] || item['epn_enabled'] === 'false') { @@ -151,5 +152,5 @@ const _parseTopology = (item) => { `${item['pdp_topology_description_library_file']}, ${item['pdp_workflow_name']}`; } return '-'; -} -export {getTasksByFlp, getTasksByEpn, parseObject, getTaskShortName, parseOdcStatusPerEnv}; +}; +export { getTasksByFlp, getTasksByEpn, parseObject, getTaskShortName, parseOdcStatusPerEnv }; diff --git a/Control/public/configuration/ConfigByCru.js b/Control/public/configuration/ConfigByCru.js index a59082958..4a25d642f 100644 --- a/Control/public/configuration/ConfigByCru.js +++ b/Control/public/configuration/ConfigByCru.js @@ -10,11 +10,11 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ /* global COG */ -import {Observable, RemoteData} from '/js/src/index.js'; +import { Observable, RemoteData } from '/js/src/index.js'; /** * Model representing Configuration CRUD @@ -52,13 +52,13 @@ export default class Config extends Observable { this.failedTasks = []; if (this.model.detectors.listRemote.isSuccess()) { const isOpen = this.model.detectors.selected !== 'GLOBAL'; - this.model.detectors.listRemote.payload.forEach((detector) => this.detectorPanel[detector] = {isOpen}); + this.model.detectors.listRemote.payload.forEach((detector) => this.detectorPanel[detector] = { isOpen }); } } /** * Select/Deselect passed host - * @param {String} host + * @param {string} host */ toggleHostSelection(host) { const index = this.selectedHosts.findIndex((element) => host === element); @@ -72,7 +72,8 @@ export default class Config extends Observable { /** * Given a detector, toggle the selection of all of its hosts - * @param {String} + * @param {string} + * @param detector */ toggleHostsByDetectorSelection(detector) { const hostsWithCru = this._getHostsWithCRUForDetector(detector); @@ -86,7 +87,7 @@ export default class Config extends Observable { /** * Give a detector name, use the hosts of the detector and check if all of them are present in selected hosts - * @param {String} detector + * @param {string} detector * @returns {boolean} */ areAllHostsForDetectorSelected(detector) { @@ -106,7 +107,7 @@ export default class Config extends Observable { this.cruMapByHost = RemoteData.loading(); this.notify(); - const {result, ok} = await this.model.loader.get(`/api/consul/crus/config`); + const { result, ok } = await this.model.loader.get('/api/consul/crus/config'); if (!ok) { this.cruMapByHost = RemoteData.failure(result.message); this.notify(); @@ -118,12 +119,12 @@ export default class Config extends Observable { } /** - * Retrieve a JSON object of aliases for FLPs, card:endpoint and links which + * Retrieve a JSON object of aliases for FLPs, card:endpoint and links which * are to be used for labeling * @example * { * "flp": { - * "alias": "mini-flp", + * "alias": "mini-flp", * }, * "cards:" { * "1106:0": { @@ -141,7 +142,7 @@ export default class Config extends Observable { this.crusAliases = RemoteData.loading(); this.notify(); - const {result, ok} = await this.model.loader.get(`/api/consul/crus/aliases`); + const { result, ok } = await this.model.loader.get('/api/consul/crus/aliases'); if (!ok) { this.crusAliases = RemoteData.failure(result.message); this.notify(); @@ -164,7 +165,7 @@ export default class Config extends Observable { } /** - * Method to send the new configuration to + * Method to send the new configuration to * the server to save it in consul */ async saveConfiguration() { @@ -176,7 +177,7 @@ export default class Config extends Observable { this.notify(); const copy = {}; this.selectedHosts.forEach((host) => copy[host] = this._getMinifiedHostInfo(host)); - const {result, ok} = await this.model.loader.post(`/api/consul/crus/config/save`, copy); + const { result, ok } = await this.model.loader.post('/api/consul/crus/config/save', copy); if (!ok) { result.ended = true; result.success = false; @@ -203,13 +204,16 @@ export default class Config extends Observable { this.notify(); const hosts = this.selectedHosts; - this.channelId = (Math.floor(Math.random() * (999999 - 100000) + 100000)).toString(); - const {result, ok} = await this.model.loader.post(`/api/execute/o2-roc-config`, + this.channelId = Math.floor(Math.random() * (999999 - 100000) + 100000).toString(); + const { result, ok } = await this.model.loader.post( + '/api/execute/o2-roc-config', { - channelId: this.channelId, vars: { - hosts, rocConfigForceConfig: this.isForceEnabled ? 'true' : 'false' - }, operation: 'o2-roc-config' - } + channelId: this.channelId, + vars: { + hosts, rocConfigForceConfig: this.isForceEnabled ? 'true' : 'false', + }, + operation: 'o2-roc-config', + }, ); this.configurationRequest = ok ? RemoteData.success(result) : RemoteData.failure(result); } @@ -219,7 +223,7 @@ export default class Config extends Observable { /** * Method to update the message with regards to the `o2-roc-config` command * If message id will match the client's it will be displayed - * @param {WebSocketMessagePayload} message + * @param {WebSocketMessagePayload} message */ setConfigurationRequest(message) { const messageId = message.id || ''; @@ -230,7 +234,7 @@ export default class Config extends Observable { if (message.success) { this.configurationRequest = RemoteData.success(message); } else { - this.failedTasks.push(message.info) + this.failedTasks.push(message.info); this.configurationRequest = RemoteData.success(message); } } @@ -270,14 +274,14 @@ export default class Config extends Observable { * Given a host, take it by cru by endpoint and build a json containing only * data that can be modified via the GUI * Currently we only set links0-12 and user logic - * @param {String} host + * @param {string} host * @returns {JSON} */ _getMinifiedHostInfo(host) { const hostCopy = {}; Object.keys(this.cruMapByHost.payload[host]).forEach((cruEndpointKey) => { const cruEndpointCopy = { - cru: {userLogicEnabled: this.cruMapByHost.payload[host][cruEndpointKey].config.cru.userLogicEnabled}, + cru: { userLogicEnabled: this.cruMapByHost.payload[host][cruEndpointKey].config.cru.userLogicEnabled }, }; Object.keys(this.cruMapByHost.payload[host][cruEndpointKey].config) .filter((key) => key.match('link[0-9]{1,2}')) // select only fields from links0 to links11 @@ -285,19 +289,19 @@ export default class Config extends Observable { const cruConfig = this.cruMapByHost.payload[host][cruEndpointKey].config; cruEndpointCopy[key] = {}; if (cruConfig[key] && cruConfig[key].enabled) { - cruEndpointCopy[key].enabled = cruConfig[key].enabled + cruEndpointCopy[key].enabled = cruConfig[key].enabled; } }); - hostCopy[cruEndpointKey] = {config: cruEndpointCopy}; - }) + hostCopy[cruEndpointKey] = { config: cruEndpointCopy }; + }); return JSON.parse(JSON.stringify(hostCopy)); } /** * Given a detector name, use the hosts per detector and the cry map by host to build a list of hosts * that belong to a detector and contain a CRU - * @param {String} detector - * @returns {Array} + * @param {string} detector + * @returns {Array} */ _getHostsWithCRUForDetector(detector) { const hostsForDetector = this.model.detectors.hostsByDetectorRemote.payload[detector]; diff --git a/Control/public/configuration/Configuration.js b/Control/public/configuration/Configuration.js index 0539a71a2..a4a65501c 100644 --- a/Control/public/configuration/Configuration.js +++ b/Control/public/configuration/Configuration.js @@ -10,9 +10,9 @@ * In applying this license CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization * or submit itself to any jurisdiction. -*/ + */ -import {Observable, RemoteData} from '/js/src/index.js'; +import { Observable, RemoteData } from '/js/src/index.js'; /** * Model representing Configuration CRUD @@ -31,7 +31,7 @@ export default class Configuration extends Observable { command: 'CONFIG', runButtonDisabled: false, expertMode: false, - expertOptions: this.getDefaultExpertOptions() + expertOptions: this.getDefaultExpertOptions(), }; this.rocStatus = RemoteData.notAsked(); this.readoutCardList = RemoteData.notAsked(); @@ -79,7 +79,7 @@ export default class Configuration extends Observable { /** * Check if all ReadoutCards under a host are selected * @param {string} hostName - * @return {boolean} + * @returns {boolean} */ areAllReadoutCardsForHostSelected(hostName) { const hosts = this.readoutCardList.payload[hostName].objects; @@ -107,7 +107,7 @@ export default class Configuration extends Observable { /** * Method to check if all host rows are opened - * @return {param} + * @returns {param} */ areAllHostRowsOpened() { return Object.keys(this.readoutCardList.payload).every((hostName) => this.readoutCardList.payload[hostName].open); @@ -115,7 +115,7 @@ export default class Configuration extends Observable { /** * Method to check if all readout cards are selected - * @return {boolean} + * @returns {boolean} */ areAllReadoutCardsSelected() { return Object.keys(this.readoutCardList.payload) @@ -138,7 +138,7 @@ export default class Configuration extends Observable { /** * Method to reset all CRUs to an unselected state and their hosts to an opened state * @param {Map>} readoutCardsByHost - * @return {Map>} + * @returns {Map>} */ deselectAllReadoutCards(readoutCardsByHost) { Object.keys(readoutCardsByHost) @@ -159,17 +159,17 @@ export default class Configuration extends Observable { /** * Method to set the value of a field within the expert panel - * @param {String} field - * @param {String} value + * @param {string} field + * @param {string} value */ setExpertOptionByField(field, value) { if (this.isFieldOfTypeBoolean(field)) { - this.actionPanel.expertOptions[field] = (value === '-') ? null : (value === 'TRUE' ? true : false); + this.actionPanel.expertOptions[field] = value === '-' ? null : value === 'TRUE' ? true : false; } else if (['onu-address', 'trigger-window-size', 'cru-id'].includes(field)) { // type number const valueNumber = parseInt(value); if (!isNaN(valueNumber)) { - if (valueNumber >= 0 && valueNumber <= (Math.pow(2, 31) - 1)) { + if (valueNumber >= 0 && valueNumber <= Math.pow(2, 31) - 1) { this.actionPanel.expertOptions[field] = valueNumber; } else { this.actionPanel.expertOptions[field] = null; @@ -194,7 +194,7 @@ export default class Configuration extends Observable { /** * Method to check if all links are selected - * @return {boolean} + * @returns {boolean} */ areAllLinksSelected() { return this.actionPanel.expertOptions.links.every((linkEnabled) => linkEnabled); @@ -207,6 +207,7 @@ export default class Configuration extends Observable { this.actionPanel.expertOptions.links.fill(!this.areAllLinksSelected()); this.notify(); } + /** * Method to build the request for AliECS - core and send it * * Build ROC Options @@ -223,13 +224,14 @@ export default class Configuration extends Observable { this.model.notification.show('Please select at least one `Readout Card` from the table below', 'danger', 3000); } } + /* * Helpers */ /** * Method to retrieve only selected links - * @return {Array} + * @returns {Array} */ getSelectedLinks() { return Object.keys(this.actionPanel.expertOptions.links) @@ -239,7 +241,7 @@ export default class Configuration extends Observable { /** * Method to return a string containing the selected options and their values * Format: --