feat: copilotkit
This commit is contained in:
parent
e4eff984f8
commit
498e688332
|
|
@ -25,6 +25,7 @@ import { MessagesController } from '@gitroom/backend/api/routes/messages.control
|
|||
import { OpenaiService } from '@gitroom/nestjs-libraries/openai/openai.service';
|
||||
import { ExtractContentService } from '@gitroom/nestjs-libraries/openai/extract.content.service';
|
||||
import { CodesService } from '@gitroom/nestjs-libraries/services/codes.service';
|
||||
import { CopilotController } from '@gitroom/backend/api/routes/copilot.controller';
|
||||
|
||||
const authenticatedController = [
|
||||
UsersController,
|
||||
|
|
@ -37,7 +38,7 @@ const authenticatedController = [
|
|||
BillingController,
|
||||
NotificationsController,
|
||||
MarketplaceController,
|
||||
MessagesController
|
||||
MessagesController,
|
||||
];
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -58,7 +59,12 @@ const authenticatedController = [
|
|||
]
|
||||
: []),
|
||||
],
|
||||
controllers: [StripeController, AuthController, ...authenticatedController],
|
||||
controllers: [
|
||||
StripeController,
|
||||
AuthController,
|
||||
CopilotController,
|
||||
...authenticatedController,
|
||||
],
|
||||
providers: [
|
||||
AuthService,
|
||||
StripeService,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import { Controller, Post, Req, Res } from '@nestjs/common';
|
||||
import { CopilotRuntime, OpenAIAdapter } from '@copilotkit/backend';
|
||||
|
||||
@Controller('/copilot')
|
||||
export class CopilotController {
|
||||
@Post('/chat')
|
||||
chat(@Req() req: Request, @Res() res: Response) {
|
||||
const copilotKit = new CopilotRuntime({});
|
||||
return copilotKit.streamHttpServerResponse(
|
||||
req,
|
||||
res,
|
||||
new OpenAIAdapter({ model: 'gpt-4o' })
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="#fff" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.84453 3.84453C2.71849 4.97056 2.71849 6.79623 3.84453 7.92226L5.43227 9.51C5.44419 9.49622 5.45669 9.48276 5.46978 9.46967L9.46978 5.46967C9.48284 5.45662 9.49625 5.44415 9.50999 5.43226L7.92226 3.84453C6.79623 2.71849 4.97056 2.71849 3.84453 3.84453Z" fill="#fff"/>
|
||||
<path d="M10.5679 6.49012C10.556 6.50386 10.5435 6.51728 10.5304 6.53033L6.53044 10.5303C6.51735 10.5434 6.5039 10.5559 6.49011 10.5678L16.0777 20.1555C17.2038 21.2815 19.0294 21.2815 20.1555 20.1555C21.2815 19.0294 21.2815 17.2038 20.1555 16.0777L10.5679 6.49012Z" fill="#fff"/>
|
||||
<path d="M16.1 2.30719C16.261 1.8976 16.8385 1.8976 16.9994 2.30719L17.4298 3.40247C17.479 3.52752 17.5776 3.62651 17.7022 3.67583L18.7934 4.1078C19.2015 4.26934 19.2015 4.849 18.7934 5.01054L17.7022 5.44252C17.5776 5.49184 17.479 5.59082 17.4298 5.71587L16.9995 6.81115C16.8385 7.22074 16.261 7.22074 16.1 6.81116L15.6697 5.71587C15.6205 5.59082 15.5219 5.49184 15.3973 5.44252L14.3061 5.01054C13.898 4.849 13.898 4.26934 14.3061 4.1078L15.3973 3.67583C15.5219 3.62651 15.6205 3.52752 15.6697 3.40247L16.1 2.30719Z" fill="#fff"/>
|
||||
<path d="M19.9672 9.12945C20.1281 8.71987 20.7057 8.71987 20.8666 9.12945L21.0235 9.5288C21.0727 9.65385 21.1713 9.75284 21.2959 9.80215L21.6937 9.95965C22.1018 10.1212 22.1018 10.7009 21.6937 10.8624L21.2959 11.0199C21.1713 11.0692 21.0727 11.1682 21.0235 11.2932L20.8666 11.6926C20.7057 12.1022 20.1281 12.1022 19.9672 11.6926L19.8103 11.2932C19.7611 11.1682 19.6625 11.0692 19.5379 11.0199L19.14 10.8624C18.732 10.7009 18.732 10.1212 19.14 9.95965L19.5379 9.80215C19.6625 9.75284 19.7611 9.65385 19.8103 9.5288L19.9672 9.12945Z" fill="#fff"/>
|
||||
<path d="M5.1332 15.3072C5.29414 14.8976 5.87167 14.8976 6.03261 15.3072L6.18953 15.7065C6.23867 15.8316 6.33729 15.9306 6.46188 15.9799L6.85975 16.1374C7.26783 16.2989 7.26783 16.8786 6.85975 17.0401L6.46188 17.1976C6.33729 17.2469 6.23867 17.3459 6.18953 17.471L6.03261 17.8703C5.87167 18.2799 5.29414 18.2799 5.1332 17.8703L4.97628 17.471C4.92714 17.3459 4.82852 17.2469 4.70393 17.1976L4.30606 17.0401C3.89798 16.8786 3.89798 16.2989 4.30606 16.1374L4.70393 15.9799C4.82852 15.9306 4.92714 15.8316 4.97628 15.7065L5.1332 15.3072Z" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -287,4 +287,44 @@ html {
|
|||
|
||||
:empty + .existing-empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:root {
|
||||
--copilot-kit-primary-color: #612AD5 !important;
|
||||
--copilot-kit-background-color: #0B0F1C !important;
|
||||
--copilot-kit-separator-color: #1F2941 !important;
|
||||
--copilot-kit-contrast-color: #FFFFFF !important;
|
||||
--copilot-kit-secondary-contrast-color: #FFFFFF !important;
|
||||
--copilot-kit-secondary-color: #000 !important;
|
||||
--copilot-kit-response-button-background-color: #000 !important;;
|
||||
--copilot-kit-response-button-color: #fff !important;;
|
||||
}
|
||||
|
||||
.copilotKitWindow {
|
||||
background-color: #0B0F1C !important;
|
||||
}
|
||||
|
||||
.copilotKitButtonIconOpen svg {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.copilotKitButtonIconOpen:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
object-fit: contain;
|
||||
color: white;
|
||||
background: url("/magic.svg") no-repeat center center / contain;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.copilotKitPopup {
|
||||
right: -2rem !important;
|
||||
bottom: 2rem !important;
|
||||
}
|
||||
|
||||
.copilotKitWindow {
|
||||
/*right: -5rem !important;*/
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import interClass from '@gitroom/react/helpers/inter.font';
|
|||
export const dynamic = 'force-dynamic';
|
||||
import './global.css';
|
||||
import 'react-tooltip/dist/react-tooltip.css';
|
||||
import "@copilotkit/react-ui/styles.css";
|
||||
|
||||
import LayoutContext from '@gitroom/frontend/components/layout/layout.context';
|
||||
import { ReactNode } from 'react';
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import React, {
|
|||
import dayjs from 'dayjs';
|
||||
import { Integrations } from '@gitroom/frontend/components/launches/calendar.context';
|
||||
import clsx from 'clsx';
|
||||
import MDEditor, { commands } from '@uiw/react-md-editor';
|
||||
import { commands } from '@uiw/react-md-editor';
|
||||
import { usePreventWindowUnload } from '@gitroom/react/helpers/use.prevent.window.unload';
|
||||
import { deleteDialog } from '@gitroom/react/helpers/delete.dialog';
|
||||
import { useModals } from '@mantine/modals';
|
||||
|
|
@ -45,6 +45,12 @@ import {
|
|||
PostToOrganization,
|
||||
} from '@gitroom/frontend/components/launches/post.to.organization';
|
||||
import { Submitted } from '@gitroom/frontend/components/launches/submitted';
|
||||
import { supportEmitter } from '@gitroom/frontend/components/layout/support';
|
||||
import { Editor } from '@gitroom/frontend/components/launches/editor';
|
||||
import { AddPostButton } from '@gitroom/frontend/components/launches/add.post.button';
|
||||
import { useStateCallback } from '@gitroom/react/helpers/use.state.callback';
|
||||
import { CopilotPopup } from '@copilotkit/react-ui';
|
||||
import { useUser } from '@gitroom/frontend/components/layout/user.context';
|
||||
|
||||
export const AddEditModal: FC<{
|
||||
date: dayjs.Dayjs;
|
||||
|
|
@ -59,7 +65,7 @@ export const AddEditModal: FC<{
|
|||
const modal = useModals();
|
||||
|
||||
// selected integrations to allow edit
|
||||
const [selectedIntegrations, setSelectedIntegrations] = useState<
|
||||
const [selectedIntegrations, setSelectedIntegrations] = useStateCallback<
|
||||
Integrations[]
|
||||
>([]);
|
||||
|
||||
|
|
@ -74,6 +80,8 @@ export const AddEditModal: FC<{
|
|||
|
||||
const fetch = useFetch();
|
||||
|
||||
const user = useUser();
|
||||
|
||||
const updateOrder = useCallback(() => {
|
||||
modal.closeAll();
|
||||
reopenModal();
|
||||
|
|
@ -111,7 +119,10 @@ export const AddEditModal: FC<{
|
|||
|
||||
// if the user exit the popup we reset the global variable with all the values
|
||||
useEffect(() => {
|
||||
supportEmitter.emit('change', false);
|
||||
|
||||
return () => {
|
||||
supportEmitter.emit('change', true);
|
||||
resetValues();
|
||||
};
|
||||
}, []);
|
||||
|
|
@ -317,6 +328,17 @@ export const AddEditModal: FC<{
|
|||
|
||||
return (
|
||||
<>
|
||||
{user?.tier.ai && (
|
||||
<CopilotPopup
|
||||
hitEscapeToClose={false}
|
||||
clickOutsideToClose={true}
|
||||
labels={{
|
||||
title: 'AI Content Assistant',
|
||||
}}
|
||||
className="!z-[499]"
|
||||
instructions="You are an assistant that help the user to schedule their social media posts"
|
||||
/>
|
||||
)}
|
||||
<div className={clsx('flex gap-[20px] bg-black')}>
|
||||
<div
|
||||
className={clsx(
|
||||
|
|
@ -344,9 +366,13 @@ export const AddEditModal: FC<{
|
|||
selectedIntegrations={[]}
|
||||
singleSelect={false}
|
||||
onChange={setSelectedIntegrations}
|
||||
isMain={true}
|
||||
/>
|
||||
)}
|
||||
<div id="renderEditor" className={clsx(!showHide.hideTopEditor && 'hidden')} />
|
||||
<div
|
||||
id="renderEditor"
|
||||
className={clsx(!showHide.hideTopEditor && 'hidden')}
|
||||
/>
|
||||
{!existingData.integration && !showHide.hideTopEditor ? (
|
||||
<>
|
||||
<div>You are in global editing mode</div>
|
||||
|
|
@ -355,7 +381,8 @@ export const AddEditModal: FC<{
|
|||
<div>
|
||||
<div className="flex gap-[4px]">
|
||||
<div className="flex-1 editor text-white">
|
||||
<MDEditor
|
||||
<Editor
|
||||
order={index}
|
||||
height={value.length > 1 ? 150 : 250}
|
||||
commands={[
|
||||
...commands
|
||||
|
|
@ -426,26 +453,7 @@ export const AddEditModal: FC<{
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
onClick={addValue(index)}
|
||||
className="!h-[24px] rounded-[3px] flex gap-[4px] w-[102px] text-[12px] font-[500]"
|
||||
>
|
||||
<div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 14 14"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M7 1.3125C5.87512 1.3125 4.7755 1.64607 3.8402 2.27102C2.90489 2.89597 2.17591 3.78423 1.74544 4.82349C1.31496 5.86274 1.20233 7.00631 1.42179 8.10958C1.64124 9.21284 2.18292 10.2263 2.97833 11.0217C3.77374 11.8171 4.78716 12.3588 5.89043 12.5782C6.99369 12.7977 8.13726 12.685 9.17651 12.2546C10.2158 11.8241 11.104 11.0951 11.729 10.1598C12.3539 9.2245 12.6875 8.12488 12.6875 7C12.6859 5.49207 12.0862 4.04636 11.0199 2.98009C9.95365 1.91382 8.50793 1.31409 7 1.3125ZM7 11.8125C6.04818 11.8125 5.11773 11.5303 4.32632 11.0014C3.53491 10.4726 2.91808 9.72103 2.55383 8.84166C2.18959 7.96229 2.09428 6.99466 2.27997 6.06113C2.46566 5.12759 2.92401 4.27009 3.59705 3.59705C4.27009 2.92401 5.1276 2.46566 6.06113 2.27997C6.99466 2.09428 7.9623 2.18958 8.84167 2.55383C9.72104 2.91808 10.4726 3.53491 11.0015 4.32632C11.5303 5.11773 11.8125 6.04818 11.8125 7C11.8111 8.27591 11.3036 9.49915 10.4014 10.4014C9.49915 11.3036 8.27591 11.8111 7 11.8125ZM9.625 7C9.625 7.11603 9.57891 7.22731 9.49686 7.30936C9.41481 7.39141 9.30353 7.4375 9.1875 7.4375H7.4375V9.1875C7.4375 9.30353 7.39141 9.41481 7.30936 9.49686C7.22731 9.57891 7.11603 9.625 7 9.625C6.88397 9.625 6.77269 9.57891 6.69064 9.49686C6.6086 9.41481 6.5625 9.30353 6.5625 9.1875V7.4375H4.8125C4.69647 7.4375 4.58519 7.39141 4.50314 7.30936C4.4211 7.22731 4.375 7.11603 4.375 7C4.375 6.88397 4.4211 6.77269 4.50314 6.69064C4.58519 6.60859 4.69647 6.5625 4.8125 6.5625H6.5625V4.8125C6.5625 4.69647 6.6086 4.58519 6.69064 4.50314C6.77269 4.42109 6.88397 4.375 7 4.375C7.11603 4.375 7.22731 4.42109 7.30936 4.50314C7.39141 4.58519 7.4375 4.69647 7.4375 4.8125V6.5625H9.1875C9.30353 6.5625 9.41481 6.60859 9.49686 6.69064C9.57891 6.77269 9.625 6.88397 9.625 7Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>Add post</div>
|
||||
</Button>
|
||||
<AddPostButton num={index} onClick={addValue(index)} />
|
||||
</div>
|
||||
</Fragment>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
import { Button } from '@gitroom/react/form/button';
|
||||
import React, { FC } from 'react';
|
||||
import { useCopilotAction, useCopilotReadable } from '@copilotkit/react-core';
|
||||
|
||||
export const AddPostButton: FC<{ onClick: () => void; num: number }> = (
|
||||
props
|
||||
) => {
|
||||
const { onClick, num } = props;
|
||||
|
||||
useCopilotAction({
|
||||
name: 'addPost_' + num,
|
||||
description: 'Add a post after the post number ' + (num + 1),
|
||||
handler: () => {
|
||||
onClick();
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={onClick}
|
||||
className="!h-[24px] rounded-[3px] flex gap-[4px] w-[102px] text-[12px] font-[500]"
|
||||
>
|
||||
<div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 14 14"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M7 1.3125C5.87512 1.3125 4.7755 1.64607 3.8402 2.27102C2.90489 2.89597 2.17591 3.78423 1.74544 4.82349C1.31496 5.86274 1.20233 7.00631 1.42179 8.10958C1.64124 9.21284 2.18292 10.2263 2.97833 11.0217C3.77374 11.8171 4.78716 12.3588 5.89043 12.5782C6.99369 12.7977 8.13726 12.685 9.17651 12.2546C10.2158 11.8241 11.104 11.0951 11.729 10.1598C12.3539 9.2245 12.6875 8.12488 12.6875 7C12.6859 5.49207 12.0862 4.04636 11.0199 2.98009C9.95365 1.91382 8.50793 1.31409 7 1.3125ZM7 11.8125C6.04818 11.8125 5.11773 11.5303 4.32632 11.0014C3.53491 10.4726 2.91808 9.72103 2.55383 8.84166C2.18959 7.96229 2.09428 6.99466 2.27997 6.06113C2.46566 5.12759 2.92401 4.27009 3.59705 3.59705C4.27009 2.92401 5.1276 2.46566 6.06113 2.27997C6.99466 2.09428 7.9623 2.18958 8.84167 2.55383C9.72104 2.91808 10.4726 3.53491 11.0015 4.32632C11.5303 5.11773 11.8125 6.04818 11.8125 7C11.8111 8.27591 11.3036 9.49915 10.4014 10.4014C9.49915 11.3036 8.27591 11.8111 7 11.8125ZM9.625 7C9.625 7.11603 9.57891 7.22731 9.49686 7.30936C9.41481 7.39141 9.30353 7.4375 9.1875 7.4375H7.4375V9.1875C7.4375 9.30353 7.39141 9.41481 7.30936 9.49686C7.22731 9.57891 7.11603 9.625 7 9.625C6.88397 9.625 6.77269 9.57891 6.69064 9.49686C6.6086 9.41481 6.5625 9.30353 6.5625 9.1875V7.4375H4.8125C4.69647 7.4375 4.58519 7.39141 4.50314 7.30936C4.4211 7.22731 4.375 7.11603 4.375 7C4.375 6.88397 4.4211 6.77269 4.50314 6.69064C4.58519 6.60859 4.69647 6.5625 4.8125 6.5625H6.5625V4.8125C6.5625 4.69647 6.6086 4.58519 6.69064 4.50314C6.77269 4.42109 6.88397 4.375 7 4.375C7.11603 4.375 7.22731 4.42109 7.30936 4.50314C7.39141 4.58519 7.4375 4.69647 7.4375 4.8125V6.5625H9.1875C9.30353 6.5625 9.41481 6.60859 9.49686 6.69064C9.57891 6.77269 9.625 6.88397 9.625 7Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>Add post</div>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
|
@ -334,9 +334,9 @@ const CalendarColumnRender: FC<{ day: number; hour: string }> = (props) => {
|
|||
<ExistingDataContextProvider value={data}>
|
||||
<AddEditModal
|
||||
reopenModal={editPost(post)}
|
||||
integrations={integrations.filter(
|
||||
integrations={integrations.slice(0).filter(
|
||||
(f) => f.id === data.integration
|
||||
)}
|
||||
).map(p => ({ ...p, picture: data.integrationPicture }))}
|
||||
date={getDate}
|
||||
/>
|
||||
</ExistingDataContextProvider>
|
||||
|
|
@ -345,7 +345,7 @@ const CalendarColumnRender: FC<{ day: number; hour: string }> = (props) => {
|
|||
title: ``,
|
||||
});
|
||||
},
|
||||
[]
|
||||
[integrations]
|
||||
);
|
||||
|
||||
const addModal = useCallback(() => {
|
||||
|
|
@ -358,7 +358,7 @@ const CalendarColumnRender: FC<{ day: number; hour: string }> = (props) => {
|
|||
},
|
||||
children: (
|
||||
<AddEditModal
|
||||
integrations={integrations}
|
||||
integrations={integrations.slice(0).map(p => ({ ...p }))}
|
||||
date={getDate}
|
||||
reopenModal={() => ({})}
|
||||
/>
|
||||
|
|
@ -366,7 +366,7 @@ const CalendarColumnRender: FC<{ day: number; hour: string }> = (props) => {
|
|||
size: '80%',
|
||||
// title: `Adding posts for ${getDate.format('DD/MM/YYYY HH:mm')}`,
|
||||
});
|
||||
}, []);
|
||||
}, [integrations]);
|
||||
|
||||
const addProvider = useAddProvider();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
import { forwardRef } from 'react';
|
||||
import type { MDEditorProps } from '@uiw/react-md-editor/src/Types';
|
||||
import { RefMDEditor } from '@uiw/react-md-editor/src/Editor';
|
||||
import MDEditor from '@uiw/react-md-editor';
|
||||
import { useCopilotAction, useCopilotReadable } from '@copilotkit/react-core';
|
||||
|
||||
export const Editor = forwardRef<
|
||||
RefMDEditor,
|
||||
MDEditorProps & { order: number, currentWatching: string, isGlobal: boolean}
|
||||
>(
|
||||
(
|
||||
props: MDEditorProps & { order: number, currentWatching: string, isGlobal: boolean },
|
||||
ref: React.ForwardedRef<RefMDEditor>
|
||||
) => {
|
||||
useCopilotReadable({
|
||||
description: 'Content of the post number ' + (props.order + 1),
|
||||
value: props.content,
|
||||
});
|
||||
|
||||
useCopilotAction({
|
||||
name: 'editPost_' + props.order,
|
||||
description: `Edit the content of post number ${props.order + 1}`,
|
||||
parameters: [
|
||||
{
|
||||
name: 'content',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
handler: ({ content }) => {
|
||||
props?.onChange?.(content);
|
||||
},
|
||||
});
|
||||
|
||||
return <MDEditor {...props} ref={ref} />;
|
||||
}
|
||||
);
|
||||
|
|
@ -4,22 +4,26 @@ import { useMoveToIntegrationListener } from '@gitroom/frontend/components/launc
|
|||
import { deleteDialog } from '@gitroom/react/helpers/delete.dialog';
|
||||
import clsx from 'clsx';
|
||||
import Image from 'next/image';
|
||||
import { useCopilotAction, useCopilotReadable } from '@copilotkit/react-core';
|
||||
import { useStateCallback } from '@gitroom/react/helpers/use.state.callback';
|
||||
|
||||
export const PickPlatforms: FC<{
|
||||
integrations: Integrations[];
|
||||
selectedIntegrations: Integrations[];
|
||||
onChange: (integrations: Integrations[]) => void;
|
||||
onChange: (integrations: Integrations[], callback: () => void) => void;
|
||||
singleSelect: boolean;
|
||||
hide?: boolean;
|
||||
isMain: boolean;
|
||||
}> = (props) => {
|
||||
const { hide, integrations, selectedIntegrations, onChange } = props;
|
||||
const { hide, isMain, integrations, selectedIntegrations, onChange } = props;
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [isLeft, setIsLeft] = useState(false);
|
||||
const [isRight, setIsRight] = useState(false);
|
||||
|
||||
const [selectedAccounts, setSelectedAccounts] =
|
||||
useState<Integrations[]>(selectedIntegrations);
|
||||
const [selectedAccounts, setSelectedAccounts] = useStateCallback<
|
||||
Integrations[]
|
||||
>(selectedIntegrations.slice(0).map((p) => ({ ...p })));
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
|
|
@ -56,21 +60,36 @@ export const PickPlatforms: FC<{
|
|||
checkLeftRight();
|
||||
}, [selectedIntegrations, integrations]);
|
||||
|
||||
useMoveToIntegrationListener([integrations], props.singleSelect, (identifier) => {
|
||||
const findIntegration = integrations.find(
|
||||
(p) => p.id === identifier
|
||||
);
|
||||
useMoveToIntegrationListener(
|
||||
[integrations],
|
||||
props.singleSelect,
|
||||
(identifier) => {
|
||||
const findIntegration = integrations.find((p) => p.id === identifier);
|
||||
|
||||
if (findIntegration) {
|
||||
addPlatform(findIntegration)();
|
||||
if (findIntegration) {
|
||||
addPlatform(findIntegration)();
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
const addPlatform = useCallback(
|
||||
(integration: Integrations) => async () => {
|
||||
const promises = [];
|
||||
if (props.singleSelect) {
|
||||
onChange([integration]);
|
||||
setSelectedAccounts([integration]);
|
||||
promises.push(
|
||||
new Promise((res) => {
|
||||
onChange([integration], () => {
|
||||
res('');
|
||||
});
|
||||
})
|
||||
);
|
||||
promises.push(
|
||||
new Promise((res) => {
|
||||
setSelectedAccounts([integration], () => {
|
||||
res('');
|
||||
});
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (selectedAccounts.includes(integration)) {
|
||||
|
|
@ -86,23 +105,83 @@ export const PickPlatforms: FC<{
|
|||
) {
|
||||
return;
|
||||
}
|
||||
onChange(changedIntegrations);
|
||||
setSelectedAccounts(changedIntegrations);
|
||||
promises.push(
|
||||
new Promise((res) => {
|
||||
onChange(changedIntegrations, () => {
|
||||
res('');
|
||||
});
|
||||
})
|
||||
);
|
||||
promises.push(
|
||||
new Promise((res) => {
|
||||
setSelectedAccounts(changedIntegrations, () => {
|
||||
res('');
|
||||
});
|
||||
})
|
||||
);
|
||||
} else {
|
||||
const changedIntegrations = [...selectedAccounts, integration];
|
||||
onChange(changedIntegrations);
|
||||
setSelectedAccounts(changedIntegrations);
|
||||
promises.push(
|
||||
new Promise((res) => {
|
||||
onChange(changedIntegrations, () => {
|
||||
res('');
|
||||
});
|
||||
})
|
||||
);
|
||||
promises.push(
|
||||
new Promise((res) => {
|
||||
setSelectedAccounts(changedIntegrations, () => {
|
||||
res('');
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
},
|
||||
[selectedAccounts]
|
||||
);
|
||||
|
||||
const handler = useCallback(
|
||||
async ({ integrationId }: { integrationId: string }) => {
|
||||
const findIntegration = integrations.find((p) => p.id === integrationId)!;
|
||||
await addPlatform(findIntegration)();
|
||||
},
|
||||
[selectedAccounts, integrations, selectedAccounts]
|
||||
);
|
||||
|
||||
useCopilotReadable({
|
||||
description: isMain ? 'All available platforms channels' : 'Possible platforms channels to edit',
|
||||
value: JSON.stringify(integrations),
|
||||
});
|
||||
|
||||
useCopilotAction(
|
||||
{
|
||||
name: isMain ? `addOrRemovePlatform` : 'setSelectedIntegration',
|
||||
description: isMain
|
||||
? `Add or remove one channel to schedule your post to, always pass the id`
|
||||
: 'Set selected integration',
|
||||
parameters: [
|
||||
{
|
||||
name: 'integrationId',
|
||||
type: 'string',
|
||||
description: 'The id of the integration',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
handler,
|
||||
},
|
||||
[addPlatform, selectedAccounts, integrations]
|
||||
);
|
||||
|
||||
if (hide) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={clsx('flex select-none', props.singleSelect && 'gap-[10px]')}>
|
||||
<div
|
||||
className={clsx('flex select-none', props.singleSelect && 'gap-[10px]')}
|
||||
>
|
||||
{props.singleSelect && (
|
||||
<div className="flex items-center">
|
||||
{isLeft && (
|
||||
|
|
@ -138,75 +217,77 @@ export const PickPlatforms: FC<{
|
|||
>
|
||||
<div className="innerComponent">
|
||||
<div className="flex">
|
||||
{integrations.filter(f => !f.inBetweenSteps).map((integration) =>
|
||||
!props.singleSelect ? (
|
||||
<div
|
||||
key={integration.id}
|
||||
className="flex gap-[8px] items-center mr-[10px]"
|
||||
>
|
||||
{integrations
|
||||
.filter((f) => !f.inBetweenSteps)
|
||||
.map((integration) =>
|
||||
!props.singleSelect ? (
|
||||
<div
|
||||
onClick={addPlatform(integration)}
|
||||
className={clsx(
|
||||
'cursor-pointer relative w-[34px] h-[34px] rounded-full flex justify-center items-center bg-fifth filter transition-all duration-500',
|
||||
selectedAccounts.findIndex(
|
||||
(p) => p.id === integration.id
|
||||
) === -1
|
||||
? 'opacity-40'
|
||||
: ''
|
||||
)}
|
||||
key={integration.id}
|
||||
className="flex gap-[8px] items-center mr-[10px]"
|
||||
>
|
||||
<img
|
||||
src={integration.picture}
|
||||
className="rounded-full"
|
||||
alt={integration.identifier}
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<Image
|
||||
src={`/icons/platforms/${integration.identifier}.png`}
|
||||
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
|
||||
alt={integration.identifier}
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div key={integration.id} className="">
|
||||
<div
|
||||
onClick={addPlatform(integration)}
|
||||
className={clsx(
|
||||
'cursor-pointer rounded-[50px] w-[200px] relative h-[40px] flex justify-center items-center bg-fifth filter transition-all duration-500',
|
||||
selectedAccounts.findIndex(
|
||||
(p) => p.id === integration.id
|
||||
) === -1
|
||||
? 'bg-third border border-third'
|
||||
: 'bg-[#291259] border border-[#5826C2]'
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center justify-center gap-[10px]">
|
||||
<div className="relative">
|
||||
<img
|
||||
src={integration.picture}
|
||||
className="rounded-full"
|
||||
alt={integration.identifier}
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
<Image
|
||||
src={`/icons/platforms/${integration.identifier}.png`}
|
||||
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
|
||||
alt={integration.identifier}
|
||||
width={15}
|
||||
height={15}
|
||||
/>
|
||||
</div>
|
||||
<div>{integration.name}</div>
|
||||
<div
|
||||
onClick={addPlatform(integration)}
|
||||
className={clsx(
|
||||
'cursor-pointer relative w-[34px] h-[34px] rounded-full flex justify-center items-center bg-fifth filter transition-all duration-500',
|
||||
selectedAccounts.findIndex(
|
||||
(p) => p.id === integration.id
|
||||
) === -1
|
||||
? 'opacity-40'
|
||||
: ''
|
||||
)}
|
||||
>
|
||||
<img
|
||||
src={integration.picture}
|
||||
className="rounded-full"
|
||||
alt={integration.identifier}
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<Image
|
||||
src={`/icons/platforms/${integration.identifier}.png`}
|
||||
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
|
||||
alt={integration.identifier}
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
) : (
|
||||
<div key={integration.id} className="">
|
||||
<div
|
||||
onClick={addPlatform(integration)}
|
||||
className={clsx(
|
||||
'cursor-pointer rounded-[50px] w-[200px] relative h-[40px] flex justify-center items-center bg-fifth filter transition-all duration-500',
|
||||
selectedAccounts.findIndex(
|
||||
(p) => p.id === integration.id
|
||||
) === -1
|
||||
? 'bg-third border border-third'
|
||||
: 'bg-[#291259] border border-[#5826C2]'
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center justify-center gap-[10px]">
|
||||
<div className="relative">
|
||||
<img
|
||||
src={integration.picture}
|
||||
className="rounded-full"
|
||||
alt={integration.identifier}
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
<Image
|
||||
src={`/icons/platforms/${integration.identifier}.png`}
|
||||
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
|
||||
alt={integration.identifier}
|
||||
width={15}
|
||||
height={15}
|
||||
/>
|
||||
</div>
|
||||
<div>{integration.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -60,9 +60,14 @@ export const LaunchesComponent = () => {
|
|||
}
|
||||
}, []);
|
||||
|
||||
const continueIntegration = useCallback((integration: any) => async () => {
|
||||
router.push(`/launches?added=${integration.identifier}&continue=${integration.id}`);
|
||||
}, []);
|
||||
const continueIntegration = useCallback(
|
||||
(integration: any) => async () => {
|
||||
router.push(
|
||||
`/launches?added=${integration.identifier}&continue=${integration.id}`
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined' && window.opener) {
|
||||
|
|
@ -74,6 +79,7 @@ export const LaunchesComponent = () => {
|
|||
return <LoadingComponent />;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
return (
|
||||
<CalendarWeekProvider integrations={sortedIntegrations}>
|
||||
<div className="flex flex-1 flex-col">
|
||||
|
|
@ -97,7 +103,10 @@ export const LaunchesComponent = () => {
|
|||
)}
|
||||
>
|
||||
{integration.inBetweenSteps && (
|
||||
<div className="absolute left-0 top-0 w-[39px] h-[46px] cursor-pointer" onClick={continueIntegration(integration)}>
|
||||
<div
|
||||
className="absolute left-0 top-0 w-[39px] h-[46px] cursor-pointer"
|
||||
onClick={continueIntegration(integration)}
|
||||
>
|
||||
<div className="bg-red-500 w-[15px] h-[15px] rounded-full -left-[5px] -top-[5px] absolute z-[200] text-[10px] flex justify-center items-center">
|
||||
!
|
||||
</div>
|
||||
|
|
@ -148,7 +157,7 @@ export const LaunchesComponent = () => {
|
|||
))}
|
||||
</div>
|
||||
<AddProviderButton update={() => update(true)} />
|
||||
{sortedIntegrations?.length > 0 && <GeneratorComponent />}
|
||||
{sortedIntegrations?.length > 0 && user?.tier.ai && <GeneratorComponent />}
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col gap-[14px]">
|
||||
<Filters />
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {PickPlatforms} from "@gitroom/frontend/components/launches/helpers/pick.
|
|||
import {IntegrationContext} from "@gitroom/frontend/components/launches/helpers/use.integration";
|
||||
import {ShowAllProviders} from "@gitroom/frontend/components/launches/providers/show.all.providers";
|
||||
import dayjs from "dayjs";
|
||||
import { useStateCallback } from '@gitroom/react/helpers/use.state.callback';
|
||||
|
||||
export const ProvidersOptions: FC<{
|
||||
integrations: Integrations[];
|
||||
|
|
@ -11,7 +12,7 @@ export const ProvidersOptions: FC<{
|
|||
date: dayjs.Dayjs;
|
||||
}> = (props) => {
|
||||
const { integrations, editorValue, date } = props;
|
||||
const [selectedIntegrations, setSelectedIntegrations] = useState([
|
||||
const [selectedIntegrations, setSelectedIntegrations] = useStateCallback([
|
||||
integrations[0],
|
||||
]);
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ export const ProvidersOptions: FC<{
|
|||
onChange={setSelectedIntegrations}
|
||||
singleSelect={true}
|
||||
hide={integrations.length === 1}
|
||||
isMain={false}
|
||||
/>
|
||||
<IntegrationContext.Provider
|
||||
value={{ value: editorValue, integration: selectedIntegrations?.[0], date }}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ import { postSelector } from '@gitroom/frontend/components/post-url-selector/pos
|
|||
import { UpDownArrow } from '@gitroom/frontend/components/launches/up.down.arrow';
|
||||
import { arrayMoveImmutable } from 'array-move';
|
||||
import { linkedinCompany } from '@gitroom/frontend/components/launches/helpers/linkedin.component';
|
||||
import { Editor } from '@gitroom/frontend/components/launches/editor';
|
||||
import { useCopilotAction, useCopilotReadable } from '@copilotkit/react-core';
|
||||
import { AddPostButton } from '@gitroom/frontend/components/launches/add.post.button';
|
||||
|
||||
// Simple component to change back to settings on after changing tab
|
||||
export const SetTab: FC<{ changeTab: () => void }> = (props) => {
|
||||
|
|
@ -81,6 +84,10 @@ export const withProvider = (
|
|||
}) => {
|
||||
const existingData = useExistingData();
|
||||
const { integration, date } = useIntegration();
|
||||
useCopilotReadable({
|
||||
description: integration?.type === 'social' ? 'force content always in MD format' : 'force content always to be fit to social media',
|
||||
value: ''
|
||||
});
|
||||
const [editInPlace, setEditInPlace] = useState(!!existingData.integration);
|
||||
const [InPlaceValue, setInPlaceValue] = useState<
|
||||
Array<{
|
||||
|
|
@ -220,6 +227,14 @@ export const withProvider = (
|
|||
);
|
||||
}, [props.value, editInPlace]);
|
||||
|
||||
useCopilotAction({
|
||||
name: editInPlace ? 'switchToGlobalEdit' : `editInPlace_${integration?.identifier}`,
|
||||
description: editInPlace ? 'Switch to global editing' : `Edit only ${integration?.identifier} this, if you want a different identifier, you have to use setSelectedIntegration first`,
|
||||
handler: async () => {
|
||||
await changeToEditor();
|
||||
},
|
||||
});
|
||||
|
||||
// this is a trick to prevent the data from being deleted, yet we don't render the elements
|
||||
if (!props.show) {
|
||||
return null;
|
||||
|
|
@ -279,7 +294,8 @@ export const withProvider = (
|
|||
<div>
|
||||
<div className="flex gap-[4px]">
|
||||
<div className="flex-1 text-white editor">
|
||||
<MDEditor
|
||||
<Editor
|
||||
order={index}
|
||||
height={InPlaceValue.length > 1 ? 200 : 250}
|
||||
value={val.content}
|
||||
commands={[
|
||||
|
|
@ -353,26 +369,7 @@ export const withProvider = (
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
onClick={addValue(index)}
|
||||
className="!h-[24px] rounded-[3px] flex gap-[4px] w-[102px] text-[12px] font-[500]"
|
||||
>
|
||||
<div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 14 14"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M7 1.3125C5.87512 1.3125 4.7755 1.64607 3.8402 2.27102C2.90489 2.89597 2.17591 3.78423 1.74544 4.82349C1.31496 5.86274 1.20233 7.00631 1.42179 8.10958C1.64124 9.21284 2.18292 10.2263 2.97833 11.0217C3.77374 11.8171 4.78716 12.3588 5.89043 12.5782C6.99369 12.7977 8.13726 12.685 9.17651 12.2546C10.2158 11.8241 11.104 11.0951 11.729 10.1598C12.3539 9.2245 12.6875 8.12488 12.6875 7C12.6859 5.49207 12.0862 4.04636 11.0199 2.98009C9.95365 1.91382 8.50793 1.31409 7 1.3125ZM7 11.8125C6.04818 11.8125 5.11773 11.5303 4.32632 11.0014C3.53491 10.4726 2.91808 9.72103 2.55383 8.84166C2.18959 7.96229 2.09428 6.99466 2.27997 6.06113C2.46566 5.12759 2.92401 4.27009 3.59705 3.59705C4.27009 2.92401 5.1276 2.46566 6.06113 2.27997C6.99466 2.09428 7.9623 2.18958 8.84167 2.55383C9.72104 2.91808 10.4726 3.53491 11.0015 4.32632C11.5303 5.11773 11.8125 6.04818 11.8125 7C11.8111 8.27591 11.3036 9.49915 10.4014 10.4014C9.49915 11.3036 8.27591 11.8111 7 11.8125ZM9.625 7C9.625 7.11603 9.57891 7.22731 9.49686 7.30936C9.41481 7.39141 9.30353 7.4375 9.1875 7.4375H7.4375V9.1875C7.4375 9.30353 7.39141 9.41481 7.30936 9.49686C7.22731 9.57891 7.11603 9.625 7 9.625C6.88397 9.625 6.77269 9.57891 6.69064 9.49686C6.6086 9.41481 6.5625 9.30353 6.5625 9.1875V7.4375H4.8125C4.69647 7.4375 4.58519 7.39141 4.50314 7.30936C4.4211 7.22731 4.375 7.11603 4.375 7C4.375 6.88397 4.4211 6.77269 4.50314 6.69064C4.58519 6.60859 4.69647 6.5625 4.8125 6.5625H6.5625V4.8125C6.5625 4.69647 6.6086 4.58519 6.69064 4.50314C6.77269 4.42109 6.88397 4.375 7 4.375C7.11603 4.375 7.22731 4.42109 7.30936 4.50314C7.39141 4.58519 7.4375 4.69647 7.4375 4.8125V6.5625H9.1875C9.30353 6.5625 9.41481 6.60859 9.49686 6.69064C9.57891 6.77269 9.625 6.88397 9.625 7Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>Add post</div>
|
||||
</Button>
|
||||
<AddPostButton onClick={addValue(index)} num={index} />
|
||||
</div>
|
||||
</Fragment>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import { Onboarding } from '@gitroom/frontend/components/onboarding/onboarding';
|
|||
import { Support } from '@gitroom/frontend/components/layout/support';
|
||||
import { ContinueProvider } from '@gitroom/frontend/components/layout/continue.provider';
|
||||
import { isGeneral } from '@gitroom/react/helpers/is.general';
|
||||
import { CopilotKit } from '@copilotkit/react-core';
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(weekOfYear);
|
||||
|
|
@ -48,38 +49,44 @@ export const LayoutSettings = ({ children }: { children: ReactNode }) => {
|
|||
|
||||
return (
|
||||
<ContextWrapper user={user}>
|
||||
<MantineWrapper>
|
||||
<ToolTip />
|
||||
<ShowMediaBoxModal />
|
||||
<ShowLinkedinCompany />
|
||||
<Toaster />
|
||||
<ShowPostSelector />
|
||||
<Onboarding />
|
||||
<Support />
|
||||
<ContinueProvider />
|
||||
<div className="min-h-[100vh] w-full max-w-[1440px] mx-auto bg-primary px-[12px] text-white flex flex-col">
|
||||
<div className="px-[23px] flex h-[80px] items-center justify-between z-[200] sticky top-0 bg-primary">
|
||||
<Link href="/" className="text-2xl flex items-center gap-[10px]">
|
||||
<div>
|
||||
<Image src="/logo.svg" width={55} height={53} alt="Logo" />
|
||||
<CopilotKit
|
||||
runtimeUrl={process.env.NEXT_PUBLIC_BACKEND_URL + '/copilot/chat'}
|
||||
>
|
||||
<MantineWrapper>
|
||||
<ToolTip />
|
||||
<ShowMediaBoxModal />
|
||||
<ShowLinkedinCompany />
|
||||
<Toaster />
|
||||
<ShowPostSelector />
|
||||
<Onboarding />
|
||||
<Support />
|
||||
<ContinueProvider />
|
||||
<div className="min-h-[100vh] w-full max-w-[1440px] mx-auto bg-primary px-[12px] text-white flex flex-col">
|
||||
<div className="px-[23px] flex h-[80px] items-center justify-between z-[200] sticky top-0 bg-primary">
|
||||
<Link href="/" className="text-2xl flex items-center gap-[10px]">
|
||||
<div>
|
||||
<Image src="/logo.svg" width={55} height={53} alt="Logo" />
|
||||
</div>
|
||||
<div className="mt-[12px]">
|
||||
{isGeneral() ? 'Postiz' : 'Gitroom'}
|
||||
</div>
|
||||
</Link>
|
||||
{user?.orgId ? <TopMenu /> : <div />}
|
||||
<div className="flex items-center gap-[8px]">
|
||||
<SettingsComponent />
|
||||
<NotificationComponent />
|
||||
<OrganizationSelector />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 flex">
|
||||
<div className="flex-1 rounded-3xl px-[23px] py-[17px] flex flex-col">
|
||||
<Title />
|
||||
<div className="flex flex-1 flex-col">{children}</div>
|
||||
</div>
|
||||
<div className="mt-[12px]">{isGeneral() ? 'Postiz' : 'Gitroom'}</div>
|
||||
</Link>
|
||||
{user?.orgId ? <TopMenu /> : <div />}
|
||||
<div className="flex items-center gap-[8px]">
|
||||
<SettingsComponent />
|
||||
<NotificationComponent />
|
||||
<OrganizationSelector />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 flex">
|
||||
<div className="flex-1 rounded-3xl px-[23px] py-[17px] flex flex-col">
|
||||
<Title />
|
||||
<div className="flex flex-1 flex-col">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MantineWrapper>
|
||||
</MantineWrapper>
|
||||
</CopilotKit>
|
||||
</ContextWrapper>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,22 @@
|
|||
'use client';
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const supportEmitter = new EventEmitter();
|
||||
|
||||
export const Support = () => {
|
||||
if (!process.env.NEXT_PUBLIC_DISCORD_SUPPORT) return null
|
||||
const [show, setShow] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
supportEmitter.on('change', setShow);
|
||||
return () => {
|
||||
supportEmitter.off('state', setShow);
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!process.env.NEXT_PUBLIC_DISCORD_SUPPORT || !show) return null
|
||||
return (
|
||||
<div className="bg-[#612AD5] fixed right-[20px] bottom-[20px] z-[500] p-[20px] text-white rounded-[20px] cursor-pointer" onClick={() => window.open(process.env.NEXT_PUBLIC_DISCORD_SUPPORT)}>Discord Support</div>
|
||||
<div className="bg-[#612AD5] fixed right-[15px] bottom-[15px] z-[500] p-[20px] text-white rounded-[20px] cursor-pointer" onClick={() => window.open(process.env.NEXT_PUBLIC_DISCORD_SUPPORT)}>Discord Support</div>
|
||||
)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -18,6 +18,10 @@
|
|||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.529.1",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@copilotkit/backend": "^0.9.0",
|
||||
"@copilotkit/react-core": "^0.25.0",
|
||||
"@copilotkit/react-textarea": "^0.35.0",
|
||||
"@copilotkit/react-ui": "^0.22.0",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@mantine/core": "^5.10.5",
|
||||
"@mantine/dates": "^5.10.5",
|
||||
|
|
|
|||
Loading…
Reference in New Issue