diff --git a/lib/public/components/detector/PhysicalDetectorSelectionDropdownModel.js b/lib/public/components/detector/PhysicalDetectorPickerModel.js similarity index 86% rename from lib/public/components/detector/PhysicalDetectorSelectionDropdownModel.js rename to lib/public/components/detector/PhysicalDetectorPickerModel.js index ec861cdd89..6aed1a2963 100644 --- a/lib/public/components/detector/PhysicalDetectorSelectionDropdownModel.js +++ b/lib/public/components/detector/PhysicalDetectorPickerModel.js @@ -11,14 +11,14 @@ * or submit itself to any jurisdiction. */ -import { SelectionDropdownModel } from '../common/selection/dropdown/SelectionDropdownModel.js'; import { RemoteData } from '/js/src/index.js'; import { detectorsProvider } from '../../services/detectors/detectorsProvider.js'; +import { PickerModel } from '../common/selection/picker/PickerModel.js'; /** * Model storing state of a selection of detectors picked from the list of all physical detectors */ -export class PhysicalDetectorSelectionDropdownModel extends SelectionDropdownModel { +export class PhysicalDetectorPickerModel extends PickerModel { /** * Constructor */ diff --git a/lib/public/views/QcFlags/GaqFlags/GaqFlagsOverviewModel.js b/lib/public/views/QcFlags/GaqFlags/GaqFlagsOverviewModel.js index 0acaae3030..15ce95abfb 100644 --- a/lib/public/views/QcFlags/GaqFlags/GaqFlagsOverviewModel.js +++ b/lib/public/views/QcFlags/GaqFlags/GaqFlagsOverviewModel.js @@ -17,7 +17,7 @@ import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js'; import { buildUrl } from '../../../utilities/fetch/buildUrl.js'; import { OverviewPageModel } from '../../../models/OverviewModel.js'; import { jsonPost } from '../../../utilities/fetch/jsonPost.js'; -import { PhysicalDetectorSelectionDropdownModel } from '../../../components/detector/PhysicalDetectorSelectionDropdownModel.js'; +import { PhysicalDetectorPickerModel } from '../../../components/detector/PhysicalDetectorPickerModel.js'; /** * GAQ Flags overview model @@ -35,8 +35,8 @@ export class GaqFlagsOverviewModel extends OverviewPageModel { this._dataPass$.bubbleTo(this); this._gaqDetectors$ = new ObservableData(RemoteData.notAsked()); this._gaqDetectors$.bubbleTo(this); - this._detectorSelectionModel = new PhysicalDetectorSelectionDropdownModel(); - this._detectorSelectionModel.bubbleTo(this); + this._gaqDetectorPickerModel = new PhysicalDetectorPickerModel(); + this._gaqDetectorPickerModel.bubbleTo(this); } /** @@ -91,8 +91,8 @@ export class GaqFlagsOverviewModel extends OverviewPageModel { */ updateDetectorSelectionModel() { this._gaqDetectors$.getCurrent().match({ - Success: (gaqDetectors) => this._detectorSelectionModel.options.match({ - Success: () => gaqDetectors.forEach(({ dplDetectorId }) => this._detectorSelectionModel.select(dplDetectorId)), + Success: (gaqDetectors) => this._gaqDetectorPickerModel.options.match({ + Success: () => gaqDetectors.forEach(({ dplDetectorId }) => this._gaqDetectorPickerModel.select(dplDetectorId)), Other: () => {}, }), Other: () => {}, @@ -140,7 +140,7 @@ export class GaqFlagsOverviewModel extends OverviewPageModel { await jsonPost('/api/dataPasses/gaq', { dataPassId: this._dataPassId, runNumbers: [this._runNumber], - dplDetectorIds: this._detectorSelectionModel.selected, + dplDetectorIds: this._gaqDetectorPickerModel.selected, }); this._submitResult = RemoteData.success(null); @@ -216,7 +216,7 @@ export class GaqFlagsOverviewModel extends OverviewPageModel { /** * Get Detector selection model */ - get detectorSelectionModel() { - return this._detectorSelectionModel; + get gaqDetectorPickerModel() { + return this._gaqDetectorPickerModel; } } diff --git a/lib/public/views/QcFlags/GaqFlags/GaqFlagsOverviewPage.js b/lib/public/views/QcFlags/GaqFlags/GaqFlagsOverviewPage.js index d3dd9ea828..b04dad3791 100644 --- a/lib/public/views/QcFlags/GaqFlags/GaqFlagsOverviewPage.js +++ b/lib/public/views/QcFlags/GaqFlags/GaqFlagsOverviewPage.js @@ -16,6 +16,7 @@ import { h } from '/js/src/index.js'; import { table } from '../../../components/common/table/table.js'; import { qcFlagsBreadcrumbs } from '../../../components/qcFlags/qcFlagsBreadcrumbs.js'; import { createGaqFlagsActiveColumns } from '../ActiveColumns/gaqFlagsActiveColumns.js'; +import { gaqDetectorsTrigger } from './gaqDetectectorSelection.js'; /** * Render GAQ Flags Overview page @@ -24,6 +25,7 @@ import { createGaqFlagsActiveColumns } from '../ActiveColumns/gaqFlagsActiveColu */ export const GaqFlagsOverviewPage = ({ qcFlags: { gaqOverviewModel }, + modalModel, }) => { const { dataPass: remoteDataPass, @@ -43,7 +45,10 @@ export const GaqFlagsOverviewPage = ({ '', { onremove: () => gaqOverviewModel.reset() }, [ - h('.flex-row.justify-between.items-center', [qcFlagsBreadcrumbs({ remoteDataPass, remoteRun }, 'GAQ')]), + h('.flex-row.justify-between.items-center', [ + qcFlagsBreadcrumbs({ remoteDataPass, remoteRun }, 'GAQ'), + gaqDetectorsTrigger(gaqOverviewModel, modalModel), + ]), h('.w-100.flex-column', [ table( remoteGaqDetectors.match({ diff --git a/lib/public/views/QcFlags/GaqFlags/gaqDetectectorSelection.js b/lib/public/views/QcFlags/GaqFlags/gaqDetectectorSelection.js index d46d289d30..0c4585b7b4 100644 --- a/lib/public/views/QcFlags/GaqFlags/gaqDetectectorSelection.js +++ b/lib/public/views/QcFlags/GaqFlags/gaqDetectectorSelection.js @@ -12,78 +12,37 @@ */ import { h } from '/js/src/index.js'; -import { runsActiveColumns } from '../ActiveColumns/runsActiveColumns.js'; +import { picker } from '../../../components/common/selection/picker/picker.js'; /** * Export form component, containing the fields to export, the export type and the export button * - * @param {RunsOverviewModel} runsOverviewModel the runsOverviewModel - * @param {array} runs the runs to export + * @param {RunsOverviewModel} gaqOverviewModel the runsOverviewModel + * @param {array} gaqDetectors the runs to export * @param {ModalHandler} modalHandler The modal handler, used to dismiss modal after export * * @return {vnode[]} the form component */ -const exportForm = (runsOverviewModel, runs, modalHandler) => { - const exportTypes = ['JSON', 'CSV']; - const selectedRunsFields = runsOverviewModel.getSelectedRunsFields() || []; - const selectedExportType = runsOverviewModel.getSelectedExportType() || exportTypes[0]; - const runsFields = Object.keys(runsActiveColumns); - const enabled = selectedRunsFields.length > 0; +const selectionForm = (gaqOverviewModel, gaqDetectors, modalHandler) => { + const { gaqDetectorPickerModel } = gaqOverviewModel; return [ - runsOverviewModel.isAllRunsTruncated - ? h( - '#truncated-export-warning.warning', - `The runs export is limited to ${runs.length} entries, only the last runs will be exported (sorted by run number)`, - ) - : null, h('label.form-check-label.f4.mt1', { for: 'run-number' }, 'Fields'), - h( - 'label.form-check-label.f6', - { for: 'run-number' }, - 'Select which fields to be exported. (CTRL + click for multiple selection)', + picker( + gaqDetectorPickerModel.options, + gaqDetectorPickerModel, + { + selector: 'gaq-detectors', + limit: null, + attributes: { class: 'scroll-y grid columns-2-lg columns-3-xl g2' }, + outlineSelection: true, + }, ), - h('select#fields.form-control', { - style: 'min-height: 20rem;', - multiple: true, - onchange: ({ target }) => runsOverviewModel.setSelectedRunsFields(target.selectedOptions), - }, [ - ...runsFields - .filter((name) => !['id', 'actions'].includes(name)) - .map((name) => h('option', { - value: name, - selected: selectedRunsFields.length ? selectedRunsFields.includes(name) : false, - }, name)), - ]), - h('label.form-check-label.f4.mt1', { for: 'run-number' }, 'Export type'), - h('label.form-check-label.f6', { for: 'run-number' }, 'Select output format'), - h('.flex-row.g3', exportTypes.map((exportType) => { - const id = `runs-export-type-${exportType}`; - return h('.form-check', [ - h('input.form-check-input', { - id, - type: 'radio', - value: exportType, - checked: selectedExportType.length ? selectedExportType.includes(exportType) : false, - name: 'runs-export-type', - onclick: () => runsOverviewModel.setSelectedExportType(exportType), - }), - h('label.form-check-label', { - for: id, - }, exportType), - ]); - })), h('button.shadow-level1.btn.btn-success.mt2#send', { - disabled: !enabled, onclick: async () => { - await runsOverviewModel.createRunsExport( - runs, - 'runs', - runsActiveColumns, - ); modalHandler.dismiss(); }, - }, runs ? 'Export' : 'Loading data'), + }, gaqDetectors ? 'Submit' : 'Loading data'), ]; }; @@ -100,11 +59,11 @@ const gaqDetectorsSelectionModal = (gaqOverviewModel, modalHandler) => { const { gaqDetectors } = gaqOverviewModel; return h('div#export-runs-modal', [ - h('h2', 'Export Runs'), - runsRemoteData.match({ + h('h2', 'GAQ detectors selection'), + gaqDetectors.match({ NotAsked: () => errorDisplay(), - Loading: () => exportForm(gaqOverviewModel, null, modalHandler), - Success: (payload) => exportForm(gaqOverviewModel, payload, modalHandler), + Loading: () => selectionForm(gaqOverviewModel, null, modalHandler), + Success: (payload) => selectionForm(gaqOverviewModel, payload, modalHandler), Failure: () => errorDisplay(), }), ]); @@ -127,4 +86,4 @@ export const gaqDetectorsTrigger = (gaqOverviewModel, modalModel, { autoMarginLe Loading: () => true, }), onclick: () => modalModel.display({ content: (modalModel) => gaqDetectorsSelectionModal(gaqOverviewModel, modalModel), size: 'medium' }), - }, 'Export Runs'); + }, 'Set GAQ Dets');