Files
rowy/src/components/Table/TableHeader/Webhooks/WebhookModal.tsx
Sidney Alcantara 47535ed369 Merge branch 'develop' into feat/webhooks
* develop: (21 commits)
  generateBiggerId: remove console.log
  fix generateSmallerId algorithm (#567)
  fix merge
  fix inline cell of connect-service
  Fixes issue where the title field name is shown rather than the value
  Update reload screen copy (#530)
  Derivatives: don't list current field in listener field options
  potentially fix side drawer randomly scrolling
  JSON field: improve tree editor dark mode
  JSON: fix array support
  CodeEditor: use text field background color
  added a temp skip button for rules setting step
  JSON editor: add code editor mode (#509)
  CodeEditor: use TextField box-shadows & fix RichTextEditor box-shadows
  CodeEditor: fix onChange not being passed as prop
  consolidate CodeEditor to components/CodeEditor, allow resize, use github themes
  add CircularProgressOptical
  Import CSV: prevent import to ID field
  Import CSV: fix crash
  User Settings: move darker dark mode to theme
  ...
2021-10-28 19:14:55 +11:00

256 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from "react";
import _isEqual from "lodash/isEqual";
import _upperFirst from "lodash/upperFirst";
import useStateRef from "react-usestateref";
import {
Grid,
TextField,
FormControlLabel,
Switch,
Stepper,
Step,
StepButton,
StepContent,
Typography,
Link,
} from "@mui/material";
import ExpandIcon from "@mui/icons-material/KeyboardArrowDown";
import InlineOpenInNewIcon from "components/InlineOpenInNewIcon";
import Modal, { IModalProps } from "components/Modal";
import Step1Secret from "./Step1Secret";
import Step2Conditions from "./Step2Conditions";
import Step3Body from "./Step3Parser";
import { useConfirmation } from "components/ConfirmationDialog";
import { webhookNames, IWebhook } from "./utils";
import { WIKI_LINKS } from "constants/externalLinks";
type StepValidation = Record<"condition" | "parser", boolean>;
export interface IWebhookModalStepProps {
webhookObject: IWebhook;
setWebhookObject: React.Dispatch<React.SetStateAction<IWebhook>>;
validation: StepValidation;
setValidation: React.Dispatch<React.SetStateAction<StepValidation>>;
validationRef: React.RefObject<StepValidation>;
}
export interface IWebhookModalProps {
handleClose: IModalProps["onClose"];
handleAdd: (webhookObject: IWebhook) => void;
handleUpdate: (webhookObject: IWebhook) => void;
mode: "add" | "update";
webhookObject: IWebhook;
}
export default function WebhookModal({
handleClose,
handleAdd,
handleUpdate,
mode,
webhookObject: initialObject,
}: IWebhookModalProps) {
const { requestConfirmation } = useConfirmation();
const [webhookObject, setWebhookObject] = useState<IWebhook>(initialObject);
const [activeStep, setActiveStep] = useState(0);
const [validation, setValidation, validationRef] =
useStateRef<StepValidation>({ condition: true, parser: true });
const edited = !_isEqual(initialObject, webhookObject);
const handleAddOrUpdate = () => {
if (mode === "add") handleAdd(webhookObject);
if (mode === "update") handleUpdate(webhookObject);
};
const stepProps = {
webhookObject,
setWebhookObject,
validation,
setValidation,
validationRef,
};
return (
<Modal
onClose={handleClose}
disableBackdropClick
disableEscapeKeyDown
fullWidth
title={`${mode === "add" ? "Add" : "Update"} webhook: ${
webhookNames[webhookObject.type]
}`}
sx={{
"& .MuiPaper-root": {
maxWidth: 742 + 20,
height: 980,
},
}}
children={
<>
<Grid
container
spacing={4}
justifyContent="center"
alignItems="center"
>
<Grid item xs={6}>
<TextField
size="small"
required
label="Webhook name"
variant="filled"
fullWidth
autoFocus
value={webhookObject.name}
error={edited && !webhookObject.name.length}
helperText={
edited && !webhookObject.name.length ? "Required" : " "
}
onChange={(event) => {
setWebhookObject({
...webhookObject,
name: event.target.value,
});
}}
/>
</Grid>
<Grid item xs={6}>
<FormControlLabel
control={
<Switch
checked={webhookObject.active}
onChange={(e) =>
setWebhookObject((webhookObject) => ({
...webhookObject,
active: e.target.checked,
}))
}
size="medium"
/>
}
label={`Webhook endpoint is ${
!webhookObject.active ? "de" : ""
}activated`}
/>
</Grid>
</Grid>
<Stepper
nonLinear
activeStep={activeStep}
orientation="vertical"
sx={{
mt: 0,
"& .MuiStepLabel-root": { width: "100%" },
"& .MuiStepLabel-label": {
display: "flex",
width: "100%",
typography: "subtitle2",
"&.Mui-active": { typography: "subtitle2" },
},
"& .MuiStepLabel-label svg": {
display: "block",
marginLeft: "auto",
my: ((24 - 18) / 2 / 8) * -1,
transition: (theme) => theme.transitions.create("transform"),
},
"& .Mui-active svg": {
transform: "rotate(180deg)",
},
}}
>
<Step>
<StepButton onClick={() => setActiveStep(0)}>
Verification
<ExpandIcon />
</StepButton>
<StepContent>
<Typography gutterBottom>
Set the verification secret for the webhook.
</Typography>
<Step1Secret {...stepProps} />
</StepContent>
</Step>
<Step>
<StepButton onClick={() => setActiveStep(1)}>
Conditions (optional)
<ExpandIcon />
</StepButton>
<StepContent>
<Typography gutterBottom>
Optionally, write a function that determines if the webhook
call should be processed. Leave the function to always return{" "}
<code>true</code> if you do not want to write additional
logic.
</Typography>
<Step2Conditions {...stepProps} />
</StepContent>
</Step>
<Step>
<StepButton onClick={() => setActiveStep(2)}>
Parser
<ExpandIcon />
</StepButton>
<StepContent>
<Typography gutterBottom>
Write the webhook parsed function. The returned object of the
parser will be added as new row{" "}
<Link
href={
WIKI_LINKS[
`webhooks${_upperFirst(webhookObject.type)}`
] || WIKI_LINKS.webhooks
}
target="_blank"
rel="noopener noreferrer"
>
Docs
<InlineOpenInNewIcon />
</Link>
</Typography>
<Step3Body {...stepProps} />
</StepContent>
</Step>
</Stepper>
</>
}
actions={{
primary: {
children: mode === "add" ? "Add" : "Update",
disabled: !edited || !webhookObject.name.length,
onClick: () => {
let warningMessage;
if (!validation.condition && !validation.parser) {
warningMessage = "Condition and webhook body are not valid";
} else if (!validation.condition) {
warningMessage = "Condition is not valid";
} else if (!validation.parser) {
warningMessage = "Webhook body is not valid";
}
if (warningMessage) {
requestConfirmation({
title: "Validation failed",
body: `${warningMessage}. Continue?`,
confirm: "Yes, I know what Im doing",
cancel: "No, Ill fix the errors",
handleConfirm: handleAddOrUpdate,
});
} else {
handleAddOrUpdate();
}
},
},
}}
/>
);
}