lhcb-ntuple-wizard 2.0.3 → 2.1.0
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.js +2 -1
- package/dist/components/DecayCard.d.ts +1 -0
- package/dist/components/{DttNameInput.js → DecayCard.js} +9 -5
- package/dist/components/DecayLatex.js +1 -1
- package/dist/components/DecayTreeCard.js +7 -10
- package/dist/components/DecayTreeGraph.d.ts +1 -2
- package/dist/components/DecayTreeGraph.js +132 -46
- package/dist/components/DeleteButton.d.ts +2 -1
- package/dist/components/DeleteButton.js +2 -2
- package/dist/components/NtupleWizard.d.ts +2 -1
- package/dist/components/NtupleWizard.js +8 -2
- package/dist/components/RequestButtonGroup.d.ts +1 -7
- package/dist/components/RequestButtonGroup.js +5 -3
- package/dist/components/RequestRow.d.ts +1 -7
- package/dist/components/RequestRow.js +6 -5
- package/dist/components/StrippingLineBadge.js +1 -1
- package/dist/components/{TupleToolDropdown.d.ts → TupleToolClassDropdown.d.ts} +2 -5
- package/dist/components/{TupleToolDropdown.js → TupleToolClassDropdown.js} +10 -4
- package/dist/components/TupleToolGroup.d.ts +1 -2
- package/dist/components/TupleToolGroup.js +5 -5
- package/dist/components/TupleToolList.d.ts +1 -2
- package/dist/components/TupleToolList.js +11 -7
- package/dist/components/VerticalLine.d.ts +7 -0
- package/dist/components/VerticalLine.js +4 -0
- package/dist/components/modals/AddTupleToolModal.d.ts +3 -4
- package/dist/components/modals/AddTupleToolModal.js +12 -12
- package/dist/components/modals/ConfigureTupleToolModal.d.ts +2 -2
- package/dist/components/modals/ConfigureTupleToolModal.js +28 -11
- package/dist/components/modals/ReasonForRequestModal.d.ts +1 -3
- package/dist/components/modals/ReasonForRequestModal.js +6 -4
- package/dist/config.d.ts +18 -47
- package/dist/config.js +26 -39
- 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 +16 -14
- package/dist/pages/RequestPage.d.ts +1 -20
- package/dist/pages/RequestPage.js +15 -16
- package/dist/providers/DttProvider.d.ts +2 -0
- package/dist/providers/DttProvider.js +4 -1
- package/dist/providers/WizardConfigProvider.d.ts +21 -0
- package/dist/providers/WizardConfigProvider.js +21 -0
- package/dist/utils/utils.js +36 -3
- package/package.json +10 -5
- package/dist/components/DttNameInput.d.ts +0 -9
package/dist/App.js
CHANGED
|
@@ -15,6 +15,7 @@ import { Archive, CodeSlash, House } from "react-bootstrap-icons";
|
|
|
15
15
|
import { config } from "./config";
|
|
16
16
|
import { NtupleWizard } from "./components/NtupleWizard";
|
|
17
17
|
import { BrowserRouter } from "react-router-dom";
|
|
18
|
+
import { Slide, ToastContainer } from "react-toastify";
|
|
18
19
|
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:
|
|
20
|
+
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: _jsxs(BrowserRouter, { children: [_jsx(ToastContainer, { transition: Slide, hideProgressBar: true }), _jsx(NtupleWizard, {})] }) })] }));
|
|
20
21
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function DecayCard(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -12,10 +12,14 @@ 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
|
-
|
|
16
|
-
|
|
15
|
+
import { useRow } from "../providers/RowProvider";
|
|
16
|
+
import { useWizardConfig } from "../providers/WizardConfigProvider";
|
|
17
|
+
export function DecayCard() {
|
|
18
|
+
const { row } = useRow();
|
|
19
|
+
const { rows, setRows, updateRow } = useRows();
|
|
17
20
|
const navigate = useNavigate();
|
|
18
21
|
const metadata = useMetadata();
|
|
22
|
+
const { basePath, variant } = useWizardConfig();
|
|
19
23
|
const [showUploadModal, setShowUploadModal] = useState(false);
|
|
20
24
|
const [dttName, setDttName] = useState(row.dtt?.getName() || "");
|
|
21
25
|
const [dttNameValid, setDttNameValid] = useState(true);
|
|
@@ -46,7 +50,7 @@ export function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, base
|
|
|
46
50
|
setAutoFocus(true);
|
|
47
51
|
};
|
|
48
52
|
const handleConfigureDtt = () => {
|
|
49
|
-
|
|
53
|
+
setRows((rows) => rows.map((r) => (r.id === row.id ? { ...r, editTree: true } : { ...r, editTree: false })));
|
|
50
54
|
void navigate(`${basePath}${VARIABLES_PATH}`);
|
|
51
55
|
};
|
|
52
56
|
const handleDeleteDtt = () => {
|
|
@@ -65,7 +69,7 @@ export function DttNameInput({ row, hideDownloadButtons, hideUploadButtons, base
|
|
|
65
69
|
? "Name cannot be empty"
|
|
66
70
|
: !allNameCharsValid(dttName.trim())
|
|
67
71
|
? "Name contains invalid characters"
|
|
68
|
-
: "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: () => {
|
|
69
73
|
downloadText(YamlFile.fromDtt(row.dtt));
|
|
70
|
-
}, 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, popupMessage: "Delete DecayTreeTuple" })] })) : (_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, { style: { overflowX: "auto" }, children: _jsx(DecayLatex, { decay: row.decay }) })] }));
|
|
71
75
|
}
|
|
@@ -95,7 +95,7 @@ export function DecayLatex({ decay, selection }) {
|
|
|
95
95
|
let latex = metadata.particleProperties[cleanName].latex;
|
|
96
96
|
// Underline marked particles
|
|
97
97
|
if (isMarked) {
|
|
98
|
-
latex = LATEX_COMMANDS.COLOR("
|
|
98
|
+
latex = LATEX_COMMANDS.COLOR("#4169E1", latex);
|
|
99
99
|
}
|
|
100
100
|
return `${openBrace}${latex}${closeBrace}`;
|
|
101
101
|
};
|
|
@@ -13,30 +13,27 @@ import { DecayTagBadge } from "./DecayTagBadge.js";
|
|
|
13
13
|
import { DecayLatex } from "./DecayLatex";
|
|
14
14
|
import { TupleToolList } from "./TupleToolList";
|
|
15
15
|
import { useMetadata } from "../providers/MetadataProvider.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { useEffect, useState } from "react";
|
|
16
|
+
import { Card, OverlayTrigger, Stack, Tooltip } from "react-bootstrap";
|
|
17
|
+
import { QuestionCircle } from "react-bootstrap-icons";
|
|
18
|
+
import { useEffect } from "react";
|
|
20
19
|
import { DecayTreeGraph } from "./DecayTreeGraph";
|
|
21
20
|
import { DecayTreeCardHeader } from "./DecayTreeCardHeader";
|
|
22
21
|
import { ParticleTagFilters } from "./ParticleTagFilters";
|
|
23
22
|
import { useDtt } from "../providers/DttProvider";
|
|
24
23
|
export function DecayTreeCard({ onConfigSaved, onDirtyUpdated }) {
|
|
25
24
|
const metadata = useMetadata();
|
|
26
|
-
const { dtt, decay, dirty } = useDtt();
|
|
27
|
-
const [selectedBranch, setSelectedBranch] = useState([]);
|
|
28
|
-
const [lockGraphZoom, setLockGraphZoom] = useState(!config.dttGraphOptions.interaction.zoomView);
|
|
25
|
+
const { dtt, decay, dirty, selectedBranch, setSelectedBranch } = useDtt();
|
|
29
26
|
useEffect(() => {
|
|
30
27
|
onDirtyUpdated(dtt.getName(), dirty);
|
|
31
28
|
}, [dtt, dirty]);
|
|
32
29
|
if (!metadata) {
|
|
33
30
|
return null;
|
|
34
31
|
}
|
|
35
|
-
return (_jsxs(Card, { children: [_jsx(DecayTreeCardHeader, { dttName: dtt.getName(), inputs: dtt.config.inputs }), _jsxs(Card.Body, { children: [
|
|
32
|
+
return (_jsxs(Card, { children: [_jsx(DecayTreeCardHeader, { dttName: dtt.getName(), inputs: dtt.config.inputs }), _jsxs(Card.Body, { children: [_jsx(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(Stack, { direction: "horizontal", style: { flexWrap: "wrap", justifyContent: "center" }, gap: 2, children: decay.tags
|
|
36
33
|
.filter((tag) => metadata.userHints.decayTags[tag].warn)
|
|
37
|
-
.map((tag) => (_jsx(DecayTagBadge, { tag: tag }, tag))) }), _jsx(DecayTreeGraph, { decay: decay,
|
|
34
|
+
.map((tag) => (_jsx(DecayTagBadge, { tag: tag }, tag))) }), _jsx(DecayTreeGraph, { decay: decay, selectedParticlesIds: selectedBranch, onNodeSelectionChanged: (nodeIds) => {
|
|
38
35
|
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, {
|
|
36
|
+
} }), _jsx(ParticleTagFilters, { branch: selectedBranch, onSelectTag: setSelectedBranch }), _jsxs(Card.Title, { className: "mt-4", children: ["Current selection: ", _jsx(DecayLatex, { decay: decay, selection: selectedBranch })] }), _jsx(TupleToolList, { onGroupSelected: (group) => {
|
|
40
37
|
const selection = group.split(",");
|
|
41
38
|
setSelectedBranch(selection);
|
|
42
39
|
}, onSave: () => onConfigSaved(dtt.config) })] })] }));
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { DecayData } from "../models/decayData";
|
|
2
2
|
interface Props {
|
|
3
3
|
decay: DecayData;
|
|
4
|
-
lockGraphZoom: boolean;
|
|
5
4
|
selectedParticlesIds: string[];
|
|
6
5
|
onNodeSelectionChanged: (nodeIds: string[]) => void;
|
|
7
6
|
}
|
|
8
|
-
export declare function DecayTreeGraph({ decay,
|
|
7
|
+
export declare function DecayTreeGraph({ decay, selectedParticlesIds, onNodeSelectionChanged }: Props): import("react/jsx-runtime").JSX.Element;
|
|
9
8
|
export {};
|
|
@@ -1,52 +1,66 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
import
|
|
2
|
+
import CytoscapeComponent from "react-cytoscapejs";
|
|
3
|
+
import cytoscape from "cytoscape";
|
|
4
|
+
import dagre from "cytoscape-dagre";
|
|
4
5
|
import { config } from "../config";
|
|
5
6
|
import { tex2svg } from "../utils/mathjaxUtils";
|
|
6
7
|
import { useMetadata } from "../providers/MetadataProvider";
|
|
7
|
-
import { useEffect,
|
|
8
|
-
|
|
8
|
+
import { useEffect, useRef } from "react";
|
|
9
|
+
cytoscape.use(dagre);
|
|
10
|
+
export function DecayTreeGraph({ decay, selectedParticlesIds, onNodeSelectionChanged }) {
|
|
9
11
|
const metadata = useMetadata();
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
const cyRef = useRef(null);
|
|
13
|
+
// Sync external selection state to cytoscape selection
|
|
12
14
|
useEffect(() => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
const cy = cyRef.current;
|
|
16
|
+
if (!cy)
|
|
17
|
+
return;
|
|
18
|
+
cy.nodes().forEach((node) => {
|
|
19
|
+
if (selectedParticlesIds.includes(node.id())) {
|
|
20
|
+
node.select();
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
node.unselect();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
15
26
|
}, [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
27
|
function makeSVG(text, colour = "black") {
|
|
26
|
-
const pipes = "\\phantom{{}^{|-}_{|-}}";
|
|
28
|
+
const pipes = "\\phantom{{}^{|-}_{|-}}";
|
|
27
29
|
const texSVG = tex2svg(`${pipes}${text}${pipes}`).innerHTML.replaceAll("currentColor", colour);
|
|
28
30
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(texSVG)}`;
|
|
29
31
|
}
|
|
30
|
-
function
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
function getHtmlTitle(text) {
|
|
33
|
+
const container = document.createElement("span");
|
|
34
|
+
container.innerText = text;
|
|
35
|
+
return container;
|
|
36
|
+
}
|
|
37
|
+
function buildElements() {
|
|
38
|
+
const elements = [];
|
|
39
|
+
if (!metadata)
|
|
40
|
+
return elements;
|
|
35
41
|
const addNodeAndEdge = (item, parentId) => {
|
|
36
42
|
const { branch, particle } = item;
|
|
37
43
|
const particleProperties = metadata.particleProperties[particle];
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
elements.push({
|
|
45
|
+
data: {
|
|
46
|
+
id: branch,
|
|
47
|
+
label: branch,
|
|
48
|
+
// Store both SVG variants so we can swap on select/unselect
|
|
49
|
+
imageSrc: makeSVG(particleProperties.latex, "black"),
|
|
50
|
+
imageSelected: makeSVG(particleProperties.latex, "#0d6efd"),
|
|
51
|
+
// Tooltip text (accessible via tippy or title attr if needed)
|
|
52
|
+
title: getHtmlTitle(particleProperties.html).innerText,
|
|
46
53
|
},
|
|
54
|
+
selected: selectedParticlesIds.includes(branch),
|
|
47
55
|
});
|
|
48
56
|
if (parentId !== null) {
|
|
49
|
-
|
|
57
|
+
elements.push({
|
|
58
|
+
data: {
|
|
59
|
+
id: `${parentId}->${branch}`,
|
|
60
|
+
source: parentId,
|
|
61
|
+
target: branch,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
50
64
|
}
|
|
51
65
|
return branch;
|
|
52
66
|
};
|
|
@@ -68,22 +82,94 @@ export function DecayTreeGraph({ decay, lockGraphZoom, selectedParticlesIds, onN
|
|
|
68
82
|
}
|
|
69
83
|
};
|
|
70
84
|
walk(decay.descriptors.mapped_list, null);
|
|
71
|
-
return
|
|
85
|
+
return elements;
|
|
72
86
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
const stylesheet = [
|
|
88
|
+
// Disable the grey circle on pan/click
|
|
89
|
+
{
|
|
90
|
+
selector: "core",
|
|
91
|
+
style: {
|
|
92
|
+
"active-bg-size": 0,
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
selector: "node",
|
|
97
|
+
style: {
|
|
98
|
+
shape: "ellipse",
|
|
99
|
+
// Use the unselected SVG as the background image
|
|
100
|
+
"background-image": "data(imageSrc)",
|
|
101
|
+
"background-fit": "contain",
|
|
102
|
+
"background-opacity": 0,
|
|
103
|
+
width: config.dttGraphOptions.nodes.width,
|
|
104
|
+
height: config.dttGraphOptions.nodes.height,
|
|
105
|
+
label: "",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
selector: "node:active",
|
|
110
|
+
style: {
|
|
111
|
+
"overlay-opacity": 0,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
selector: "node.hover",
|
|
116
|
+
style: {
|
|
117
|
+
"background-opacity": 0.2,
|
|
118
|
+
"background-color": config.dttGraphOptions.nodes.hoverColor,
|
|
78
119
|
},
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
selector: "node:selected",
|
|
123
|
+
style: {
|
|
124
|
+
// Swap to the selected SVG when the node is selected
|
|
125
|
+
"background-image": "data(imageSelected)",
|
|
83
126
|
},
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
selector: "edge",
|
|
130
|
+
style: {
|
|
131
|
+
"curve-style": "bezier",
|
|
132
|
+
"target-arrow-shape": "triangle",
|
|
133
|
+
width: config.dttGraphOptions.edges.width,
|
|
134
|
+
"line-color": config.dttGraphOptions.edges.color,
|
|
135
|
+
"target-arrow-color": config.dttGraphOptions.edges.color,
|
|
136
|
+
events: "no",
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
return (_jsx(CytoscapeComponent, { elements: buildElements(), stylesheet: stylesheet, style: { width: "100%", height: config.dttGraphOptions.height }, autoungrabify: !config.dttGraphOptions.nodes.draggable, autounselectify: false, boxSelectionEnabled: true, cy: (cy) => {
|
|
141
|
+
cyRef.current = cy;
|
|
142
|
+
// Set up zoom
|
|
143
|
+
cy.userZoomingEnabled(false);
|
|
144
|
+
cy.minZoom(config.dttGraphOptions.zoomMin);
|
|
145
|
+
cy.maxZoom(config.dttGraphOptions.zoomMax);
|
|
146
|
+
// Handle zoom event
|
|
147
|
+
cy.container()?.addEventListener("wheel", (e) => {
|
|
148
|
+
if (!(e.ctrlKey || e.metaKey))
|
|
149
|
+
return;
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
const zoom = cy.zoom();
|
|
152
|
+
const factor = 1 + (e.deltaY < 0 ? config.dttGraphOptions.zoomStep : -config.dttGraphOptions.zoomStep);
|
|
153
|
+
cy.zoom({
|
|
154
|
+
level: zoom * factor,
|
|
155
|
+
renderedPosition: { x: e.offsetX, y: e.offsetY },
|
|
156
|
+
});
|
|
157
|
+
}, { passive: false });
|
|
158
|
+
// Handle node selection events
|
|
159
|
+
cy.off("select unselect", "node");
|
|
160
|
+
cy.on("select unselect", "node", () => {
|
|
161
|
+
const selected = cy.nodes(":selected").map((n) => n.id());
|
|
162
|
+
onNodeSelectionChanged(selected);
|
|
163
|
+
});
|
|
164
|
+
// Handle hover events
|
|
165
|
+
cy.on("mouseover", "node", (e) => {
|
|
166
|
+
e.target.addClass("hover");
|
|
167
|
+
});
|
|
168
|
+
cy.on("mouseout", "node", (e) => {
|
|
169
|
+
e.target.removeClass("hover");
|
|
170
|
+
});
|
|
171
|
+
}, layout: {
|
|
172
|
+
...config.dttGraphOptions.layout,
|
|
173
|
+
name: "dagre",
|
|
88
174
|
} }));
|
|
89
175
|
}
|
|
@@ -3,7 +3,8 @@ interface Props {
|
|
|
3
3
|
action: () => void;
|
|
4
4
|
outline?: boolean;
|
|
5
5
|
disabled?: boolean;
|
|
6
|
+
popupMessage?: string;
|
|
6
7
|
children?: ReactNode;
|
|
7
8
|
}
|
|
8
|
-
export declare function DeleteButton({ action, outline, disabled, children }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export declare function DeleteButton({ action, outline, disabled, popupMessage, children }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
9
10
|
export {};
|
|
@@ -11,9 +11,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
\*****************************************************************************/
|
|
12
12
|
import { Button, OverlayTrigger, Popover } from "react-bootstrap";
|
|
13
13
|
import { Trash } from "react-bootstrap-icons";
|
|
14
|
-
export function DeleteButton({ action, outline, disabled, children }) {
|
|
14
|
+
export function DeleteButton({ action, outline, disabled, popupMessage = "Confirm", children }) {
|
|
15
15
|
if (disabled) {
|
|
16
16
|
return null;
|
|
17
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:
|
|
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: popupMessage }) }) }), children: _jsxs(Button, { variant: outline ? "outline-danger" : "danger", disabled: disabled, children: [_jsx(Trash, {}), " ", children] }) }));
|
|
19
19
|
}
|
|
@@ -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,16 @@ 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(
|
|
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, { config: {
|
|
29
|
+
loader: { load: ["[tex]/color"] },
|
|
30
|
+
tex: {
|
|
31
|
+
packages: { "[+]": ["color"] },
|
|
32
|
+
},
|
|
33
|
+
}, children: pathname.endsWith(SELECT_DECAYS_PATH) ? (_jsx(DecaySearchPage, {})) : pathname.endsWith(VARIABLES_PATH) ? (_jsx(DecayTreeConfigPage, {})) : (_jsx(RequestPage, {})) }) }) }) }) }));
|
|
28
34
|
}
|
|
@@ -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,13 +10,15 @@ 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();
|
|
17
19
|
const navigate = useNavigate();
|
|
18
20
|
const [showProdUploadModal, setShowProdUploadModal] = useState(false);
|
|
19
|
-
const
|
|
21
|
+
const configureAllDtts = async () => {
|
|
20
22
|
setRows((prev) => prev.map((r) => ({ ...r, editTree: true })));
|
|
21
23
|
await navigate(`${basePath}${VARIABLES_PATH}`);
|
|
22
24
|
};
|
|
@@ -24,6 +26,6 @@ export function RequestButtonGroup({ variant, basePath }) {
|
|
|
24
26
|
return null;
|
|
25
27
|
}
|
|
26
28
|
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
|
-
|
|
29
|
+
configureAllDtts().catch(console.error);
|
|
28
30
|
}, 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
31
|
}
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
|
|
2
|
-
hideDownloadButtons: boolean;
|
|
3
|
-
hideUploadButtons: boolean;
|
|
4
|
-
basePath: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function RequestRow({ hideDownloadButtons, hideUploadButtons, basePath }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
-
export {};
|
|
1
|
+
export declare function RequestRow(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -2,19 +2,20 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Button, Col, OverlayTrigger, Popover, Row } from "react-bootstrap";
|
|
3
3
|
import { InfoCircle } from "react-bootstrap-icons";
|
|
4
4
|
import { StrippingLineInfo } from "./StrippingLineInfo";
|
|
5
|
-
import {
|
|
6
|
-
import { DttNameInput } from "./DttNameInput";
|
|
5
|
+
import { DecayCard } from "./DecayCard";
|
|
7
6
|
import { useMetadata } from "../providers/MetadataProvider";
|
|
8
|
-
import { useRows } from "../providers/RowsProvider";
|
|
9
7
|
import { BookkeepingPathDropdown } from "./BookkeepingPathDropdown";
|
|
10
8
|
import { StrippingLineDropdown } from "./StrippingLineDropdown";
|
|
11
9
|
import { useRow } from "../providers/RowProvider";
|
|
12
|
-
|
|
10
|
+
import { VerticalLine } from "./VerticalLine";
|
|
11
|
+
import { DeleteButton } from "./DeleteButton";
|
|
12
|
+
import { useRows } from "../providers/RowsProvider";
|
|
13
|
+
export function RequestRow() {
|
|
13
14
|
const metadata = useMetadata();
|
|
14
15
|
const { row } = useRow();
|
|
15
16
|
const { removeRow } = useRows();
|
|
16
17
|
if (!metadata) {
|
|
17
18
|
return null;
|
|
18
19
|
}
|
|
19
|
-
return (_jsxs(Row, { className: "align-items-
|
|
20
|
+
return (_jsxs(Row, { className: "align-items-stretch mt-1", children: [_jsx(Col, { xs: 5, children: _jsx(DecayCard, {}) }), _jsxs(Col, { xs: 6, className: "d-flex flex-column gap-2", children: [_jsx(Row, { children: _jsxs("div", { className: "d-flex flex-row justify-content-between align-items-center gap-3", children: [_jsx("div", { style: { width: "100%" }, children: _jsx(StrippingLineDropdown, {}) }), _jsx(OverlayTrigger, { trigger: "click", 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(Row, { children: _jsx(BookkeepingPathDropdown, {}) })] }), _jsxs(Col, { xs: 1, className: "d-flex align-items-center justify-content-center gap-4", children: [_jsx(VerticalLine, {}), _jsx(DeleteButton, { action: () => removeRow(row.id), popupMessage: "Delete row" })] })] }));
|
|
20
21
|
}
|
|
@@ -24,5 +24,5 @@ export function StrippingLineBadge({ version, line, stream, showLink }) {
|
|
|
24
24
|
target: "_blank",
|
|
25
25
|
}
|
|
26
26
|
: {};
|
|
27
|
-
return (_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: metadata ? metadata.strippingHints[version].description : "..." }), children: _jsx(Badge, { pill: true, bg: "info", ...badgeProps, children: "S" + version }) }));
|
|
27
|
+
return (_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { style: { zIndex: 9999 }, children: metadata ? metadata.strippingHints[version].description : "..." }), children: _jsx(Badge, { pill: true, bg: "info", ...badgeProps, children: "S" + version }) }));
|
|
28
28
|
}
|
|
@@ -10,12 +10,9 @@
|
|
|
10
10
|
\*****************************************************************************/
|
|
11
11
|
import { GroupBase, Props as SelectProps } from "react-select";
|
|
12
12
|
import { ReactNode } from "react";
|
|
13
|
-
type
|
|
13
|
+
type ToolDropdownOption = {
|
|
14
14
|
value: string;
|
|
15
15
|
label: ReactNode;
|
|
16
16
|
};
|
|
17
|
-
|
|
18
|
-
filterToolTags: string[];
|
|
19
|
-
}
|
|
20
|
-
export declare function TupleToolDropdown({ filterToolTags, ...props }: Props): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare function TupleToolClassDropdown(props: SelectProps<ToolDropdownOption, false, GroupBase<ToolDropdownOption>>): import("react/jsx-runtime").JSX.Element;
|
|
21
18
|
export {};
|
|
@@ -13,17 +13,23 @@ import Select from "react-select";
|
|
|
13
13
|
import { TupleToolLabel } from "./TupleToolLabel";
|
|
14
14
|
import { useMetadata } from "../providers/MetadataProvider.js";
|
|
15
15
|
import { TupleTool } from "../models/tupleTool";
|
|
16
|
-
|
|
16
|
+
import { useDtt } from "../providers/DttProvider";
|
|
17
|
+
export function TupleToolClassDropdown(props) {
|
|
17
18
|
const metadata = useMetadata();
|
|
19
|
+
const { selectedBranch } = useDtt();
|
|
20
|
+
const allowedTags = ["IParticleTupleTool", ...(selectedBranch.length === 0 ? ["IEventTupleTool"] : [])];
|
|
21
|
+
const disallowedTools = ["LoKi__Hybrid__ArrayTupleTool"];
|
|
22
|
+
// Group tools by tag
|
|
18
23
|
const options = metadata
|
|
19
|
-
?
|
|
24
|
+
? allowedTags.map((allowedTag) => ({
|
|
20
25
|
label: allowedTag,
|
|
21
26
|
options: Object.keys(metadata.tupleTools.tupleTools)
|
|
22
27
|
.sort()
|
|
23
28
|
.map(TupleTool.fromString)
|
|
24
29
|
.map((tool) => ({ value: tool.toString(), label: _jsx(TupleToolLabel, { tool: tool }) }))
|
|
25
|
-
.filter((tool) => metadata.tupleTools.tupleTools[tool.value].tags.includes(allowedTag)
|
|
30
|
+
.filter((tool) => metadata.tupleTools.tupleTools[tool.value].tags.includes(allowedTag) &&
|
|
31
|
+
!disallowedTools.includes(tool.value)),
|
|
26
32
|
}))
|
|
27
33
|
: [];
|
|
28
|
-
return (_jsx("div", { className: "react-select form-control p-0", children: _jsx(Select, { options: options, isLoading: !metadata, ...props }) }));
|
|
34
|
+
return (_jsx("div", { className: "react-select form-control p-0", children: _jsx(Select, { placeholder: "TupleTool class", options: options, isLoading: !metadata, ...props }) }));
|
|
29
35
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
interface Props {
|
|
2
|
-
branch: string[];
|
|
3
2
|
onGroupSelected: (group: string) => void;
|
|
4
3
|
}
|
|
5
|
-
export declare function TupleToolGroup({
|
|
4
|
+
export declare function TupleToolGroup({ onGroupSelected }: Props): import("react/jsx-runtime").JSX.Element;
|
|
6
5
|
export {};
|
|
@@ -3,14 +3,14 @@ import { Button, Card, ListGroup, OverlayTrigger, Popover } from "react-bootstra
|
|
|
3
3
|
import { PencilSquare } from "react-bootstrap-icons";
|
|
4
4
|
import { DecayLatex } from "./DecayLatex";
|
|
5
5
|
import { useDtt } from "../providers/DttProvider";
|
|
6
|
-
export function TupleToolGroup({
|
|
7
|
-
const { dtt, decay } = useDtt();
|
|
6
|
+
export function TupleToolGroup({ onGroupSelected }) {
|
|
7
|
+
const { dtt, decay, selectedBranch } = useDtt();
|
|
8
8
|
let groups = {};
|
|
9
|
-
if (
|
|
9
|
+
if (selectedBranch.length === 0) {
|
|
10
10
|
groups = dtt.config.groups;
|
|
11
11
|
}
|
|
12
|
-
else if (
|
|
13
|
-
const filteredGroups = Object.entries(dtt.config.groups).filter(([key]) => key.includes(
|
|
12
|
+
else if (selectedBranch.length === 1) {
|
|
13
|
+
const filteredGroups = Object.entries(dtt.config.groups).filter(([key]) => key.includes(selectedBranch[0]));
|
|
14
14
|
groups = Object.fromEntries(filteredGroups);
|
|
15
15
|
}
|
|
16
16
|
const groupKeys = Object.keys(groups);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
interface Props {
|
|
2
|
-
branch: string[];
|
|
3
2
|
onGroupSelected: (group: string) => void;
|
|
4
3
|
onSave: () => void;
|
|
5
4
|
}
|
|
6
|
-
export declare function TupleToolList({
|
|
5
|
+
export declare function TupleToolList({ onGroupSelected, onSave }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
7
6
|
export {};
|
|
@@ -19,19 +19,23 @@ import { TupleToolGroup } from "./TupleToolGroup";
|
|
|
19
19
|
import { AddTupleToolModal } from "./modals/AddTupleToolModal";
|
|
20
20
|
import { ConfigureTupleToolModal } from "./modals/ConfigureTupleToolModal";
|
|
21
21
|
import { useDtt } from "../providers/DttProvider";
|
|
22
|
-
export function TupleToolList({
|
|
22
|
+
export function TupleToolList({ onGroupSelected, onSave }) {
|
|
23
23
|
const metadata = useMetadata();
|
|
24
|
-
const { dtt, dirty, save, revert, removeTool } = useDtt();
|
|
24
|
+
const { dtt, dirty, save, revert, removeTool, selectedBranch } = useDtt();
|
|
25
25
|
const [showAddModal, setShowAddModal] = useState(false);
|
|
26
|
-
const [
|
|
26
|
+
const [showConfigModal, setShowConfigModal] = useState(null);
|
|
27
27
|
if (!metadata) {
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
|
-
const tools = dtt.listTools(
|
|
31
|
-
const filterToolTags = branch.length === 0 ? ["IParticleTupleTool", "IEventTupleTool"] : ["IParticleTupleTool"];
|
|
30
|
+
const tools = dtt.listTools(selectedBranch);
|
|
32
31
|
return (_jsxs(_Fragment, { children: [_jsxs(Card, { children: [_jsxs(Card.Header, { className: "d-flex justify-content-between align-items-start", children: [_jsxs("span", { children: [tools.length, " TupleTool", tools.length === 1 ? "" : "s"] }), _jsx(Button, { variant: "success", size: "sm", onClick: () => setShowAddModal(true), children: _jsx(PlusLg, {}) })] }), _jsx(ListGroup, { variant: "flush", children: tools.map((tool) => {
|
|
33
|
-
return (_jsxs(ListGroup.Item, { className: "d-flex justify-content-between align-items-start", variant:
|
|
34
|
-
}) })] }), showAddModal && (_jsx(AddTupleToolModal, {
|
|
32
|
+
return (_jsxs(ListGroup.Item, { className: "d-flex justify-content-between align-items-start", variant: showConfigModal?.tool.equals(tool) ? "secondary" : "", children: [_jsx(TupleToolLabel, { tool: tool }), _jsxs(ButtonGroup, { size: "sm", children: [_jsx(Button, { variant: "outline-secondary", onClick: () => setShowConfigModal({ tool, deleteIfCancelled: false }), children: _jsx(PencilSquare, {}) }), _jsx(DeleteButton, { outline: true, action: () => removeTool(selectedBranch, tool) })] })] }, tool.toString()));
|
|
33
|
+
}) })] }), showAddModal && (_jsx(AddTupleToolModal, { onClose: (newTool) => {
|
|
34
|
+
setShowAddModal(false);
|
|
35
|
+
if (newTool && newTool.class === "LoKi__Hybrid__TupleTool") {
|
|
36
|
+
setShowConfigModal({ tool: newTool, deleteIfCancelled: true });
|
|
37
|
+
}
|
|
38
|
+
} })), showConfigModal && (_jsx(ConfigureTupleToolModal, { tool: showConfigModal.tool, deleteIfCancelled: showConfigModal.deleteIfCancelled, onClose: () => setShowConfigModal(null) })), selectedBranch.length === 0 && Object.keys(dtt.config.groups).length > 0 && (_jsx(TupleToolGroup, { onGroupSelected: onGroupSelected })), _jsxs(ButtonGroup, { className: "mt-2", children: [_jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Save changes to this DecayTreeTuple" }), children: _jsx(Button, { onClick: () => {
|
|
35
39
|
save();
|
|
36
40
|
onSave();
|
|
37
41
|
}, disabled: !dirty, children: "Save" }) }), _jsx(OverlayTrigger, { overlay: _jsx(Tooltip, { children: "Discard changes to this DecayTreeTuple" }), children: _jsx(Button, { variant: "outline-danger", onClick: revert, disabled: !dirty, children: "Revert" }) })] })] }));
|