lhcb-ntuple-wizard 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -4
- package/dist/App.js +1 -3
- package/dist/components/BookkeepingPathDropdown.d.ts +1 -0
- package/dist/components/BookkeepingPathDropdown.js +35 -0
- package/dist/components/DatasetInfo.d.ts +1 -1
- package/dist/components/DatasetInfo.js +9 -3
- package/dist/components/DttNameInput.js +13 -16
- package/dist/components/NtupleWizard.d.ts +2 -7
- package/dist/components/NtupleWizard.js +6 -11
- package/dist/components/ProductionNameInput.d.ts +1 -0
- package/dist/components/ProductionNameInput.js +7 -0
- package/dist/components/RequestButtonGroup.d.ts +7 -0
- package/dist/components/RequestButtonGroup.js +29 -0
- package/dist/components/RequestEmailInput.d.ts +1 -0
- package/dist/components/RequestEmailInput.js +7 -0
- package/dist/components/RequestRow.d.ts +7 -0
- package/dist/components/RequestRow.js +20 -0
- package/dist/components/StrippingLineBadge.js +2 -3
- package/dist/components/StrippingLineDropdown.d.ts +1 -0
- package/dist/components/StrippingLineDropdown.js +48 -0
- package/dist/components/modals/ReasonForRequestModal.d.ts +2 -3
- package/dist/components/modals/ReasonForRequestModal.js +3 -10
- package/dist/components/modals/UploadDttConfigModal.d.ts +2 -2
- package/dist/components/modals/UploadDttConfigModal.js +55 -25
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/models/bkPath.d.ts +9 -9
- package/dist/models/bkPath.js +37 -30
- package/dist/models/dtt.d.ts +33 -3
- package/dist/models/dtt.js +62 -0
- package/dist/models/yamlFile.d.ts +0 -1
- package/dist/models/yamlFile.js +1 -24
- package/dist/pages/DecaySearchPage.js +1 -1
- package/dist/pages/DecayTreeConfigPage.js +2 -4
- package/dist/pages/RequestPage.d.ts +10 -0
- package/dist/pages/RequestPage.js +105 -0
- package/dist/providers/RequestProvider.d.ts +14 -1
- package/dist/providers/RequestProvider.js +48 -2
- package/dist/providers/RowProvider.d.ts +15 -0
- package/dist/providers/RowProvider.js +41 -0
- package/dist/providers/RowsProvider.d.ts +4 -1
- package/dist/providers/RowsProvider.js +9 -2
- package/dist/utils/utils.d.ts +15 -0
- package/dist/utils/utils.js +535 -0
- package/package.json +8 -4
- package/dist/components/LineTableRow.d.ts +0 -9
- package/dist/components/LineTableRow.js +0 -123
- package/dist/components/SubmitRequestButton.d.ts +0 -11
- package/dist/components/SubmitRequestButton.js +0 -39
- package/dist/components/modals/UploadProdConfigModal.d.ts +0 -5
- package/dist/components/modals/UploadProdConfigModal.js +0 -27
- package/dist/models/strippingLineOption.d.ts +0 -6
- package/dist/models/strippingLineOption.js +0 -1
- package/dist/pages/LinesTablePage.d.ts +0 -14
- package/dist/pages/LinesTablePage.js +0 -120
- package/dist/providers/ProductionConfigProvider.d.ts +0 -14
- package/dist/providers/ProductionConfigProvider.js +0 -76
package/README.md
CHANGED
|
@@ -53,11 +53,10 @@ const App = () => {
|
|
|
53
53
|
return (
|
|
54
54
|
<NtupleWizard
|
|
55
55
|
basePath="/"
|
|
56
|
-
decaysPath="/select-decays"
|
|
57
|
-
variablesPath="/variables"
|
|
58
|
-
submitLocation="" // Leave empty to hide the submit button -> overrides hideDownloadButtons to false
|
|
59
56
|
contactEmail="" // Leave empty to let the user fill in their email address
|
|
60
|
-
|
|
57
|
+
submitLocation="" // Some endpoint to submit the request to
|
|
58
|
+
requestReasonMessage="Please provide a reason for your request."
|
|
59
|
+
requestSubmittedMessage={<>Some message to display when the request is submitted</>}
|
|
61
60
|
/>
|
|
62
61
|
);
|
|
63
62
|
};
|
package/dist/App.js
CHANGED
|
@@ -16,7 +16,5 @@ import { config } from "./config";
|
|
|
16
16
|
import { NtupleWizard } from "./components/NtupleWizard";
|
|
17
17
|
import { BrowserRouter } from "react-router-dom";
|
|
18
18
|
export function App() {
|
|
19
|
-
return (_jsxs(_Fragment, { children: [_jsx(Navbar, { collapseOnSelect: true, expand: "lg", bg: "dark", variant: "dark", children: _jsxs(Container, { children: [_jsxs(Navbar.Brand, { href: "/", children: [_jsx("img", { src: "/logo.svg", height: "30", className: "d-inline-block align-top", alt: "LHCb logo" }), " LHCb NTuple Wizard"] }), _jsx(Navbar.Toggle, { "aria-controls": "responsive-navbar-nav" }), _jsx(Navbar.Collapse, { className: "justify-content-end", children: _jsxs(Nav, { children: [_jsxs(NavDropdown, { title: "About", id: "about-dropdown", menuVariant: "dark", children: [_jsxs(NavDropdown.Item, { href: "https://lhcb-dpa.web.cern.ch/lhcb-dpa/wp6/ntupling-wizard.html", target: "_blank", children: [_jsx(House, {}), " Project home"] }), _jsxs(NavDropdown.Item, { href: "https://gitlab.cern.ch/lhcb-dpa/wp6-analysis-preservation-and-open-data/lhcb-ntuple-wizard-frontend", target: "_blank", children: [_jsx(CodeSlash, {}), " Source code"] }), _jsxs(NavDropdown.Item, { href: config.metadata_baseurl, target: "_blank", children: [_jsx(Archive, {}), " Metadata files"] })] }), _jsx(Nav.Link, { href: "https://opendata.cern.ch/", target: "_blank", children: _jsx("img", { src: "/open_data_portal.png", height: "30", alt: "CERN Open Data Portal" }) })] }) })] }) }), _jsx(Container, { className: "mt-4", children: _jsx(BrowserRouter, { children: _jsx(NtupleWizard, {
|
|
20
|
-
, contactEmail: "" // Leave empty to let the user fill in their email address
|
|
21
|
-
, hideDownloadButtons: false, hideUploadButtons: false, requestReasonMessage: "Please provide a reason for your request.", requestSubmittedMessage: _jsx(_Fragment, { children: "Your request has been submitted." }) }) }) })] }));
|
|
19
|
+
return (_jsxs(_Fragment, { children: [_jsx(Navbar, { collapseOnSelect: true, expand: "lg", bg: "dark", variant: "dark", children: _jsxs(Container, { children: [_jsxs(Navbar.Brand, { href: "/", children: [_jsx("img", { src: "/logo.svg", height: "30", className: "d-inline-block align-top", alt: "LHCb logo" }), " LHCb NTuple Wizard"] }), _jsx(Navbar.Toggle, { "aria-controls": "responsive-navbar-nav" }), _jsx(Navbar.Collapse, { className: "justify-content-end", children: _jsxs(Nav, { children: [_jsxs(NavDropdown, { title: "About", id: "about-dropdown", menuVariant: "dark", children: [_jsxs(NavDropdown.Item, { href: "https://lhcb-dpa.web.cern.ch/lhcb-dpa/wp6/ntupling-wizard.html", target: "_blank", children: [_jsx(House, {}), " Project home"] }), _jsxs(NavDropdown.Item, { href: "https://gitlab.cern.ch/lhcb-dpa/wp6-analysis-preservation-and-open-data/lhcb-ntuple-wizard-frontend", target: "_blank", children: [_jsx(CodeSlash, {}), " Source code"] }), _jsxs(NavDropdown.Item, { href: config.metadata_baseurl, target: "_blank", children: [_jsx(Archive, {}), " Metadata files"] })] }), _jsx(Nav.Link, { href: "https://opendata.cern.ch/", target: "_blank", children: _jsx("img", { src: "/open_data_portal.png", height: "30", alt: "CERN Open Data Portal" }) })] }) })] }) }), _jsx(Container, { className: "mt-4", children: _jsx(BrowserRouter, { children: _jsx(NtupleWizard, {}) }) })] }));
|
|
22
20
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function BookkeepingPathDropdown(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import Creatable from "react-select/creatable";
|
|
3
|
+
import { useRow } from "../providers/RowProvider";
|
|
4
|
+
import { useCallback, useMemo } from "react";
|
|
5
|
+
import { useRows } from "../providers/RowsProvider";
|
|
6
|
+
import { useMetadata } from "../providers/MetadataProvider";
|
|
7
|
+
import { DatasetInfo } from "./DatasetInfo";
|
|
8
|
+
export function BookkeepingPathDropdown() {
|
|
9
|
+
const metadata = useMetadata();
|
|
10
|
+
const { row, validateBkPath, updateBkPaths } = useRow();
|
|
11
|
+
const { updateRow } = useRows();
|
|
12
|
+
if (!metadata) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const getOptionFromPath = useCallback((path) => ({
|
|
16
|
+
value: path,
|
|
17
|
+
label: _jsx(DatasetInfo, { pathString: path }),
|
|
18
|
+
}), []);
|
|
19
|
+
const defaultPaths = useMemo(() => {
|
|
20
|
+
const defaults = metadata.dataset.filter((path) => validateBkPath(path)).map(getOptionFromPath);
|
|
21
|
+
return [...defaults, ...row.pathOptions.map(getOptionFromPath)];
|
|
22
|
+
}, [metadata.dataset, row.pathOptions, validateBkPath, getOptionFromPath]);
|
|
23
|
+
const handleCreatePath = useCallback((path) => {
|
|
24
|
+
if (!validateBkPath(path)) {
|
|
25
|
+
alert(`The path '${path}' is not valid for the selected stripping line.`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
updateRow(row.id, (r) => ({
|
|
29
|
+
...r,
|
|
30
|
+
paths: [...r.paths, path],
|
|
31
|
+
pathOptions: [...r.pathOptions, path],
|
|
32
|
+
}));
|
|
33
|
+
}, [row.id, validateBkPath, updateRow]);
|
|
34
|
+
return (_jsx(Creatable, { isMulti: true, options: defaultPaths, value: row.paths.map(getOptionFromPath), isDisabled: !row.lines.length, placeholder: "Bookkeeping path", onChange: (v) => updateBkPaths(v.map((i) => i.value)), onCreateOption: handleCreatePath, closeMenuOnSelect: false }));
|
|
35
|
+
}
|
|
@@ -14,8 +14,14 @@ import { YearBadge } from "./YearBadge.js";
|
|
|
14
14
|
import { PolarityBadge } from "./PolarityBadge.js";
|
|
15
15
|
import { StrippingLineBadge } from "./StrippingLineBadge";
|
|
16
16
|
import { DatasetEventTypeBadge } from "./DatasetEventTypeBadge";
|
|
17
|
-
import BkPath from "../models/bkPath.js";
|
|
17
|
+
import { BkPath } from "../models/bkPath.js";
|
|
18
18
|
export function DatasetInfo({ pathString }) {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
try {
|
|
20
|
+
const path = new BkPath(pathString);
|
|
21
|
+
return (_jsxs("span", { children: [path.fileName, _jsx("br", {}), _jsxs(Stack, { direction: "horizontal", style: { flexWrap: "wrap" }, gap: 1, children: [_jsx(DatasetEventTypeBadge, { eventType: path.eventType }), _jsx(YearBadge, { year: path.year }), _jsx(PolarityBadge, { polarity: path.polarity || "?" }), _jsx(StrippingLineBadge, { version: path.strippingVersion })] })] }));
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
console.error("Error parsing bookkeeping path:", e);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
21
27
|
}
|
|
@@ -9,10 +9,10 @@ import { useRows } from "../providers/RowsProvider";
|
|
|
9
9
|
import { useNavigate } from "react-router-dom";
|
|
10
10
|
import { useMetadata } from "../providers/MetadataProvider";
|
|
11
11
|
import { downloadText } from "../utils/utils";
|
|
12
|
-
import { UploadDttConfigModal } from "./modals/UploadDttConfigModal";
|
|
13
12
|
import { YamlFile } from "../models/yamlFile";
|
|
13
|
+
import { UploadDttConfigModal } from "./modals/UploadDttConfigModal";
|
|
14
14
|
export function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, variablesPath }) {
|
|
15
|
-
const { rows,
|
|
15
|
+
const { rows, updateRow } = useRows();
|
|
16
16
|
const navigate = useNavigate();
|
|
17
17
|
const metadata = useMetadata();
|
|
18
18
|
const [showUploadModal, setShowUploadModal] = useState(false);
|
|
@@ -38,26 +38,25 @@ export function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, vari
|
|
|
38
38
|
}
|
|
39
39
|
const handleCreateDTT = () => {
|
|
40
40
|
const dtt = Dtt.create(row.decay.descriptors.template, row.decay.descriptors.mapped_list.flatMap((item) => (Array.isArray(item) ? item : [item])), [], "", metadata.tupleTools.tupleTools);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
updateRow(row.id, (r) => ({
|
|
42
|
+
...r,
|
|
43
|
+
dtt: dtt.withInputsFromLines(row.lines),
|
|
44
|
+
}));
|
|
44
45
|
setAutoFocus(true);
|
|
45
46
|
};
|
|
46
|
-
const handleConfigureDtt = (
|
|
47
|
-
|
|
47
|
+
const handleConfigureDtt = () => {
|
|
48
|
+
updateRow(row.id, (r) => ({ ...r, editTree: true }));
|
|
48
49
|
void navigate(variablesPath);
|
|
49
50
|
};
|
|
50
|
-
const handleDeleteDtt = (
|
|
51
|
-
|
|
51
|
+
const handleDeleteDtt = () => {
|
|
52
|
+
updateRow(row.id, (r) => ({ ...r, dtt: null }));
|
|
52
53
|
setDttName("");
|
|
53
54
|
};
|
|
54
55
|
return (_jsxs(Card, { children: [_jsxs(Card.Header, { className: "d-flex justify-content-between align-items-start gap-2", children: [row.dtt && (_jsxs(InputGroup, { hasValidation: true, children: [_jsx(FormControl, { autoFocus: autoFocus, placeholder: "DecayTree", value: dttName, onBlur: () => {
|
|
55
56
|
if (!validateName()) {
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
-
return prev.map((r) => r.id === row.id ? { ...r, dtt: r.dtt.withName(dttName) } : r);
|
|
60
|
-
});
|
|
59
|
+
updateRow(row.id, (r) => ({ ...r, dtt: r.dtt.withName(dttName) }));
|
|
61
60
|
}, onChange: (event) => {
|
|
62
61
|
setDttName(event.target.value);
|
|
63
62
|
setDttNameValid(true);
|
|
@@ -65,9 +64,7 @@ export function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, vari
|
|
|
65
64
|
? "Name cannot be empty"
|
|
66
65
|
: !allNameCharsValid(dttName.trim())
|
|
67
66
|
? "Name contains invalid characters"
|
|
68
|
-
: "
|
|
69
|
-
handleConfigureDtt(row.id);
|
|
70
|
-
}, disabled: !dttNameValid, className: "align-items-center d-flex", children: _jsx(GearWideConnected, {}) }) }), !hideDownloadButtons && (_jsx(_Fragment, { children: _jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Download DecayTreeTuple YAML configuration file" }), children: _jsx(Button, { className: "align-items-center d-flex ms-auto", type: "button", onClick: () => {
|
|
67
|
+
: "Name is already taken" })] })), _jsx(ButtonGroup, { children: row.dtt ? (_jsxs(_Fragment, { children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Configure this DecayTreeTuple" }), children: _jsx(Button, { type: "submit", variant: "secondary", onClick: handleConfigureDtt, disabled: !dttNameValid, className: "align-items-center d-flex", children: _jsx(GearWideConnected, {}) }) }), !hideDownloadButtons && (_jsx(_Fragment, { children: _jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Download DecayTreeTuple YAML configuration file" }), children: _jsx(Button, { className: "align-items-center d-flex ms-auto", type: "button", onClick: () => {
|
|
71
68
|
downloadText(YamlFile.fromDtt(row.dtt));
|
|
72
|
-
}, disabled: !dttNameValid, children: _jsx(Download, {}) }) }) })), _jsx(DeleteButton, { action:
|
|
69
|
+
}, disabled: !dttNameValid, children: _jsx(Download, {}) }) }) })), _jsx(DeleteButton, { action: handleDeleteDtt })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "d-flex align-items-center gap-2", children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Please add a DecayTreeTuple in order to complete the production configuration" }), children: _jsx(ExclamationCircle, { width: 20, height: 20, className: "text-danger me-2" }) }), _jsxs(ButtonGroup, { children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Add a DecayTreeTuple" }), children: _jsx(Button, { type: "submit", variant: "success", onClick: handleCreateDTT, disabled: !metadata, children: _jsx(PlusLg, {}) }) }), !hideUploadButtons && (_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Upload DecayTreeTuple configuration file" }), children: _jsx(Button, { className: "ms-auto", type: "button", onClick: () => setShowUploadModal(true), children: _jsx(Upload, {}) }) }))] })] }), showUploadModal && (_jsx(UploadDttConfigModal, { currentRow: row, onClose: () => setShowUploadModal(false) }))] })) })] }), _jsx(Card.Body, { children: _jsx(DecayLatex, { decay: row.decay }) })] }));
|
|
73
70
|
}
|
|
@@ -11,16 +11,11 @@
|
|
|
11
11
|
import "bootstrap/dist/css/bootstrap.css";
|
|
12
12
|
import { ReactNode } from "react";
|
|
13
13
|
interface Props {
|
|
14
|
-
basePath
|
|
15
|
-
decaysPath: string;
|
|
16
|
-
variablesPath: string;
|
|
14
|
+
basePath?: string;
|
|
17
15
|
contactEmail?: string;
|
|
18
16
|
submitLocation?: string;
|
|
19
|
-
hideDownloadButtons?: boolean;
|
|
20
|
-
hideUploadButtons?: boolean;
|
|
21
17
|
requestReasonMessage?: string;
|
|
22
18
|
requestSubmittedMessage?: ReactNode;
|
|
23
|
-
csrfToken?: string;
|
|
24
19
|
}
|
|
25
|
-
export declare function NtupleWizard({ basePath,
|
|
20
|
+
export declare function NtupleWizard({ basePath, contactEmail, submitLocation, requestReasonMessage, requestSubmittedMessage, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
26
21
|
export {};
|
|
@@ -14,20 +14,15 @@ import { useLocation } from "react-router-dom";
|
|
|
14
14
|
import { MetadataProvider } from "../providers/MetadataProvider.js";
|
|
15
15
|
import { DecaySearchPage } from "../pages/DecaySearchPage";
|
|
16
16
|
import { DecayTreeConfigPage } from "../pages/DecayTreeConfigPage";
|
|
17
|
-
import {
|
|
17
|
+
import { RequestPage } from "../pages/RequestPage";
|
|
18
18
|
import { MathJaxContext } from "better-react-mathjax";
|
|
19
19
|
import { RowsProvider } from "../providers/RowsProvider.js";
|
|
20
20
|
import { RequestProvider } from "../providers/RequestProvider";
|
|
21
|
-
import {
|
|
22
|
-
export function NtupleWizard({ basePath
|
|
21
|
+
import { SELECT_DECAYS_PATH, VARIABLES_PATH } from "../constants";
|
|
22
|
+
export function NtupleWizard({ basePath = "", contactEmail, submitLocation, requestReasonMessage, requestSubmittedMessage, }) {
|
|
23
23
|
const { pathname } = useLocation();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
localStorage.setItem("email", props.contactEmail);
|
|
27
|
-
emailIsKnown = true;
|
|
24
|
+
if (contactEmail) {
|
|
25
|
+
localStorage.setItem("email", contactEmail);
|
|
28
26
|
}
|
|
29
|
-
|
|
30
|
-
hideDownloadButtons = false;
|
|
31
|
-
}
|
|
32
|
-
return (_jsx(MetadataProvider, { children: _jsx(ProductionConfigProvider, { children: _jsx(RowsProvider, { children: _jsx(RequestProvider, { children: _jsx(MathJaxContext, { children: pathname.endsWith("/select-decays") ? (_jsx(DecaySearchPage, { basePath: basePath })) : pathname.endsWith("/variables") ? (_jsx(DecayTreeConfigPage, { basePath: basePath })) : (_jsx(LinesTablePage, { decaysPath: decaysPath, variablesPath: variablesPath, submitLocation: submitLocation, hideDownloadButtons: hideDownloadButtons, hideUploadButtons: hideUploadButtons, emailIsKnown: emailIsKnown, requestReasonMessage: requestReasonMessage, requestSubmittedMessage: requestSubmittedMessage, csrfToken: csrfToken })) }) }) }) }) }));
|
|
27
|
+
return (_jsx(MetadataProvider, { children: _jsx(RowsProvider, { children: _jsx(RequestProvider, { emailIsKnown: !!contactEmail, children: _jsx(MathJaxContext, { children: pathname.endsWith(SELECT_DECAYS_PATH) ? (_jsx(DecaySearchPage, { basePath: basePath })) : pathname.endsWith(VARIABLES_PATH) ? (_jsx(DecayTreeConfigPage, { basePath: basePath })) : (_jsx(RequestPage, { basePath: basePath, submitLocation: submitLocation, requestReasonMessage: requestReasonMessage, requestSubmittedMessage: requestSubmittedMessage })) }) }) }) }));
|
|
33
28
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ProductionNameInput(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { FormControl, InputGroup, OverlayTrigger, Tooltip } from "react-bootstrap";
|
|
3
|
+
import { useRequest } from "../providers/RequestProvider";
|
|
4
|
+
export function ProductionNameInput() {
|
|
5
|
+
const { productionName, setProductionName, showErrors } = useRequest();
|
|
6
|
+
return (_jsxs(InputGroup, { hasValidation: true, children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Name of this production. This will become the subdirectory in AnalysisProductions" }), children: _jsx(InputGroup.Text, { children: "Production name" }) }), _jsx(FormControl, { value: productionName, onChange: (event) => setProductionName(event.target.value.replaceAll(/[^\w]/g, "")), isInvalid: showErrors && !productionName, placeholder: "MyAnalysis" }), _jsx(FormControl.Feedback, { type: "invalid", children: "Please enter a production name" })] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { NtupleWizardVariant } from "../pages/RequestPage";
|
|
2
|
+
interface Props {
|
|
3
|
+
variant: NtupleWizardVariant;
|
|
4
|
+
basePath: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function RequestButtonGroup({ variant, basePath }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Badge, Button, ButtonGroup, OverlayTrigger, Tooltip } from "react-bootstrap";
|
|
3
|
+
import { SELECT_DECAYS_PATH, VARIABLES_PATH } from "../constants";
|
|
4
|
+
import { useNavigate } from "react-router-dom";
|
|
5
|
+
import { Download, GearWideConnected, PlusLg, Upload } from "react-bootstrap-icons";
|
|
6
|
+
import { UploadDttConfigModal } from "./modals/UploadDttConfigModal";
|
|
7
|
+
import { downloadText } from "../utils/utils";
|
|
8
|
+
import { YamlFile } from "../models/yamlFile";
|
|
9
|
+
import { useRows } from "../providers/RowsProvider";
|
|
10
|
+
import { useMetadata } from "../providers/MetadataProvider";
|
|
11
|
+
import { useRequest } from "../providers/RequestProvider";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
export function RequestButtonGroup({ variant, basePath }) {
|
|
14
|
+
const metadata = useMetadata();
|
|
15
|
+
const { validation } = useRequest();
|
|
16
|
+
const { rows, configuredRows, setRows } = useRows();
|
|
17
|
+
const navigate = useNavigate();
|
|
18
|
+
const [showProdUploadModal, setShowProdUploadModal] = useState(false);
|
|
19
|
+
const handleSubmitRows = async () => {
|
|
20
|
+
setRows((prev) => prev.map((r) => ({ ...r, editTree: true })));
|
|
21
|
+
await navigate(`${basePath}${VARIABLES_PATH}`);
|
|
22
|
+
};
|
|
23
|
+
if (!metadata) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return (_jsxs(_Fragment, { children: [showProdUploadModal && _jsx(UploadDttConfigModal, { onClose: () => setShowProdUploadModal(false) }), _jsxs(ButtonGroup, { children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Select decays" }), children: _jsxs(Button, { type: "submit", variant: "success", onClick: () => void navigate(`${basePath}${SELECT_DECAYS_PATH}`), className: "align-items-center d-flex gap-1", children: [_jsx(PlusLg, {}), " Select decays"] }) }), variant === "standalone" && (_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Upload Production configuration file" }), children: _jsx(Button, { className: "ms-auto align-items-center d-flex", type: "button", onClick: () => setShowProdUploadModal(true), children: _jsx(Upload, {}) }) })), _jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Configure all DecayTreeTuples" }), children: _jsxs(Button, { type: "submit", variant: "secondary", onClick: () => {
|
|
27
|
+
handleSubmitRows().catch(console.error);
|
|
28
|
+
}, disabled: !validation.allRowsHaveDtt, className: "align-items-center d-flex gap-1", children: [_jsx(GearWideConnected, {}), " ", _jsx(Badge, { pill: true, bg: "primary", children: configuredRows.length })] }) }), variant === "standalone" && (_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Download Analysis Production configuration file (info.yaml)" }), children: _jsx(Button, { variant: "primary", type: "button", onClick: () => downloadText(YamlFile.createInfoYaml(rows, metadata)), disabled: !validation.allRowsHaveDtt || !validation.allRowsHavePaths || !validation.isEmailValid, className: "align-items-center d-flex", children: _jsx(Download, {}) }) }))] })] }));
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function RequestEmailInput(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { FormControl, InputGroup, OverlayTrigger, Tooltip } from "react-bootstrap";
|
|
3
|
+
import { useRequest } from "../providers/RequestProvider";
|
|
4
|
+
export function RequestEmailInput() {
|
|
5
|
+
const { contactEmails, setContactEmails, showErrors, validation } = useRequest();
|
|
6
|
+
return (_jsxs(InputGroup, { hasValidation: true, className: "mt-1", children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Email address(es) to notify (comma-separated)" }), children: _jsx(InputGroup.Text, { children: "Email(s)" }) }), _jsx(FormControl, { value: contactEmails.join(", "), onChange: (event) => setContactEmails(event.target.value.split(/[\s,]+/).filter(Boolean)), isInvalid: showErrors && !validation.isEmailValid, placeholder: "name@example.com" }), _jsx(FormControl.Feedback, { type: "invalid", children: "Please enter valid email addresses" })] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
hideDownloadButtons: boolean;
|
|
3
|
+
hideUploadButtons: boolean;
|
|
4
|
+
variablesPath: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function RequestRow({ hideDownloadButtons, hideUploadButtons, variablesPath }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Col, OverlayTrigger, Popover, Row } from "react-bootstrap";
|
|
3
|
+
import { InfoCircle } from "react-bootstrap-icons";
|
|
4
|
+
import { StrippingLineInfo } from "./StrippingLineInfo";
|
|
5
|
+
import { DeleteButton } from "./DeleteButton";
|
|
6
|
+
import { DttNameInput } from "./DttNameInput";
|
|
7
|
+
import { useMetadata } from "../providers/MetadataProvider";
|
|
8
|
+
import { useRows } from "../providers/RowsProvider";
|
|
9
|
+
import { BookkeepingPathDropdown } from "./BookkeepingPathDropdown";
|
|
10
|
+
import { StrippingLineDropdown } from "./StrippingLineDropdown";
|
|
11
|
+
import { useRow } from "../providers/RowProvider";
|
|
12
|
+
export function RequestRow({ hideDownloadButtons, hideUploadButtons, variablesPath }) {
|
|
13
|
+
const metadata = useMetadata();
|
|
14
|
+
const { row } = useRow();
|
|
15
|
+
const { removeRow } = useRows();
|
|
16
|
+
if (!metadata) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
return (_jsxs(Row, { className: "align-items-center", children: [_jsx(Col, { lg: true, children: _jsx(DttNameInput, { row: row, hideDownloadButtons: hideDownloadButtons, hideUploadButtons: hideUploadButtons, variablesPath: variablesPath }) }), _jsx(Col, { lg: true, children: _jsx(StrippingLineDropdown, {}) }), _jsx(Col, { xs: "auto", children: _jsx(OverlayTrigger, { trigger: "click", placement: "right", rootClose: true, overlay: _jsx(Popover, { children: _jsx(Popover.Body, { children: row.lines.map((line) => (_jsx(StrippingLineInfo, { line: line.line, stream: line.stream, versions: line.versions, showLink: true }, line.line))) }) }), children: _jsx(Button, { disabled: row.lines.length === 0, children: _jsx(InfoCircle, {}) }) }) }), _jsx(Col, { children: _jsx(BookkeepingPathDropdown, {}) }), _jsx(Col, { xs: "auto", children: _jsx(DeleteButton, { action: () => removeRow(row.id) }) })] }));
|
|
20
|
+
}
|
|
@@ -9,7 +9,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
9
9
|
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
10
|
* or submit itself to any jurisdiction. *
|
|
11
11
|
\*****************************************************************************/
|
|
12
|
-
import { Badge, OverlayTrigger,
|
|
12
|
+
import { Badge, OverlayTrigger, Tooltip } from "react-bootstrap";
|
|
13
13
|
import { useMetadata } from "../providers/MetadataProvider.js";
|
|
14
14
|
export function StrippingLineBadge({ version, line, stream, showLink }) {
|
|
15
15
|
const metadata = useMetadata();
|
|
@@ -17,7 +17,6 @@ export function StrippingLineBadge({ version, line, stream, showLink }) {
|
|
|
17
17
|
const url = line && metadata && stream
|
|
18
18
|
? metadata.stripping[version][line].url[stream]
|
|
19
19
|
: `http://lhcbdoc.web.cern.ch/lhcbdoc/stripping/config/stripping${version}/index.html`;
|
|
20
|
-
const { description } = metadata ? metadata.strippingHints[version] : { description: _jsx(Spinner, { animation: "border" }) };
|
|
21
20
|
const badgeProps = showLink
|
|
22
21
|
? {
|
|
23
22
|
as: "a",
|
|
@@ -25,5 +24,5 @@ export function StrippingLineBadge({ version, line, stream, showLink }) {
|
|
|
25
24
|
target: "_blank",
|
|
26
25
|
}
|
|
27
26
|
: {};
|
|
28
|
-
return (_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: description }), children: _jsx(Badge, { pill: true, bg: "info", ...badgeProps, children: "S" + version }) }));
|
|
27
|
+
return (_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: metadata ? metadata.strippingHints[version].description : "..." }), children: _jsx(Badge, { pill: true, bg: "info", ...badgeProps, children: "S" + version }) }));
|
|
29
28
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function StrippingLineDropdown(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import Select from "react-select";
|
|
3
|
+
import { useRow } from "../providers/RowProvider";
|
|
4
|
+
import { StrippingLineInfo } from "./StrippingLineInfo";
|
|
5
|
+
import { useRows } from "../providers/RowsProvider";
|
|
6
|
+
import { useCallback, useMemo } from "react";
|
|
7
|
+
export function StrippingLineDropdown() {
|
|
8
|
+
const { row, updateBkPaths } = useRow();
|
|
9
|
+
const { updateRow } = useRows();
|
|
10
|
+
const handleStrippingLineChanged = useCallback((lineOption) => {
|
|
11
|
+
const lines = [
|
|
12
|
+
{
|
|
13
|
+
stream: lineOption.group,
|
|
14
|
+
line: lineOption.value,
|
|
15
|
+
versions: row.decay.lines[`${lineOption.group}/${lineOption.value}`],
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
updateBkPaths(row.paths, lines);
|
|
19
|
+
updateRow(row.id, (r) => ({
|
|
20
|
+
...r,
|
|
21
|
+
lines,
|
|
22
|
+
dtt: r.dtt ? r.dtt.withInputsFromLines(lines) : null,
|
|
23
|
+
}));
|
|
24
|
+
}, [row, updateBkPaths, updateRow]);
|
|
25
|
+
const strippingLineOptions = useMemo(() => {
|
|
26
|
+
const grouped = {};
|
|
27
|
+
Object.entries(row.decay.lines).forEach(([streamLine, versions]) => {
|
|
28
|
+
const [stream, line] = streamLine.split("/");
|
|
29
|
+
grouped[stream] ??= [];
|
|
30
|
+
if (grouped[stream].some((o) => o.value === line))
|
|
31
|
+
return;
|
|
32
|
+
grouped[stream].push({
|
|
33
|
+
value: line,
|
|
34
|
+
group: stream,
|
|
35
|
+
label: _jsx(StrippingLineInfo, { line: line, stream: stream, versions: versions }),
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
return Object.entries(grouped).map(([label, options]) => ({
|
|
39
|
+
label,
|
|
40
|
+
options,
|
|
41
|
+
}));
|
|
42
|
+
}, [row.decay.lines]);
|
|
43
|
+
return (_jsx(Select, { options: strippingLineOptions, value: row.lines.map((l) => ({
|
|
44
|
+
value: l.line,
|
|
45
|
+
group: l.stream,
|
|
46
|
+
label: _jsx(StrippingLineInfo, { line: l.line, stream: l.stream, versions: l.versions, showLink: false }),
|
|
47
|
+
})), placeholder: "Stripping line", onChange: (v) => handleStrippingLineChanged(v), menuPortalTarget: document.body, menuPosition: "fixed", styles: { menuPortal: (b) => ({ ...b, zIndex: 9999 }) } }));
|
|
48
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
interface Props {
|
|
2
2
|
submitLocation: string;
|
|
3
3
|
onClose: (submitted: boolean) => void;
|
|
4
|
-
requestReasonMessage
|
|
5
|
-
csrfToken?: string;
|
|
4
|
+
requestReasonMessage: string;
|
|
6
5
|
}
|
|
7
|
-
export declare function ReasonForRequestModal({ submitLocation, onClose, requestReasonMessage
|
|
6
|
+
export declare function ReasonForRequestModal({ submitLocation, onClose, requestReasonMessage }: Props): import("react/jsx-runtime").JSX.Element;
|
|
8
7
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Alert, Button, FormControl, InputGroup, Modal, OverlayTrigger, Spinner, Tooltip } from "react-bootstrap";
|
|
3
3
|
import { useRequest } from "../../providers/RequestProvider";
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
import { useRows } from "../../providers/RowsProvider";
|
|
6
|
-
export function ReasonForRequestModal({ submitLocation, onClose, requestReasonMessage
|
|
6
|
+
export function ReasonForRequestModal({ submitLocation, onClose, requestReasonMessage }) {
|
|
7
7
|
const { generateAllFiles } = useRows();
|
|
8
8
|
const { productionName, reasonForRequest, setReasonForRequest } = useRequest();
|
|
9
9
|
const [requestLoading, setRequestLoading] = useState(false);
|
|
@@ -19,17 +19,10 @@ export function ReasonForRequestModal({ submitLocation, onClose, requestReasonMe
|
|
|
19
19
|
formData.append("email", localStorage.getItem("email") || "");
|
|
20
20
|
formData.append("name", productionName);
|
|
21
21
|
formData.append("reasonForRequest", reasonForRequest);
|
|
22
|
-
let headers = {};
|
|
23
|
-
if (csrfToken) {
|
|
24
|
-
headers = {
|
|
25
|
-
"X-Csrf-Token": csrfToken,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
22
|
fetch(url, {
|
|
29
23
|
method: "POST",
|
|
30
24
|
body: formData,
|
|
31
25
|
credentials: "include",
|
|
32
|
-
headers: headers,
|
|
33
26
|
})
|
|
34
27
|
.then((response) => {
|
|
35
28
|
if (!response.ok) {
|
|
@@ -45,5 +38,5 @@ export function ReasonForRequestModal({ submitLocation, onClose, requestReasonMe
|
|
|
45
38
|
setRequestLoading(false);
|
|
46
39
|
});
|
|
47
40
|
};
|
|
48
|
-
return (_jsxs(Modal, { show: true, onHide: () => onClose(false), size: "lg", children: [_jsx(Modal.Header, { closeButton: true, children: _jsx(Modal.Title, { children: "Reason for request" }) }), _jsxs(Modal.Body, { children: [_jsx(Alert, { children: requestReasonMessage }), requestError && _jsx(Alert, { variant: "danger", children: requestError }), _jsxs(InputGroup, { hasValidation: true, children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Reason for requesting the chosen ntuples" }), children: _jsx(InputGroup.Text, { children: "Reason for request" }) }), _jsx(FormControl, { as: "textarea", rows: 3, value: reasonForRequest, onChange: (event) => setReasonForRequest(event.target.value), isValid: !!reasonForRequest, placeholder: "I need these ntuples for..." })] })] }), _jsx(Modal.Footer, { children: _jsx(Button, { variant: "primary", onClick: () => submitRequest(submitLocation), children: requestLoading ? _jsx(Spinner, { animation: "border" }) : "Submit" }) })] }));
|
|
41
|
+
return (_jsxs(Modal, { show: true, onHide: () => onClose(false), size: "lg", children: [_jsx(Modal.Header, { closeButton: true, children: _jsx(Modal.Title, { children: "Reason for request" }) }), _jsxs(Modal.Body, { children: [_jsx(Alert, { children: requestReasonMessage }), requestError && _jsx(Alert, { variant: "danger", children: requestError }), _jsxs(InputGroup, { hasValidation: true, children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Reason for requesting the chosen ntuples" }), children: _jsx(InputGroup.Text, { children: "Reason for request" }) }), _jsx(FormControl, { as: "textarea", rows: 3, value: reasonForRequest, onChange: (event) => setReasonForRequest(event.target.value), isValid: !!reasonForRequest, placeholder: "I need these ntuples for..." })] })] }), _jsx(Modal.Footer, { children: _jsx(Button, { variant: "primary", disabled: !reasonForRequest || requestLoading, onClick: () => submitRequest(submitLocation), children: requestLoading ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { animation: "border", size: "sm" }), " Submitting..."] })) : ("Submit request") }) })] }));
|
|
49
42
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RowData } from "../../models/rowData";
|
|
2
2
|
interface Props {
|
|
3
|
-
row: RowData;
|
|
4
3
|
onClose: () => void;
|
|
4
|
+
currentRow?: RowData;
|
|
5
5
|
}
|
|
6
|
-
export declare function UploadDttConfigModal({
|
|
6
|
+
export declare function UploadDttConfigModal({ onClose, currentRow }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
7
7
|
export {};
|
|
@@ -1,35 +1,65 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Button, Form, Modal } from "react-bootstrap";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import { Button, Form, ListGroup, Modal } from "react-bootstrap";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { useMetadata } from "../../providers/MetadataProvider";
|
|
5
5
|
import { useRows } from "../../providers/RowsProvider";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
import { useRequest } from "../../providers/RequestProvider";
|
|
7
|
+
import { parseProductionFiles } from "../../utils/utils";
|
|
8
|
+
export function UploadDttConfigModal({ onClose, currentRow }) {
|
|
9
|
+
const metadata = useMetadata();
|
|
10
|
+
const { setRows, updateRow } = useRows();
|
|
11
|
+
const { setContactEmails } = useRequest();
|
|
12
|
+
const [files, setFiles] = useState([]);
|
|
13
|
+
const [loading, setLoading] = useState(false);
|
|
14
|
+
async function handleImport(metadata) {
|
|
15
|
+
if (files.length === 0) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
setLoading(true);
|
|
19
|
+
const { rows, emails, errors, warnings } = await parseProductionFiles(Array.from(files), metadata);
|
|
20
|
+
setLoading(false);
|
|
21
|
+
if (Object.keys(errors).length > 0) {
|
|
22
|
+
const errorMessages = Object.entries(errors)
|
|
23
|
+
.map(([file, error]) => `${file}: ${error}`)
|
|
24
|
+
.join("\n");
|
|
25
|
+
alert(`Some errors were found while importing the configuration files:\n\n${errorMessages}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
else if (Object.keys(warnings).length > 0) {
|
|
29
|
+
const warningMessages = Object.entries(warnings)
|
|
30
|
+
.map(([file, warning]) => `${file}: ${warning}`)
|
|
31
|
+
.join("\n");
|
|
32
|
+
if (!confirm(`Some warnings were found while importing the configuration files:\n\n${warningMessages}\n\nContinue?`)) {
|
|
12
33
|
return;
|
|
13
34
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
}
|
|
36
|
+
if (currentRow) {
|
|
37
|
+
const importedRow = rows[0];
|
|
38
|
+
const importedConfig = importedRow.dtt.config;
|
|
39
|
+
if (importedConfig.descriptorTemplate === currentRow.decay.descriptors.template) {
|
|
40
|
+
updateRow(currentRow.id, (r) => ({
|
|
41
|
+
...r,
|
|
42
|
+
dtt: importedRow.dtt.withInputsFromLines(currentRow.lines),
|
|
43
|
+
}));
|
|
21
44
|
onClose();
|
|
22
45
|
}
|
|
23
46
|
else {
|
|
24
47
|
alert("Make sure to upload a previously downloaded configuration file for the same decay.");
|
|
25
48
|
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
setRows(rows);
|
|
52
|
+
setContactEmails(emails);
|
|
53
|
+
onClose();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (!metadata) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
return (_jsxs(Modal, { show: true, animation: false, children: [_jsx(Modal.Header, { children: _jsx(Modal.Title, { children: " Upload configuration file " }) }), _jsxs(Modal.Body, { children: [_jsx(Form.Group, { controlId: "formFile2", className: "mb-3", children: _jsx(Form.Control, { type: "file", multiple: !currentRow, accept: ".yaml", onChange: (event) => {
|
|
60
|
+
const files = event.target.files;
|
|
61
|
+
if (files) {
|
|
62
|
+
setFiles(Array.from(files));
|
|
63
|
+
}
|
|
64
|
+
} }) }), files.length > 0 && (_jsx(ListGroup, { children: files.map((file, i) => (_jsx(ListGroup.Item, { children: file.name }, i))) }))] }), _jsxs(Modal.Footer, { children: [_jsx(Button, { variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { disabled: loading, variant: "primary", onClick: () => void handleImport(metadata), children: loading ? "Importing..." : "Import" })] })] }));
|
|
35
65
|
}
|
package/dist/models/bkPath.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export declare class BkPath {
|
|
2
|
+
year: string;
|
|
3
|
+
strippingVersion: string;
|
|
4
|
+
polarity: string | null;
|
|
5
|
+
eventType: string;
|
|
6
|
+
fileName: string;
|
|
4
7
|
constructor(path: string);
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
getFilename(): string;
|
|
9
|
-
getEventType(): string;
|
|
10
|
-
isValid(): boolean;
|
|
8
|
+
private static extractMcParts;
|
|
9
|
+
private static extractLhcbParts;
|
|
10
|
+
private static isValid;
|
|
11
11
|
}
|