|
| 1 | +/** |
| 2 | + * @license |
| 3 | + * Copyright CERN and copyright holders of ALICE O2. This software is |
| 4 | + * distributed under the terms of the GNU General Public License v3 (GPL |
| 5 | + * Version 3), copied verbatim in the file "COPYING". |
| 6 | + * |
| 7 | + * See http://alice-o2.web.cern.ch/license for full licensing information. |
| 8 | + * |
| 9 | + * In applying this license CERN does not waive the privileges and immunities |
| 10 | + * granted to it by virtue of its status as an Intergovernmental Organization |
| 11 | + * or submit itself to any jurisdiction. |
| 12 | + */ |
| 13 | + |
| 14 | +import { DATA_EXPORT_TYPES } from '../../../domain/enums/DataExportTypes.js'; |
| 15 | +import errorAlert from '../errorAlert.js'; |
| 16 | +import spinner from '../spinner.js'; |
| 17 | +import { h } from '/js/src/index.js'; |
| 18 | + |
| 19 | +/** |
| 20 | + * Export form component, containing the fields to export, the export type and the export button |
| 21 | + * |
| 22 | + * @param {DataExportModel} exportModel export model |
| 23 | + * @param {ModalHandler} modalHandler The modal handler, used to dismiss modal after export |
| 24 | + * |
| 25 | + * @return {Component} the form component |
| 26 | + */ |
| 27 | +const exportForm = (exportModel, modalHandler) => { |
| 28 | + const { selectedFields, selectedExportType, dataExportConfiguration } = exportModel; |
| 29 | + const fields = Object.keys(dataExportConfiguration); |
| 30 | + |
| 31 | + const fieldsSelected = selectedFields.length > 0; |
| 32 | + |
| 33 | + const fieldsSelectionLabels = [ |
| 34 | + h('label.form-check-label.f4.mt1', { for: 'fields' }, 'Fields'), |
| 35 | + h( |
| 36 | + 'label.form-check-label.f6', |
| 37 | + { for: 'fields' }, |
| 38 | + 'Select which fields to be exported. (CTRL + click for multiple selection)', |
| 39 | + ), |
| 40 | + ]; |
| 41 | + |
| 42 | + const fieldsSelection = h('select#fields.form-control', { |
| 43 | + style: 'min-height: 20rem;', |
| 44 | + multiple: true, |
| 45 | + onchange: ({ target }) => exportModel.setSelectedFields(target.selectedOptions), |
| 46 | + }, [ |
| 47 | + ...fields |
| 48 | + .filter((name) => !['id', 'actions'].includes(name)) |
| 49 | + .map((name) => h('option', { |
| 50 | + value: name, |
| 51 | + selected: selectedFields.length ? selectedFields.includes(name) : false, |
| 52 | + }, name)), |
| 53 | + ]); |
| 54 | + |
| 55 | + const exportTypeSelectionLabels = [ |
| 56 | + h('label.form-check-label.f4.mt1', 'Export type'), |
| 57 | + h('label.form-check-label.f6', 'Select output format'), |
| 58 | + ]; |
| 59 | + |
| 60 | + const exportTypeSelect = h('.flex-row.g3', DATA_EXPORT_TYPES.map((exportType) => { |
| 61 | + const id = `data-export-type-${exportType}`; |
| 62 | + return h('.form-check', [ |
| 63 | + h('input.form-check-input', { |
| 64 | + id, |
| 65 | + type: 'radio', |
| 66 | + value: exportType, |
| 67 | + checked: selectedExportType.length ? selectedExportType.includes(exportType) : false, |
| 68 | + name: 'export-type', |
| 69 | + onclick: () => exportModel.setSelectedExportType(exportType), |
| 70 | + }), |
| 71 | + h('label.form-check-label', { |
| 72 | + for: id, |
| 73 | + }, exportType), |
| 74 | + ]); |
| 75 | + })); |
| 76 | + |
| 77 | + const exportBtn = h('button.shadow-level1.btn.btn-success.mt2#send', { |
| 78 | + disabled: !fieldsSelected, |
| 79 | + onclick: async () => { |
| 80 | + await exportModel.createExport(); |
| 81 | + modalHandler.dismiss(); |
| 82 | + }, |
| 83 | + }, 'Export'); |
| 84 | + |
| 85 | + const dataLength = exportModel.items.match({ Success: ({ length } = {}) => length, Other: () => null }); |
| 86 | + const { totalExistingItemsCount } = exportModel; |
| 87 | + |
| 88 | + const truncatedDataInfo = dataLength && dataLength < totalExistingItemsCount |
| 89 | + ? h( |
| 90 | + '#truncated-export-warning.warning', |
| 91 | + `The data export is limited to ${dataLength} entries, only the most recent data will be exported`, |
| 92 | + ) |
| 93 | + : null; |
| 94 | + |
| 95 | + return [ |
| 96 | + truncatedDataInfo, |
| 97 | + fieldsSelectionLabels, |
| 98 | + fieldsSelection, |
| 99 | + exportTypeSelectionLabels, |
| 100 | + exportTypeSelect, |
| 101 | + exportBtn, |
| 102 | + ]; |
| 103 | +}; |
| 104 | + |
| 105 | +/** |
| 106 | + * A function to construct the exports data screen |
| 107 | + * |
| 108 | + * @param {DataExportModel} exportModel export model |
| 109 | + * @param {ModalHandler} modalHandler The modal handler, used to dismiss modal after export |
| 110 | + * @return {Component} Return the view of the inputs |
| 111 | + */ |
| 112 | +const exportModal = (exportModel, modalHandler) => { |
| 113 | + exportModel.callForData(); |
| 114 | + |
| 115 | + return h('div#export-data-modal', [ |
| 116 | + h('h2.w-50', 'Export data'), |
| 117 | + exportModel.items.match({ |
| 118 | + NotAsked: () => errorAlert(), |
| 119 | + Failure: (errors) => errorAlert(errors), |
| 120 | + Loading: () => spinner({ size: 2, absolute: false }), |
| 121 | + Other: () => exportForm(exportModel, modalHandler), |
| 122 | + }), |
| 123 | + ]); |
| 124 | +}; |
| 125 | + |
| 126 | +/** |
| 127 | + * Builds a button which will open popover for data export |
| 128 | + * |
| 129 | + * @param {DataExportModel} exportModel export model |
| 130 | + * @param {ModalModel} modalModel modal model |
| 131 | + * @param {object} [displayConfiguration] additional display options |
| 132 | + * @param {boolean} [displayConfiguration.autoMarginLeft = true] if true margin left is set to auto, otherwise not |
| 133 | + * @returns {Component} button |
| 134 | + */ |
| 135 | +export const exportTriggerAndModal = (exportModel, modalModel, { autoMarginLeft = true } = {}) => |
| 136 | + h(`button.btn.btn-primary${autoMarginLeft ? '.mlauto' : ''}#export-data-trigger`, { |
| 137 | + disabled: exportModel.disabled, |
| 138 | + onclick: () => modalModel.display({ content: (modalModel) => exportModal(exportModel, modalModel), size: 'medium' }), |
| 139 | + }, 'Export data'); |
0 commit comments