lhcb-ntuple-wizard 2.0.2 → 2.0.4
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/dist/components/DttNameInput.d.ts +1 -9
- package/dist/components/DttNameInput.js +9 -4
- package/dist/components/NtupleWizard.d.ts +2 -1
- package/dist/components/NtupleWizard.js +3 -2
- package/dist/components/RequestButtonGroup.d.ts +1 -7
- package/dist/components/RequestButtonGroup.js +3 -1
- package/dist/components/RequestRow.d.ts +1 -7
- package/dist/components/RequestRow.js +2 -2
- package/dist/components/modals/ReasonForRequestModal.d.ts +1 -3
- package/dist/components/modals/ReasonForRequestModal.js +6 -4
- package/dist/components/modals/UploadDttConfigModal.js +6 -17
- package/dist/models/yamlFile.d.ts +14 -0
- package/dist/models/yamlFile.js +15 -14
- package/dist/pages/DecaySearchPage.d.ts +1 -5
- package/dist/pages/DecaySearchPage.js +3 -1
- package/dist/pages/DecayTreeConfigPage.d.ts +1 -5
- package/dist/pages/DecayTreeConfigPage.js +3 -1
- package/dist/pages/RequestPage.d.ts +1 -10
- package/dist/pages/RequestPage.js +33 -35
- package/dist/providers/WizardConfigProvider.d.ts +21 -0
- package/dist/providers/WizardConfigProvider.js +21 -0
- package/dist/utils/utils.d.ts +7 -11
- package/dist/utils/utils.js +474 -476
- package/package.json +1 -1
- package/dist/models/blobFile.d.ts +0 -12
- package/dist/models/blobFile.js +0 -1
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
interface Props {
|
|
3
|
-
row: RowData;
|
|
4
|
-
hideDownloadButtons: boolean;
|
|
5
|
-
hideUploadButtons: boolean;
|
|
6
|
-
variablesPath: string;
|
|
7
|
-
}
|
|
8
|
-
export declare function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, variablesPath }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
-
export {};
|
|
1
|
+
export declare function DttNameInput(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -11,10 +11,15 @@ import { useMetadata } from "../providers/MetadataProvider";
|
|
|
11
11
|
import { downloadText } from "../utils/utils";
|
|
12
12
|
import { YamlFile } from "../models/yamlFile";
|
|
13
13
|
import { UploadDttConfigModal } from "./modals/UploadDttConfigModal";
|
|
14
|
-
|
|
14
|
+
import { VARIABLES_PATH } from "../constants";
|
|
15
|
+
import { useRow } from "../providers/RowProvider";
|
|
16
|
+
import { useWizardConfig } from "../providers/WizardConfigProvider";
|
|
17
|
+
export function DttNameInput() {
|
|
18
|
+
const { row } = useRow();
|
|
15
19
|
const { rows, updateRow } = useRows();
|
|
16
20
|
const navigate = useNavigate();
|
|
17
21
|
const metadata = useMetadata();
|
|
22
|
+
const { basePath, variant } = useWizardConfig();
|
|
18
23
|
const [showUploadModal, setShowUploadModal] = useState(false);
|
|
19
24
|
const [dttName, setDttName] = useState(row.dtt?.getName() || "");
|
|
20
25
|
const [dttNameValid, setDttNameValid] = useState(true);
|
|
@@ -46,7 +51,7 @@ export function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, vari
|
|
|
46
51
|
};
|
|
47
52
|
const handleConfigureDtt = () => {
|
|
48
53
|
updateRow(row.id, (r) => ({ ...r, editTree: true }));
|
|
49
|
-
void navigate(
|
|
54
|
+
void navigate(`${basePath}${VARIABLES_PATH}`);
|
|
50
55
|
};
|
|
51
56
|
const handleDeleteDtt = () => {
|
|
52
57
|
updateRow(row.id, (r) => ({ ...r, dtt: null }));
|
|
@@ -64,7 +69,7 @@ export function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, vari
|
|
|
64
69
|
? "Name cannot be empty"
|
|
65
70
|
: !allNameCharsValid(dttName.trim())
|
|
66
71
|
? "Name contains invalid characters"
|
|
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, {}) }) }),
|
|
72
|
+
: "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, {}) }) }), variant === "standalone" && (_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: () => {
|
|
68
73
|
downloadText(YamlFile.fromDtt(row.dtt));
|
|
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, {}) }) }),
|
|
74
|
+
}, 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, {}) }) }), variant === "standalone" && (_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 }) })] }));
|
|
70
75
|
}
|
|
@@ -16,6 +16,7 @@ interface Props {
|
|
|
16
16
|
submitLocation?: string;
|
|
17
17
|
requestReasonMessage?: string;
|
|
18
18
|
requestSubmittedMessage?: ReactNode;
|
|
19
|
+
onRequestSubmitted?: () => void;
|
|
19
20
|
}
|
|
20
|
-
export declare function NtupleWizard({ basePath, contactEmail, submitLocation, requestReasonMessage, requestSubmittedMessage, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare function NtupleWizard({ basePath, contactEmail, submitLocation, requestReasonMessage, requestSubmittedMessage, onRequestSubmitted, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
21
22
|
export {};
|
|
@@ -19,10 +19,11 @@ import { MathJaxContext } from "better-react-mathjax";
|
|
|
19
19
|
import { RowsProvider } from "../providers/RowsProvider.js";
|
|
20
20
|
import { RequestProvider } from "../providers/RequestProvider";
|
|
21
21
|
import { SELECT_DECAYS_PATH, VARIABLES_PATH } from "../constants";
|
|
22
|
-
|
|
22
|
+
import { WizardConfigProvider } from "../providers/WizardConfigProvider";
|
|
23
|
+
export function NtupleWizard({ basePath = "", contactEmail, submitLocation, requestReasonMessage, requestSubmittedMessage, onRequestSubmitted, }) {
|
|
23
24
|
const { pathname } = useLocation();
|
|
24
25
|
if (contactEmail) {
|
|
25
26
|
localStorage.setItem("email", contactEmail);
|
|
26
27
|
}
|
|
27
|
-
return (_jsx(MetadataProvider, { children: _jsx(RowsProvider, { children: _jsx(RequestProvider, { emailIsKnown: !!contactEmail, children: _jsx(MathJaxContext, { children: pathname.endsWith(SELECT_DECAYS_PATH) ? (_jsx(DecaySearchPage, {
|
|
28
|
+
return (_jsx(MetadataProvider, { children: _jsx(WizardConfigProvider, { basePath: basePath, submitLocation: submitLocation, requestReasonMessage: requestReasonMessage, requestSubmittedMessage: requestSubmittedMessage, onRequestSubmitted: onRequestSubmitted, children: _jsx(RowsProvider, { children: _jsx(RequestProvider, { emailIsKnown: !!contactEmail, children: _jsx(MathJaxContext, { children: pathname.endsWith(SELECT_DECAYS_PATH) ? (_jsx(DecaySearchPage, {})) : pathname.endsWith(VARIABLES_PATH) ? (_jsx(DecayTreeConfigPage, {})) : (_jsx(RequestPage, {})) }) }) }) }) }));
|
|
28
29
|
}
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
|
|
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 {};
|
|
1
|
+
export declare function RequestButtonGroup(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -10,7 +10,9 @@ import { useRows } from "../providers/RowsProvider";
|
|
|
10
10
|
import { useMetadata } from "../providers/MetadataProvider";
|
|
11
11
|
import { useRequest } from "../providers/RequestProvider";
|
|
12
12
|
import { useState } from "react";
|
|
13
|
-
|
|
13
|
+
import { useWizardConfig } from "../providers/WizardConfigProvider";
|
|
14
|
+
export function RequestButtonGroup() {
|
|
15
|
+
const { variant, basePath } = useWizardConfig();
|
|
14
16
|
const metadata = useMetadata();
|
|
15
17
|
const { validation } = useRequest();
|
|
16
18
|
const { rows, configuredRows, setRows } = useRows();
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
|
|
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 {};
|
|
1
|
+
export declare function RequestRow(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -9,12 +9,12 @@ import { useRows } from "../providers/RowsProvider";
|
|
|
9
9
|
import { BookkeepingPathDropdown } from "./BookkeepingPathDropdown";
|
|
10
10
|
import { StrippingLineDropdown } from "./StrippingLineDropdown";
|
|
11
11
|
import { useRow } from "../providers/RowProvider";
|
|
12
|
-
export function RequestRow(
|
|
12
|
+
export function RequestRow() {
|
|
13
13
|
const metadata = useMetadata();
|
|
14
14
|
const { row } = useRow();
|
|
15
15
|
const { removeRow } = useRows();
|
|
16
16
|
if (!metadata) {
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
|
-
return (_jsxs(Row, { className: "align-items-center", children: [_jsx(Col, { lg: true, children: _jsx(DttNameInput, {
|
|
19
|
+
return (_jsxs(Row, { className: "align-items-center", children: [_jsx(Col, { lg: true, children: _jsx(DttNameInput, {}) }), _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
20
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
interface Props {
|
|
2
|
-
submitLocation: string;
|
|
3
2
|
onClose: (submitted: boolean) => void;
|
|
4
|
-
requestReasonMessage: string;
|
|
5
3
|
}
|
|
6
|
-
export declare function ReasonForRequestModal({
|
|
4
|
+
export declare function ReasonForRequestModal({ onClose }: Props): import("react/jsx-runtime").JSX.Element;
|
|
7
5
|
export {};
|
|
@@ -3,12 +3,14 @@ import { Alert, Button, FormControl, InputGroup, Modal, OverlayTrigger, Spinner,
|
|
|
3
3
|
import { useRequest } from "../../providers/RequestProvider";
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
import { useRows } from "../../providers/RowsProvider";
|
|
6
|
-
|
|
6
|
+
import { useWizardConfig } from "../../providers/WizardConfigProvider";
|
|
7
|
+
export function ReasonForRequestModal({ onClose }) {
|
|
7
8
|
const { generateAllFiles } = useRows();
|
|
8
9
|
const { productionName, reasonForRequest, setReasonForRequest } = useRequest();
|
|
10
|
+
const { requestReasonMessage, submitLocation } = useWizardConfig();
|
|
9
11
|
const [requestLoading, setRequestLoading] = useState(false);
|
|
10
12
|
const [requestError, setRequestError] = useState(null);
|
|
11
|
-
const submitRequest = (
|
|
13
|
+
const submitRequest = () => {
|
|
12
14
|
setRequestLoading(true);
|
|
13
15
|
setRequestError(null);
|
|
14
16
|
const allFiles = generateAllFiles();
|
|
@@ -19,7 +21,7 @@ export function ReasonForRequestModal({ submitLocation, onClose, requestReasonMe
|
|
|
19
21
|
formData.append("email", localStorage.getItem("email") || "");
|
|
20
22
|
formData.append("name", productionName);
|
|
21
23
|
formData.append("reasonForRequest", reasonForRequest);
|
|
22
|
-
fetch(
|
|
24
|
+
fetch(submitLocation, {
|
|
23
25
|
method: "POST",
|
|
24
26
|
body: formData,
|
|
25
27
|
credentials: "include",
|
|
@@ -38,5 +40,5 @@ export function ReasonForRequestModal({ submitLocation, onClose, requestReasonMe
|
|
|
38
40
|
setRequestLoading(false);
|
|
39
41
|
});
|
|
40
42
|
};
|
|
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:
|
|
43
|
+
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, children: requestLoading ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { animation: "border", size: "sm" }), " Submitting..."] })) : ("Submit request") }) })] }));
|
|
42
44
|
}
|
|
@@ -16,25 +16,14 @@ export function UploadDttConfigModal({ onClose, currentRow }) {
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
setLoading(true);
|
|
19
|
-
const
|
|
19
|
+
const result = await parseProductionFiles(Array.from(files), metadata);
|
|
20
20
|
setLoading(false);
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
.map(([file, error]) => `${file}: ${error}`)
|
|
24
|
-
.join("\n");
|
|
25
|
-
alert(`Some errors were found while importing the configuration files:\n\n${errorMessages}`);
|
|
21
|
+
if (typeof result === "string") {
|
|
22
|
+
alert(result);
|
|
26
23
|
return;
|
|
27
24
|
}
|
|
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?`)) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
25
|
if (currentRow) {
|
|
37
|
-
const importedRow = rows[0];
|
|
26
|
+
const importedRow = result.rows[0];
|
|
38
27
|
const importedConfig = importedRow.dtt.config;
|
|
39
28
|
if (importedConfig.descriptorTemplate === currentRow.decay.descriptors.template) {
|
|
40
29
|
updateRow(currentRow.id, (r) => ({
|
|
@@ -48,8 +37,8 @@ export function UploadDttConfigModal({ onClose, currentRow }) {
|
|
|
48
37
|
}
|
|
49
38
|
}
|
|
50
39
|
else {
|
|
51
|
-
setRows(rows);
|
|
52
|
-
setContactEmails(emails);
|
|
40
|
+
setRows(result.rows);
|
|
41
|
+
setContactEmails(result.emails);
|
|
53
42
|
onClose();
|
|
54
43
|
}
|
|
55
44
|
}
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import Dtt from "./dtt";
|
|
2
2
|
import { RowData } from "./rowData";
|
|
3
3
|
import { MetadataContext } from "../providers/MetadataProvider";
|
|
4
|
+
import { JobConfig } from "./jobConfig";
|
|
5
|
+
interface InfoYamlDefaults {
|
|
6
|
+
application: string;
|
|
7
|
+
wg: string;
|
|
8
|
+
inform: string[];
|
|
9
|
+
automatically_configure: boolean;
|
|
10
|
+
output: string;
|
|
11
|
+
}
|
|
12
|
+
export type InfoYaml = {
|
|
13
|
+
defaults: InfoYamlDefaults;
|
|
14
|
+
} & {
|
|
15
|
+
[K in string as K extends "defaults" ? never : K]?: JobConfig;
|
|
16
|
+
};
|
|
4
17
|
export declare class YamlFile {
|
|
5
18
|
name: string;
|
|
6
19
|
content: string;
|
|
@@ -8,3 +21,4 @@ export declare class YamlFile {
|
|
|
8
21
|
static fromDtt(dtt: Dtt): YamlFile;
|
|
9
22
|
static createInfoYaml(rows: RowData[], metadata: MetadataContext): YamlFile;
|
|
10
23
|
}
|
|
24
|
+
export {};
|
package/dist/models/yamlFile.js
CHANGED
|
@@ -14,15 +14,7 @@ export class YamlFile {
|
|
|
14
14
|
const uniquePathSet = new Set(rows.flatMap((row) => row.paths));
|
|
15
15
|
const uniquePaths = [...uniquePathSet].sort();
|
|
16
16
|
const pathIndex = new Map(uniquePaths.map((p, i) => [p, i]));
|
|
17
|
-
const
|
|
18
|
-
defaults: {
|
|
19
|
-
application: `DaVinci/${metadata.tupleTools.applicationInfo.DaVinci}`,
|
|
20
|
-
wg: "OpenData",
|
|
21
|
-
inform: [],
|
|
22
|
-
automatically_configure: true,
|
|
23
|
-
output: "DVNtuple.root",
|
|
24
|
-
},
|
|
25
|
-
};
|
|
17
|
+
const jobs = {};
|
|
26
18
|
for (const row of rows) {
|
|
27
19
|
if (!row.dtt)
|
|
28
20
|
continue;
|
|
@@ -32,8 +24,8 @@ export class YamlFile {
|
|
|
32
24
|
continue;
|
|
33
25
|
const key = `job${jobID}`;
|
|
34
26
|
const dttFile = row.dtt.getName();
|
|
35
|
-
if (key
|
|
36
|
-
|
|
27
|
+
if (jobs[key]) {
|
|
28
|
+
jobs[key].options.push(dttFile);
|
|
37
29
|
}
|
|
38
30
|
else {
|
|
39
31
|
const job = {
|
|
@@ -42,14 +34,23 @@ export class YamlFile {
|
|
|
42
34
|
};
|
|
43
35
|
if (path.includes("MDST")) {
|
|
44
36
|
const stream = row.lines[0]?.stream;
|
|
45
|
-
if (stream)
|
|
37
|
+
if (stream)
|
|
46
38
|
job.root_in_tes = `/Event/${stream}`;
|
|
47
|
-
}
|
|
48
39
|
}
|
|
49
|
-
|
|
40
|
+
jobs[key] = job;
|
|
50
41
|
}
|
|
51
42
|
}
|
|
52
43
|
}
|
|
44
|
+
const info = {
|
|
45
|
+
defaults: {
|
|
46
|
+
application: `DaVinci/${metadata.tupleTools.applicationInfo.DaVinci}`,
|
|
47
|
+
wg: "OpenData",
|
|
48
|
+
inform: [],
|
|
49
|
+
automatically_configure: true,
|
|
50
|
+
output: "DVNtuple.root",
|
|
51
|
+
},
|
|
52
|
+
...jobs,
|
|
53
|
+
};
|
|
53
54
|
return new YamlFile("info.yaml", yaml.dump(info));
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -20,6 +20,7 @@ import { ParticleDropdown } from "../components/ParticleDropdown";
|
|
|
20
20
|
import { getSelectTagOptions, TagDropdown } from "../components/TagDropdown";
|
|
21
21
|
import { useRows } from "../providers/RowsProvider";
|
|
22
22
|
import { LoadingIndicator } from "../components/LoadingIndicator";
|
|
23
|
+
import { useWizardConfig } from "../providers/WizardConfigProvider";
|
|
23
24
|
var MatchType;
|
|
24
25
|
(function (MatchType) {
|
|
25
26
|
MatchType["any"] = "any";
|
|
@@ -31,9 +32,10 @@ var HeadMatchType;
|
|
|
31
32
|
HeadMatchType["exactly"] = "exactly";
|
|
32
33
|
HeadMatchType["category"] = "category";
|
|
33
34
|
})(HeadMatchType || (HeadMatchType = {}));
|
|
34
|
-
export function DecaySearchPage(
|
|
35
|
+
export function DecaySearchPage() {
|
|
35
36
|
const metadata = useMetadata();
|
|
36
37
|
const { rows, setRows } = useRows();
|
|
38
|
+
const { basePath } = useWizardConfig();
|
|
37
39
|
const [selectedContains, setSelectedContains] = useState([]);
|
|
38
40
|
const [selectedHead, setSelectedHead] = useState(null);
|
|
39
41
|
const [selectedHeadTags, setSelectedHeadTags] = useState([]);
|
|
@@ -18,10 +18,12 @@ import Dtt from "../models/dtt";
|
|
|
18
18
|
import { DttProvider } from "../providers/DttProvider";
|
|
19
19
|
import { LoadingIndicator } from "../components/LoadingIndicator";
|
|
20
20
|
import { useEffect, useState } from "react";
|
|
21
|
-
|
|
21
|
+
import { useWizardConfig } from "../providers/WizardConfigProvider";
|
|
22
|
+
export function DecayTreeConfigPage() {
|
|
22
23
|
const navigate = useNavigate();
|
|
23
24
|
const metadata = useMetadata();
|
|
24
25
|
const { rows, updateRow } = useRows();
|
|
26
|
+
const { basePath } = useWizardConfig();
|
|
25
27
|
const [dirtyDtts, setDirtyDtts] = useState(new Set());
|
|
26
28
|
// Listen for when the user is about to leave the page and alert them if there are unsaved changes
|
|
27
29
|
useEffect(() => {
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export type NtupleWizardVariant = "standalone" | "embedded";
|
|
3
|
-
interface Props {
|
|
4
|
-
basePath: string;
|
|
5
|
-
submitLocation?: string;
|
|
6
|
-
requestReasonMessage?: string;
|
|
7
|
-
requestSubmittedMessage?: ReactNode;
|
|
8
|
-
}
|
|
9
|
-
export declare function RequestPage({ basePath, submitLocation, requestReasonMessage, requestSubmittedMessage }: Props): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
export {};
|
|
1
|
+
export declare function RequestPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -9,12 +9,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
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 yaml from "js-yaml";
|
|
13
12
|
import { useEffect, useState } from "react";
|
|
14
13
|
import { Alert, Button, Col, Row, Stack } from "react-bootstrap";
|
|
15
14
|
import { Download, Send } from "react-bootstrap-icons";
|
|
16
15
|
import { useLocation } from "react-router-dom";
|
|
17
|
-
import { downloadZip,
|
|
16
|
+
import { downloadZip, processProductionFiles } from "../utils/utils";
|
|
18
17
|
import { DeleteButton } from "../components/DeleteButton";
|
|
19
18
|
import { useMetadata } from "../providers/MetadataProvider";
|
|
20
19
|
import { ConfigFilesUploadingAlert } from "../components/ConfigFilesUploadingAlert";
|
|
@@ -23,56 +22,54 @@ import { useRequest } from "../providers/RequestProvider";
|
|
|
23
22
|
import { LoadingIndicator } from "../components/LoadingIndicator";
|
|
24
23
|
import { RequestRow } from "../components/RequestRow";
|
|
25
24
|
import { UploadDttConfigModal } from "../components/modals/UploadDttConfigModal";
|
|
26
|
-
import { VARIABLES_PATH } from "../constants";
|
|
27
25
|
import { ReasonForRequestModal } from "../components/modals/ReasonForRequestModal";
|
|
28
26
|
import { RowProvider } from "../providers/RowProvider";
|
|
29
27
|
import { ProductionNameInput } from "../components/ProductionNameInput";
|
|
30
28
|
import { RequestEmailInput } from "../components/RequestEmailInput";
|
|
31
29
|
import { RequestButtonGroup } from "../components/RequestButtonGroup";
|
|
32
|
-
|
|
30
|
+
import { useWizardConfig } from "../providers/WizardConfigProvider";
|
|
31
|
+
export function RequestPage() {
|
|
33
32
|
const location = useLocation();
|
|
34
33
|
const metadata = useMetadata();
|
|
35
34
|
const { rows, setRows, generateAllFiles } = useRows();
|
|
36
|
-
const { emailIsKnown, productionName, validation, showErrors, clearAll, trySubmit } = useRequest();
|
|
35
|
+
const { emailIsKnown, productionName, setProductionName, validation, showErrors, clearAll, trySubmit } = useRequest();
|
|
36
|
+
const { variant, requestSubmittedMessage, onRequestSubmitted } = useWizardConfig();
|
|
37
37
|
const [showProdUploadModal, setShowProdUploadModal] = useState(false);
|
|
38
38
|
const [prodUploadLoading, setProdUploadLoading] = useState(false);
|
|
39
39
|
const [requestSubmitted, setRequestSubmitted] = useState(false);
|
|
40
40
|
const [showReasonForRequestModal, setShowReasonForRequestModal] = useState(false);
|
|
41
|
-
const variant = submitLocation ? "embedded" : "standalone";
|
|
42
41
|
useEffect(() => {
|
|
43
42
|
if (!metadata) {
|
|
44
43
|
return;
|
|
45
44
|
}
|
|
46
45
|
const urlParams = new URLSearchParams(location.search);
|
|
47
46
|
if (urlParams.get("clone") === "1") {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
47
|
+
const infoYamlString = localStorage.getItem("infoYamlToClone");
|
|
48
|
+
const dttConfigsString = localStorage.getItem("dttConfigsToClone");
|
|
49
|
+
if (!dttConfigsString) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
setProdUploadLoading(true);
|
|
53
|
+
setRows([]);
|
|
54
|
+
try {
|
|
55
|
+
const infoYaml = infoYamlString ? JSON.parse(infoYamlString) : null;
|
|
56
|
+
const dttConfigs = JSON.parse(dttConfigsString);
|
|
57
|
+
const result = processProductionFiles(metadata, dttConfigs, infoYaml);
|
|
58
|
+
if (typeof result === "string") {
|
|
59
|
+
// Show the error message
|
|
60
|
+
alert(result);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
setRows(result.rows);
|
|
64
|
+
setProductionName("");
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
setProdUploadLoading(false);
|
|
68
|
+
localStorage.removeItem("infoYamlToClone");
|
|
69
|
+
localStorage.removeItem("dttConfigsToClone");
|
|
67
70
|
}
|
|
68
|
-
const { rows } = await parseProductionFiles(yamlFiles, metadata);
|
|
69
|
-
setRows(rows);
|
|
70
|
-
}
|
|
71
|
-
finally {
|
|
72
|
-
setProdUploadLoading(false);
|
|
73
|
-
localStorage.removeItem("yamlFilesToClone");
|
|
74
71
|
}
|
|
75
|
-
}
|
|
72
|
+
}, [metadata, location.search]);
|
|
76
73
|
const handlePrimaryAction = async () => {
|
|
77
74
|
if (trySubmit()) {
|
|
78
75
|
if (variant === "standalone") {
|
|
@@ -90,16 +87,17 @@ export function RequestPage({ basePath, submitLocation, requestReasonMessage, re
|
|
|
90
87
|
if (requestSubmitted) {
|
|
91
88
|
return (_jsx(Row, { className: "mt-3", children: _jsx(Col, { children: _jsxs(Alert, { variant: "success", dismissible: true, onClose: () => setRequestSubmitted(false), children: [_jsx(Alert.Heading, { children: "Request submitted!" }), requestSubmittedMessage] }) }) }));
|
|
92
89
|
}
|
|
93
|
-
return (_jsxs(_Fragment, { children: [showReasonForRequestModal && (_jsx(ReasonForRequestModal, {
|
|
90
|
+
return (_jsxs(_Fragment, { children: [showReasonForRequestModal && (_jsx(ReasonForRequestModal, { onClose: (submitted) => {
|
|
94
91
|
setShowReasonForRequestModal(false);
|
|
95
92
|
if (submitted) {
|
|
96
93
|
setRequestSubmitted(true);
|
|
94
|
+
onRequestSubmitted?.();
|
|
97
95
|
}
|
|
98
|
-
} })), showProdUploadModal && _jsx(UploadDttConfigModal, { onClose: () => setShowProdUploadModal(false) }), _jsxs("div", { className: "d-flex flex-column gap-3", children: [rows.map((row) => (_jsx(RowProvider, { row: row, children: _jsx(RequestRow, {
|
|
96
|
+
} })), showProdUploadModal && _jsx(UploadDttConfigModal, { onClose: () => setShowProdUploadModal(false) }), _jsxs("div", { className: "d-flex flex-column gap-3", children: [rows.map((row) => (_jsx(RowProvider, { row: row, children: _jsx(RequestRow, {}, row.id) }, row.id))), prodUploadLoading && _jsx(ConfigFilesUploadingAlert, {}), showErrors &&
|
|
99
97
|
(rows.length === 0 ||
|
|
100
98
|
!validation.allRowsHaveDtt ||
|
|
101
99
|
!validation.allRowsHaveStrippingLine ||
|
|
102
100
|
!validation.allRowsHavePaths) && (_jsx(Alert, { variant: "danger", className: "mb-0", children: rows.length === 0
|
|
103
101
|
? "Please select at least one decay"
|
|
104
|
-
: "Please name all DecayTreeTuples and select at least one stripping line and bookkeeping path for each decay" })), _jsx(Row, { children: _jsx(Col, { xs: "auto", children: _jsx(RequestButtonGroup, {
|
|
102
|
+
: "Please name all DecayTreeTuples and select at least one stripping line and bookkeeping path for each decay" })), _jsx(Row, { children: _jsx(Col, { xs: "auto", children: _jsx(RequestButtonGroup, {}) }) }), _jsx(Row, { children: _jsxs(Col, { xs: 4, children: [_jsx(ProductionNameInput, {}), !emailIsKnown && _jsx(RequestEmailInput, {}), _jsxs(Stack, { direction: "horizontal", gap: 1, className: "mt-3 mb-3", children: [_jsxs(Button, { className: "align-items-center d-flex gap-1", onClick: () => void handlePrimaryAction(), children: [variant === "standalone" ? _jsx(Download, {}) : _jsx(Send, {}), variant === "standalone" ? "Download" : "Submit"] }), _jsx(DeleteButton, { action: clearAll, disabled: validation.isEmptySession, outline: undefined, children: "Clear all" })] })] }) })] })] }));
|
|
105
103
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
type NtupleWizardVariant = "standalone" | "embedded";
|
|
3
|
+
interface WizardConfigContextType {
|
|
4
|
+
variant: NtupleWizardVariant;
|
|
5
|
+
basePath: string;
|
|
6
|
+
submitLocation?: string;
|
|
7
|
+
requestReasonMessage?: string;
|
|
8
|
+
requestSubmittedMessage?: ReactNode;
|
|
9
|
+
onRequestSubmitted?: () => void;
|
|
10
|
+
}
|
|
11
|
+
interface WizardConfigProviderProps {
|
|
12
|
+
basePath: string;
|
|
13
|
+
submitLocation?: string;
|
|
14
|
+
requestReasonMessage?: string;
|
|
15
|
+
requestSubmittedMessage?: ReactNode;
|
|
16
|
+
onRequestSubmitted?: () => void;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
export declare const WizardConfigProvider: ({ basePath, submitLocation, requestReasonMessage, requestSubmittedMessage, onRequestSubmitted, children, }: WizardConfigProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare const useWizardConfig: () => WizardConfigContextType;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
const WizardConfigContext = createContext(null);
|
|
4
|
+
export const WizardConfigProvider = ({ basePath, submitLocation, requestReasonMessage, requestSubmittedMessage, onRequestSubmitted, children, }) => {
|
|
5
|
+
const variant = submitLocation ? "embedded" : "standalone";
|
|
6
|
+
return (_jsx(WizardConfigContext.Provider, { value: {
|
|
7
|
+
variant,
|
|
8
|
+
basePath,
|
|
9
|
+
submitLocation,
|
|
10
|
+
requestReasonMessage,
|
|
11
|
+
requestSubmittedMessage,
|
|
12
|
+
onRequestSubmitted,
|
|
13
|
+
}, children: children }));
|
|
14
|
+
};
|
|
15
|
+
export const useWizardConfig = () => {
|
|
16
|
+
const ctx = useContext(WizardConfigContext);
|
|
17
|
+
if (!ctx) {
|
|
18
|
+
throw new Error("useWizardConfig must be used within a WizardConfigProvider");
|
|
19
|
+
}
|
|
20
|
+
return ctx;
|
|
21
|
+
};
|
package/dist/utils/utils.d.ts
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
import { YamlFile } from "../models/yamlFile";
|
|
2
|
-
import {
|
|
1
|
+
import { InfoYaml, YamlFile } from "../models/yamlFile";
|
|
2
|
+
import { SavedDttConfig } from "../models/dtt";
|
|
3
3
|
import { RowData } from "../models/rowData";
|
|
4
4
|
import { MetadataContext } from "../providers/MetadataProvider";
|
|
5
|
-
|
|
6
|
-
* Parses a set of production configuration files to DttConfigs and returns the corresponding rows and emails.
|
|
7
|
-
* @param files The files to parse
|
|
8
|
-
* @param metadata The metadata to use for parsing
|
|
9
|
-
* @returns The parsed rows and emails
|
|
10
|
-
*/
|
|
11
|
-
export declare const parseProductionFiles: (files: (BlobFile | File)[], metadata: MetadataContext) => Promise<{
|
|
5
|
+
export declare function parseProductionFiles(files: File[], metadata: MetadataContext): Promise<string | {
|
|
12
6
|
rows: RowData[];
|
|
13
7
|
emails: string[];
|
|
14
|
-
errors: Record<string, string>;
|
|
15
|
-
warnings: Record<string, string>;
|
|
16
8
|
}>;
|
|
9
|
+
export declare function processProductionFiles(metadata: MetadataContext, configs: SavedDttConfig[], infoYaml: InfoYaml | null): string | {
|
|
10
|
+
rows: RowData[];
|
|
11
|
+
emails: string[];
|
|
12
|
+
};
|
|
17
13
|
/**
|
|
18
14
|
* Sanitizes a user-provided filename to prevent path traversal (Zip Slip)
|
|
19
15
|
* and unsafe filesystem characters.
|