Skip to content

Commit 20d043a

Browse files
authored
[O2B-1078] runs overview extraction (#1285)
* refactor init * refactor home page * aadjustment * general refactor, remove dependencie on global model * refactor * amend export button disablement * rename * cleanup * rename * cleanup * refactor * rename * rename * amend test * cleanup * amend test * cleanup * docs * remove unnecessary fetch * remove outdated stuff * refactor
1 parent 3f05d2a commit 20d043a

9 files changed

Lines changed: 171 additions & 173 deletions

File tree

lib/public/Model.js

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { Loader, Observable, QueryRouter, sessionService } from '/js/src/index.j
1515

1616
import Logs from './views/Logs/Logs.js';
1717
import Tags from './views/Tags/Tags.js';
18-
import Runs from './views/Runs/Runs.js';
18+
import { RunsModel } from './views/Runs/RunsModel.js';
1919
import Subsystems from './views/Subsystems/Subsystems.js';
2020
import Flps from './views/Flps/Flps.js';
2121
import { EnvironmentModel } from './views/Environments/EnvironmentModel.js';
@@ -90,10 +90,7 @@ export default class Model extends Observable {
9090
this.lhcFills = new LhcFills(this);
9191
this.lhcFills.bubbleTo(this);
9292

93-
/**
94-
* @type {RunModel}
95-
*/
96-
this.runs = new Runs(this);
93+
this.runs = new RunsModel(this);
9794
this.runs.bubbleTo(this);
9895

9996
this.subsystems = new Subsystems(this);
@@ -158,7 +155,7 @@ export default class Model extends Observable {
158155
case 'home':
159156
// Setting the rows per page also collects all the runs and logs
160157
this.logs.fetchAllLogs();
161-
this.runs.fetchAllRuns();
158+
this.runs.loadOverview();
162159
break;
163160
case 'lhc-period-overview':
164161
this.lhcPeriods.loadOverview();
@@ -179,7 +176,6 @@ export default class Model extends Observable {
179176
// Prevent loading extra rows when it's not necessary
180177
if (!this.logs.pagination.isInfiniteScrollEnabled) {
181178
this.logs.fetchAllLogs();
182-
this.runs.fetchAllRuns();
183179
}
184180
break;
185181
case 'log-detail':
@@ -189,10 +185,7 @@ export default class Model extends Observable {
189185
this.logs.loadCreation(this.router.params);
190186
break;
191187
case 'run-overview':
192-
// Prevent loading extra rows when it's not necessary
193-
if (!this.runs.pagination.isInfiniteScrollEnabled) {
194-
this.runs.fetchAllRuns();
195-
}
188+
this.runs.loadOverview();
196189
break;
197190
case 'run-detail':
198191
this.runs.loadDetails(this.router.params);
@@ -283,18 +276,6 @@ export default class Model extends Observable {
283276
return this.session.access.includes('admin');
284277
}
285278

286-
/**
287-
* Display a modal on the screen
288-
* @see ModalModel
289-
*
290-
* @param {Modal} modal the modal to display
291-
*
292-
* @returns {void}
293-
*/
294-
modal(modal) {
295-
this.modalModel.display(modal);
296-
}
297-
298279
/**
299280
* Returns an observable notified once the app's configuration is modified
300281
*/

lib/public/components/Filters/RunsFilter/o2stop.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ today.setMinutes(today.getMinutes() - today.getTimezoneOffset());
2121

2222
/**
2323
* Returns the creation date filter components
24-
* @param {RunModel} runModel the run model object
24+
* @param {RunsOverviewModel} runsOverviewModel the run model object
2525
* @return {vnode} Two date selection boxes to control the minimum and maximum creation dates for the log filters
2626
*/
27-
const o2endFilter = (runModel) => {
27+
const o2endFilter = (runsOverviewModel) => {
2828
const date = new Date();
29-
const o2from = runModel.getO2endFilterFrom();
30-
const o2to = runModel.getO2endFilterTo();
31-
const o2fromTime = runModel.getO2endFilterFromTime();
32-
const o2toTime = runModel.getO2endFilterToTime();
29+
const o2from = runsOverviewModel.getO2endFilterFrom();
30+
const o2to = runsOverviewModel.getO2endFilterTo();
31+
const o2fromTime = runsOverviewModel.getO2endFilterFromTime();
32+
const o2toTime = runsOverviewModel.getO2endFilterToTime();
3333
const now = `${date.getHours()}:${(date.getMinutes() < 10 ? '0' : '') + date.getMinutes()}`;
3434
return h('', [
3535
h('.f6', 'Ended from:'),
@@ -39,7 +39,7 @@ const o2endFilter = (runModel) => {
3939
placeholder: DATE_FORMAT,
4040
max: o2to || today,
4141
value: o2from,
42-
oninput: (e) => runModel.setO2endFilter('From', e.target.value, e.target.validity.valid),
42+
oninput: (e) => runsOverviewModel.setO2endFilter('From', e.target.value, e.target.validity.valid),
4343
}, ''),
4444
h('input.w-50.mv1', {
4545
type: 'time',
@@ -51,10 +51,10 @@ const o2endFilter = (runModel) => {
5151
oninput: (e) => {
5252
const time = e.target.value ? e.target.value : '00:00';
5353
if (!o2from) {
54-
runModel.setO2endFilter('From', today, true);
55-
runModel.setO2endFilter('FromTime', time, e.target.value <= now);
54+
runsOverviewModel.setO2endFilter('From', today, true);
55+
runsOverviewModel.setO2endFilter('FromTime', time, e.target.value <= now);
5656
} else {
57-
runModel.setO2endFilter('FromTime', time, e.target.validity.valid);
57+
runsOverviewModel.setO2endFilter('FromTime', time, e.target.validity.valid);
5858
}
5959
},
6060
}, ''),
@@ -65,7 +65,7 @@ const o2endFilter = (runModel) => {
6565
min: o2from,
6666
max: today,
6767
value: o2to,
68-
oninput: (e) => runModel.setO2endFilter('To', e.target.value, e.target.validity.valid),
68+
oninput: (e) => runsOverviewModel.setO2endFilter('To', e.target.value, e.target.validity.valid),
6969
}, ''),
7070

7171
h('input.w-50.mv1', {
@@ -78,9 +78,9 @@ const o2endFilter = (runModel) => {
7878
const time = e.target.value ? e.target.value :
7979
today == o2from ? now : '23:59';
8080
if (!o2to) {
81-
runModel.setO2endFilter('To', today, true);
81+
runsOverviewModel.setO2endFilter('To', today, true);
8282
}
83-
runModel.setO2endFilter('ToTime', time, e.target.validity.valid);
83+
runsOverviewModel.setO2endFilter('ToTime', time, e.target.validity.valid);
8484
},
8585
}, ''),
8686
]);

lib/public/view.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { h, switchCase } from '/js/src/index.js';
1515
import NavBar from './components/NavBar/index.js';
1616
import LogsOverview from './views/Logs/Overview/index.js';
1717
import { LogCreationPage } from './views/Logs/Create/LogCreationPage.js';
18-
import RunsOverview from './views/Runs/Overview/index.js';
18+
import { RunsOverviewPage } from './views/Runs/Overview/RunsOverviewPage.js';
1919
import { RunDetailsPage } from './views/Runs/Details/RunDetailsPage.js';
2020
import SubsystemOverview from './views/Subsystems/Overview/index.js';
2121
import SubsystemDetail from './views/Subsystems/Details/index.js';
@@ -57,7 +57,7 @@ export default (model) => {
5757
'lhc-fill-overview': Index,
5858
'lhc-fill-details': LhcFillDetailsPage,
5959

60-
'run-overview': RunsOverview,
60+
'run-overview': RunsOverviewPage,
6161
'run-detail': RunDetailsPage,
6262

6363
statistics: StatisticsPage,

lib/public/views/Home/Overview/index.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,21 @@ const PAGE_USED_HEIGHT = 155;
2626
* @param {Object} model Pass the model to access the defined functions
2727
* @return {vnode} Return the view of the page with the filtering options
2828
*/
29-
const HomeOverviewScreen = (model) => {
29+
const HomeOverviewScreen = ({ logs: logsModel, runs: { overviewModel: runsOverviewModel } }) => {
3030
const rowCount = estimateDisplayableRowsCount(TABLEROW_HEIGHT, PAGE_USED_HEIGHT);
31-
model.logs.pagination.provideDefaultItemsPerPage(rowCount);
32-
model.runs.pagination.provideDefaultItemsPerPage(rowCount);
33-
34-
const logs = model.logs.getLogs();
35-
const runs = model.runs.getRuns();
31+
logsModel.pagination.provideDefaultItemsPerPage(rowCount);
32+
runsOverviewModel.pagination.provideDefaultItemsPerPage(rowCount);
3633

3734
return h('.flex-row.w-100', [
3835
h('.flex-column.w-50', {
3936
style: 'padding-right: 1rem;',
4037
}, [
4138
h('h2', 'Log Entries'),
42-
table(logs, logsActiveColumns, null, { profile: 'home' }),
39+
table(logsModel.getLogs(), logsActiveColumns, null, { profile: 'home' }),
4340
]),
4441
h('.flex-column.w-50', [
4542
h('h2', 'Runs'),
46-
table(runs, runsActiveColumns, null, { profile: 'home' }),
43+
table(runsOverviewModel.runs, runsActiveColumns, null, { profile: 'home' }),
4744
]),
4845
]);
4946
};

lib/public/views/Runs/Runs.js renamed to lib/public/views/Runs/Overview/RunsOverviewModel.js

Lines changed: 33 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,29 @@
1212
*/
1313

1414
import { Observable, RemoteData } from '/js/src/index.js';
15-
import { createCSVExport, createJSONExport } from '../../utilities/export.js';
16-
import { TagFilterModel } from '../../components/Filters/common/TagFilterModel.js';
17-
import { debounce } from '../../utilities/debounce.js';
18-
import { PaginationModel } from '../../components/Pagination/PaginationModel.js';
19-
import { getRemoteDataSlice } from '../../utilities/fetch/getRemoteDataSlice.js';
20-
import { DetectorsFilterModel } from '../../components/Filters/RunsFilter/DetectorsFilterModel.js';
21-
import { RunDetailsModel } from './Details/RunDetailsModel.js';
22-
import { RunTypesSelectionDropdownModel } from '../../components/runTypes/RunTypesSelectionDropdownModel.js';
23-
import { EorReasonFilterModel } from '../../components/Filters/RunsFilter/EorReasonsFilterModel.js';
15+
import { createCSVExport, createJSONExport } from '../../../utilities/export.js';
16+
import { TagFilterModel } from '../../../components/Filters/common/TagFilterModel.js';
17+
import { debounce } from '../../../utilities/debounce.js';
18+
import { PaginationModel } from '../../../components/Pagination/PaginationModel.js';
19+
import { getRemoteDataSlice } from '../../../utilities/fetch/getRemoteDataSlice.js';
20+
import { DetectorsFilterModel } from '../../../components/Filters/RunsFilter/DetectorsFilterModel.js';
21+
import { RunTypesSelectionDropdownModel } from '../../../components/runTypes/RunTypesSelectionDropdownModel.js';
22+
import { EorReasonFilterModel } from '../../../components/Filters/RunsFilter/EorReasonsFilterModel.js';
23+
import pick from '../../../utilities/pick.js';
2424

2525
/**
2626
* Model representing handlers for runs page
2727
*
2828
* @implements {OverviewModel}
2929
*/
30-
export default class RunModel extends Observable {
30+
export class RunsOverviewModel extends Observable {
3131
/**
3232
* The constructor of the Overview model object
3333
* @param {Model} model Pass the model to access the defined functions
3434
* @return {Object} Constructs the Overview model
3535
*/
3636
constructor(model) {
3737
super();
38-
this.model = model;
39-
40-
/**
41-
* @type {RunDetailsModel}
42-
* @private
43-
*/
44-
this._detailsModel = null;
4538

4639
this._listingTagsFilterModel = new TagFilterModel();
4740
this._listingTagsFilterModel.observe(() => this._applyFilters(true));
@@ -59,7 +52,7 @@ export default class RunModel extends Observable {
5952
this._eorReasonsFilterModel.observe(() => this._applyFilters());
6053

6154
this._pagination = new PaginationModel();
62-
this._pagination.observe(() => this.fetchAllRuns());
55+
this._pagination.observe(() => this.fetchRuns());
6356
this._pagination.itemsPerPageSelector$.observe(() => this.notify());
6457

6558
// Content
@@ -69,41 +62,17 @@ export default class RunModel extends Observable {
6962
this.reset(false);
7063

7164
// eslint-disable-next-line no-return-assign,require-jsdoc
72-
const updateDebounceTime = () => this._debouncedFetchAllRuns = debounce(this.fetchAllRuns.bind(this), model.inputDebounceTime);
65+
const updateDebounceTime = () => this._debouncedFetchAllRuns = debounce(this.fetchRuns.bind(this), model.inputDebounceTime);
7366
model.appConfiguration$.observe(() => updateDebounceTime());
7467
updateDebounceTime();
7568
}
7669

77-
/**
78-
* Load the details page for the given run
79-
* @param {string} [params.runNumber = null] the runNumber of the run to display
80-
* @param {string} [params.id = null] Usage of this paramter is deprecated, use runNumber if feasible,
81-
* @param {string} [params.panel = null] the key of the panel to display
82-
* @return {void}
83-
*/
84-
loadDetails({ runNumber = null, id: runId = null, panel: panelKey = null }) {
85-
runId = runId ? Number(runId) : runId;
86-
runNumber = runNumber ? Number(runNumber) : runNumber;
87-
88-
if (!this._detailsModel) {
89-
this._detailsModel = new RunDetailsModel();
90-
this._detailsModel.bubbleTo(this);
91-
}
92-
this._detailsModel.clearAndLoad({ runId, runNumber, panelKey });
93-
}
94-
9570
/**
9671
* Retrieve every relevant run from the API
97-
*
98-
* @param {boolean} clear if true, any previous data will be discarded, even in infinite mode
99-
*
100-
* @return {undefined} Injects the data object with the response data
72+
* @return {void} Injects the data object with the response data
10173
*/
102-
async fetchAllRuns(clear = false) {
103-
/**
104-
* @type {Run[]}
105-
*/
106-
const concatenateWith = !clear && this._pagination.currentPage !== 1 && this._pagination.isInfiniteScrollEnabled
74+
async fetchRuns() {
75+
const concatenateWith = this._pagination.currentPage !== 1 && this._pagination.isInfiniteScrollEnabled
10776
? this._currentPageRuns.payload || []
10877
: [];
10978

@@ -112,8 +81,6 @@ export default class RunModel extends Observable {
11281
this.notify();
11382
}
11483

115-
this._allRuns = RemoteData.notAsked();
116-
11784
const params = {
11885
...this._getFilterQueryParams(),
11986
'page[offset]': this._pagination.firstItemOffset,
@@ -134,15 +101,25 @@ export default class RunModel extends Observable {
134101

135102
/**
136103
* Create the export with the variables set in the model, handling errors appropriately
137-
* @param {Object} content The source content.
104+
* @param {object[]} runs The source content.
138105
* @param {string} fileName The name of the file including the output format.
106+
* @param {Object<string, Function<*, string>>} exportFormats defines how particual fields of data units will be formated
139107
* @return {void}
140108
*/
141-
async createRunsExport(content, fileName) {
142-
if (content.length > 0) {
109+
async createRunsExport(runs, fileName, exportFormats) {
110+
if (runs.length > 0) {
111+
const selectedRunsFields = this.getSelectedRunsFields() || [];
112+
runs = runs.map((selectedRun) => {
113+
const entries = Object.entries(pick(selectedRun, selectedRunsFields));
114+
const formattedEntries = entries.map(([key, value]) => {
115+
const formatExport = exportFormats[key].exportFormat || ((identity) => identity);
116+
return [key, formatExport(value, selectedRun)];
117+
});
118+
return Object.fromEntries(formattedEntries);
119+
}),
143120
this.getSelectedExportType() === 'CSV'
144-
? createCSVExport(content, `${fileName}.csv`, 'text/csv;charset=utf-8;')
145-
: createJSONExport(content, `${fileName}.json`, 'application/json');
121+
? createCSVExport(runs, `${fileName}.csv`, 'text/csv;charset=utf-8;')
122+
: createJSONExport(runs, `${fileName}.json`, 'application/json');
146123
} else {
147124
this._currentPageRuns = RemoteData.failure([
148125
{
@@ -154,14 +131,6 @@ export default class RunModel extends Observable {
154131
}
155132
}
156133

157-
/**
158-
* Getter for all the run data
159-
* @return {RemoteData} Returns all of the filtered runs
160-
*/
161-
getRuns() {
162-
return this.runs;
163-
}
164-
165134
/**
166135
* Get the field values that will be exported
167136
* @return {Array} the field objects of the current export being created
@@ -845,7 +814,7 @@ export default class RunModel extends Observable {
845814
*/
846815
get allRuns() {
847816
if (this._allRuns.isNotAsked()) {
848-
this._fetchAllRunsWithoutPaging();
817+
this._fetchAllRunsWithoutPagination();
849818
}
850819

851820
return this._allRuns;
@@ -900,15 +869,6 @@ export default class RunModel extends Observable {
900869
return this._pagination;
901870
}
902871

903-
/**
904-
* Returns the run details sub models
905-
*
906-
* @return {RunDetailsModel|null} the sub-model
907-
*/
908-
get detailsModel() {
909-
return this._detailsModel;
910-
}
911-
912872
/**
913873
* Returns the list of URL params corresponding to the currently applied filter
914874
*
@@ -1005,7 +965,7 @@ export default class RunModel extends Observable {
1005965
* @return {Promise<void>} void
1006966
* @private
1007967
*/
1008-
async _fetchAllRunsWithoutPaging() {
968+
async _fetchAllRunsWithoutPagination() {
1009969
if (this.runs.isSuccess() && this.runs.payload.length === this._pagination.itemsCount) {
1010970
this._allRuns = RemoteData.success([...this.runs.payload]);
1011971
this.notify();
@@ -1037,6 +997,6 @@ export default class RunModel extends Observable {
1037997
*/
1038998
_applyFilters(now = false) {
1039999
this._pagination.currentPage = 1;
1040-
now ? this.fetchAllRuns() : this._debouncedFetchAllRuns(true);
1000+
now ? this.fetchRuns() : this._debouncedFetchAllRuns(true);
10411001
}
10421002
}

0 commit comments

Comments
 (0)