File size: 5,435 Bytes
f8b5d42 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | import { useRef, useState } from "react";
import { DotsThreeOutline } from "@phosphor-icons/react";
import showToast from "@/utils/toast";
import { useModal } from "@/hooks/useModal";
import ModalWrapper from "@/components/ModalWrapper";
import Embed from "@/models/embed";
import paths from "@/utils/paths";
import { nFormatter } from "@/utils/numbers";
import EditEmbedModal from "./EditEmbedModal";
import CodeSnippetModal from "./CodeSnippetModal";
import moment from "moment";
export default function EmbedRow({ embed }) {
const rowRef = useRef(null);
const [enabled, setEnabled] = useState(Number(embed.enabled) === 1);
const {
isOpen: isSettingsOpen,
openModal: openSettingsModal,
closeModal: closeSettingsModal,
} = useModal();
const {
isOpen: isSnippetOpen,
openModal: openSnippetModal,
closeModal: closeSnippetModal,
} = useModal();
const handleSuspend = async () => {
if (
!window.confirm(
`Are you sure you want to disabled this embed?\nOnce disabled the embed will no longer respond to any chat requests.`
)
)
return false;
const { success, error } = await Embed.updateEmbed(embed.id, {
enabled: !enabled,
});
if (!success) showToast(error, "error", { clear: true });
if (success) {
showToast(
`Embed ${enabled ? "has been disabled" : "is active"}.`,
"success",
{ clear: true }
);
setEnabled(!enabled);
}
};
const handleDelete = async () => {
if (
!window.confirm(
`Are you sure you want to delete this embed?\nOnce deleted this embed will no longer respond to chats or be active.\n\nThis action is irreversible.`
)
)
return false;
const { success, error } = await Embed.deleteEmbed(embed.id);
if (!success) showToast(error, "error", { clear: true });
if (success) {
rowRef?.current?.remove();
showToast("Embed deleted from system.", "success", { clear: true });
}
};
return (
<>
<tr
ref={rowRef}
className="bg-transparent text-white text-opacity-80 text-xs font-medium border-b border-white/10 h-10"
>
<th
scope="row"
className="px-6 whitespace-nowrap flex item-center gap-x-1"
>
<a
href={paths.workspace.chat(embed.workspace.slug)}
target="_blank"
rel="noreferrer"
className="text-white flex items-center hover:underline"
>
{embed.workspace.name}
</a>
</th>
<th scope="row" className="px-6 whitespace-nowrap">
{nFormatter(embed._count.embed_chats)}
</th>
<th scope="row" className="px-6 whitespace-nowrap">
<ActiveDomains domainList={embed.allowlist_domains} />
</th>
<th
scope="row"
className="px-6 whitespace-nowrap text-theme-text-secondary !font-normal"
>
{
// If the embed was created more than a day ago, show the date, otherwise show the time ago
moment(embed.createdAt).diff(moment(), "days") > 0
? moment(embed.createdAt).format("MMM D, YYYY")
: moment(embed.createdAt).fromNow()
}
</th>
<td className="px-6 flex items-center gap-x-6 h-full mt-1">
<button
onClick={openSnippetModal}
className="group text-xs font-medium text-theme-text-secondary px-2 py-1 rounded-lg hover:bg-theme-button-code-hover-bg"
>
<span className="group-hover:text-theme-button-code-hover-text">
Code
</span>
</button>
<button
onClick={handleSuspend}
className="group text-xs font-medium text-theme-text-secondary px-2 py-1 rounded-lg hover:bg-theme-button-disable-hover-bg"
>
<span className="group-hover:text-theme-button-disable-hover-text">
{enabled ? "Disable" : "Enable"}
</span>
</button>
<button
onClick={handleDelete}
className="group text-xs font-medium text-theme-text-secondary px-2 py-1 rounded-lg hover:bg-theme-button-delete-hover-bg"
>
<span className="group-hover:text-theme-button-delete-hover-text">
Delete
</span>
</button>
<button
onClick={openSettingsModal}
className="text-xs font-medium text-theme-button-text hover:text-theme-text-secondary hover:bg-theme-hover px-2 py-1 rounded-lg"
>
<DotsThreeOutline weight="fill" className="h-5 w-5" />
</button>
</td>
</tr>
<ModalWrapper isOpen={isSettingsOpen}>
<EditEmbedModal embed={embed} closeModal={closeSettingsModal} />
</ModalWrapper>
<ModalWrapper isOpen={isSnippetOpen}>
<CodeSnippetModal embed={embed} closeModal={closeSnippetModal} />
</ModalWrapper>
</>
);
}
function ActiveDomains({ domainList }) {
if (!domainList) return <p>all</p>;
try {
const domains = JSON.parse(domainList);
return (
<div className="flex flex-col gap-y-2">
{domains.map((domain, index) => {
return (
<p key={index} className="font-mono !font-normal">
{domain}
</p>
);
})}
</div>
);
} catch {
return <p>all</p>;
}
}
|