Skip to content

Commit

Permalink
integration card updated
Browse files Browse the repository at this point in the history
  • Loading branch information
n4ze3m committed Jun 18, 2023
1 parent f492e08 commit f86b85b
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 2 deletions.
195 changes: 195 additions & 0 deletions app/ui/src/components/Bot/Integration/IntegrationForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import { Divider, Form, notification } from "antd";
import { Switch } from "@headlessui/react";
import React from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import api from "../../../services/api";
import { useParams } from "react-router-dom";
import axios from "axios";

//@ts-ignore
function classNames(...classes) {
return classes.filter(Boolean).join(" ");
}
type Props = {
onClose: () => void;
data: {
name: string;
channel: string;
logo: string;
description: string;
link: string;
fields: {
name: string;
type: string;
title: string;
description: string;
help: string;
requiredMessage: string;
value: string;
}[];
isPaused: boolean;
status: string;
color: string;
textColor: string;
};
};

export const IntegrationForm: React.FC<Props> = ({ onClose, data }) => {
const [enabled, setEnabled] = React.useState(!data.isPaused);
const params = useParams<{ id: string }>();

const onSubmit = async (value: any) => {
const response = await api.post(`/bot/integration/${params.id}`, {
provider: data.channel,
value,
});
return response.data;
};

const client = useQueryClient();

const { mutate: updateIntegration, isLoading: isUpdating } = useMutation(
onSubmit,
{
onSuccess: () => {
client.invalidateQueries(["getBotEIntegration", params.id]);
notification.success({
message: "Success",
description: "Integration updated successfully",
});
onClose();
},
onError: (e: any) => {
if (axios.isAxiosError(e)) {
const message =
e.response?.data?.message ||
e?.response?.data?.error ||
e.message ||
"Something went wrong";
notification.error({
message: "Error",
description: message,
});
return;
}

notification.error({
message: "Error",
description: e.message || "Something went wrong",
});
},
}
);

const { mutate: toggleIntegration, isLoading: isToggling } = useMutation(
async () => {
const response = await api.post(`/bot/integration/${params.id}/toggle`, {
provider: data.channel,
});
return response.data;
},
{
onSuccess: () => {
client.invalidateQueries(["getBotEIntegration", params.id]);
notification.success({
message: "Success",
description: "Integration toggled successfully",
});
onClose();
},
onError: (e: any) => {
if (axios.isAxiosError(e)) {
const message =
e.response?.data?.message ||
e?.response?.data?.error ||
e.message ||
"Something went wrong";
notification.error({
message: "Error",
description: message,
});
return;
}

notification.error({
message: "Error",
description: e.message || "Something went wrong",
});
},
}
);

return (
<>
<Form
initialValues={{
...data.fields.reduce((acc, field) => {
//@ts-ignore
acc[field.name] = field.value;
return acc;
}, {}),
}}
layout="vertical"
className="space-y-6"
onFinish={updateIntegration}
>
{data.fields.map((field, index) => {
return (
<Form.Item
key={index}
label={field.title}
name={field.name}
rules={[{ required: true, message: field.requiredMessage }]}
>
<input
type="password"
placeholder={field.help}
className="border border-gray-300 rounded-md px-4 py-2 w-full focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500"
/>
</Form.Item>
);
})}

<Form.Item>
<button
type="submit"
disabled={isUpdating || isToggling}
className="flex w-full justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
{isUpdating ? "Saving..." : "Save"}
</button>
</Form.Item>
</Form>
<Divider />
<Switch.Group as="div" className="flex items-center justify-between">
<Switch.Label as="span" className="ml-3">
<span className="text-sm font-medium text-gray-600">
Enable integration
</span>
</Switch.Label>
<Switch
disabled={
data.status.toLowerCase() === "connect" || isToggling || isUpdating
}
checked={enabled}
onChange={(e) => {
setEnabled(e);
toggleIntegration();
}}
className={classNames(
enabled ? "bg-indigo-600" : "bg-gray-200",
"relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50"
)}
>
<span
aria-hidden="true"
className={classNames(
enabled ? "translate-x-5" : "translate-x-0",
"pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
)}
/>
</Switch>
</Switch.Group>
</>
);
};
51 changes: 49 additions & 2 deletions app/ui/src/components/Bot/Integration/IntegrationGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { Modal } from "antd";
import React from "react";
import { IntegrationForm } from "./IntegrationForm";

type Props = {
data: {
name: string;
Expand All @@ -22,6 +26,28 @@ type Props = {
};

export const IntegrationGrid: React.FC<Props> = ({ data }) => {
const [open, setOpen] = React.useState(false);
const [selectedIntegration, setSelectedIntegration] = React.useState<{
name: string;
channel: string;
logo: string;
description: string;
link: string;
fields: {
name: string;
type: string;
title: string;
description: string;
help: string;
requiredMessage: string;
value: string;
}[];
isPaused: boolean;
status: string;
color: string;
textColor: string;
} | null>();

return (
<div className="px-4 sm:px-6 lg:px-8">
<div className="sm:flex sm:items-center">
Expand All @@ -36,7 +62,12 @@ export const IntegrationGrid: React.FC<Props> = ({ data }) => {
<div className="mt-8 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{data.map((integration) => (
<div className="relative group bg-white p-6 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-500 rounded-lg overflow-hidden shadow-sm hover:shadow-lg transition-shadow duration-300 ease-in-out cursor-pointer">
<div>
<div
onClick={() => {
setSelectedIntegration(integration);
setOpen(true);
}}
>
<div className="mb-4">
<div className="flex items-center justify-between">
<img
Expand All @@ -50,7 +81,10 @@ export const IntegrationGrid: React.FC<Props> = ({ data }) => {
style={{
backgroundColor: integration.color,
color: integration.textColor,
borderColor: integration.color !== "#fff" ? integration.color : "#000",
borderColor:
integration.color !== "#fff"
? integration.color
: "#000",
}}
>
{integration.status}
Expand All @@ -72,6 +106,19 @@ export const IntegrationGrid: React.FC<Props> = ({ data }) => {
</div>
))}
</div>

{/* MODAL */}
<Modal
title={`${selectedIntegration?.name} Integration`}
open={open}
onCancel={() => setOpen(false)}
footer={null}
>
<IntegrationForm
onClose={() => setOpen(false)}
data={selectedIntegration!}
/>
</Modal>
</div>
);
};

0 comments on commit f86b85b

Please sign in to comment.