Skip to content

Commit

Permalink
Merge pull request #53 from DrDroidLab/@feature/support-dd-query-ui
Browse files Browse the repository at this point in the history
add dd support
  • Loading branch information
dimittal authored Apr 27, 2024
2 parents fb4aadb + 9503db1 commit 7bd0497
Show file tree
Hide file tree
Showing 11 changed files with 698 additions and 397 deletions.
107 changes: 107 additions & 0 deletions web/src/components/Playbooks/steps/OptionRender.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import { updateStep } from '../../../store/features/playbook/playbookSlice.ts';
import SelectComponent from '../../SelectComponent';
import ValueComponent from '../../ValueComponent';
import styles from './index.module.css';

export default function OptionRender({ data, removeErrors, task, stepIndex }) {
const dispatch = useDispatch();

const handleChange = (...args) => {
if (data.handleChange) {
data.handleChange(...args);
} else {
dispatch(updateStep({ index: stepIndex, key: data.key, value: args[0] }));
}

removeErrors(data.key);
};

const handleTextAreaChange = e => {
const val = e.target.value;
if (data.handleChange) {
data.handleChange(e);
} else {
dispatch(updateStep({ index: stepIndex, key: data.key, value: val }));
}

removeErrors(data.key);
};

const error = data.key ? task.showError && !data.selected && !task[`${data.key}`] : false;

switch (data.type) {
case 'options':
if (!(data.options?.length > 0)) return;
return (
<SelectComponent
key={data.key}
data={data.options}
placeholder={`Select ${data.label}`}
onSelectionChange={handleChange}
selected={data.selected ?? task[`${data.key}`]}
searchable={true}
disabled={data.disabled}
error={error}
{...data.additionalProps}
/>
);
case 'text-row':
case 'text':
return (
<div
className={`flex ${
data.type === 'text' ? 'flex-col' : 'flex-row items-center justify-center gap-2'
}`}
>
<p
style={{
marginTop: data.type === 'text' ? '10px' : '',
fontSize: '13px',
color: '#676666'
}}
>
<b>{data.label}</b>
</p>
<ValueComponent
key={data.key}
placeHolder={`Enter ${data?.label}`}
valueType={'STRING'}
onValueChange={handleChange}
value={data.selected || task[`${data.key}`]}
error={error}
{...data.additionalProps}
/>
</div>
);
case 'multiline':
return (
<div key={data.key} style={{ display: 'flex', flexDirection: 'column', width: '100%' }}>
<p style={{ marginTop: '10px', fontSize: '13px', color: '#676666' }}>
<b>{data.label}</b>
</p>
<textarea
className={styles['notes']}
rows={4}
value={data.value ?? task[`${data.key}`]}
onChange={handleTextAreaChange}
disabled={data.disabled}
style={error ? { borderColor: 'red' } : {}}
/>
</div>
);

case 'button':
return (
<button
className="p-1 border-2 w-fit border-purple-500 hover:bg-purple-500 text-purple-500 hover:text-white transition-all rounded cursor-pointer leading-none"
onClick={data.handleClick}
>
{data.label}
</button>
);
default:
return;
}
}
171 changes: 30 additions & 141 deletions web/src/components/Playbooks/steps/TaskDetails.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
/* eslint-disable react-hooks/exhaustive-deps */
import SelectComponent from '../../SelectComponent/index.jsx';
import styles from './index.module.css';
import { CircularProgress } from '@mui/material';
import { useLazyGetAssetsQuery } from '../../../store/features/playbook/api/index.ts';
import { useEffect, useRef } from 'react';
import { useDispatch } from 'react-redux';
import {
setErrors,
setSelectedGrafanaOptions,
updateStep
} from '../../../store/features/playbook/playbookSlice.ts';
import ValueComponent from '../../ValueComponent/index.jsx';
import { CircularProgress } from "@mui/material";
import { useLazyGetAssetsQuery } from "../../../store/features/playbook/api/index.ts";
import { useEffect, useRef } from "react";
import { useDispatch } from "react-redux";
import { setErrors } from "../../../store/features/playbook/playbookSlice.ts";
import OptionRender from "./OptionRender.jsx";
import VariablesBox from "./VariablesBox.jsx";

