Merge pull request #1459 from satti-hari-krishna-reddy/new-sigma
sigma detection ui
This commit is contained in:
@@ -535,6 +535,8 @@ const AngularWorkflow = (defaultprops) => {
|
||||
const [listCache, setListCache] = React.useState([]);
|
||||
const [selectedOption, setSelectedOption] = React.useState("");
|
||||
const [tenzirConfigModalOpen, setTenzirConfigModalOpen] = React.useState(false);
|
||||
const [rules, setRules] = React.useState([]);
|
||||
const [sigmaFilesNames, setSigmaFileNames] = React.useState("")
|
||||
|
||||
const [distributedFromParent, setDistributedFromParent] = React.useState("")
|
||||
const [suborgWorkflows, setSuborgWorkflows] = React.useState([])
|
||||
@@ -1438,7 +1440,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
});
|
||||
};
|
||||
|
||||
const handleKafkaSubmit = (trigger) => {
|
||||
const handleCommandSubmit = (trigger) => {
|
||||
if (trigger.trigger_type !== "PIPELINE") {
|
||||
toast("Unable to save the configuration");
|
||||
return;
|
||||
@@ -1446,18 +1448,48 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
|
||||
trigger.parameters = []
|
||||
|
||||
const topic = document.getElementById('topic')?.value;
|
||||
const bootstrapServers = document.getElementById('bootstrap_servers')?.value;
|
||||
const groupId = document.getElementById('group_id')?.value;
|
||||
//const autoOffsetReset = document.getElementById('auto_offset_reset')?.value;
|
||||
const command = document.getElementById('sigma')?.value
|
||||
|
||||
if(command) {
|
||||
trigger.parameters.push({
|
||||
name: "command",
|
||||
value: command
|
||||
})
|
||||
} else {
|
||||
toast("Please enter the comamnd");
|
||||
return;
|
||||
}
|
||||
|
||||
// if (autoOffsetReset) {
|
||||
// trigger.parameters.push({
|
||||
// name: "auto_offset_reset",
|
||||
// value: autoOffsetReset
|
||||
// });
|
||||
// }
|
||||
|
||||
setTenzirConfigModalOpen(false);
|
||||
};
|
||||
|
||||
const handleSubmit = (trigger) => {
|
||||
if (trigger.trigger_type !== "PIPELINE") {
|
||||
toast("Unable to save the configuration");
|
||||
return;
|
||||
}
|
||||
if (selectedOption === "Kafka Queue") {
|
||||
trigger.parameters = []
|
||||
|
||||
const topic = document.getElementById('topic')?.value
|
||||
const bootstrapServers = document.getElementById('bootstrap_servers')?.value
|
||||
const groupId = document.getElementById('group_id')?.value
|
||||
const autoOffsetReset = document.getElementById('auto_offset_reset')?.value;
|
||||
|
||||
if(topic) {
|
||||
trigger.parameters.push({
|
||||
name: "topic",
|
||||
value: topic
|
||||
});
|
||||
})
|
||||
} else {
|
||||
toast("please enter the topic name");
|
||||
toast("Please enter the topic name");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1478,16 +1510,33 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
});
|
||||
}
|
||||
|
||||
// if (autoOffsetReset) {
|
||||
// trigger.parameters.push({
|
||||
// name: "auto_offset_reset",
|
||||
// value: autoOffsetReset
|
||||
// });
|
||||
// }
|
||||
if (autoOffsetReset) {
|
||||
trigger.parameters.push({
|
||||
name: "auto_offset_reset",
|
||||
value: autoOffsetReset
|
||||
});
|
||||
}
|
||||
|
||||
setTenzirConfigModalOpen(false);
|
||||
} else if (selectedOption === "Syslog listener") {
|
||||
trigger.parameters = []
|
||||
|
||||
const endpoint = document.getElementById('endpoint')?.value
|
||||
|
||||
if(endpoint) {
|
||||
trigger.parameters.push({
|
||||
name: "endpoint",
|
||||
value: endpoint
|
||||
})
|
||||
} else {
|
||||
toast("Please enter your endpoint");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
const handleColoring = (actionId, status, label) => {
|
||||
if (cy === undefined) {
|
||||
return
|
||||
@@ -8245,11 +8294,11 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
toast("Pipeline deleted!")
|
||||
return
|
||||
}
|
||||
|
||||
if (trigger.parameters){
|
||||
trigger.parameters.push({
|
||||
name: data.name,
|
||||
value: data.command,
|
||||
});
|
||||
});}
|
||||
|
||||
if (data.type === "stop") trigger.status = "stopped";
|
||||
else trigger.status = "running";
|
||||
@@ -8257,7 +8306,6 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
|
||||
setSelectedTrigger(trigger);
|
||||
setWorkflow(workflow);
|
||||
console.log("Should set the status to running and save");
|
||||
saveWorkflow(workflow);
|
||||
}
|
||||
})
|
||||
@@ -8332,6 +8380,32 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
});
|
||||
};
|
||||
|
||||
const getSigmaInfo = () => {
|
||||
const url = globalUrl + "/api/v1/files/detection/sigma_rules";
|
||||
|
||||
fetch(url, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
if (responseJson["success"] === false) {
|
||||
toast("Failed to get sigma rules");
|
||||
} else {
|
||||
setRules(responseJson.sigma_info);
|
||||
|
||||
}
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
console.log("Error in getting sigma files: ", error);
|
||||
toast("An error occurred while fetching sigma rules");
|
||||
});
|
||||
};
|
||||
|
||||
const parsedHeight = isMobile ? bodyHeight - appBarSize * 4 : bodyHeight - appBarSize - 50
|
||||
const appViewStyle = {
|
||||
marginLeft: 5,
|
||||
@@ -15277,6 +15351,14 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
}
|
||||
|
||||
</div>
|
||||
const defaultEnvironment = environments.find(
|
||||
(env) => env.default && env.Name.toLowerCase() !== "cloud"
|
||||
);
|
||||
|
||||
if (selectedTrigger.trigger_type === "PIPELINE" && selectedTrigger.environment === "onprem" && defaultEnvironment !== undefined) {
|
||||
selectedTrigger.environment = defaultEnvironment.Name
|
||||
setSelectedTrigger(selectedTrigger) }
|
||||
|
||||
const PipelineSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined && selectedTrigger.trigger_type !== "SCHEDULE" ? null :
|
||||
<div style={appApiViewStyle}>
|
||||
<h3 style={{ marginBottom: "5px" }}>
|
||||
@@ -15375,14 +15457,32 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
<div
|
||||
key="syslogListener"
|
||||
onClick={() => {
|
||||
// setSelectedOption("Syslog listener")
|
||||
// setTenzirConfigModalOpen(true);
|
||||
}}
|
||||
if(selectedTrigger.status === "running"){
|
||||
//toast("please stop the trigger to edit the configuration");
|
||||
return;
|
||||
} else {
|
||||
setSelectedOption("Syslog listener");
|
||||
const url = `${globalUrl}/api/v1/pipelines/pipeline_${selectedTrigger.id}`
|
||||
const command = `from tcp://192.168.1.100:5162 read syslog | import`
|
||||
const pipelineConfig = {
|
||||
command: command,
|
||||
name: selectedTrigger.label,
|
||||
type: "create",
|
||||
environment: selectedTrigger.environment,
|
||||
workflow_id: workflow.id,
|
||||
trigger_id: selectedTrigger.id,
|
||||
start_node: "",
|
||||
url:url,
|
||||
};
|
||||
submitPipeline(selectedTrigger, selectedTriggerIndex, pipelineConfig);
|
||||
|
||||
|
||||
}}}
|
||||
style={{
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
padding: 10,
|
||||
cursor: "not-allowed",
|
||||
cursor: "pointer",
|
||||
marginTop: 5,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
@@ -15392,27 +15492,46 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
control={
|
||||
<Radio
|
||||
checked={selectedOption === "Syslog listener"}
|
||||
onChange={() => setSelectedOption("Syslog listener")}
|
||||
onChange={() => {
|
||||
if (selectedTrigger.status !== "running"){
|
||||
setSelectedOption("Syslog listener")}}
|
||||
}
|
||||
value={"Syslog listener"}
|
||||
name="option"
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
label="Start Syslog listener"
|
||||
label= {selectedOption === "Syslog listener" && selectedTrigger.status === "running" ? "listening at 192.168.1.100:5162" : "Start Syslog listener"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
key="sigmaRulesearch"
|
||||
onClick={() => {
|
||||
// setSelectedOption("Sigma Rulesearch")
|
||||
// setTenzirConfigModalOpen(true);
|
||||
}}
|
||||
if(selectedTrigger.status === "running"){
|
||||
// toast("please stop the trigger to edit the configuration");
|
||||
return;
|
||||
} else {
|
||||
setSelectedOption("SigmaRule");
|
||||
const url = `${globalUrl}/api/v1/pipelines/pipeline_${selectedTrigger.id}`
|
||||
const command = `export | sigma /var/lib/tenzir/sigma_rules | to ${url}`
|
||||
const pipelineConfig = {
|
||||
command: command,
|
||||
name: selectedTrigger.label,
|
||||
type: "create",
|
||||
environment: selectedTrigger.environment,
|
||||
workflow_id: workflow.id,
|
||||
trigger_id: selectedTrigger.id,
|
||||
start_node: "",
|
||||
url:url,
|
||||
};
|
||||
submitPipeline(selectedTrigger, selectedTriggerIndex, pipelineConfig);
|
||||
|
||||
}}}
|
||||
style={{
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
padding: 10,
|
||||
cursor: "not-allowed",
|
||||
cursor: "pointer",
|
||||
marginTop: 5,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
@@ -15421,11 +15540,12 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Radio
|
||||
checked={selectedOption === "Sigma Rulesearch"}
|
||||
onChange={() => setSelectedOption("Sigma Rulesearch")}
|
||||
checked={selectedOption === "SigmaRule"}
|
||||
onChange={() => {
|
||||
if (selectedTrigger.status !== "running"){
|
||||
setSelectedOption("SigmaRule")}}}
|
||||
value={"Sigma Rulesearch"}
|
||||
name="option"
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
label="Run Sigma Rulesearch"
|
||||
@@ -15456,7 +15576,9 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
control={
|
||||
<Radio
|
||||
checked={selectedOption === "Kafka Queue"}
|
||||
onChange={() => setSelectedOption("Kafka Queue")}
|
||||
onChange={() => {
|
||||
if (selectedTrigger.status !== "running"){
|
||||
setSelectedOption("Kafka Queue")}}}
|
||||
value={"Kafka Queue"}
|
||||
name="option"
|
||||
/>
|
||||
@@ -15472,10 +15594,12 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
disabled={selectedTrigger.status === "running"}
|
||||
onClick={() => {
|
||||
|
||||
if (selectedOption === "Kafka Queue"){
|
||||
const url = `${globalUrl}/api/v1/pipelines/pipeline_${selectedTrigger.id}`
|
||||
const topic = (selectedTrigger?.parameters?.find(param => param.name === "topic")?.value) || ''
|
||||
const bootstrapServers = (selectedTrigger?.parameters?.find(param => param.name === "bootstrap_servers")?.value) || ''
|
||||
const groupId = (selectedTrigger?.parameters?.find(param => param.name === "group_id")?.value) || ''
|
||||
// const autoOffsetReset = (selectedTrigger?.parameters?.find(param => param.name === "auto_offset_reset")?.value) || ''
|
||||
const autoOffsetReset = (selectedTrigger?.parameters?.find(param => param.name === "auto_offset_reset")?.value) || ''
|
||||
let command = "from kafka"
|
||||
|
||||
if(topic) {
|
||||
@@ -15496,15 +15620,15 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
} else {
|
||||
command = `${command},group.id=${selectedTrigger.id}`
|
||||
}
|
||||
// if(autoOffsetReset) {
|
||||
// command = `${command},auto.offset.reset=${autoOffsetReset}`
|
||||
// } else {
|
||||
// command = `${command},auto.offset.reset=earliest`
|
||||
if(autoOffsetReset) {
|
||||
command = `${command},auto.offset.reset=${autoOffsetReset}`
|
||||
} else {
|
||||
command = `${command},auto.offset.reset=earliest`
|
||||
|
||||
// }
|
||||
}
|
||||
command = `${command},auto.offset.reset=earliest`
|
||||
command = `${command},client.id=${selectedTrigger.id},enable.auto.commit=true,auto.commit.interval.ms=1`
|
||||
command = `${command} read json | to ${globalUrl}/api/v1/pipelines/pipeline_${selectedTrigger.id}`
|
||||
command = `${command} read json | to ${url}`
|
||||
|
||||
const pipelineConfig = {
|
||||
command: command,
|
||||
@@ -15514,9 +15638,11 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
workflow_id: workflow.id,
|
||||
trigger_id: selectedTrigger.id,
|
||||
start_node: "",
|
||||
url: url,
|
||||
};
|
||||
submitPipeline(selectedTrigger, selectedTriggerIndex, pipelineConfig);
|
||||
}}
|
||||
}
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Start
|
||||
@@ -21229,146 +21355,142 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
</Dialog>
|
||||
) : null;
|
||||
|
||||
const tenzirConfigModal = tenzirConfigModalOpen ? (
|
||||
<Dialog
|
||||
PaperComponent={PaperComponent}
|
||||
hideBackdrop={true}
|
||||
disableEnforceFocus={true}
|
||||
disableBackdropClick={true}
|
||||
style={{ pointerEvents: "none" }}
|
||||
open={tenzirConfigModalOpen}
|
||||
PaperProps={{
|
||||
style: {
|
||||
pointerEvents: "auto",
|
||||
color: "white",
|
||||
minWidth: 600,
|
||||
minHeight: 450,
|
||||
maxHeight: 450,
|
||||
padding: 15,
|
||||
overflow: "hidden",
|
||||
zIndex: 10012,
|
||||
border: theme.palette.defaultBorder,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
flex: 2,
|
||||
padding: 0,
|
||||
minHeight: isMobile ? "90%" : 700,
|
||||
maxHeight: isMobile ? "90%" : 700,
|
||||
overflowY: "auto",
|
||||
overflowX: isMobile ? "auto" : "hidden",
|
||||
}}
|
||||
>
|
||||
<DialogTitle id="tenzir-config-modal" style={{ cursor: "move" }}>
|
||||
<div style={{ color: "white" }}>Configuration options for {selectedOption}</div>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
{selectedOption === "Kafka Queue" && (
|
||||
<>
|
||||
<b>Topic</b>
|
||||
<TextField
|
||||
id="topic"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"topic name"}
|
||||
defaultValue={(selectedTrigger?.parameters?.find(param => param.name === "topic")?.value) || ''}
|
||||
/>
|
||||
<b>bootstrap.servers</b>
|
||||
<TextField
|
||||
id="bootstrap_servers"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"broker1.example.com:9092,192.168.1.100:9092"}
|
||||
defaultValue={(selectedTrigger?.parameters?.find(param => param.name === "bootstrap_servers")?.value) || ''}
|
||||
/>
|
||||
<b>group.id</b>
|
||||
<TextField
|
||||
id="group_id"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"tenzir"}
|
||||
defaultValue={(selectedTrigger?.parameters?.find(param => param.name === "group_id")?.value) || ''}
|
||||
/>
|
||||
{/* <b>auto.offest.reset</b>
|
||||
<TextField
|
||||
id="auto_offset_reset"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"earliest"}
|
||||
defaultValue={(selectedTrigger?.parameters?.find(param => param.name === "auto_offset_reset")?.value) || ''}
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
style={{ borderRadius: "0px" }}
|
||||
onClick={() => {
|
||||
setTenzirConfigModalOpen(false);
|
||||
const TenzirConfigModal = () => {
|
||||
if (!tenzirConfigModalOpen) return null;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
PaperComponent={PaperComponent}
|
||||
hideBackdrop={true}
|
||||
disableEnforceFocus={true}
|
||||
disableBackdropClick={true}
|
||||
style={{ pointerEvents: "none" }}
|
||||
open={tenzirConfigModalOpen}
|
||||
PaperProps={{
|
||||
style: {
|
||||
pointerEvents: "auto",
|
||||
color: "white",
|
||||
minWidth: 600,
|
||||
minHeight: 550,
|
||||
maxHeight: 550,
|
||||
padding: 15,
|
||||
overflow: "hidden",
|
||||
zIndex: 10012,
|
||||
border: theme.palette.defaultBorder,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle id="tenzir-config-modal" style={{ cursor: "move" }}>
|
||||
<div style={{ color: "white" }}>Configuration options for Kafka</div>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
{selectedOption === "Kafka Queue" ? (
|
||||
<div>
|
||||
<b>Topic</b>
|
||||
<TextField
|
||||
id="topic"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
style={{ borderRadius: "0px" }}
|
||||
onClick={() => {
|
||||
handleKafkaSubmit(selectedTrigger);
|
||||
InputProps={{
|
||||
style: {},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</div>
|
||||
placeholder={"topic name"}
|
||||
defaultValue={
|
||||
selectedTrigger?.parameters?.find(
|
||||
(param) => param.name === "topic",
|
||||
)?.value || ""
|
||||
}
|
||||
/>
|
||||
<b>bootstrap.servers</b>
|
||||
<TextField
|
||||
id="bootstrap_servers"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"broker1.example.com:9092,192.168.1.100:9092"}
|
||||
defaultValue={
|
||||
selectedTrigger?.parameters?.find(
|
||||
(param) => param.name === "bootstrap_servers",
|
||||
)?.value || ""
|
||||
}
|
||||
/>
|
||||
<b>group.id</b>
|
||||
<TextField
|
||||
id="group_id"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"tenzir"}
|
||||
defaultValue={
|
||||
selectedTrigger?.parameters?.find(
|
||||
(param) => param.name === "group_id",
|
||||
)?.value || ""
|
||||
}
|
||||
/>
|
||||
<b>auto.offest.reset</b>
|
||||
<TextField
|
||||
id="auto_offset_reset"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"earliest"}
|
||||
defaultValue={
|
||||
selectedTrigger?.parameters?.find(
|
||||
(param) => param.name === "auto_offset_reset",
|
||||
)?.value || ""
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : null}{" "}
|
||||
|
||||
<IconButton
|
||||
style={{
|
||||
zIndex: 5000,
|
||||
position: "absolute",
|
||||
top: 14,
|
||||
right: 18,
|
||||
color: "grey",
|
||||
}}
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button
|
||||
style={{ borderRadius: "0px" }}
|
||||
onClick={() => {
|
||||
setTenzirConfigModalOpen(false);
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Dialog>
|
||||
) : null;
|
||||
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
style={{ borderRadius: "0px" }}
|
||||
onClick={() => {
|
||||
handleSubmit(selectedTrigger);
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const SuggestionBoxUi = () => {
|
||||
@@ -21947,7 +22069,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
{codePopoutModal}
|
||||
{workflowRevisions}
|
||||
{authenticationModal}
|
||||
{tenzirConfigModal}
|
||||
{<TenzirConfigModal/>}
|
||||
{/*editWorkflowModal*/}
|
||||
{authgroupModal}
|
||||
{executionArgumentModal}
|
||||
|
||||
Reference in New Issue
Block a user