lhcb-ntuple-wizard-test 2.0.0 → 2.0.1
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/App.d.ts +12 -0
- package/dist/App.js +22 -0
- package/dist/components/ConfigFilesUploadingAlert.d.ts +1 -0
- package/dist/components/ConfigFilesUploadingAlert.js +5 -0
- package/dist/components/DatasetEventTypeBadge.d.ts +5 -0
- package/dist/components/DatasetEventTypeBadge.js +23 -0
- package/dist/components/DatasetInfo.d.ts +5 -0
- package/dist/components/DatasetInfo.js +21 -0
- package/dist/components/DecayLatex.d.ts +7 -0
- package/dist/components/DecayLatex.js +103 -0
- package/dist/components/DecayList.d.ts +8 -0
- package/dist/components/DecayList.js +37 -0
- package/dist/components/DecayListItem.d.ts +11 -0
- package/dist/components/DecayListItem.js +23 -0
- package/dist/components/DecayTagBadge.d.ts +5 -0
- package/dist/components/DecayTagBadge.js +21 -0
- package/dist/components/DecayTreeCard.d.ts +7 -0
- package/dist/components/DecayTreeCard.js +43 -0
- package/dist/components/DecayTreeCardHeader.d.ts +7 -0
- package/dist/components/DecayTreeCardHeader.js +5 -0
- package/dist/components/DecayTreeGraph.d.ts +9 -0
- package/dist/components/DecayTreeGraph.js +89 -0
- package/dist/components/DeleteButton.d.ts +9 -0
- package/dist/components/DeleteButton.js +19 -0
- package/dist/components/DttNameInput.d.ts +9 -0
- package/dist/components/DttNameInput.js +73 -0
- package/dist/components/LineTableRow.d.ts +9 -0
- package/dist/components/LineTableRow.js +123 -0
- package/dist/components/LoadingIndicator.d.ts +6 -0
- package/dist/components/LoadingIndicator.js +5 -0
- package/dist/components/NtupleWizard.d.ts +26 -0
- package/dist/components/NtupleWizard.js +33 -0
- package/dist/components/NumStrippingLinesBadge.d.ts +8 -0
- package/dist/components/NumStrippingLinesBadge.js +10 -0
- package/dist/components/ParticleDropdown.d.ts +8 -0
- package/dist/components/ParticleDropdown.js +33 -0
- package/dist/components/ParticleTagBadge.d.ts +9 -0
- package/dist/components/ParticleTagBadge.js +22 -0
- package/dist/components/ParticleTagFilters.d.ts +6 -0
- package/dist/components/ParticleTagFilters.js +51 -0
- package/dist/components/PolarityBadge.d.ts +5 -0
- package/dist/components/PolarityBadge.js +15 -0
- package/dist/components/StrippingLineBadge.d.ts +7 -0
- package/dist/components/StrippingLineBadge.js +29 -0
- package/dist/components/StrippingLineInfo.d.ts +8 -0
- package/dist/components/StrippingLineInfo.js +17 -0
- package/dist/components/SubmitRequestButton.d.ts +11 -0
- package/dist/components/SubmitRequestButton.js +39 -0
- package/dist/components/TagDropdown.d.ts +12 -0
- package/dist/components/TagDropdown.js +31 -0
- package/dist/components/TupleToolDocsAccordion.d.ts +5 -0
- package/dist/components/TupleToolDocsAccordion.js +14 -0
- package/dist/components/TupleToolDropdown.d.ts +21 -0
- package/dist/components/TupleToolDropdown.js +29 -0
- package/dist/components/TupleToolGroup.d.ts +6 -0
- package/dist/components/TupleToolGroup.js +22 -0
- package/dist/components/TupleToolLabel.d.ts +6 -0
- package/dist/components/TupleToolLabel.js +20 -0
- package/dist/components/TupleToolList.d.ts +7 -0
- package/dist/components/TupleToolList.js +38 -0
- package/dist/components/YearBadge.d.ts +5 -0
- package/dist/components/YearBadge.js +15 -0
- package/dist/components/modals/AddTupleToolModal.d.ts +7 -0
- package/dist/components/modals/AddTupleToolModal.js +32 -0
- package/dist/components/modals/ConfigureTupleToolModal.d.ts +8 -0
- package/dist/components/modals/ConfigureTupleToolModal.js +43 -0
- package/dist/components/modals/ReasonForRequestModal.d.ts +8 -0
- package/dist/components/modals/ReasonForRequestModal.js +49 -0
- package/dist/components/modals/UploadDttConfigModal.d.ts +7 -0
- package/dist/components/modals/UploadDttConfigModal.js +35 -0
- package/dist/components/modals/UploadProdConfigModal.d.ts +5 -0
- package/dist/components/modals/UploadProdConfigModal.js +27 -0
- package/dist/components/tupleToolParams/BoolParamInput.d.ts +16 -0
- package/dist/components/tupleToolParams/BoolParamInput.js +15 -0
- package/dist/components/tupleToolParams/DictParamInput.d.ts +14 -0
- package/dist/components/tupleToolParams/DictParamInput.js +31 -0
- package/dist/components/tupleToolParams/ListParamInput.d.ts +14 -0
- package/dist/components/tupleToolParams/ListParamInput.js +46 -0
- package/dist/components/tupleToolParams/NumParamInput.d.ts +18 -0
- package/dist/components/tupleToolParams/NumParamInput.js +25 -0
- package/dist/components/tupleToolParams/StrParamInput.d.ts +19 -0
- package/dist/components/tupleToolParams/StrParamInput.js +22 -0
- package/dist/config.d.ts +78 -0
- package/dist/config.js +72 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/models/bkPath.d.ts +11 -0
- package/dist/models/bkPath.js +40 -0
- package/dist/models/blobFile.d.ts +12 -0
- package/dist/models/blobFile.js +1 -0
- package/dist/models/decayData.d.ts +15 -0
- package/dist/models/decayData.js +1 -0
- package/dist/models/dropdownOption.d.ts +5 -0
- package/dist/models/dropdownOption.js +1 -0
- package/dist/models/dtt.d.ts +108 -0
- package/dist/models/dtt.js +149 -0
- package/dist/models/jobConfig.d.ts +7 -0
- package/dist/models/jobConfig.js +1 -0
- package/dist/models/particle.d.ts +12 -0
- package/dist/models/particle.js +1 -0
- package/dist/models/particleTag.d.ts +4 -0
- package/dist/models/particleTag.js +1 -0
- package/dist/models/rowData.d.ts +15 -0
- package/dist/models/rowData.js +1 -0
- package/dist/models/strippingLine.d.ts +5 -0
- package/dist/models/strippingLine.js +1 -0
- package/dist/models/strippingLineOption.d.ts +6 -0
- package/dist/models/strippingLineOption.js +1 -0
- package/dist/models/tupleTool.d.ts +8 -0
- package/dist/models/tupleTool.js +18 -0
- package/dist/models/tupleTreeGraphData.d.ts +20 -0
- package/dist/models/tupleTreeGraphData.js +1 -0
- package/dist/models/yamlFile.d.ts +11 -0
- package/dist/models/yamlFile.js +78 -0
- package/dist/pages/DecaySearchPage.d.ts +5 -0
- package/dist/pages/DecaySearchPage.js +197 -0
- package/dist/pages/DecayTreeConfigPage.d.ts +5 -0
- package/dist/pages/DecayTreeConfigPage.js +63 -0
- package/dist/pages/LinesTablePage.d.ts +14 -0
- package/dist/pages/LinesTablePage.js +120 -0
- package/dist/providers/DttProvider.d.ts +24 -0
- package/dist/providers/DttProvider.js +77 -0
- package/dist/providers/MetadataProvider.d.ts +87 -0
- package/dist/providers/MetadataProvider.js +50 -0
- package/dist/providers/ProductionConfigProvider.d.ts +14 -0
- package/dist/providers/ProductionConfigProvider.js +76 -0
- package/dist/providers/RequestProvider.d.ts +15 -0
- package/dist/providers/RequestProvider.js +35 -0
- package/dist/providers/RowsProvider.d.ts +14 -0
- package/dist/providers/RowsProvider.js +31 -0
- package/dist/utils/mathjaxUtils.d.ts +12 -0
- package/dist/utils/mathjaxUtils.js +24 -0
- package/dist/utils/utils.d.ts +31 -0
- package/dist/utils/utils.js +80 -0
- package/package.json +3 -2
package/dist/App.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*****************************************************************************\
|
|
2
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
3
|
+
* *
|
|
4
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
5
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
6
|
+
* *
|
|
7
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
8
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
9
|
+
* or submit itself to any jurisdiction. *
|
|
10
|
+
\*****************************************************************************/
|
|
11
|
+
import "bootstrap/dist/css/bootstrap.css";
|
|
12
|
+
export declare function App(): import("react/jsx-runtime").JSX.Element;
|
package/dist/App.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************\
|
|
3
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
\*****************************************************************************/
|
|
12
|
+
import "bootstrap/dist/css/bootstrap.css";
|
|
13
|
+
import { Container, Nav, Navbar, NavDropdown } from "react-bootstrap";
|
|
14
|
+
import { Archive, CodeSlash, House } from "react-bootstrap-icons";
|
|
15
|
+
import { config } from "./config";
|
|
16
|
+
import { NtupleWizard } from "./components/NtupleWizard";
|
|
17
|
+
import { BrowserRouter } from "react-router-dom";
|
|
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, { basePath: "/", decaysPath: "/select-decays", variablesPath: "/variables", submitLocation: "" // Leave empty to hide the submit button -> overrides hideDownloadButtons to false
|
|
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." }) }) }) })] }));
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ConfigFilesUploadingAlert(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Alert, Col, Row, Spinner } from "react-bootstrap";
|
|
3
|
+
export function ConfigFilesUploadingAlert() {
|
|
4
|
+
return (_jsx(Alert, { variant: "primary", children: _jsxs(Row, { children: [_jsx(Col, { xs: 1, style: { width: "50px", verticalAlign: "middle" }, children: _jsx(Spinner, { animation: "border", role: "status", className: "mt-1 mb-2" }) }), _jsxs(Col, { children: [_jsx(Alert.Heading, { children: "Uploading configuration files..." }), "Please wait while the cloned configuration files are being uploaded."] })] }) }));
|
|
5
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************\
|
|
3
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
\*****************************************************************************/
|
|
12
|
+
import { Badge } from "react-bootstrap";
|
|
13
|
+
export function DatasetEventTypeBadge({ eventType }) {
|
|
14
|
+
const content = "" + eventType === "90000000" ? "Data" : "" + eventType;
|
|
15
|
+
const linkProps = content === "Data"
|
|
16
|
+
? {}
|
|
17
|
+
: {
|
|
18
|
+
as: "a",
|
|
19
|
+
href: "http://lhcbdoc.web.cern.ch/lhcbdoc/decfiles/",
|
|
20
|
+
target: "_blank",
|
|
21
|
+
};
|
|
22
|
+
return (_jsx(Badge, { pill: true, ...linkProps, bg: "primary", children: content }));
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************\
|
|
3
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
\*****************************************************************************/
|
|
12
|
+
import { Stack } from "react-bootstrap";
|
|
13
|
+
import { YearBadge } from "./YearBadge.js";
|
|
14
|
+
import { PolarityBadge } from "./PolarityBadge.js";
|
|
15
|
+
import { StrippingLineBadge } from "./StrippingLineBadge";
|
|
16
|
+
import { DatasetEventTypeBadge } from "./DatasetEventTypeBadge";
|
|
17
|
+
import BkPath from "../models/bkPath.js";
|
|
18
|
+
export function DatasetInfo({ pathString }) {
|
|
19
|
+
const path = new BkPath(pathString);
|
|
20
|
+
return (_jsxs("span", { children: [path.getFilename(), _jsx("br", {}), _jsxs(Stack, { direction: "horizontal", style: { flexWrap: "wrap" }, gap: 1, children: [_jsx(DatasetEventTypeBadge, { eventType: path.getEventType() }), _jsx(YearBadge, { year: path.getYear() }), _jsx(PolarityBadge, { polarity: path.getPolarity() || "?" }), _jsx(StrippingLineBadge, { version: path.getStrippingVersion() })] })] }));
|
|
21
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************\
|
|
3
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
\*****************************************************************************/
|
|
12
|
+
import { MathJax } from "better-react-mathjax";
|
|
13
|
+
import { OverlayTrigger, Popover } from "react-bootstrap";
|
|
14
|
+
import { useMetadata } from "../providers/MetadataProvider";
|
|
15
|
+
export function DecayLatex({ decay, selection }) {
|
|
16
|
+
const metadata = useMetadata();
|
|
17
|
+
if (!metadata) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const LOKI_MARKERS = {
|
|
21
|
+
SELECTION_PREFIX: "^",
|
|
22
|
+
ARROW: "->",
|
|
23
|
+
};
|
|
24
|
+
const LATEX_COMMANDS = {
|
|
25
|
+
ARROW: "\\to",
|
|
26
|
+
TEXT: (content) => `\\text{${content}}`,
|
|
27
|
+
COLOR: (color, content) => `\\textcolor{${color}}{${content}}`,
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Removes leading and trailing braces from LoKi selector string
|
|
31
|
+
*/
|
|
32
|
+
const cleanLoKiSelector = (selector) => {
|
|
33
|
+
return selector.replace(/^\[/, "").replace(/^\^\[/, "^").replace(/\]CC$/, "");
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Counts occurrences of a pattern in a string
|
|
37
|
+
*/
|
|
38
|
+
const countMatches = (text, pattern) => {
|
|
39
|
+
return (text.match(pattern) || []).length;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Extracts and processes braces from particle names for sub-decay handling
|
|
43
|
+
*/
|
|
44
|
+
const extractBraces = (name) => {
|
|
45
|
+
const openCount = countMatches(name, /\(/g);
|
|
46
|
+
const closeCount = countMatches(name, /\)/g);
|
|
47
|
+
if (name.startsWith("(")) {
|
|
48
|
+
return {
|
|
49
|
+
cleanName: name.replace(/^\(/, ""),
|
|
50
|
+
openBrace: "(",
|
|
51
|
+
closeBrace: "",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (name.endsWith(")") && closeCount > openCount) {
|
|
55
|
+
const extraClosingBraces = closeCount - openCount;
|
|
56
|
+
return {
|
|
57
|
+
cleanName: name.replace(/\)+$/, ""),
|
|
58
|
+
openBrace: "",
|
|
59
|
+
closeBrace: ")".repeat(extraClosingBraces),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { cleanName: name, openBrace: "", closeBrace: "" };
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Converts a LoKi decay selector string to LaTeX representation
|
|
66
|
+
*/
|
|
67
|
+
const displaySelectionDescriptor = (selection) => {
|
|
68
|
+
// Generate LoKi selector by marking selected particles with '^'
|
|
69
|
+
const decaySelector = decay.descriptors.template.replace(/\${(\w+)}/g, (_, variableName) => {
|
|
70
|
+
return selection.includes(variableName) ? LOKI_MARKERS.SELECTION_PREFIX : "";
|
|
71
|
+
});
|
|
72
|
+
const cleanedSelector = cleanLoKiSelector(decaySelector);
|
|
73
|
+
const particles = cleanedSelector.split(" ");
|
|
74
|
+
const latexTokens = particles.map((particle) => convertParticleToLatex(particle));
|
|
75
|
+
return latexTokens.join(" ");
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Converts a single particle token to LaTeX representation
|
|
79
|
+
*/
|
|
80
|
+
const convertParticleToLatex = (particle) => {
|
|
81
|
+
// Handle arrow tokens
|
|
82
|
+
if (particle === LOKI_MARKERS.ARROW) {
|
|
83
|
+
return LATEX_COMMANDS.ARROW;
|
|
84
|
+
}
|
|
85
|
+
const isMarked = particle.startsWith(LOKI_MARKERS.SELECTION_PREFIX);
|
|
86
|
+
const particleName = particle.replace(/^\^/, "");
|
|
87
|
+
// Handle sub-decay braces
|
|
88
|
+
const { cleanName, openBrace, closeBrace } = extractBraces(particleName);
|
|
89
|
+
// Validate particle exists in metadata
|
|
90
|
+
if (!metadata.particleProperties[cleanName]) {
|
|
91
|
+
console.error(`${cleanName} not found in particle property metadata!`);
|
|
92
|
+
return LATEX_COMMANDS.TEXT(particle);
|
|
93
|
+
}
|
|
94
|
+
// Get base LaTeX representation
|
|
95
|
+
let latex = metadata.particleProperties[cleanName].latex;
|
|
96
|
+
// Underline marked particles
|
|
97
|
+
if (isMarked) {
|
|
98
|
+
latex = LATEX_COMMANDS.COLOR("RoyalBlue", latex);
|
|
99
|
+
}
|
|
100
|
+
return `${openBrace}${latex}${closeBrace}`;
|
|
101
|
+
};
|
|
102
|
+
return (_jsx(OverlayTrigger, { overlay: _jsxs(Popover, { children: [_jsx(Popover.Header, { children: "LoKi descriptor" }), _jsx(Popover.Body, { children: _jsx("code", { children: decay.descriptors.plain }) })] }), children: _jsx("span", { children: _jsx(MathJax, { inline: true, children: `\\(${selection && selection.length > 0 ? displaySelectionDescriptor(selection) : decay.descriptors.latex}\\)` }) }) }));
|
|
103
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DecayData } from "../models/decayData";
|
|
2
|
+
interface Props {
|
|
3
|
+
decays: DecayData[];
|
|
4
|
+
selectedDecays: DecayData[];
|
|
5
|
+
onItemSelected: (decays: DecayData[]) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function DecayList({ decays, selectedDecays, onItemSelected }: Props): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************\
|
|
3
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
\*****************************************************************************/
|
|
12
|
+
import InfiniteScroll from "react-infinite-scroll-component";
|
|
13
|
+
import { DecayListItem } from "./DecayListItem";
|
|
14
|
+
import { Alert, ListGroup, Spinner } from "react-bootstrap";
|
|
15
|
+
import { config } from "../config.js";
|
|
16
|
+
import { useState } from "react";
|
|
17
|
+
export function DecayList({ decays, selectedDecays, onItemSelected }) {
|
|
18
|
+
const [items, setItems] = useState(decays.length > config.batch_size ? decays.slice(0, config.batch_size) : decays);
|
|
19
|
+
const [index, setIndex] = useState(decays.length > config.batch_size ? config.batch_size - 1 : decays.length);
|
|
20
|
+
const fetchMoreData = () => {
|
|
21
|
+
setItems((prev) => prev.concat(decays.slice(index + 1, index + 1 + config.batch_size)));
|
|
22
|
+
setIndex((prev) => (prev + config.batch_size < decays.length ? prev + config.batch_size : decays.length));
|
|
23
|
+
};
|
|
24
|
+
const decaysShown = items.length;
|
|
25
|
+
if (decaysShown === 0) {
|
|
26
|
+
return _jsx(Alert, { variant: "danger", children: "No matching decays" });
|
|
27
|
+
}
|
|
28
|
+
return (_jsxs(_Fragment, { children: [_jsx(ListGroup, { variant: "flush", id: "scrollableDiv", style: { height: "50vh", overflowY: "scroll" }, children: _jsx(InfiniteScroll, { dataLength: decaysShown, next: fetchMoreData, hasMore: decaysShown < decays.length, loader: _jsxs(Alert, { variant: "warning", children: [_jsx(Spinner, { size: "sm", animation: "border" }), " Loading next", " ", Math.min(config.batch_size, decays.length - decaysShown), " decays..."] }), scrollableTarget: "scrollableDiv", children: items.map((decay) => (_jsx(DecayListItem, { decay: decay, initiallySelected: selectedDecays.some((selected) => selected.descriptors.plain === decay.descriptors.plain), onItemSelected: (decayItem) => {
|
|
29
|
+
if (decayItem.selected) {
|
|
30
|
+
const newSelectedDecays = selectedDecays.filter((decay) => decay.descriptors.plain !== decayItem.decay.descriptors.plain);
|
|
31
|
+
onItemSelected(newSelectedDecays);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
onItemSelected([...selectedDecays, decayItem.decay]);
|
|
35
|
+
}
|
|
36
|
+
} }, decay.descriptors.plain))) }) }), _jsxs(Alert, { variant: "light", children: ["Showing ", decaysShown, " of ", decays.length, " matching decays"] })] }));
|
|
37
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DecayData } from "../models/decayData";
|
|
2
|
+
interface Props {
|
|
3
|
+
decay: DecayData;
|
|
4
|
+
initiallySelected?: boolean;
|
|
5
|
+
onItemSelected: (arg: {
|
|
6
|
+
selected: boolean;
|
|
7
|
+
decay: DecayData;
|
|
8
|
+
}) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function DecayListItem({ decay, initiallySelected, onItemSelected }: Props): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************\
|
|
3
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
\*****************************************************************************/
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import { InputGroup, ListGroup } from "react-bootstrap";
|
|
14
|
+
import { DecayLatex } from "./DecayLatex";
|
|
15
|
+
import { DecayTagBadge } from "./DecayTagBadge.js";
|
|
16
|
+
import { NumStrippingLinesBadge } from "./NumStrippingLinesBadge.js";
|
|
17
|
+
export function DecayListItem({ decay, initiallySelected = false, onItemSelected }) {
|
|
18
|
+
const [selected, setSelected] = useState(initiallySelected);
|
|
19
|
+
return (_jsx(ListGroup.Item, { as: "li", style: { cursor: "pointer" }, onClick: () => {
|
|
20
|
+
setSelected(!selected);
|
|
21
|
+
onItemSelected({ selected, decay: decay });
|
|
22
|
+
}, children: _jsxs(InputGroup, { children: [_jsx(InputGroup.Checkbox, { checked: selected, readOnly: true }), _jsxs("div", { className: `react-select form-control p-2 d-flex flex-column align-items-start gap-1 ${selected ? "list-group-item-primary" : "list-group-item-light"}`, children: [_jsx(DecayLatex, { decay: decay }), _jsxs("div", { className: "d-flex flex-row flex-wrap gap-1", children: [_jsx(NumStrippingLinesBadge, { strippingLines: decay.lines, selected: selected }), decay.tags.map((tag) => (_jsx(DecayTagBadge, { tag: tag }, tag)))] })] })] }) }));
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************\
|
|
3
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
\*****************************************************************************/
|
|
12
|
+
import { Badge, OverlayTrigger, Tooltip } from "react-bootstrap";
|
|
13
|
+
import { useMetadata } from "../providers/MetadataProvider.js";
|
|
14
|
+
export function DecayTagBadge({ tag, ...props }) {
|
|
15
|
+
const metadata = useMetadata();
|
|
16
|
+
if (!metadata) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const tagInfo = metadata.userHints.decayTags[tag];
|
|
20
|
+
return (_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: tagInfo.description }), children: _jsx(Badge, { pill: true, bg: tagInfo.warn ? "danger" : "warning", text: tagInfo.warn ? "light" : "dark", ...props, children: tag }) }));
|
|
21
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DttConfig } from "../models/dtt.js";
|
|
2
|
+
interface Props {
|
|
3
|
+
onConfigSaved: (config: DttConfig) => void;
|
|
4
|
+
onDirtyUpdated: (dttId: string, dirty: boolean) => void;
|
|
5
|
+
}
|
|
6
|
+
export declare function DecayTreeCard({ onConfigSaved, onDirtyUpdated }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************
|
|
3
|
+
* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
*****************************************************************************/
|
|
12
|
+
import { DecayTagBadge } from "./DecayTagBadge.js";
|
|
13
|
+
import { DecayLatex } from "./DecayLatex";
|
|
14
|
+
import { TupleToolList } from "./TupleToolList";
|
|
15
|
+
import { useMetadata } from "../providers/MetadataProvider.js";
|
|
16
|
+
import { Button, Card, OverlayTrigger, Stack, Tooltip } from "react-bootstrap";
|
|
17
|
+
import { Lock, QuestionCircle, Search, Unlock } from "react-bootstrap-icons";
|
|
18
|
+
import { config } from "../config.js";
|
|
19
|
+
import { useEffect, useState } from "react";
|
|
20
|
+
import { DecayTreeGraph } from "./DecayTreeGraph";
|
|
21
|
+
import { DecayTreeCardHeader } from "./DecayTreeCardHeader";
|
|
22
|
+
import { ParticleTagFilters } from "./ParticleTagFilters";
|
|
23
|
+
import { useDtt } from "../providers/DttProvider";
|
|
24
|
+
export function DecayTreeCard({ onConfigSaved, onDirtyUpdated }) {
|
|
25
|
+
const metadata = useMetadata();
|
|
26
|
+
const { dtt, decay, dirty } = useDtt();
|
|
27
|
+
const [selectedBranch, setSelectedBranch] = useState([]);
|
|
28
|
+
const [lockGraphZoom, setLockGraphZoom] = useState(!config.dttGraphOptions.interaction.zoomView);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
onDirtyUpdated(dtt.getName(), dirty);
|
|
31
|
+
}, [dtt, dirty]);
|
|
32
|
+
if (!metadata) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return (_jsxs(Card, { children: [_jsx(DecayTreeCardHeader, { dttName: dtt.getName(), inputs: dtt.config.inputs }), _jsxs(Card.Body, { children: [_jsxs(Card.Title, { className: "d-flex justify-content-between align-items-start", children: [_jsxs("span", { children: [_jsx(OverlayTrigger, { placement: "bottom", overlay: _jsx(Tooltip, { children: "Click to select particles to configure. Hold ctrl to select multiple. Clear the selection to configure the entire decay." }), children: _jsx(QuestionCircle, {}) }), " ", "Configure ", _jsx(DecayLatex, { decay: decay })] }), _jsx(OverlayTrigger, { placement: "bottom", overlay: _jsxs(Tooltip, { children: ["Click to ", lockGraphZoom ? "unlock" : "lock", " scroll-to-zoom."] }), children: _jsxs(Button, { onClick: () => setLockGraphZoom(!lockGraphZoom), variant: "secondary-outline", children: [lockGraphZoom ? _jsx(Lock, {}) : _jsx(Unlock, {}), _jsx(Search, {})] }) })] }), _jsx(Stack, { direction: "horizontal", style: { flexWrap: "wrap", justifyContent: "center" }, gap: 2, children: decay.tags
|
|
36
|
+
.filter((tag) => metadata.userHints.decayTags[tag].warn)
|
|
37
|
+
.map((tag) => (_jsx(DecayTagBadge, { tag: tag }, tag))) }), _jsx(DecayTreeGraph, { decay: decay, lockGraphZoom: lockGraphZoom, selectedParticlesIds: selectedBranch, onNodeSelectionChanged: (nodeIds) => {
|
|
38
|
+
setSelectedBranch([...nodeIds].sort());
|
|
39
|
+
} }), _jsx(ParticleTagFilters, { branch: selectedBranch, onSelectTag: setSelectedBranch }), _jsxs(Card.Title, { className: "mt-4", children: ["Current selection: ", _jsx(DecayLatex, { decay: decay, selection: selectedBranch })] }), _jsx(TupleToolList, { branch: selectedBranch, onGroupSelected: (group) => {
|
|
40
|
+
const selection = group.split(",");
|
|
41
|
+
setSelectedBranch(selection);
|
|
42
|
+
}, onSave: () => onConfigSaved(dtt.config) })] })] }));
|
|
43
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Accordion, Card, ListGroup, OverlayTrigger, Popover } from "react-bootstrap";
|
|
3
|
+
export function DecayTreeCardHeader({ dttName, inputs }) {
|
|
4
|
+
return (_jsxs(Card.Header, { className: "d-flex flex-column align-items-start", children: [_jsx(OverlayTrigger, { placement: "bottom", overlay: _jsx(Popover, { children: _jsxs(Popover.Body, { children: ["The ROOT TTree will be found under ", _jsx("code", { children: `DecayTreeTuple/${dttName}` }), "."] }) }), children: _jsxs(Card.Title, { children: ["Tree name: ", _jsx("code", { children: dttName })] }) }), _jsx(Accordion, { style: { width: "100%" }, children: _jsxs(Accordion.Item, { eventKey: "0", children: [_jsxs(Accordion.Header, { children: [(inputs || []).length, " input location", (inputs || []).length === 1 ? "" : "s"] }), _jsx(Accordion.Body, { children: _jsx(ListGroup, { variant: "flush", children: !inputs || inputs.length === 0 ? (_jsx(ListGroup.Item, { children: "Choose at least one Stripping line, otherwise no decay candidates will be selected" })) : (inputs.map((location, i) => (_jsx(ListGroup.Item, { children: _jsx("code", { children: location }) }, i)))) }) })] }) })] }));
|
|
5
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DecayData } from "../models/decayData";
|
|
2
|
+
interface Props {
|
|
3
|
+
decay: DecayData;
|
|
4
|
+
lockGraphZoom: boolean;
|
|
5
|
+
selectedParticlesIds: string[];
|
|
6
|
+
onNodeSelectionChanged: (nodeIds: string[]) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function DecayTreeGraph({ decay, lockGraphZoom, selectedParticlesIds, onNodeSelectionChanged }: Props): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @ts-expect-error The react-graph-vis package does not have types
|
|
3
|
+
import Graph from "react-graph-vis";
|
|
4
|
+
import { config } from "../config";
|
|
5
|
+
import { tex2svg } from "../utils/mathjaxUtils";
|
|
6
|
+
import { useMetadata } from "../providers/MetadataProvider";
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
|
+
export function DecayTreeGraph({ decay, lockGraphZoom, selectedParticlesIds, onNodeSelectionChanged }) {
|
|
9
|
+
const metadata = useMetadata();
|
|
10
|
+
// eslint-disable-next-line
|
|
11
|
+
const [network, setNetwork] = useState(null);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
// eslint-disable-next-line
|
|
14
|
+
network?.selectNodes(selectedParticlesIds);
|
|
15
|
+
}, [selectedParticlesIds]);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
// eslint-disable-next-line
|
|
18
|
+
network?.setOptions({ interaction: { zoomView: lockGraphZoom } });
|
|
19
|
+
}, [lockGraphZoom]);
|
|
20
|
+
function htmlTitle(text) {
|
|
21
|
+
const container = document.createElement("span");
|
|
22
|
+
container.innerText = text;
|
|
23
|
+
return container;
|
|
24
|
+
}
|
|
25
|
+
function makeSVG(text, colour = "black") {
|
|
26
|
+
const pipes = "\\phantom{{}^{|-}_{|-}}"; // looks weird but helps ensure uniform text scaling
|
|
27
|
+
const texSVG = tex2svg(`${pipes}${text}${pipes}`).innerHTML.replaceAll("currentColor", colour);
|
|
28
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(texSVG)}`;
|
|
29
|
+
}
|
|
30
|
+
function buildGraph() {
|
|
31
|
+
const graph = { nodes: [], edges: [] };
|
|
32
|
+
if (!metadata) {
|
|
33
|
+
return graph;
|
|
34
|
+
}
|
|
35
|
+
const addNodeAndEdge = (item, parentId) => {
|
|
36
|
+
const { branch, particle } = item;
|
|
37
|
+
const particleProperties = metadata.particleProperties[particle];
|
|
38
|
+
graph.nodes.push({
|
|
39
|
+
id: branch,
|
|
40
|
+
label: branch,
|
|
41
|
+
title: htmlTitle(particleProperties.html),
|
|
42
|
+
shape: "image",
|
|
43
|
+
image: {
|
|
44
|
+
selected: makeSVG(particleProperties.latex, "#0d6efd"),
|
|
45
|
+
unselected: makeSVG(particleProperties.latex, "black"),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
if (parentId !== null) {
|
|
49
|
+
graph.edges.push({ from: parentId, to: branch });
|
|
50
|
+
}
|
|
51
|
+
return branch;
|
|
52
|
+
};
|
|
53
|
+
const walk = (term, parentId) => {
|
|
54
|
+
if (!Array.isArray(term)) {
|
|
55
|
+
return addNodeAndEdge(term, parentId);
|
|
56
|
+
}
|
|
57
|
+
let lastParentId = parentId;
|
|
58
|
+
for (const element of term) {
|
|
59
|
+
if (Array.isArray(element)) {
|
|
60
|
+
if (lastParentId == null) {
|
|
61
|
+
throw new Error("Nested decay without parent node");
|
|
62
|
+
}
|
|
63
|
+
walk(element, lastParentId);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
lastParentId = addNodeAndEdge(element, parentId);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
walk(decay.descriptors.mapped_list, null);
|
|
71
|
+
return graph;
|
|
72
|
+
}
|
|
73
|
+
return (_jsx(Graph, { graph: buildGraph(), options: config.dttGraphOptions, events: {
|
|
74
|
+
// @ts-expect-error The react-graph-vis package does not have types
|
|
75
|
+
selectNode: (event) => {
|
|
76
|
+
// eslint-disable-next-line
|
|
77
|
+
onNodeSelectionChanged(event.nodes);
|
|
78
|
+
},
|
|
79
|
+
// @ts-expect-error The react-graph-vis package does not have types
|
|
80
|
+
deselectNode: (event) => {
|
|
81
|
+
// eslint-disable-next-line
|
|
82
|
+
onNodeSelectionChanged(event.nodes);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
// @ts-expect-error The react-graph-vis package does not have types
|
|
86
|
+
getNetwork: (n) => {
|
|
87
|
+
setNetwork(n);
|
|
88
|
+
} }));
|
|
89
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
interface Props {
|
|
3
|
+
action: () => void;
|
|
4
|
+
outline?: boolean;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare function DeleteButton({ action, outline, disabled, children }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*****************************************************************************\
|
|
3
|
+
* (c) Copyright 2021-2022 CERN for the benefit of the LHCb Collaboration *
|
|
4
|
+
* *
|
|
5
|
+
* This software is distributed under the terms of the GNU General Public *
|
|
6
|
+
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
|
|
7
|
+
* *
|
|
8
|
+
* In applying this licence, CERN does not waive the privileges and immunities *
|
|
9
|
+
* granted to it by virtue of its status as an Intergovernmental Organization *
|
|
10
|
+
* or submit itself to any jurisdiction. *
|
|
11
|
+
\*****************************************************************************/
|
|
12
|
+
import { Button, OverlayTrigger, Popover } from "react-bootstrap";
|
|
13
|
+
import { Trash } from "react-bootstrap-icons";
|
|
14
|
+
export function DeleteButton({ action, outline, disabled, children }) {
|
|
15
|
+
if (disabled) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return (_jsx(OverlayTrigger, { trigger: "click", placement: "auto", rootClose: true, overlay: _jsx(Popover, { children: _jsx(Popover.Body, { children: _jsx(Button, { variant: "danger", onClick: action, children: "Confirm" }) }) }), children: _jsxs(Button, { variant: outline ? "outline-danger" : "danger", disabled: disabled, children: [_jsx(Trash, {}), " ", children] }) }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RowData } from "../models/rowData";
|
|
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 {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Button, ButtonGroup, Card, FormControl, InputGroup, OverlayTrigger, Tooltip } from "react-bootstrap";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Download, ExclamationCircle, GearWideConnected, PlusLg, Upload } from "react-bootstrap-icons";
|
|
5
|
+
import { DeleteButton } from "./DeleteButton";
|
|
6
|
+
import { DecayLatex } from "./DecayLatex";
|
|
7
|
+
import Dtt from "../models/dtt";
|
|
8
|
+
import { useRows } from "../providers/RowsProvider";
|
|
9
|
+
import { useNavigate } from "react-router-dom";
|
|
10
|
+
import { useMetadata } from "../providers/MetadataProvider";
|
|
11
|
+
import { downloadText } from "../utils/utils";
|
|
12
|
+
import { UploadDttConfigModal } from "./modals/UploadDttConfigModal";
|
|
13
|
+
import { YamlFile } from "../models/yamlFile";
|
|
14
|
+
export function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, variablesPath }) {
|
|
15
|
+
const { rows, setRows } = useRows();
|
|
16
|
+
const navigate = useNavigate();
|
|
17
|
+
const metadata = useMetadata();
|
|
18
|
+
const [showUploadModal, setShowUploadModal] = useState(false);
|
|
19
|
+
const [dttName, setDttName] = useState(row.dtt?.getName() || "");
|
|
20
|
+
const [dttNameValid, setDttNameValid] = useState(true);
|
|
21
|
+
const [autoFocus, setAutoFocus] = useState(false);
|
|
22
|
+
if (!metadata) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
function allNameCharsValid(name) {
|
|
26
|
+
const pattern = /^[a-zA-Z0-9_:-]+$/;
|
|
27
|
+
return pattern.test(name);
|
|
28
|
+
}
|
|
29
|
+
function validateName() {
|
|
30
|
+
const trimmedName = dttName.trim();
|
|
31
|
+
const isNameEmpty = trimmedName === "";
|
|
32
|
+
const areCharsValid = allNameCharsValid(trimmedName);
|
|
33
|
+
const otherRowNames = rows.filter((r) => r.id !== row.id).map((row) => row.dtt?.getName() || "");
|
|
34
|
+
const isNameDuplicate = otherRowNames.includes(trimmedName);
|
|
35
|
+
const valid = !isNameEmpty && areCharsValid && !isNameDuplicate;
|
|
36
|
+
setDttNameValid(valid);
|
|
37
|
+
return valid;
|
|
38
|
+
}
|
|
39
|
+
const handleCreateDTT = () => {
|
|
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
|
+
setRows((prev) => {
|
|
42
|
+
return prev.map((r) => (r.id === row.id ? { ...r, dtt: dtt.withInputsFromLines(row.lines) } : r));
|
|
43
|
+
});
|
|
44
|
+
setAutoFocus(true);
|
|
45
|
+
};
|
|
46
|
+
const handleConfigureDtt = (id) => {
|
|
47
|
+
setRows(rows.map((row) => ({ ...row, editTree: row.id === id })));
|
|
48
|
+
void navigate(variablesPath);
|
|
49
|
+
};
|
|
50
|
+
const handleDeleteDtt = (id) => {
|
|
51
|
+
setRows((prev) => prev.map((r) => (r.id === id ? { ...r, dtt: null } : r)));
|
|
52
|
+
setDttName("");
|
|
53
|
+
};
|
|
54
|
+
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
|
+
if (!validateName()) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
setRows((prev) => {
|
|
59
|
+
return prev.map((r) => r.id === row.id ? { ...r, dtt: r.dtt.withName(dttName) } : r);
|
|
60
|
+
});
|
|
61
|
+
}, onChange: (event) => {
|
|
62
|
+
setDttName(event.target.value);
|
|
63
|
+
setDttNameValid(true);
|
|
64
|
+
}, isInvalid: !dttNameValid }), _jsx(FormControl.Feedback, { type: "invalid", children: dttName.trim() === ""
|
|
65
|
+
? "Name cannot be empty"
|
|
66
|
+
: !allNameCharsValid(dttName.trim())
|
|
67
|
+
? "Name contains invalid characters"
|
|
68
|
+
: "Must give a unique name" })] })), _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: () => {
|
|
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: () => {
|
|
71
|
+
downloadText(YamlFile.fromDtt(row.dtt));
|
|
72
|
+
}, disabled: !dttNameValid, children: _jsx(Download, {}) }) }) })), _jsx(DeleteButton, { action: () => handleDeleteDtt(row.id) })] })) : (_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, { row: row, onClose: () => setShowUploadModal(false) }))] })) })] }), _jsx(Card.Body, { children: _jsx(DecayLatex, { decay: row.decay }) })] }));
|
|
73
|
+
}
|