function TaskDetails({ task, data, stepIndex }) {
const [triggerGetAssets, { isFetching }] = useLazyGetAssetsQuery();
Expand All @@ -20,19 +15,20 @@ function TaskDetails({ task, data, stepIndex }) {
const getAssets = () => {
triggerGetAssets({
filter: data.assetFilterQuery,
stepIndex
stepIndex,
});
};

const setDefaultErrors = () => {
const errors = {};
for (let step of data.builder) {
for (let value of step) {
if (value.isOptional) continue;
if (!value.key || value.selected) {
break;
}
errors[value.key] = {
message: 'Please enter a value'
message: "Please enter a value",
};
}
}
Expand All @@ -41,7 +37,7 @@ function TaskDetails({ task, data, stepIndex }) {
dispatch(setErrors({ index: stepIndex, errors }));
};

const removeErrors = key => {
const removeErrors = (key) => {
const errors = structuredClone(task.errors ?? {});
delete errors[key];

Expand All @@ -68,94 +64,20 @@ function TaskDetails({ task, data, stepIndex }) {
}
}, [task]);

function handleOption(data) {
const handleChange = (...args) => {
if (data.handleChange) {
data.handleChange(...args);
} else {
dispatch(updateStep({ index: stepIndex, key: data.key, value: args[0] }));
}

removeErrors(data.key);
};

const handleTextAreaChange = e => {
const val = e.target.value;
if (data.handleChange) {
data.handleChange(e);
} else {
dispatch(updateStep({ index: stepIndex, key: data.key, value: val }));
}

removeErrors(data.key);
};

const error = data.key ? task.showError && !data.selected && !task[`${data.key}`] : false;

switch (data.type) {
case 'options':
if (!(data.options?.length > 0)) return;
return (
<SelectComponent
key={data.key}
data={data.options}
placeholder={`Select ${data.label}`}
onSelectionChange={handleChange}
selected={data.selected ?? task[`${data.key}`]}
searchable={true}
disabled={data.disabled}
error={error}
/>
);
case 'text':
return (
<div className="flex flex-col">
<p style={{ marginTop: '10px', fontSize: '13px', color: '#676666' }}>
<b>{data.label}</b>
</p>
<ValueComponent
key={data.key}
placeHolder={`Enter ${data?.label}`}
valueType={'STRING'}
onValueChange={handleChange}
value={data.selected || task[`${data.key}`]}
error={error}
/>
</div>
);
case 'multiline':
return (
<div key={data.key} style={{ display: 'flex', flexDirection: 'column', width: '100%' }}>
<p style={{ marginTop: '10px', fontSize: '13px', color: '#676666' }}>
<b>{data.label}</b>
</p>
<textarea
className={styles['notes']}
rows={4}
value={data.value ?? task[`${data.key}`]}
onChange={handleTextAreaChange}
disabled={data.disabled}
style={error ? { borderColor: 'red' } : {}}
/>
</div>
);
default:
return;
}
}

const handleVariableChange = (_, val) => {
dispatch(setSelectedGrafanaOptions({ index: stepIndex, option: val }));
};

return (
<>
{data?.builder?.map((step, index) => (
<div
key={index}
style={{ display: 'flex', marginTop: '5px', gap: '5px', alignItems: 'center' }}
>
{step.map(value => {
style={{
display: "flex",
marginTop: "5px",
gap: "5px",
alignItems: "center",
flexWrap: "wrap",
justifyContent: "flex-start",
}}>
{step.map((value) => {
let flag = true;
for (let val of value?.requires ?? []) {
if (!task[val]) {
Expand All @@ -164,54 +86,21 @@ function TaskDetails({ task, data, stepIndex }) {
}
}

if (flag) return handleOption(value);
if (flag)
return (
<OptionRender
data={value}
removeErrors={removeErrors}
stepIndex={stepIndex}
task={task}
/>
);
else return <></>;
})}
{isFetching && <CircularProgress size={20} />}
</div>
))}
<div className={styles['variables-box']}>
{task?.options && task?.options?.length > 0 && (
<div style={{ display: 'flex', gap: '5px', flexDirection: 'row' }}>
<p style={{ fontSize: '12px', color: 'darkgray', marginTop: '5px' }}>Variables</p>
{task?.options.map((option, i) => {
return (
<div key={stepIndex} style={{ display: 'flex', gap: '5px' }}>
{option?.values?.length > 0 ? (
<SelectComponent
data={option?.values.map((e, i) => {
return {
id: e,
label: e,
option
};
})}
placeholder={`Select ${option?.label?.label}`}
onSelectionChange={handleVariableChange}
selected={
task?.selectedOptions ? task?.selectedOptions[option?.variable] : ''
}
searchable={true}
/>
) : (
<ValueComponent
placeHolder={`Enter ${option?.variable}`}
valueType={'STRING'}
onValueChange={val =>
handleVariableChange({
id: val,
label: option.variable
})
}
value={task?.selectedOptions ? task?.selectedOptions[option?.variable] : ''}
/>
)}
</div>
);
})}
</div>
)}
</div>
<VariablesBox />
</>
);
}
Expand Down
58 changes: 58 additions & 0 deletions web/src/components/Playbooks/steps/VariablesBox.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import SelectComponent from '../../SelectComponent';
import styles from './index.module.css';
import { useDispatch } from 'react-redux';
import { setSelectedGrafanaOptions } from '../../../store/features/playbook/playbookSlice.ts';
import ValueComponent from '../../ValueComponent';

function VariablesBox({ task, stepIndex }) {
const dispatch = useDispatch();
const handleVariableChange = (_, val) => {
dispatch(setSelectedGrafanaOptions({ index: stepIndex, option: val }));
};

return (
<div className={styles['variables-box']}>
{task?.options && task?.options?.length > 0 && (
<div style={{ display: 'flex', gap: '5px', flexDirection: 'row' }}>
<p style={{ fontSize: '12px', color: 'darkgray', marginTop: '5px' }}>Variables</p>
{task?.options.map((option, i) => {
return (
<div key={stepIndex} style={{ display: 'flex', gap: '5px' }}>
{option?.values?.length > 0 ? (
<SelectComponent
data={option?.values.map((e, i) => {
return {
id: e,
label: e,
option
};
})}
placeholder={`Select ${option?.label?.label}`}
onSelectionChange={handleVariableChange}
selected={task?.selectedOptions ? task?.selectedOptions[option?.variable] : ''}
searchable={true}
/>
) : (
<ValueComponent
placeHolder={`Enter ${option?.variable}`}
valueType={'STRING'}
onValueChange={val =>
handleVariableChange({
id: val,
label: option.variable
})
}
value={task?.selectedOptions ? task?.selectedOptions[option?.variable] : ''}
/>
)}
</div>
);
})}
</div>
)}
</div>
);
}

export default VariablesBox;
Loading

0 comments on commit 7bd0497

Please sign in to comment.