diff --git a/apps/backend/src/api/routes/integrations.controller.ts b/apps/backend/src/api/routes/integrations.controller.ts index abb4de6e..332de202 100644 --- a/apps/backend/src/api/routes/integrations.controller.ts +++ b/apps/backend/src/api/routes/integrations.controller.ts @@ -1,5 +1,13 @@ import { - Body, Controller, Delete, Get, Param, Post, Put, Query, UseFilters + Body, + Controller, + Delete, + Get, + Param, + Post, + Put, + Query, + UseFilters, } from '@nestjs/common'; import { ioRedis } from '@gitroom/nestjs-libraries/redis/redis.service'; import { ConnectIntegrationDto } from '@gitroom/nestjs-libraries/dtos/integrations/connect.integration.dto'; @@ -42,6 +50,11 @@ export class IntegrationsController { return this._integrationManager.getAllIntegrations(); } + @Get('/:identifier/internal-plugs') + getInternalPlugs(@Param('identifier') identifier: string) { + return this._integrationManager.getInternalPlugs(identifier); + } + @Get('/customers') getCustomers(@GetOrgFromRequest() org: Organization) { return this._integrationService.customers(org.id); @@ -66,11 +79,7 @@ export class IntegrationsController { @Param('id') id: string, @Body() body: { name: string } ) { - return this._integrationService.updateOnCustomerName( - org.id, - id, - body.name - ); + return this._integrationService.updateOnCustomerName(org.id, id, body.name); } @Get('/list') diff --git a/apps/frontend/src/components/launches/add.edit.model.tsx b/apps/frontend/src/components/launches/add.edit.model.tsx index 6cfcbaf5..74308b33 100644 --- a/apps/frontend/src/components/launches/add.edit.model.tsx +++ b/apps/frontend/src/components/launches/add.edit.model.tsx @@ -71,6 +71,7 @@ function countCharacters(text: string, type: string): number { export const AddEditModal: FC<{ date: dayjs.Dayjs; integrations: Integrations[]; + allIntegrations?: Integrations[]; reopenModal: () => void; mutate: () => void; onlyValues?: Array<{ @@ -538,11 +539,13 @@ export const AddEditModal: FC<{ disableForm={true} > - {uniqBy(ints, (u) => u?.customer?.name).filter(f => f.customer?.name).map((p) => ( - - ))} + {uniqBy(ints, (u) => u?.customer?.name) + .filter((f) => f.customer?.name) + .map((p) => ( + + ))} )} @@ -814,6 +817,7 @@ export const AddEditModal: FC<{ {!!selectedIntegrations.length && (
= ({ .map((char) => originalMap?.[char] || char) .join(''); + Transforms.insertText(editor, newText); + ReactEditor.focus(editor); }; return ( diff --git a/apps/frontend/src/components/launches/calendar.tsx b/apps/frontend/src/components/launches/calendar.tsx index 80c9ad71..4d6f54da 100644 --- a/apps/frontend/src/components/launches/calendar.tsx +++ b/apps/frontend/src/components/launches/calendar.tsx @@ -357,6 +357,7 @@ export const CalendarColumn: FC<{ children: ( ({ ...p }))} reopenModal={editPost(post)} mutate={reloadCalendarView} integrations={integrations @@ -419,6 +421,7 @@ export const CalendarColumn: FC<{ }, children: ( ({ ...p }))} integrations={integrations.slice(0).map((p) => ({ ...p }))} mutate={reloadCalendarView} date={ diff --git a/apps/frontend/src/components/launches/generator/generator.tsx b/apps/frontend/src/components/launches/generator/generator.tsx index 4369eb1d..5237f0c3 100644 --- a/apps/frontend/src/components/launches/generator/generator.tsx +++ b/apps/frontend/src/components/launches/generator/generator.tsx @@ -143,6 +143,7 @@ const FirstStep: FC = (props) => { }, children: ( ({ ...p }))} integrations={integrations.slice(0).map((p) => ({ ...p }))} mutate={reloadCalendarView} date={dayjs.utc(load.date).local()} diff --git a/apps/frontend/src/components/launches/helpers/pick.platform.component.tsx b/apps/frontend/src/components/launches/helpers/pick.platform.component.tsx index 394c92e3..b733bfa7 100644 --- a/apps/frontend/src/components/launches/helpers/pick.platform.component.tsx +++ b/apps/frontend/src/components/launches/helpers/pick.platform.component.tsx @@ -7,7 +7,6 @@ import Image from 'next/image'; import { useCopilotAction, useCopilotReadable } from '@copilotkit/react-core'; import { useStateCallback } from '@gitroom/react/helpers/use.state.callback'; import { timer } from '@gitroom/helpers/utils/timer'; -import dayjs from 'dayjs'; export const PickPlatforms: FC<{ integrations: Integrations[]; diff --git a/apps/frontend/src/components/launches/helpers/use.integration.ts b/apps/frontend/src/components/launches/helpers/use.integration.ts index 80c91814..091a4a03 100644 --- a/apps/frontend/src/components/launches/helpers/use.integration.ts +++ b/apps/frontend/src/components/launches/helpers/use.integration.ts @@ -7,11 +7,12 @@ import dayjs from 'dayjs'; export const IntegrationContext = createContext<{ date: dayjs.Dayjs; integration: Integrations | undefined; + allIntegrations: Integrations[]; value: Array<{ content: string; id?: string; image?: Array<{ path: string; id: string }>; }>; -}>({ integration: undefined, value: [], date: dayjs() }); +}>({ integration: undefined, value: [], date: dayjs(), allIntegrations: [] }); export const useIntegration = () => useContext(IntegrationContext); diff --git a/apps/frontend/src/components/launches/internal.channels.tsx b/apps/frontend/src/components/launches/internal.channels.tsx new file mode 100644 index 00000000..02837631 --- /dev/null +++ b/apps/frontend/src/components/launches/internal.channels.tsx @@ -0,0 +1,165 @@ +import { FC, useEffect, useState } from 'react'; +import { + Integrations, + useCalendar, +} from '@gitroom/frontend/components/launches/calendar.context'; +import { PickPlatforms } from '@gitroom/frontend/components/launches/helpers/pick.platform.component'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; +import { Select } from '@gitroom/react/form/select'; +import { Slider } from '@gitroom/react/form/slider'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; +import clsx from 'clsx'; + +const delayOptions = [ + { + name: 'Immediately', + value: 0, + }, + { + name: '1 hour', + value: 3600000, + }, + { + name: '2 hours', + value: 7200000, + }, + { + name: '3 hours', + value: 10800000, + }, + { + name: '8 hours', + value: 28800000, + }, + { + name: '12 hours', + value: 43200000, + }, + { + name: '15 hours', + value: 54000000, + }, + { + name: '24 hours', + value: 86400000, + }, +]; +export const InternalChannels: FC<{ + plugs: { + identifier: string; + title: string; + description: string; + pickIntegration: string[]; + fields: { + name: string; + description: string; + type: string; + placeholder: string; + validation?: RegExp; + }[]; + }[]; +}> = (props) => { + const { plugs } = props; + + return ( +
+ {plugs.map((plug, index) => ( + + ))} +
+ ); +}; + +const Plug: FC<{ + plug: { + identifier: string; + title: string; + description: string; + pickIntegration: string[]; + fields: { + name: string; + description: string; + type: string; + placeholder: string; + validation?: RegExp; + }[]; + }; +}> = ({ plug }) => { + const { allIntegrations, integration } = useIntegration(); + const { watch, setValue, control, register } = useSettings(); + const val = watch(`plug--${plug.identifier}--integrations`); + const active = watch(`plug--${plug.identifier}--active`); + + // const selectedIntegrationsValue = watch( + // `plug.${plug.identifier}.integrations` + // ); + // + // console.log(selectedIntegrationsValue); + const [localValue, setLocalValue] = useState( + (val || []).map((p: any) => ({ ...p })) + ); + useEffect(() => { + setValue(`plug--${plug.identifier}--integrations`, [...localValue]); + }, [localValue, plug, setValue]); + + const [allowedIntegrations] = useState( + allIntegrations.filter( + (i) => + plug.pickIntegration.includes(i.identifier) && integration?.id !== i.id + ) + ); + + return ( +
+
+
{plug.title}
+
+ + setValue(`plug--${plug.identifier}--active`, p === 'on') + } + fill={true} + /> +
+
+
+ {!allowedIntegrations.length ? ( + 'No available accounts' + ) : ( +
+
{plug.description}
+ +
Accounts that will engage:
+ +
+ )} +
+
+ ); +}; diff --git a/apps/frontend/src/components/launches/providers.options.tsx b/apps/frontend/src/components/launches/providers.options.tsx index 0698b1ee..52621f89 100644 --- a/apps/frontend/src/components/launches/providers.options.tsx +++ b/apps/frontend/src/components/launches/providers.options.tsx @@ -8,6 +8,7 @@ import { useStateCallback } from '@gitroom/react/helpers/use.state.callback'; export const ProvidersOptions: FC<{ integrations: Integrations[]; + allIntegrations: Integrations[]; editorValue: Array<{ id?: string; content: string }>; date: dayjs.Dayjs; }> = (props) => { @@ -32,7 +33,7 @@ export const ProvidersOptions: FC<{ isMain={false} /> void }> = (props) => { @@ -101,6 +104,7 @@ export const withProvider = function ( const { integration, date } = useIntegration(); const [showLinkedinPopUp, setShowLinkedinPopUp] = useState(false); const [uploading, setUploading] = useState(false); + const fetch = useFetch(); useCopilotReadable({ description: @@ -343,6 +347,12 @@ export const withProvider = function ( [changeImage] ); + const getInternalPlugs = useCallback(async () => { + return (await fetch(`/integrations/${props.identifier}/internal-plugs`)).json(); + }, [props.identifier]); + + const {data} = useSWR(`internal-${props.identifier}`, getInternalPlugs); + // this is a trick to prevent the data from being deleted, yet we don't render the elements if (!props.show) { return null; @@ -364,7 +374,7 @@ export const withProvider = function ( Preview
- {!!SettingsComponent && ( + {(!!SettingsComponent || !!data?.internalPlugs?.length) && (