From c283f2ef1769cdceff80fe17adf9431b295c26e5 Mon Sep 17 00:00:00 2001 From: moellep Date: Wed, 28 Feb 2024 00:50:02 +0000 Subject: [PATCH] fix #6588 Allow analysis queue to be reordered also fix #6587 show queue order on pending list and allow sorting on queue order Scan items may be moved to the front or back of the list --- sirepo/package_data/static/js/raydata.js | 82 +++++++++++++++++++++--- sirepo/raydata/scan_monitor.py | 26 ++++++++ sirepo/template/raydata.py | 4 ++ 3 files changed, 103 insertions(+), 9 deletions(-) diff --git a/sirepo/package_data/static/js/raydata.js b/sirepo/package_data/static/js/raydata.js index 630bd0ca95..273fdb5b6b 100644 --- a/sirepo/package_data/static/js/raydata.js +++ b/sirepo/package_data/static/js/raydata.js @@ -80,9 +80,6 @@ SIREPO.app.factory('columnsService', function(appState, requestSender, $rootScop self.allColumnsWithHeading = null; self.selectSearchFieldText = 'Select Search Field'; - // POSIT: status + sirepo.template.raydata._DEFAULT_COLUMNS - self.DEFAULT_COLUMNS = ['status', 'start', 'stop', 'suid']; - function loadColumns() { requestSender.sendStatelessCompute( appState, @@ -100,6 +97,14 @@ SIREPO.app.factory('columnsService', function(appState, requestSender, $rootScop ); } + self.defaultColumns = (analysisStatus) => { + const res = ['status', 'start', 'stop', 'suid']; + if (analysisStatus == 'queued') { + res.splice(1, 0, 'queue order'); + } + return res; + }; + self.updateColumns = columns => { if (! columns || ! columns.length) { return; @@ -461,7 +466,6 @@ SIREPO.app.directive('replayPanel', function() { panelState: panelState, } ); - }; }, }; @@ -500,7 +504,10 @@ SIREPO.app.directive('scansTable', function() { -
+ +
+ +
@@ -542,8 +549,8 @@ SIREPO.app.directive('scansTable', function() { let scanArgs = { pageCount: 0, pageNumber: 0, - sortColumn: 'start', - sortOrder: false, + sortColumn: $scope.analysisStatus == 'queued' ? 'queue order' : 'start', + sortOrder: $scope.analysisStatus == 'queued', }; const errorOptions = { @@ -674,7 +681,7 @@ SIREPO.app.directive('scansTable', function() { function setColumnHeaders() { $scope.columnHeaders = [ - ...columnsService.DEFAULT_COLUMNS, + ...columnsService.defaultColumns($scope.analysisStatus), ...appState.models.metadataColumns.selected ]; } @@ -774,6 +781,10 @@ SIREPO.app.directive('scansTable', function() { } }; + $scope.refreshScans = () => { + sendScanRequest(true, true); + }; + $scope.runAnalysis = (scanId, forceRun) => { if (! forceRun) { const scan = findScan(scanId); @@ -824,7 +835,7 @@ SIREPO.app.directive('scansTable', function() { }; $scope.showDeleteButton = index => { - return index > columnsService.DEFAULT_COLUMNS.length - 1; + return index > columnsService.defaultColumns($scope.analysisStatus).length - 1; }; $scope.showPdfButton = () => { @@ -1230,3 +1241,56 @@ SIREPO.app.directive('searchTermText', function() { }, }; }); + + +SIREPO.app.directive('queueOrder', function() { + return { + restrict: 'A', + scope: { + scan: '=', + numberOfScans: '@', + refreshScans: '&', + }, + template: ` + {{ scan['queue order'] }}   + + + + `, + controller: function(appState, requestSender, $scope) { + $scope.buttons = [ + { + title: 'Move to end of queue', + rotate: 'rotate(90deg)', + visible: () => $scope.scan['queue order'] < $scope.numberOfScans - 1, + click: () => reorderScan('last'), + }, + { + title: 'Move to beginning of queue', + rotate: 'rotate(270deg)', + visible: () => $scope.scan['queue order'] > 1, + click: () => reorderScan('first'), + }, + ]; + + function reorderScan(action) { + requestSender.sendStatelessCompute( + appState, + () => $scope.refreshScans(), + { + method: 'reorder_scan', + args: { + catalogName: appState.models.catalog.catalogName, + rduid: $scope.scan.rduid, + action: action, + } + }, + ); + } + }, + }; +}); diff --git a/sirepo/raydata/scan_monitor.py b/sirepo/raydata/scan_monitor.py index b639b885f6..89ddb6e1c4 100644 --- a/sirepo/raydata/scan_monitor.py +++ b/sirepo/raydata/scan_monitor.py @@ -427,6 +427,22 @@ def _request_get_scans(self, req_data): ) return _scan_info_result(l, s, req_data) + def _request_reorder_scan(self, req_data): + i = _scan_index(req_data.rduid, req_data) + if i >= 0: + s = _SCANS_AWAITING_ANALYSIS.pop(i) + if s.rduid != req_data.rduid: + raise AssertionError( + f"Failed to pop() correct scan: {req_data.rduid} != {s.rduid}" + ) + if req_data.action == "first": + _SCANS_AWAITING_ANALYSIS.insert(0, s) + elif req_data.action == "last": + _SCANS_AWAITING_ANALYSIS.append(s) + else: + raise AssertionError(f"Unknown reorder action {req_data.action}") + return PKDict(data="ok") + def _request_run_analysis(self, req_data): _queue_for_analysis( sirepo.raydata.databroker.get_metadata(req_data.rduid, req_data.catalogName) @@ -567,6 +583,14 @@ def _queue_for_analysis(scan_metadata): _Analysis.set_scan_status(s, _AnalysisStatus.PENDING) +def _scan_index(rduid, req_data): + s = PKDict( + rduid=rduid, + catalog_name=req_data.catalogName, + ) + return _SCANS_AWAITING_ANALYSIS.index(s) if s in _SCANS_AWAITING_ANALYSIS else -1 + + def _scan_info(rduid, status, req_data, all_columns): m = sirepo.raydata.databroker.get_metadata(rduid, req_data.catalogName) d = PKDict( @@ -584,6 +608,8 @@ def _scan_info(rduid, status, req_data, all_columns): for c in m.get_start_fields(): all_columns.add(c) + + d["queue order"] = _scan_index(rduid, req_data) + 1 return d diff --git a/sirepo/template/raydata.py b/sirepo/template/raydata.py index ad4bff674c..f006d6bd98 100644 --- a/sirepo/template/raydata.py +++ b/sirepo/template/raydata.py @@ -65,6 +65,10 @@ def stateless_compute_download_analysis_pdfs(data, data_file_uri=None, **kwargs) return _request_scan_monitor(PKDict(method="download_analysis_pdfs", data=data)) +def stateless_compute_reorder_scan(data, **kwargs): + return _request_scan_monitor(PKDict(method="reorder_scan", data=data)) + + def stateless_compute_run_analysis(data, **kwargs): return _request_scan_monitor(PKDict(method="run_analysis", data=data))