From af2f952ed06f8eaef7a222deb7ab6a3d831c324e Mon Sep 17 00:00:00 2001 From: Nevo David Date: Thu, 26 Jun 2025 20:00:42 +0700 Subject: [PATCH] feat: new postiz modal --- apps/frontend/src/app/global.scss | 6 +- .../components/launches/add.edit.model.tsx | 1002 ----------------- .../components/launches/add.post.button.tsx | 40 - .../src/components/launches/ai.image.tsx | 4 + .../src/components/launches/bold.text.tsx | 119 -- .../src/components/launches/calendar.tsx | 1 - .../launches/connect.with.wallet.tsx | 0 .../src/components/launches/editor.tsx | 123 -- .../launches/finisher/thread.finisher.tsx | 64 -- .../launches/general.preview.component.tsx | 29 +- .../launches/generator/generator.tsx | 2 +- .../launches/helpers/linkedin.component.tsx | 32 + .../src/components/launches/new.post.tsx | 4 +- .../launches/post.to.organization.tsx | 82 -- .../components/launches/providers.options.tsx | 54 - .../providers/bluesky/bluesky.provider.tsx | 27 - .../facebook/facebook.continue.tsx | 119 -- .../instagram/instagram.continue.tsx | 121 -- .../linkedin/linkedin.continue.tsx | 108 -- .../providers/continue-provider/list.tsx | 8 - .../providers/devto/devto.provider.tsx | 93 -- .../launches/providers/devto/devto.tags.tsx | 71 -- .../launches/providers/devto/fonts/SFNS.woff2 | Bin 90060 -> 0 bytes .../providers/devto/select.organization.tsx | 55 - .../discord/discord.channel.select.tsx | 55 - .../providers/discord/discord.provider.tsx | 20 - .../providers/dribbble/dribbble.provider.tsx | 47 - .../providers/dribbble/dribbble.teams.tsx | 58 - .../providers/facebook/facebook.provider.tsx | 2 - .../providers/hashnode/hashnode.provider.tsx | 95 -- .../hashnode/hashnode.publications.tsx | 55 - .../providers/hashnode/hashnode.tags.tsx | 76 -- .../providers/high.order.provider.tsx | 707 ------------ .../instagram/instagram.collaborators.tsx | 88 -- .../providers/instagram/instagram.tags.tsx | 100 -- .../providers/lemmy/lemmy.provider.tsx | 82 -- .../launches/providers/lemmy/subreddit.tsx | 160 --- .../providers/linkedin/linkedin.provider.tsx | 50 - .../providers/mastodon/mastodon.provider.tsx | 3 - .../medium/fonts/Charter Bold Italic.ttf | Bin 40436 -> 0 bytes .../providers/medium/fonts/Charter Bold.ttf | Bin 41036 -> 0 bytes .../providers/medium/fonts/Charter Italic.ttf | Bin 40796 -> 0 bytes .../medium/fonts/Charter Regular.ttf | Bin 42036 -> 0 bytes .../providers/medium/fonts/stylesheet.css | 37 - .../providers/medium/medium.provider.tsx | 89 -- .../providers/medium/medium.publications.tsx | 56 - .../launches/providers/medium/medium.tags.tsx | 80 -- .../providers/nostr/nostr.provider.tsx | 10 - .../providers/pinterest/pinterest.board.tsx | 59 - .../pinterest/pinterest.provider.tsx | 74 -- .../providers/reddit/reddit.provider.tsx | 219 ---- .../launches/providers/reddit/subreddit.tsx | 283 ----- .../launches/providers/show.all.providers.tsx | 159 --- .../providers/slack/slack.channel.select.tsx | 55 - .../providers/slack/slack.provider.tsx | 20 - .../providers/telegram/telegram.provider.tsx | 10 - .../providers/threads/threads.provider.tsx | 15 - .../providers/tiktok/tiktok.provider.tsx | 370 ------ .../launches/providers/vk/vk.provider.tsx | 10 - .../launches/providers/warpcast/subreddit.tsx | 144 --- .../providers/warpcast/warpcast.provider.tsx | 68 -- .../providers/x/fonts/Chirp-Bold.woff2 | Bin 45016 -> 0 bytes .../providers/x/fonts/Chirp-Regular.woff2 | Bin 44660 -> 0 bytes .../launches/providers/x/x.provider.tsx | 111 -- .../providers/youtube/youtube.provider.tsx | 72 -- .../src/components/launches/submitted.tsx | 41 - .../src/components/launches/u.text.tsx | 126 --- .../components/layout/continue.provider.tsx | 2 +- .../marketplace/preview.popup.dynamic.tsx | 16 +- .../new-launch/add.edit.modal.inner.tsx | 99 -- .../components/new-launch/add.edit.modal.tsx | 143 ++- .../src/components/new-launch/bold.text.tsx | 2 +- .../src/components/new-launch/editor.tsx | 345 +++++- .../new-launch/finisher/thread.finisher.tsx | 7 +- .../new-launch/helpers/date.picker.tsx | 102 -- .../new-launch/helpers/dnd.provider.tsx | 10 - .../new-launch/helpers/isuscitizen.utils.tsx | 6 - .../new-launch/helpers/linkedin.component.tsx | 189 ---- .../helpers/new.image.component.tsx | 91 -- .../helpers/top.title.component.tsx | 68 -- .../helpers/use.custom.provider.function.ts | 29 - .../new-launch/helpers/use.existing.data.tsx | 21 - .../new-launch/helpers/use.expend.tsx | 31 - .../new-launch/helpers/use.formatting.ts | 49 - .../helpers/use.hide.top.editor.tsx | 31 - .../new-launch/helpers/use.integration.tsx | 27 - .../helpers/use.move.to.integration.tsx | 47 - .../new-launch/helpers/use.values.ts | 96 -- .../components/new-launch/manage.modal.tsx | 445 ++++++++ .../new-launch/picks.socials.component.tsx | 22 +- .../providers/bluesky/bluesky.provider.tsx | 2 - .../facebook/facebook.continue.tsx | 4 +- .../instagram/instagram.continue.tsx | 4 +- .../linkedin/linkedin.continue.tsx | 4 +- .../providers/devto/devto.provider.tsx | 5 +- .../new-launch/providers/devto/devto.tags.tsx | 4 +- .../providers/devto/select.organization.tsx | 4 +- .../discord/discord.channel.select.tsx | 4 +- .../providers/discord/discord.provider.tsx | 2 +- .../providers/dribbble/dribbble.provider.tsx | 2 +- .../providers/dribbble/dribbble.teams.tsx | 4 +- .../providers/hashnode/hashnode.provider.tsx | 4 +- .../hashnode/hashnode.publications.tsx | 4 +- .../providers/hashnode/hashnode.tags.tsx | 4 +- .../providers/high.order.provider.tsx | 199 +++- .../instagram/instagram.collaborators.tsx | 2 +- .../providers/instagram/instagram.tags.tsx | 4 +- .../providers/lemmy/lemmy.provider.tsx | 2 +- .../new-launch/providers/lemmy/subreddit.tsx | 4 +- .../providers/linkedin/linkedin.provider.tsx | 2 +- .../providers/medium/medium.provider.tsx | 4 +- .../providers/medium/medium.publications.tsx | 4 +- .../providers/medium/medium.tags.tsx | 2 +- .../providers/pinterest/pinterest.board.tsx | 4 +- .../pinterest/pinterest.provider.tsx | 2 +- .../providers/reddit/reddit.provider.tsx | 6 +- .../new-launch/providers/reddit/subreddit.tsx | 6 +- .../providers/show.all.providers.tsx | 67 +- .../providers/slack/slack.channel.select.tsx | 4 +- .../providers/slack/slack.provider.tsx | 2 +- .../providers/tiktok/tiktok.provider.tsx | 4 +- .../providers/warpcast/subreddit.tsx | 4 +- .../providers/warpcast/warpcast.provider.tsx | 2 +- .../new-launch/providers/x/x.provider.tsx | 2 +- .../providers/youtube/youtube.provider.tsx | 2 +- .../components/new-launch/select.current.tsx | 185 ++- .../src/components/new-launch/store.ts | 208 +++- .../src/components/new-launch/u.text.tsx | 2 +- apps/frontend/src/components/sets/sets.tsx | 2 +- apps/frontend/src/components/signature.tsx | 2 +- .../standalone-modal/standalone.modal.tsx | 2 +- i18n.lock | 10 +- .../translation/locales/ar/translation.json | 12 +- .../translation/locales/bn/translation.json | 12 +- .../translation/locales/de/translation.json | 12 +- .../translation/locales/en/translation.json | 6 +- .../translation/locales/es/translation.json | 12 +- .../translation/locales/fr/translation.json | 12 +- .../translation/locales/he/translation.json | 12 +- .../translation/locales/it/translation.json | 12 +- .../translation/locales/ja/translation.json | 12 +- .../translation/locales/ko/translation.json | 12 +- .../translation/locales/pt/translation.json | 12 +- .../translation/locales/ru/translation.json | 12 +- .../translation/locales/tr/translation.json | 12 +- .../translation/locales/vi/translation.json | 12 +- .../translation/locales/zh/translation.json | 12 +- package.json | 2 +- pnpm-lock.yaml | 33 +- 149 files changed, 1722 insertions(+), 7025 deletions(-) delete mode 100644 apps/frontend/src/components/launches/add.edit.model.tsx delete mode 100644 apps/frontend/src/components/launches/add.post.button.tsx delete mode 100644 apps/frontend/src/components/launches/bold.text.tsx delete mode 100644 apps/frontend/src/components/launches/connect.with.wallet.tsx delete mode 100644 apps/frontend/src/components/launches/editor.tsx delete mode 100644 apps/frontend/src/components/launches/finisher/thread.finisher.tsx delete mode 100644 apps/frontend/src/components/launches/post.to.organization.tsx delete mode 100644 apps/frontend/src/components/launches/providers.options.tsx delete mode 100644 apps/frontend/src/components/launches/providers/bluesky/bluesky.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/continue-provider/facebook/facebook.continue.tsx delete mode 100644 apps/frontend/src/components/launches/providers/continue-provider/instagram/instagram.continue.tsx delete mode 100644 apps/frontend/src/components/launches/providers/continue-provider/linkedin/linkedin.continue.tsx delete mode 100644 apps/frontend/src/components/launches/providers/continue-provider/list.tsx delete mode 100644 apps/frontend/src/components/launches/providers/devto/devto.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/devto/devto.tags.tsx delete mode 100644 apps/frontend/src/components/launches/providers/devto/fonts/SFNS.woff2 delete mode 100644 apps/frontend/src/components/launches/providers/devto/select.organization.tsx delete mode 100644 apps/frontend/src/components/launches/providers/discord/discord.channel.select.tsx delete mode 100644 apps/frontend/src/components/launches/providers/discord/discord.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/dribbble/dribbble.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/dribbble/dribbble.teams.tsx delete mode 100644 apps/frontend/src/components/launches/providers/facebook/facebook.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/hashnode/hashnode.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/hashnode/hashnode.publications.tsx delete mode 100644 apps/frontend/src/components/launches/providers/hashnode/hashnode.tags.tsx delete mode 100644 apps/frontend/src/components/launches/providers/high.order.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/instagram/instagram.collaborators.tsx delete mode 100644 apps/frontend/src/components/launches/providers/instagram/instagram.tags.tsx delete mode 100644 apps/frontend/src/components/launches/providers/lemmy/lemmy.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/lemmy/subreddit.tsx delete mode 100644 apps/frontend/src/components/launches/providers/linkedin/linkedin.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/mastodon/mastodon.provider.tsx delete mode 100755 apps/frontend/src/components/launches/providers/medium/fonts/Charter Bold Italic.ttf delete mode 100755 apps/frontend/src/components/launches/providers/medium/fonts/Charter Bold.ttf delete mode 100755 apps/frontend/src/components/launches/providers/medium/fonts/Charter Italic.ttf delete mode 100755 apps/frontend/src/components/launches/providers/medium/fonts/Charter Regular.ttf delete mode 100755 apps/frontend/src/components/launches/providers/medium/fonts/stylesheet.css delete mode 100644 apps/frontend/src/components/launches/providers/medium/medium.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/medium/medium.publications.tsx delete mode 100644 apps/frontend/src/components/launches/providers/medium/medium.tags.tsx delete mode 100644 apps/frontend/src/components/launches/providers/nostr/nostr.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/pinterest/pinterest.board.tsx delete mode 100644 apps/frontend/src/components/launches/providers/pinterest/pinterest.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/reddit/reddit.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/reddit/subreddit.tsx delete mode 100644 apps/frontend/src/components/launches/providers/show.all.providers.tsx delete mode 100644 apps/frontend/src/components/launches/providers/slack/slack.channel.select.tsx delete mode 100644 apps/frontend/src/components/launches/providers/slack/slack.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/telegram/telegram.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/threads/threads.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/vk/vk.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/warpcast/subreddit.tsx delete mode 100644 apps/frontend/src/components/launches/providers/warpcast/warpcast.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/x/fonts/Chirp-Bold.woff2 delete mode 100644 apps/frontend/src/components/launches/providers/x/fonts/Chirp-Regular.woff2 delete mode 100644 apps/frontend/src/components/launches/providers/x/x.provider.tsx delete mode 100644 apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx delete mode 100644 apps/frontend/src/components/launches/submitted.tsx delete mode 100644 apps/frontend/src/components/launches/u.text.tsx delete mode 100644 apps/frontend/src/components/new-launch/add.edit.modal.inner.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/date.picker.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/dnd.provider.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/isuscitizen.utils.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/linkedin.component.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/new.image.component.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/top.title.component.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/use.custom.provider.function.ts delete mode 100644 apps/frontend/src/components/new-launch/helpers/use.existing.data.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/use.expend.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/use.formatting.ts delete mode 100644 apps/frontend/src/components/new-launch/helpers/use.hide.top.editor.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/use.integration.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/use.move.to.integration.tsx delete mode 100644 apps/frontend/src/components/new-launch/helpers/use.values.ts create mode 100644 apps/frontend/src/components/new-launch/manage.modal.tsx diff --git a/apps/frontend/src/app/global.scss b/apps/frontend/src/app/global.scss index d968196e..d7473664 100644 --- a/apps/frontend/src/app/global.scss +++ b/apps/frontend/src/app/global.scss @@ -99,6 +99,7 @@ html { cursor: text; display: flex; align-items: center; + margin-right: 0 !important; } .react-tags.is-active { @@ -191,6 +192,7 @@ html { .react-tags__combobox-input { /* prevent autoresize overflowing the container */ max-width: 100%; + width: 100% !important; /* remove styles and layout from this element */ margin: 0; padding: 0; @@ -198,7 +200,7 @@ html { outline: none; background: none; /* match the font styles */ - font-size: inherit; + font-size: 16px; line-height: inherit; } @@ -434,7 +436,7 @@ div div .set-font-family { } .tags-top .react-tags__combobox { - height: 35px; + height: 44px; display: flex; background-color: #141c2c; padding-left: 10px; diff --git a/apps/frontend/src/components/launches/add.edit.model.tsx b/apps/frontend/src/components/launches/add.edit.model.tsx deleted file mode 100644 index 80caafd4..00000000 --- a/apps/frontend/src/components/launches/add.edit.model.tsx +++ /dev/null @@ -1,1002 +0,0 @@ -'use client'; - -import React, { - FC, - Fragment, - MouseEventHandler, - useCallback, - useEffect, - useMemo, - ClipboardEvent, - useState, - memo, -} from 'react'; -import dayjs from 'dayjs'; -import { Integrations } from '@gitroom/frontend/components/launches/calendar.context'; -import clsx from 'clsx'; -import { usePreventWindowUnload } from '@gitroom/react/helpers/use.prevent.window.unload'; -import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; -import { useModals } from '@mantine/modals'; -import { useHideTopEditor } from '@gitroom/frontend/components/launches/helpers/use.hide.top.editor'; -import { Button } from '@gitroom/react/form/button'; -// @ts-ignore -import useKeypress from 'react-use-keypress'; -import { - getValues, - resetValues, -} from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { useMoveToIntegration } from '@gitroom/frontend/components/launches/helpers/use.move.to.integration'; -import { useExistingData } from '@gitroom/frontend/components/launches/helpers/use.existing.data'; -import { MultiMediaComponent } from '@gitroom/frontend/components/media/media.component'; -import { useExpend } from '@gitroom/frontend/components/launches/helpers/use.expend'; -import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; -import { PickPlatforms } from '@gitroom/frontend/components/launches/helpers/pick.platform.component'; -import { ProvidersOptions } from '@gitroom/frontend/components/launches/providers.options'; -import useSWR from 'swr'; -import { useToaster } from '@gitroom/react/toaster/toaster'; -import { UpDownArrow } from '@gitroom/frontend/components/launches/up.down.arrow'; -import { DatePicker } from '@gitroom/frontend/components/launches/helpers/date.picker'; -import { arrayMoveImmutable } from 'array-move'; -import { - Information, - 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'; -import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; -import Image from 'next/image'; -import { weightedLength } from '@gitroom/helpers/utils/count.length'; -import { useClickOutside } from '@gitroom/frontend/components/layout/click.outside'; -import { useUppyUploader } from '@gitroom/frontend/components/media/new.uploader'; -import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; -import { DropFiles } from '@gitroom/frontend/components/layout/drop.files'; -import { SelectCustomer } from '@gitroom/frontend/components/launches/select.customer'; -import { TagsComponent } from './tags.component'; -import { RepeatComponent } from '@gitroom/frontend/components/launches/repeat.component'; -import { MergePost } from '@gitroom/frontend/components/launches/merge.post'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -import { type CreatePostDto } from '@gitroom/nestjs-libraries/dtos/posts/create.post.dto'; -import { uniq } from 'lodash'; -import { SetContext } from '@gitroom/frontend/components/launches/set.context'; -function countCharacters(text: string, type: string): number { - if (type !== 'x') { - return text.length; - } - return weightedLength(text); -} - -export const AddEditModal: FC<{ - date: dayjs.Dayjs; - integrations: Integrations[]; - allIntegrations?: Integrations[]; - set?: CreatePostDto; - addEditSets?: (data: any) => void; - reopenModal: () => void; - mutate: () => void; - padding?: string; - customClose?: () => void; - onlyValues?: Array<{ - content: string; - id?: string; - image?: Array<{ - id: string; - path: string; - }>; - }>; -}> = memo((props) => { - const { - date, - integrations: ints, - reopenModal, - mutate, - onlyValues, - padding, - customClose, - addEditSets, - set, - } = props; - - const [customer, setCustomer] = useState(''); - const [loading, setLoading] = useState(false); - const [uploading, setUploading] = useState(false); - const [canUseClose, setCanUseClose] = useState(true); - const t = useT(); - - // selected integrations to allow edit - const [selectedIntegrations, setSelectedIntegrations] = useStateCallback< - Integrations[] - >([]); - - const integrations = useMemo(() => { - if (!customer) { - return ints; - } - const list = ints.filter((f) => f?.customer?.id === customer); - if (list.length === 1 && !set) { - setSelectedIntegrations([list[0]]); - } - return list; - }, [customer, ints, set]); - const [dateState, setDateState] = useState(date); - - // hook to open a new modal - const modal = useModals(); - - const selectIntegrationsDefault = useMemo(() => { - if (!set) { - return []; - } - - const keepReference: Integrations[] = []; - const neededIntegrations = uniq(set.posts.flatMap((p) => p.integration.id)); - for (const i of ints) { - if (neededIntegrations.indexOf(i.id) > -1) { - keepReference.push(i); - } - } - - return keepReference; - }, [set]); - - useEffect(() => { - if (set?.posts) { - setSelectedIntegrations(selectIntegrationsDefault); - } - }, [selectIntegrationsDefault]); - - // value of each editor - const [value, setValue] = useState< - Array<{ - content: string; - id?: string; - image?: Array<{ - id: string; - path: string; - }>; - }> - >( - onlyValues - ? onlyValues - : set - ? set?.posts?.[0]?.value || [ - { - content: '', - }, - ] - : [ - { - content: '', - }, - ] - ); - const fetch = useFetch(); - const user = useUser(); - const updateOrder = useCallback(() => { - modal.closeAll(); - reopenModal(); - }, [reopenModal, modal]); - - // prevent the window exit by mistake - usePreventWindowUnload(true); - - // hook to move the settings in the right place to fix missing fields - const moveToIntegration = useMoveToIntegration(); - - // hook to test if the top editor should be hidden - const showHide = useHideTopEditor(); - - // merge all posts and delete all the comments - const merge = useCallback(() => { - setValue( - value.reduce( - (all, current) => { - all[0].content = all[0].content + current.content + '\n'; - all[0].image = [...all[0].image, ...(current.image || [])]; - return all; - }, - [ - { - content: '', - id: value[0].id, - image: [] as { - id: string; - path: string; - }[], - }, - ] - ) - ); - }, [value]); - const [showError, setShowError] = useState(false); - - // are we in edit mode? - const existingData = useExistingData(); - const [inter, setInter] = useState(existingData?.posts?.[0]?.intervalInDays); - const [tags, setTags] = useState( - // @ts-ignore - existingData?.posts?.[0]?.tags?.map((p: any) => ({ - label: p.tag.name, - value: p.tag.name, - })) || [] - ); - - // Post for - const [postFor, setPostFor] = useState(); - const expend = useExpend(); - const toaster = useToaster(); - - // if it's edit just set the current integration - useEffect(() => { - if (existingData.integration) { - setSelectedIntegrations([ - integrations.find((p) => p.id === existingData.integration)!, - ]); - } else if (integrations.length === 1) { - setSelectedIntegrations([integrations[0]]); - } - }, [existingData.integration]); - - // 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(); - }; - }, []); - - // Change the value of the global editor - const changeValue = useCallback( - (index: number) => (newValue: string) => { - return setValue((prev) => { - prev[index].content = newValue; - return [...prev]; - }); - }, - [value] - ); - const changeImage = useCallback( - (index: number) => - (newValue: { - target: { - name: string; - value?: Array<{ - id: string; - path: string; - }>; - }; - }) => { - return setValue((prev) => { - return prev.map((p, i) => { - if (i === index) { - return { - ...p, - image: newValue.target.value, - }; - } - return p; - }); - }); - }, - [] - ); - - // Add another editor - const addValue = useCallback( - (index: number) => () => { - setValue((prev) => { - return prev.reduce( - (acc, p, i) => { - acc.push(p); - if (i === index) { - acc.push({ - content: '', - }); - } - return acc; - }, - [] as Array<{ - content: string; - }> - ); - }); - }, - [] - ); - const changePosition = useCallback( - (index: number) => (type: 'up' | 'down') => { - if (type === 'up' && index !== 0) { - setValue((prev) => { - return arrayMoveImmutable(prev, index, index - 1); - }); - } else if (type === 'down') { - setValue((prev) => { - return arrayMoveImmutable(prev, index, index + 1); - }); - } - }, - [] - ); - - // Delete post - const deletePost = useCallback( - (index: number) => async () => { - if ( - !(await deleteDialog( - 'Are you sure you want to delete this post?', - 'Yes, delete it!' - )) - ) { - return; - } - setValue((prev) => { - prev.splice(index, 1); - return [...prev]; - }); - }, - [value] - ); - - // override the close modal to ask the user if he is sure to close - const askClose = useCallback(async () => { - if (!canUseClose) { - return; - } - if ( - await deleteDialog( - t( - 'are_you_sure_you_want_to_close_this_modal_all_data_will_be_lost', - 'Are you sure you want to close this modal? (all data will be lost)' - ), - t('yes_close_it', 'Yes, close it!') - ) - ) { - if (customClose) { - customClose(); - return; - } - modal.closeAll(); - } - }, [canUseClose]); - - // sometimes it's easier to click escape to close - useKeypress('Escape', askClose); - const postNow = useCallback( - ((e) => { - e.stopPropagation(); - e.preventDefault(); - return schedule('now')(); - }) as MouseEventHandler, - [] - ); - - // function to send to the server and save - const schedule = useCallback( - (type: 'draft' | 'now' | 'schedule' | 'delete') => async () => { - setLoading(true); - if (type === 'delete') { - if ( - !(await deleteDialog( - 'Are you sure you want to delete this post?', - 'Yes, delete it!' - )) - ) { - setLoading(false); - return; - } - await fetch(`/posts/${existingData.group}`, { - method: 'DELETE', - }); - mutate(); - modal.closeAll(); - return; - } - const values = getValues(); - const allKeys = Object.keys(values).map((v) => ({ - integration: integrations.find((p) => p.id === v), - value: values[v].posts, - valid: values[v].isValid, - group: existingData?.group, - trigger: values[v].trigger, - settings: values[v].settings(), - checkValidity: values[v].checkValidity, - maximumCharacters: values[v].maximumCharacters, - })); - if (type !== 'draft') { - for (const key of allKeys) { - if (key.checkValidity) { - const check = await key.checkValidity( - key?.value.map((p: any) => p.image || []), - key.settings, - JSON.parse(key?.integration?.additionalSettings || '[]') - ); - if (typeof check === 'string') { - toaster.show(check, 'warning'); - setLoading(false); - return; - } - } - if ( - key.value.some((p) => { - return ( - countCharacters(p.content, key?.integration?.identifier || '') > - (key.maximumCharacters || 1000000) - ); - }) - ) { - if ( - !(await deleteDialog( - `${key?.integration?.name} post is too long, it will be cropped, do you want to continue?`, - 'Yes, continue' - )) - ) { - await key.trigger(); - moveToIntegration({ - identifier: key?.integration?.id!, - toPreview: true, - }); - setLoading(false); - return; - } - } - if (key.value.some((p) => !p.content || p.content.length < 6)) { - setShowError(true); - setLoading(false); - return; - } - if (!key.valid) { - await key.trigger(); - moveToIntegration({ - identifier: key?.integration?.id!, - }); - setLoading(false); - return; - } - } - } - const shortLinkUrl = await ( - await fetch('/posts/should-shortlink', { - method: 'POST', - body: JSON.stringify({ - messages: allKeys.flatMap((p) => - p.value.flatMap((a) => - a.content.slice(0, p.maximumCharacters || 1000000) - ) - ), - }), - }) - ).json(); - - setLoading(false); - const shortLink = !shortLinkUrl.ask - ? false - : await deleteDialog( - 'Do you want to shortlink the URLs? it will let you get statistics over clicks', - 'Yes, shortlink it!' - ); - - setLoading(true); - - const data = { - ...(postFor - ? { - order: postFor.id, - } - : {}), - type, - inter, - tags, - shortLink, - date: dateState.utc().format('YYYY-MM-DDTHH:mm:ss'), - posts: allKeys.map((p) => ({ - ...p, - value: p.value.map((a) => ({ - ...a, - content: a.content.slice(0, p.maximumCharacters || 1000000), - })), - })), - }; - - addEditSets - ? addEditSets(data) - : await fetch('/posts', { - method: 'POST', - body: JSON.stringify(data), - }); - existingData.group = makeId(10); - - if (!addEditSets) { - mutate(); - toaster.show( - !existingData.integration - ? 'Added successfully' - : 'Updated successfully' - ); - } - if (customClose) { - setTimeout(() => { - customClose(); - }, 2000); - } - - if (!addEditSets) { - modal.closeAll(); - } - }, - [ - inter, - postFor, - dateState, - value, - integrations, - existingData, - selectedIntegrations, - tags, - addEditSets, - ] - ); - const uppy = useUppyUploader({ - onUploadSuccess: () => { - /**empty**/ - }, - allowedFileTypes: 'image/*,video/mp4', - }); - const pasteImages = useCallback( - (index: number, currentValue: any[], isFile?: boolean) => { - return async (event: ClipboardEvent | File[]) => { - // @ts-ignore - const clipboardItems = isFile - ? // @ts-ignore - event.map((p) => ({ - kind: 'file', - getAsFile: () => p, - })) - : // @ts-ignore - event.clipboardData?.items; // Ensure clipboardData is available - if (!clipboardItems) { - return; - } - const files: File[] = []; - - // @ts-ignore - for (const item of clipboardItems) { - if (item.kind === 'file') { - const file = item.getAsFile(); - if (file) { - const isImage = file.type.startsWith('image/'); - const isVideo = file.type.startsWith('video/'); - if (isImage || isVideo) { - files.push(file); // Collect images or videos - } - } - } - } - if (files.length === 0) { - return; - } - setUploading(true); - const lastValues = [...currentValue]; - for (const file of files) { - uppy.addFile(file); - const upload = await uppy.upload(); - uppy.clear(); - if (upload?.successful?.length) { - lastValues.push(upload?.successful[0]?.response?.body?.saved!); - changeImage(index)({ - target: { - name: 'image', - value: [...lastValues], - }, - }); - } - } - setUploading(false); - }; - }, - [changeImage] - ); - const getPostsMarketplace = useCallback(async () => { - return ( - await fetch(`/posts/marketplace/${existingData?.posts?.[0]?.id}`) - ).json(); - }, []); - const { data } = useSWR( - `/posts/marketplace/${existingData?.posts?.[0]?.id}`, - getPostsMarketplace - ); - const canSendForPublication = useMemo(() => { - if (!postFor) { - return true; - } - return selectedIntegrations.every((integration) => { - const find = postFor.missing.find( - (p) => p.integration.integration.id === integration.id - ); - if (!find) { - return false; - } - return find.missing !== 0; - }); - }, [data, postFor, selectedIntegrations]); - useClickOutside(askClose); - return ( - - {user?.tier?.ai && ( - - )} -
- {uploading && ( -
- -
- )} -
-
- -
- - { - setCustomer(val); - setSelectedIntegrations([]); - }} - /> - - - {!selectedIntegrations.length && ( - - - - )} -
-
- - {!existingData.integration && integrations.length > 1 ? ( -
- !f.disabled)} - selectedIntegrations={selectIntegrationsDefault} - singleSelect={false} - onChange={setSelectedIntegrations} - isMain={true} - /> -
- ) : ( -
- {selectedIntegrations?.[0]?.identifier} - {selectedIntegrations?.[0]?.identifier === 'youtube' ? ( - - ) : ( - {selectedIntegrations?.[0]?.identifier} - )} -
- )} -
- {!existingData.integration && !showHide.hideTopEditor ? ( - <> -
- {t( - 'you_are_in_global_editing_mode', - 'You are in global editing mode' - )} -
- {value.map((p, index) => ( - -
-
-
- - 1 ? 150 : 250} - value={p.content} - totalPosts={value.length} - preview="edit" - onPaste={pasteImages(index, p.image || [])} - // @ts-ignore - onChange={changeValue(index)} - /> - - - {showError && - (!p.content || p.content.length < 6) && ( -
- {t( - 'the_post_should_be_at_least_6_characters_long', - 'The post should be at least 6 characters long' - )} -
- )} -
-
- setCanUseClose(false)} - onClose={() => setCanUseClose(true)} - /> -
-
- {value.length > 1 && ( -
-
- - - -
-
- {t('delete_post', 'Delete Post')} -
-
- )} -
-
-
-
- -
-
-
-
- -
-
- ))} - {value.length > 1 && ( -
- -
- )} - - ) : null} -
-
-
-
- - {!!existingData.integration && ( - - )} - - {addEditSets && ( - - )} - - {!addEditSets && ( - - )} - - {!addEditSets && ( - - )} - -
-
-
-
-
-
- - setTags(e.target.value)} - /> - - - - -
- {!!selectedIntegrations.length && ( -
- -
- )} -
-
- - ); -}); diff --git a/apps/frontend/src/components/launches/add.post.button.tsx b/apps/frontend/src/components/launches/add.post.button.tsx deleted file mode 100644 index 18c3e728..00000000 --- a/apps/frontend/src/components/launches/add.post.button.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Button } from '@gitroom/react/form/button'; -import React, { FC } from 'react'; -import { useCopilotAction, useCopilotReadable } from '@copilotkit/react-core'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const AddPostButton: FC<{ - onClick: () => void; - num: number; -}> = (props) => { - const { onClick, num } = props; - const t = useT(); - useCopilotAction({ - name: 'addPost_' + num, - description: 'Add a post after the post number ' + num, - handler: () => { - onClick(); - }, - }); - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/ai.image.tsx b/apps/frontend/src/components/launches/ai.image.tsx index 700e0b54..862fc67c 100644 --- a/apps/frontend/src/components/launches/ai.image.tsx +++ b/apps/frontend/src/components/launches/ai.image.tsx @@ -4,6 +4,7 @@ import clsx from 'clsx'; import Loading from 'react-loading'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; const list = [ 'Realistic', 'Cartoon', @@ -27,10 +28,12 @@ export const AiImage: FC<{ const t = useT(); const { value, onChange } = props; const [loading, setLoading] = useState(false); + const setLocked = useLaunchStore(p => p.setLocked); const fetch = useFetch(); const generateImage = useCallback( (type: string) => async () => { setLoading(true); + setLocked(true); const image = await ( await fetch('/media/generate-image-with-prompt', { method: 'POST', @@ -49,6 +52,7 @@ ${type} }) ).json(); setLoading(false); + setLocked(false); onChange(image); }, [value, onChange] diff --git a/apps/frontend/src/components/launches/bold.text.tsx b/apps/frontend/src/components/launches/bold.text.tsx deleted file mode 100644 index 96ad3318..00000000 --- a/apps/frontend/src/components/launches/bold.text.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { FC, useCallback } from 'react'; -import { Editor, Transforms } from 'slate'; -import { ReactEditor } from 'slate-react'; -const originalMap = { - a: '𝗮', - b: '𝗯', - c: '𝗰', - d: '𝗱', - e: '𝗲', - f: '𝗳', - g: '𝗴', - h: '𝗵', - i: '𝗶', - j: '𝗷', - k: '𝗸', - l: '𝗹', - m: '𝗺', - n: '𝗻', - o: '𝗼', - p: '𝗽', - q: '𝗾', - r: '𝗿', - s: '𝘀', - t: '𝘁', - u: '𝘂', - v: '𝘃', - w: '𝘄', - x: '𝘅', - y: '𝘆', - z: '𝘇', - A: '𝗔', - B: '𝗕', - C: '𝗖', - D: '𝗗', - E: '𝗘', - F: '𝗙', - G: '𝗚', - H: '𝗛', - I: '𝗜', - J: '𝗝', - K: '𝗞', - L: '𝗟', - M: '𝗠', - N: '𝗡', - O: '𝗢', - P: '𝗣', - Q: '𝗤', - R: '𝗥', - S: '𝗦', - T: '𝗧', - U: '𝗨', - V: '𝗩', - W: '𝗪', - X: '𝗫', - Y: '𝗬', - Z: '𝗭', - '1': '𝟭', - '2': '𝟮', - '3': '𝟯', - '4': '𝟰', - '5': '𝟱', - '6': '𝟲', - '7': '𝟳', - '8': '𝟴', - '9': '𝟵', - '0': '𝟬', -}; -const reverseMap = Object.fromEntries( - Object.entries(originalMap).map(([key, value]) => [value, key]) -); -export const BoldText: FC<{ - editor: any; - currentValue: string; -}> = ({ editor }) => { - const mark = () => { - const selectedText = Editor.string(editor, editor.selection); - const newText = Array.from( - !selectedText ? prompt('What do you want to write?') || '' : selectedText - ) - .map((char) => { - // @ts-ignore - return originalMap?.[char] || reverseMap?.[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 cb5cf495..c55e617a 100644 --- a/apps/frontend/src/components/launches/calendar.tsx +++ b/apps/frontend/src/components/launches/calendar.tsx @@ -31,7 +31,6 @@ import 'dayjs/locale/tr'; import 'dayjs/locale/vi'; import localizedFormat from 'dayjs/plugin/localizedFormat'; import { useModals } from '@mantine/modals'; -import { AddEditModal as AddEditModal2 } from '@gitroom/frontend/components/launches/add.edit.model'; import clsx from 'clsx'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { ExistingDataContextProvider } from '@gitroom/frontend/components/launches/helpers/use.existing.data'; diff --git a/apps/frontend/src/components/launches/connect.with.wallet.tsx b/apps/frontend/src/components/launches/connect.with.wallet.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/frontend/src/components/launches/editor.tsx b/apps/frontend/src/components/launches/editor.tsx deleted file mode 100644 index 1e470841..00000000 --- a/apps/frontend/src/components/launches/editor.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { forwardRef, useCallback, useRef, useState } from 'react'; -import type { MDEditorProps } from '@uiw/react-md-editor/src/Types'; -import { RefMDEditor } from '@uiw/react-md-editor/src/Editor'; -import { useCopilotAction, useCopilotReadable } from '@copilotkit/react-core'; -import { CopilotTextarea } from '@copilotkit/react-textarea'; -import clsx from 'clsx'; -import { useUser } from '@gitroom/frontend/components/layout/user.context'; -import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; -import { Transforms } from 'slate'; -import EmojiPicker from 'emoji-picker-react'; -import { Theme } from 'emoji-picker-react'; -import { BoldText } from '@gitroom/frontend/components/launches/bold.text'; -import { UText } from '@gitroom/frontend/components/launches/u.text'; -import { SignatureBox } from '@gitroom/frontend/components/signature'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const Editor = forwardRef< - RefMDEditor, - MDEditorProps & { - order: number; - totalPosts: number; - disabledCopilot?: boolean; - } ->( - ( - props: MDEditorProps & { - order: number; - totalPosts: number; - disabledCopilot?: boolean; - }, - ref: React.ForwardedRef - ) => { - const user = useUser(); - const [id] = useState(makeId(10)); - const newRef = useRef(null); - const [emojiPickerOpen, setEmojiPickerOpen] = useState(false); - const t = useT(); - - useCopilotReadable({ - ...(props.disabledCopilot ? { available: 'disabled' } : {}), - description: 'Content of the post number ' + (props.order + 1), - value: JSON.stringify({ - content: props.value, - order: props.order, - allowAddContent: props?.value?.length === 0, - }), - }); - useCopilotAction({ - ...(props.disabledCopilot ? { available: 'disabled' } : {}), - name: 'editPost_' + props.order, - description: `Edit the content of post number ${props.order}`, - parameters: [ - { - name: 'content', - type: 'string', - }, - ], - handler: async ({ content }) => { - props?.onChange?.(content); - }, - }); - const addText = useCallback( - (emoji: string) => { - setTimeout(() => { - // @ts-ignore - Transforms.insertText(newRef?.current?.editor!, emoji); - }, 10); - }, - [props.value, id] - ); - return ( - <> -
- - - -
setEmojiPickerOpen(!emojiPickerOpen)} - > - {t('', '\uD83D\uDE00')} -
-
-
- { - addText(e.emoji); - setEmojiPickerOpen(false); - }} - open={emojiPickerOpen} - /> -
-
- 1 && '!max-h-80' - )} - value={props.value} - onChange={(e) => { - props?.onChange?.(e.target.value); - }} - onPaste={props.onPaste} - placeholder={t('write_your_reply', 'Write your reply...')} - autosuggestionsConfig={{ - textareaPurpose: `Assist me in writing social media posts.`, - chatApiConfigs: {}, - disabled: !user?.tier?.ai, - }} - /> -
- - ); - } -); diff --git a/apps/frontend/src/components/launches/finisher/thread.finisher.tsx b/apps/frontend/src/components/launches/finisher/thread.finisher.tsx deleted file mode 100644 index 736d8291..00000000 --- a/apps/frontend/src/components/launches/finisher/thread.finisher.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { Slider } from '@gitroom/react/form/slider'; -import clsx from 'clsx'; -import { useState } from 'react'; -import { Editor } from '@gitroom/frontend/components/launches/editor'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; - -export const ThreadFinisher = () => { - const integration = useIntegration(); - const { register, watch, setValue } = useSettings(); - const t = useT(); - - register('active_thread_finisher', { - value: false, - }); - - register('thread_finisher', { - value: t('that_a_wrap', { - username: - integration.integration?.display || integration.integration?.name, - }), - }); - - const slider = watch('active_thread_finisher'); - const value = watch('thread_finisher'); - - return ( -
-
-
Add a thread finisher
-
- setValue('active_thread_finisher', p === 'on')} - fill={true} - /> -
-
-
-
-
-
-
- setValue('thread_finisher', val)} - value={value} - height={150} - totalPosts={1} - order={1} - preview="edit" - /> -
-
-
-
-
-
- ); -}; diff --git a/apps/frontend/src/components/launches/general.preview.component.tsx b/apps/frontend/src/components/launches/general.preview.component.tsx index 1858f4df..004e193c 100644 --- a/apps/frontend/src/components/launches/general.preview.component.tsx +++ b/apps/frontend/src/components/launches/general.preview.component.tsx @@ -6,10 +6,13 @@ import { VideoOrImage } from '@gitroom/react/helpers/video.or.image'; import { FC } from 'react'; import { textSlicer } from '@gitroom/helpers/utils/count.length'; import interClass from '@gitroom/react/helpers/inter.font'; +import Image from 'next/image'; +import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; export const GeneralPreviewComponent: FC<{ maximumCharacters?: number; }> = (props) => { const { value: topValue, integration } = useIntegration(); + const current = useLaunchStore((state) => state.current); const mediaDir = useMediaDirectory(); const newValues = useFormatting(topValue, { removeMarkdown: true, @@ -41,11 +44,23 @@ export const GeneralPreviewComponent: FC<{ )} >
- x +
+ x + + {current !== 'global' && ( + {integration.identifier} + )} +
{index !== topValue.length - 1 && (
)} @@ -53,7 +68,7 @@ export const GeneralPreviewComponent: FC<{
- {integration?.name} + {current === 'global' ? 'Global Edit' : integration?.name}
- {integration?.display || '@username'} + {current === 'global' ? '' : integration?.display || '@username'}
 {
   const { integrations, reloadCalendarView } = useCalendar();
   const modal = useModals();
diff --git a/apps/frontend/src/components/launches/helpers/linkedin.component.tsx b/apps/frontend/src/components/launches/helpers/linkedin.component.tsx
index 03a0893d..0dc5ecb8 100644
--- a/apps/frontend/src/components/launches/helpers/linkedin.component.tsx
+++ b/apps/frontend/src/components/launches/helpers/linkedin.component.tsx
@@ -15,6 +15,7 @@ import { Input } from '@gitroom/react/form/input';
 import { Button } from '@gitroom/react/form/button';
 import { useToaster } from '@gitroom/react/toaster/toaster';
 import { useT } from '@gitroom/react/translation/get.transation.service.client';
+import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store';
 const postUrlEmitter = new EventEmitter();
 export const ShowLinkedinCompany = () => {
   const [showPostSelector, setShowPostSelector] = useState(false);
@@ -53,6 +54,37 @@ export const ShowLinkedinCompany = () => {
     
   );
 };
+
+export const LinkedinCompanyPop: FC<{
+  addText: (value: any) => void;
+}> = (props) => {
+  const current = useLaunchStore((state) => state.current);
+  return (
+     {
+        postUrlEmitter.emit('show', {
+          id: current,
+          callback: (value: any) => {
+            props.addText(value);
+          },
+        });
+      }}
+      data-tooltip-id="tooltip"
+      data-tooltip-content="Add a LinkedIn Company"
+      className="mx-[10px] cursor-pointer"
+      width="20"
+      height="20"
+      viewBox="0 0 26 26"
+      fill="none"
+      xmlns="http://www.w3.org/2000/svg"
+    >
+      
+    
+  );
+};
 export const showPostSelector = (id: string) => {
   return new Promise((resolve) => {
     postUrlEmitter.emit('show', {
diff --git a/apps/frontend/src/components/launches/new.post.tsx b/apps/frontend/src/components/launches/new.post.tsx
index f1cb8c8d..efa76eb1 100644
--- a/apps/frontend/src/components/launches/new.post.tsx
+++ b/apps/frontend/src/components/launches/new.post.tsx
@@ -1,12 +1,12 @@
 import React, { useCallback } from 'react';
-import { AddEditModal } from '@gitroom/frontend/components/launches/add.edit.model';
 import { useModals } from '@mantine/modals';
 import dayjs from 'dayjs';
 import { useCalendar } from '@gitroom/frontend/components/launches/calendar.context';
 import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
 import { useT } from '@gitroom/react/translation/get.transation.service.client';
 import { SetSelectionModal } from '@gitroom/frontend/components/launches/calendar';
-import { useSet } from '@gitroom/frontend/components/launches/set.context';
+import { AddEditModal } from '@gitroom/frontend/components/new-launch/add.edit.modal';
+
 export const NewPost = () => {
   const fetch = useFetch();
   const modal = useModals();
diff --git a/apps/frontend/src/components/launches/post.to.organization.tsx b/apps/frontend/src/components/launches/post.to.organization.tsx
deleted file mode 100644
index cda02339..00000000
--- a/apps/frontend/src/components/launches/post.to.organization.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-'use client';
-
-import { FC, useEffect } from 'react';
-import { CustomSelect } from '@gitroom/react/form/custom.select';
-import { FormProvider, useForm } from 'react-hook-form';
-export interface Information {
-  buyer: Buyer;
-  usedIds: Array<{
-    id: string;
-    status: 'NO' | 'WAITING_CONFIRMATION' | 'YES';
-  }>;
-  id: string;
-  missing: Missing[];
-}
-export interface Buyer {
-  id: string;
-  name: string;
-  picture: Picture;
-}
-export interface Picture {
-  id: string;
-  path: string;
-}
-export interface Missing {
-  integration: Integration;
-  missing: number;
-}
-export interface Integration {
-  quantity: number;
-  integration: Integration2;
-}
-export interface Integration2 {
-  id: string;
-  name: string;
-  providerIdentifier: string;
-}
-export const PostToOrganization: FC<{
-  information: Information[];
-  onChange: (order?: Information) => void;
-  selected?: string;
-}> = (props) => {
-  const { information, onChange, selected } = props;
-  const form = useForm();
-  const postFor = form.watch('post_for');
-  useEffect(() => {
-    onChange(information?.find((p) => p.id === postFor?.value)!);
-  }, [postFor]);
-  useEffect(() => {
-    if (!selected || !information?.length) {
-      return;
-    }
-    const findIt = information?.find((p) => p.id === selected);
-    form.setValue('post_for', {
-      value: findIt?.id,
-    });
-    onChange(information?.find((p) => p.id === selected)!);
-  }, [selected, information]);
-  if (!information?.length) {
-    return null;
-  }
-  return (
-    
-       ({
-          label: 'For: ' + p?.buyer?.name,
-          value: p?.id,
-          icon: (
-            
-          ),
-        }))}
-      />
-    
-  );
-};
diff --git a/apps/frontend/src/components/launches/providers.options.tsx b/apps/frontend/src/components/launches/providers.options.tsx
deleted file mode 100644
index 8d4bc337..00000000
--- a/apps/frontend/src/components/launches/providers.options.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import { FC, useEffect, useState } from 'react';
-import { Integrations } from '@gitroom/frontend/components/launches/calendar.context';
-import { PickPlatforms } from '@gitroom/frontend/components/launches/helpers/pick.platform.component';
-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<{
-  hideEditOnlyThis: boolean;
-  integrations: Integrations[];
-  allIntegrations: Integrations[];
-  editorValue: Array<{
-    id?: string;
-    content: string;
-  }>;
-  date: dayjs.Dayjs;
-}> = (props) => {
-  const { integrations, editorValue, date, hideEditOnlyThis } = props;
-  const [selectedIntegrations, setSelectedIntegrations] = useStateCallback([
-    integrations[0],
-  ]);
-  useEffect(() => {
-    if (integrations.indexOf(selectedIntegrations[0]) === -1) {
-      setSelectedIntegrations([integrations[0]]);
-    }
-  }, [integrations, selectedIntegrations]);
-  return (
-    
- - - - -
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/bluesky/bluesky.provider.tsx b/apps/frontend/src/components/launches/providers/bluesky/bluesky.provider.tsx deleted file mode 100644 index 5f63ccd5..00000000 --- a/apps/frontend/src/components/launches/providers/bluesky/bluesky.provider.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { ThreadFinisher } from '@gitroom/frontend/components/launches/finisher/thread.finisher'; - -const SettingsComponent = () => { - return ; -}; - -export default withProvider( - SettingsComponent, - undefined, - undefined, - async (posts) => { - if ( - posts.some( - (p) => p.some((a) => a.path.indexOf('mp4') > -1) && p.length > 1 - ) - ) { - return 'You can only upload one video to Bluesky per post.'; - } - - if (posts.some((p) => p.length > 4)) { - return 'There can be maximum 4 pictures in a post.'; - } - return true; - }, - 300 -); diff --git a/apps/frontend/src/components/launches/providers/continue-provider/facebook/facebook.continue.tsx b/apps/frontend/src/components/launches/providers/continue-provider/facebook/facebook.continue.tsx deleted file mode 100644 index 97ae18bb..00000000 --- a/apps/frontend/src/components/launches/providers/continue-provider/facebook/facebook.continue.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { FC, useCallback, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import useSWR from 'swr'; -import clsx from 'clsx'; -import { Button } from '@gitroom/react/form/button'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const FacebookContinue: FC<{ - closeModal: () => void; - existingId: string[]; -}> = (props) => { - const { closeModal, existingId } = props; - const call = useCustomProviderFunction(); - const { integration } = useIntegration(); - const [page, setSelectedPage] = useState(null); - const fetch = useFetch(); - const loadPages = useCallback(async () => { - try { - const pages = await call.get('pages'); - return pages; - } catch (e) { - closeModal(); - } - }, []); - const setPage = useCallback( - (id: string) => () => { - setSelectedPage(id); - }, - [] - ); - const { data, isLoading } = useSWR('load-pages', loadPages, { - refreshWhenHidden: false, - refreshWhenOffline: false, - revalidateOnFocus: false, - revalidateIfStale: false, - revalidateOnMount: true, - revalidateOnReconnect: false, - refreshInterval: 0, - }); - const t = useT(); - - const saveInstagram = useCallback(async () => { - await fetch(`/integrations/facebook/${integration?.id}`, { - method: 'POST', - body: JSON.stringify({ - page, - }), - }); - closeModal(); - }, [integration, page]); - const filteredData = useMemo(() => { - return ( - data?.filter((p: { id: string }) => !existingId.includes(p.id)) || [] - ); - }, [data]); - if (!isLoading && !data?.length) { - return ( -
- {t( - 'we_couldn_t_find_any_business_connected_to_the_selected_pages', - "We couldn't find any business connected to the selected pages." - )} -
- {t( - 'we_recommend_you_to_connect_all_the_pages_and_all_the_businesses', - 'We recommend you to connect all the pages and all the businesses.' - )} -
- {t( - 'please_close_this_dialog_delete_your_integration_and_add_a_new_channel_again', - 'Please close this dialog, delete your integration and add a new channel\n again.' - )} -
- ); - } - return ( -
-
{t('select_page', 'Select Page:')}
-
- {filteredData?.map( - (p: { - id: string; - username: string; - name: string; - picture: { - data: { - url: string; - }; - }; - }) => ( -
-
- profile -
-
{p.name}
-
- ) - )} -
-
- -
-
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/continue-provider/instagram/instagram.continue.tsx b/apps/frontend/src/components/launches/providers/continue-provider/instagram/instagram.continue.tsx deleted file mode 100644 index ddf6c23f..00000000 --- a/apps/frontend/src/components/launches/providers/continue-provider/instagram/instagram.continue.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import { FC, useCallback, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import useSWR from 'swr'; -import clsx from 'clsx'; -import { Button } from '@gitroom/react/form/button'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const InstagramContinue: FC<{ - closeModal: () => void; - existingId: string[]; -}> = (props) => { - const { closeModal, existingId } = props; - const call = useCustomProviderFunction(); - const { integration } = useIntegration(); - const [page, setSelectedPage] = useState(null); - const fetch = useFetch(); - const loadPages = useCallback(async () => { - try { - const pages = await call.get('pages'); - return pages; - } catch (e) { - closeModal(); - } - }, []); - const t = useT(); - - const setPage = useCallback( - (param: { id: string; pageId: string }) => () => { - setSelectedPage(param); - }, - [] - ); - const { data, isLoading } = useSWR('load-pages', loadPages, { - refreshWhenHidden: false, - refreshWhenOffline: false, - revalidateOnFocus: false, - revalidateIfStale: false, - revalidateOnMount: true, - revalidateOnReconnect: false, - refreshInterval: 0, - }); - const saveInstagram = useCallback(async () => { - await fetch(`/integrations/instagram/${integration?.id}`, { - method: 'POST', - body: JSON.stringify(page), - }); - closeModal(); - }, [integration, page]); - const filteredData = useMemo(() => { - return ( - data?.filter((p: { id: string }) => !existingId.includes(p.id)) || [] - ); - }, [data]); - if (!isLoading && !data?.length) { - return ( -
- {t( - 'we_couldn_t_find_any_business_connected_to_the_selected_pages', - "We couldn't find any business connected to the selected pages." - )} -
- {t( - 'we_recommend_you_to_connect_all_the_pages_and_all_the_businesses', - 'We recommend you to connect all the pages and all the businesses.' - )} -
- {t( - 'please_close_this_dialog_delete_your_integration_and_add_a_new_channel_again', - 'Please close this dialog, delete your integration and add a new channel\n again.' - )} -
- ); - } - return ( -
-
{t('select_instagram_account', 'Select Instagram Account:')}
-
- {filteredData?.map( - (p: { - id: string; - pageId: string; - username: string; - name: string; - picture: { - data: { - url: string; - }; - }; - }) => ( -
-
- profile -
-
{p.name}
-
- ) - )} -
-
- -
-
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/continue-provider/linkedin/linkedin.continue.tsx b/apps/frontend/src/components/launches/providers/continue-provider/linkedin/linkedin.continue.tsx deleted file mode 100644 index 594fceb4..00000000 --- a/apps/frontend/src/components/launches/providers/continue-provider/linkedin/linkedin.continue.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { FC, useCallback, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import useSWR from 'swr'; -import clsx from 'clsx'; -import { Button } from '@gitroom/react/form/button'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const LinkedinContinue: FC<{ - closeModal: () => void; - existingId: string[]; -}> = (props) => { - const { closeModal, existingId } = props; - const t = useT(); - - const call = useCustomProviderFunction(); - const { integration } = useIntegration(); - const [page, setSelectedPage] = useState(null); - const fetch = useFetch(); - const loadPages = useCallback(async () => { - try { - const pages = await call.get('companies'); - return pages; - } catch (e) { - closeModal(); - } - }, []); - const setPage = useCallback( - (param: { id: string; pageId: string }) => () => { - setSelectedPage(param); - }, - [] - ); - const { data, isLoading } = useSWR('load-pages', loadPages, { - refreshWhenHidden: false, - refreshWhenOffline: false, - revalidateOnFocus: false, - revalidateIfStale: false, - revalidateOnMount: true, - revalidateOnReconnect: false, - refreshInterval: 0, - }); - const saveLinkedin = useCallback(async () => { - await fetch(`/integrations/linkedin-page/${integration?.id}`, { - method: 'POST', - body: JSON.stringify(page), - }); - closeModal(); - }, [integration, page]); - const filteredData = useMemo(() => { - return ( - data?.filter((p: { id: string }) => !existingId.includes(p.id)) || [] - ); - }, [data]); - if (!isLoading && !data?.length) { - return ( -
- {t( - 'we_couldn_t_find_any_business_connected_to_your_linkedin_page', - "We couldn't find any business connected to your LinkedIn Page." - )} -
- {t( - 'please_close_this_dialog_create_a_new_page_and_add_a_new_channel_again', - 'Please close this dialog, create a new page, and add a new channel again.' - )} -
- ); - } - return ( -
-
{t('select_linkedin_page', 'Select Linkedin Page:')}
-
- {filteredData?.map( - (p: { - id: string; - pageId: string; - username: string; - name: string; - picture: string; - }) => ( -
-
- profile -
-
{p.name}
-
- ) - )} -
-
- -
-
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/continue-provider/list.tsx b/apps/frontend/src/components/launches/providers/continue-provider/list.tsx deleted file mode 100644 index b621aae1..00000000 --- a/apps/frontend/src/components/launches/providers/continue-provider/list.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { InstagramContinue } from '@gitroom/frontend/components/launches/providers/continue-provider/instagram/instagram.continue'; -import { FacebookContinue } from '@gitroom/frontend/components/launches/providers/continue-provider/facebook/facebook.continue'; -import { LinkedinContinue } from '@gitroom/frontend/components/launches/providers/continue-provider/linkedin/linkedin.continue'; -export const continueProviderList = { - instagram: InstagramContinue, - facebook: FacebookContinue, - 'linkedin-page': LinkedinContinue, -}; diff --git a/apps/frontend/src/components/launches/providers/devto/devto.provider.tsx b/apps/frontend/src/components/launches/providers/devto/devto.provider.tsx deleted file mode 100644 index d457517e..00000000 --- a/apps/frontend/src/components/launches/providers/devto/devto.provider.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { FC } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { DevToSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/dev.to.settings.dto'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { Input } from '@gitroom/react/form/input'; -import { MediaComponent } from '@gitroom/frontend/components/media/media.component'; -import { SelectOrganization } from '@gitroom/frontend/components/launches/providers/devto/select.organization'; -import { DevtoTags } from '@gitroom/frontend/components/launches/providers/devto/devto.tags'; -import { useMediaDirectory } from '@gitroom/react/helpers/use.media.directory'; -import clsx from 'clsx'; -import localFont from 'next/font/local'; -import MDEditor from '@uiw/react-md-editor'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { Canonical } from '@gitroom/react/form/canonical'; -const font = localFont({ - src: [ - { - path: './fonts/SFNS.woff2', - }, - ], -}); -const DevtoPreview: FC = () => { - const { value } = useIntegration(); - const settings = useSettings(); - const image = useMediaDirectory(); - const [coverPicture, title, tags] = settings.watch([ - 'main_image', - 'title', - 'tags', - ]); - return ( -
- {!!coverPicture?.path && ( -
- cover_picture -
- )} -
-
{title}
-
- {tags?.map((p: any) => ( -
#{p.label}
- ))} -
-
-
- p.content).join('\n')} - /> -
-
- ); -}; -const DevtoSettings: FC = () => { - const form = useSettings(); - const { date } = useIntegration(); - return ( - <> - - - -
- -
-
- -
- - ); -}; -export default withProvider(DevtoSettings, DevtoPreview, DevToSettingsDto); diff --git a/apps/frontend/src/components/launches/providers/devto/devto.tags.tsx b/apps/frontend/src/components/launches/providers/devto/devto.tags.tsx deleted file mode 100644 index 32ed4469..00000000 --- a/apps/frontend/src/components/launches/providers/devto/devto.tags.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { FC, useCallback, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { ReactTags } from 'react-tag-autocomplete'; -import interClass from '@gitroom/react/helpers/inter.font'; -export const DevtoTags: FC<{ - name: string; - label: string; - onChange: (event: { - target: { - value: any[]; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name, label } = props; - const customFunc = useCustomProviderFunction(); - const [tags, setTags] = useState([]); - const { getValues } = useSettings(); - const [tagValue, setTagValue] = useState([]); - const onDelete = useCallback( - (tagIndex: number) => { - const modify = tagValue.filter((_, i) => i !== tagIndex); - setTagValue(modify); - onChange({ - target: { - value: modify, - name, - }, - }); - }, - [tagValue] - ); - const onAddition = useCallback( - (newTag: any) => { - if (tagValue.length >= 4) { - return; - } - const modify = [...tagValue, newTag]; - setTagValue(modify); - onChange({ - target: { - value: modify, - name, - }, - }); - }, - [tagValue] - ); - useEffect(() => { - customFunc.get('tags').then((data) => setTags(data)); - const settings = getValues()[props.name]; - if (settings) { - setTagValue(settings); - } - }, []); - if (!tags.length) { - return null; - } - return ( -
-
{label}
- -
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/devto/fonts/SFNS.woff2 b/apps/frontend/src/components/launches/providers/devto/fonts/SFNS.woff2 deleted file mode 100644 index c9d0228f1b6115cb4a33b6978f7bc2f7c26f975d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90060 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 D+mzy+ diff --git a/apps/frontend/src/components/launches/providers/devto/select.organization.tsx b/apps/frontend/src/components/launches/providers/devto/select.organization.tsx deleted file mode 100644 index d1aa52e8..00000000 --- a/apps/frontend/src/components/launches/providers/devto/select.organization.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const SelectOrganization: FC<{ - name: string; - onChange: (event: { - target: { - value: string; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name } = props; - const t = useT(); - const customFunc = useCustomProviderFunction(); - const [orgs, setOrgs] = useState([]); - const { getValues } = useSettings(); - const [currentMedia, setCurrentMedia] = useState(); - const onChangeInner = (event: { - target: { - value: string; - name: string; - }; - }) => { - setCurrentMedia(event.target.value); - onChange(event); - }; - useEffect(() => { - customFunc.get('organizations').then((data) => setOrgs(data)); - const settings = getValues()[props.name]; - if (settings) { - setCurrentMedia(settings); - } - }, []); - if (!orgs.length) { - return null; - } - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/providers/discord/discord.channel.select.tsx b/apps/frontend/src/components/launches/providers/discord/discord.channel.select.tsx deleted file mode 100644 index 51825ca8..00000000 --- a/apps/frontend/src/components/launches/providers/discord/discord.channel.select.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const DiscordChannelSelect: FC<{ - name: string; - onChange: (event: { - target: { - value: string; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name } = props; - const t = useT(); - const customFunc = useCustomProviderFunction(); - const [publications, setOrgs] = useState([]); - const { getValues } = useSettings(); - const [currentMedia, setCurrentMedia] = useState(); - const onChangeInner = (event: { - target: { - value: string; - name: string; - }; - }) => { - setCurrentMedia(event.target.value); - onChange(event); - }; - useEffect(() => { - customFunc.get('channels').then((data) => setOrgs(data)); - const settings = getValues()[props.name]; - if (settings) { - setCurrentMedia(settings); - } - }, []); - if (!publications.length) { - return null; - } - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx b/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx deleted file mode 100644 index 4b2eaf4f..00000000 --- a/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { FC } from 'react'; -import { DiscordDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/discord.dto'; -import { DiscordChannelSelect } from '@gitroom/frontend/components/launches/providers/discord/discord.channel.select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -const DiscordComponent: FC = () => { - const form = useSettings(); - return ( -
- -
- ); -}; -export default withProvider( - DiscordComponent, - undefined, - DiscordDto, - undefined, - 1980 -); diff --git a/apps/frontend/src/components/launches/providers/dribbble/dribbble.provider.tsx b/apps/frontend/src/components/launches/providers/dribbble/dribbble.provider.tsx deleted file mode 100644 index 09d4d094..00000000 --- a/apps/frontend/src/components/launches/providers/dribbble/dribbble.provider.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { FC } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { Input } from '@gitroom/react/form/input'; -import { DribbbleTeams } from '@gitroom/frontend/components/launches/providers/dribbble/dribbble.teams'; -import { DribbbleDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/dribbble.dto'; -const DribbbleSettings: FC = () => { - const { register, control } = useSettings(); - return ( -
- - -
- ); -}; -export default withProvider( - DribbbleSettings, - undefined, - DribbbleDto, - async ([firstItem, ...otherItems]) => { - const isMp4 = firstItem?.find((item) => item.path.indexOf('mp4') > -1); - if (firstItem.length !== 1) { - return 'Dribbble requires one item'; - } - if (isMp4) { - return 'Dribbble does not support mp4 files'; - } - const details = await new Promise<{ - width: number; - height: number; - }>((resolve, reject) => { - const url = new Image(); - url.onload = function () { - // @ts-ignore - resolve({ width: this.width, height: this.height }); - }; - url.src = firstItem[0].path; - }); - if ( - (details?.width === 400 && details?.height === 300) || - (details?.width === 800 && details?.height === 600) - ) { - return true; - } - return 'Invalid image size. Dribbble requires 400x300 or 800x600 px images.'; - } -); diff --git a/apps/frontend/src/components/launches/providers/dribbble/dribbble.teams.tsx b/apps/frontend/src/components/launches/providers/dribbble/dribbble.teams.tsx deleted file mode 100644 index da54e464..00000000 --- a/apps/frontend/src/components/launches/providers/dribbble/dribbble.teams.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const DribbbleTeams: FC<{ - name: string; - onChange: (event: { - target: { - value: string; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name } = props; - const t = useT(); - const customFunc = useCustomProviderFunction(); - const [orgs, setOrgs] = useState(); - const { getValues } = useSettings(); - const [currentMedia, setCurrentMedia] = useState(); - const onChangeInner = (event: { - target: { - value: string; - name: string; - }; - }) => { - setCurrentMedia(event.target.value); - onChange(event); - }; - useEffect(() => { - customFunc.get('teams').then((data) => setOrgs(data)); - const settings = getValues()[props.name]; - if (settings) { - setCurrentMedia(settings); - } - }, []); - if (!orgs) { - return null; - } - if (!orgs.length) { - return <>; - } - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/providers/facebook/facebook.provider.tsx b/apps/frontend/src/components/launches/providers/facebook/facebook.provider.tsx deleted file mode 100644 index 8372a93f..00000000 --- a/apps/frontend/src/components/launches/providers/facebook/facebook.provider.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -export default withProvider(null, undefined, undefined, undefined, 63206); diff --git a/apps/frontend/src/components/launches/providers/hashnode/hashnode.provider.tsx b/apps/frontend/src/components/launches/providers/hashnode/hashnode.provider.tsx deleted file mode 100644 index 216fb34c..00000000 --- a/apps/frontend/src/components/launches/providers/hashnode/hashnode.provider.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { FC } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { Input } from '@gitroom/react/form/input'; -import { HashnodePublications } from '@gitroom/frontend/components/launches/providers/hashnode/hashnode.publications'; -import { HashnodeTags } from '@gitroom/frontend/components/launches/providers/hashnode/hashnode.tags'; -import { HashnodeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/hashnode.settings.dto'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { useMediaDirectory } from '@gitroom/react/helpers/use.media.directory'; -import clsx from 'clsx'; -import MDEditor from '@uiw/react-md-editor'; -import { Plus_Jakarta_Sans } from 'next/font/google'; -import { MediaComponent } from '@gitroom/frontend/components/media/media.component'; -import { Canonical } from '@gitroom/react/form/canonical'; -const font = Plus_Jakarta_Sans({ - subsets: ['latin'], -}); -const HashnodePreview: FC = () => { - const { value } = useIntegration(); - const settings = useSettings(); - const image = useMediaDirectory(); - const [coverPicture, title, subtitle] = settings.watch([ - 'main_image', - 'title', - 'subtitle', - ]); - return ( -
- {!!coverPicture?.path && ( -
- cover_picture -
- )} -
-
- {title} -
-
- {subtitle} -
-
-
- p.content).join('\n')} - /> -
-
- ); -}; -const HashnodeSettings: FC = () => { - const form = useSettings(); - const { date } = useIntegration(); - return ( - <> - - - - -
- -
-
- -
- - ); -}; -export default withProvider( - HashnodeSettings, - HashnodePreview, - HashnodeSettingsDto -); diff --git a/apps/frontend/src/components/launches/providers/hashnode/hashnode.publications.tsx b/apps/frontend/src/components/launches/providers/hashnode/hashnode.publications.tsx deleted file mode 100644 index fdaf25ef..00000000 --- a/apps/frontend/src/components/launches/providers/hashnode/hashnode.publications.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const HashnodePublications: FC<{ - name: string; - onChange: (event: { - target: { - value: string; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name } = props; - const t = useT(); - const customFunc = useCustomProviderFunction(); - const [publications, setOrgs] = useState([]); - const { getValues } = useSettings(); - const [currentMedia, setCurrentMedia] = useState(); - const onChangeInner = (event: { - target: { - value: string; - name: string; - }; - }) => { - setCurrentMedia(event.target.value); - onChange(event); - }; - useEffect(() => { - customFunc.get('publications').then((data) => setOrgs(data)); - const settings = getValues()[props.name]; - if (settings) { - setCurrentMedia(settings); - } - }, []); - if (!publications.length) { - return null; - } - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/providers/hashnode/hashnode.tags.tsx b/apps/frontend/src/components/launches/providers/hashnode/hashnode.tags.tsx deleted file mode 100644 index 32d22a52..00000000 --- a/apps/frontend/src/components/launches/providers/hashnode/hashnode.tags.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { ReactTags } from 'react-tag-autocomplete'; -import interClass from '@gitroom/react/helpers/inter.font'; -export const HashnodeTags: FC<{ - name: string; - label: string; - onChange: (event: { - target: { - value: any[]; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name, label } = props; - const customFunc = useCustomProviderFunction(); - const [tags, setTags] = useState([]); - const { getValues, formState: form } = useSettings(); - const [tagValue, setTagValue] = useState([]); - const onDelete = useCallback( - (tagIndex: number) => { - const modify = tagValue.filter((_, i) => i !== tagIndex); - setTagValue(modify); - onChange({ - target: { - value: modify, - name, - }, - }); - }, - [tagValue] - ); - const onAddition = useCallback( - (newTag: any) => { - if (tagValue.length >= 4) { - return; - } - const modify = [...tagValue, newTag]; - setTagValue(modify); - onChange({ - target: { - value: modify, - name, - }, - }); - }, - [tagValue] - ); - useEffect(() => { - customFunc.get('tags').then((data) => setTags(data)); - const settings = getValues()[props.name]; - if (settings) { - setTagValue(settings); - } - }, []); - const err = useMemo(() => { - if (!form || !form.errors[props?.name!]) return; - return form?.errors?.[props?.name!]?.message! as string; - }, [form?.errors?.[props?.name!]?.message]); - if (!tags.length) { - return null; - } - return ( -
-
{label}
- -
{err || <> }
-
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/high.order.provider.tsx b/apps/frontend/src/components/launches/providers/high.order.provider.tsx deleted file mode 100644 index 83647bc2..00000000 --- a/apps/frontend/src/components/launches/providers/high.order.provider.tsx +++ /dev/null @@ -1,707 +0,0 @@ -'use client'; - -import React, { - FC, - Fragment, - ReactNode, - useCallback, - useEffect, - useMemo, - useState, - ClipboardEvent, - memo, -} from 'react'; -import { Button } from '@gitroom/react/form/button'; -import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; -import { useHideTopEditor } from '@gitroom/frontend/components/launches/helpers/use.hide.top.editor'; -import { useValues } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { FormProvider } from 'react-hook-form'; -import { useMoveToIntegrationListener } from '@gitroom/frontend/components/launches/helpers/use.move.to.integration'; -import { useExistingData } from '@gitroom/frontend/components/launches/helpers/use.existing.data'; -import { - IntegrationContext, - useIntegration, -} from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { MultiMediaComponent } from '@gitroom/frontend/components/media/media.component'; -import { createPortal } from 'react-dom'; -import clsx from 'clsx'; -import { postSelector } from '@gitroom/frontend/components/post-url-selector/post.url.selector'; -import { UpDownArrow } from '@gitroom/frontend/components/launches/up.down.arrow'; -import { arrayMoveImmutable } from 'array-move'; -import { - LinkedinCompany, - 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'; -import { GeneralPreviewComponent } from '@gitroom/frontend/components/launches/general.preview.component'; -import { capitalize } from 'lodash'; -import { useUppyUploader } from '@gitroom/frontend/components/media/new.uploader'; -import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; -import { DropFiles } from '@gitroom/frontend/components/layout/drop.files'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import useSWR from 'swr'; -import { InternalChannels } from '@gitroom/frontend/components/launches/internal.channels'; -import { MergePost } from '@gitroom/frontend/components/launches/merge.post'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -import { useSet } from '@gitroom/frontend/components/launches/set.context'; -import { SeparatePost } from '@gitroom/frontend/components/launches/separate.post'; -import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; - -// Simple component to change back to settings on after changing tab -export const SetTab: FC<{ - changeTab: () => void; -}> = (props) => { - useEffect(() => { - return () => { - setTimeout(() => { - props.changeTab(); - }, 500); - }; - }, []); - return null; -}; - -// This is a simple function that if we edit in place, we hide the editor on top -export const EditorWrapper: FC<{ - children: ReactNode; -}> = ({ children }) => { - const showHide = useHideTopEditor(); - const [showEditor, setShowEditor] = useState(false); - useEffect(() => { - setShowEditor(true); - showHide.hide(); - return () => { - showHide.show(); - setShowEditor(false); - }; - }, []); - if (!showEditor) { - return null; - } - return children; -}; -export const withProvider = function ( - SettingsComponent: FC<{ - values?: any; - }> | null, - CustomPreviewComponent?: FC<{ - maximumCharacters?: number; - }>, - dto?: any, - checkValidity?: ( - value: Array< - Array<{ - path: string; - }> - >, - settings: T, - additionalSettings: any, - ) => Promise, - maximumCharacters?: number | ((settings: any) => number) -) { - return (props: { - identifier: string; - id: string; - value: Array<{ - content: string; - id?: string; - image?: Array<{ - path: string; - id: string; - }>; - }>; - hideMenu?: boolean; - show: boolean; - hideEditOnlyThis?: boolean; - }) => { - const existingData = useExistingData(); - const t = useT(); - const { allIntegrations, integration, date } = useIntegration(); - const [showLinkedinPopUp, setShowLinkedinPopUp] = useState(false); - const [uploading, setUploading] = useState(false); - const [showComponent, setShowComponent] = useState(false); - const fetch = useFetch(); - useEffect(() => { - setTimeout(() => { - setShowComponent(true); - }, 1); - }, []); - 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<{ - id?: string; - content: string; - image?: Array<{ - id: string; - path: string; - }>; - }> - >( - // @ts-ignore - existingData.integration - ? existingData.posts.map((p) => ({ - id: p.id, - content: p.content, - image: p.image, - })) - : [ - { - content: '', - }, - ] - ); - const [showTab, setShowTab] = useState(0); - const Component = useMemo(() => { - return SettingsComponent ? SettingsComponent : () => <>; - }, [SettingsComponent]); - - // in case there is an error on submit, we change to the settings tab for the specific provider - useMoveToIntegrationListener( - [props.id], - true, - ({ identifier, toPreview }) => { - if (identifier === props.id) { - setShowTab(toPreview ? 1 : 2); - } - } - ); - - const set = useSet(); - - // this is a smart function, it updates the global value without updating the states (too heavy) and set the settings validation - const form = useValues( - set?.set - ? set?.set?.posts?.find((p) => p?.integration?.id === props?.id) - ?.settings - : existingData.settings, - props.id, - props.identifier, - editInPlace ? InPlaceValue : props.value, - dto, - checkValidity, - !maximumCharacters - ? undefined - : typeof maximumCharacters === 'number' - ? maximumCharacters - : maximumCharacters(JSON.parse(integration?.additionalSettings || '[]')) - ); - - // change editor value - const changeValue = useCallback( - (index: number) => (newValue: string) => { - return setInPlaceValue((prev) => { - prev[index].content = newValue; - return [...prev]; - }); - }, - [InPlaceValue] - ); - - const merge = useCallback(() => { - setInPlaceValue( - InPlaceValue.reduce( - (all, current) => { - all[0].content = all[0].content + current.content + '\n'; - all[0].image = [...all[0].image, ...(current.image || [])]; - return all; - }, - [ - { - content: '', - id: InPlaceValue[0].id, - image: [] as { - id: string; - path: string; - }[], - }, - ] - ) - ); - }, [InPlaceValue]); - - const separatePosts = useCallback( - (posts: string[]) => { - setInPlaceValue( - posts.map((p, i) => ({ - content: p, - id: InPlaceValue?.[i]?.id || makeId(10), - image: InPlaceValue?.[i]?.image || [], - })) - ); - }, - [InPlaceValue] - ); - - const changeImage = useCallback( - (index: number) => - (newValue: { - target: { - name: string; - value?: Array<{ - id: string; - path: string; - }>; - }; - }) => { - return setInPlaceValue((prev) => { - prev[index].image = newValue.target.value; - return [...prev]; - }); - }, - [InPlaceValue] - ); - - // add another local editor - const addValue = useCallback( - (index: number) => () => { - setInPlaceValue((prev) => { - return prev.reduce( - (acc, p, i) => { - acc.push(p); - if (i === index) { - acc.push({ - content: '', - }); - } - return acc; - }, - [] as Array<{ - content: string; - }> - ); - }); - }, - [] - ); - const changePosition = useCallback( - (index: number) => (type: 'up' | 'down') => { - if (type === 'up' && index !== 0) { - setInPlaceValue((prev) => { - return arrayMoveImmutable(prev, index, index - 1); - }); - } else if (type === 'down') { - setInPlaceValue((prev) => { - return arrayMoveImmutable(prev, index, index + 1); - }); - } - }, - [] - ); - - // Delete post - const deletePost = useCallback( - (index: number) => async () => { - if ( - !(await deleteDialog( - 'Are you sure you want to delete this post?', - 'Yes, delete it!' - )) - ) { - return; - } - setInPlaceValue((prev) => { - prev.splice(index, 1); - return [...prev]; - }); - }, - [InPlaceValue] - ); - - // This is a function if we want to switch from the global editor to edit in place - const changeToEditor = useCallback(async () => { - if ( - !(await deleteDialog( - !editInPlace - ? 'Are you sure you want to edit only this?' - : 'Are you sure you want to revert it back to global editing?', - 'Yes, edit in place!' - )) - ) { - return false; - } - setEditInPlace(!editInPlace); - setInPlaceValue( - editInPlace - ? [ - { - content: '', - }, - ] - : props.value.map((p) => ({ - id: p.id, - content: p.content, - image: p.image, - })) - ); - }, [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(); - }, - }); - const tagPersonOrCompany = useCallback( - (integration: string, editor: (value: string) => void) => () => { - setShowLinkedinPopUp( - { - editor(tag); - }} - id={integration} - onClose={() => setShowLinkedinPopUp(false)} - /> - ); - }, - [] - ); - const uppy = useUppyUploader({ - onUploadSuccess: () => { - /**empty**/ - }, - allowedFileTypes: 'image/*,video/mp4', - }); - const pasteImages = useCallback( - (index: number, currentValue: any[], isFile?: boolean) => { - return async (event: ClipboardEvent | File[]) => { - // @ts-ignore - const clipboardItems = isFile - ? // @ts-ignore - event.map((p) => ({ - kind: 'file', - getAsFile: () => p, - })) - : // @ts-ignore - event.clipboardData?.items; // Ensure clipboardData is available - if (!clipboardItems) { - return; - } - const files: File[] = []; - - // @ts-ignore - for (const item of clipboardItems) { - if (item.kind === 'file') { - const file = item.getAsFile(); - if (file) { - const isImage = file.type.startsWith('image/'); - const isVideo = file.type.startsWith('video/'); - if (isImage || isVideo) { - files.push(file); // Collect images or videos - } - } - } - } - if (files.length === 0) { - return; - } - setUploading(true); - const lastValues = [...currentValue]; - for (const file of files) { - uppy.addFile(file); - const upload = await uppy.upload(); - uppy.clear(); - if (upload?.successful?.length) { - lastValues.push(upload?.successful[0]?.response?.body?.saved!); - changeImage(index)({ - target: { - name: 'image', - value: [...lastValues], - }, - }); - } - } - setUploading(false); - }; - }, - [changeImage] - ); - const getInternalPlugs = useCallback(async () => { - return ( - await fetch(`/integrations/${props.identifier}/internal-plugs`) - ).json(); - }, [props.identifier]); - const { data, isLoading } = useSWR( - `internal-${props.identifier}`, - getInternalPlugs, - { - revalidateOnReconnect: true, - } - ); - - // this is a trick to prevent the data from being deleted, yet we don't render the elements - if (!props.show || !showComponent || isLoading) { - return null; - } - return ( - - setShowTab(0)} /> - {showLinkedinPopUp ? showLinkedinPopUp : null} -
- {!props.hideMenu && ( -
-
- -
- {(!!SettingsComponent || !!data?.internalPlugs?.length) && ( -
- -
- )} - {!existingData.integration && !props.hideEditOnlyThis && ( -
- -
- )} -
- )} - {editInPlace && - createPortal( - - {uploading && ( -
- -
- )} -
- {!existingData?.integration && ( -
- {t( - 'you_are_now_editing_only', - 'You are now editing only' - )} - {integration?.name} ( - {capitalize(integration?.identifier.replace('-', ' '))}) -
- )} - {InPlaceValue.map((val, index) => ( - -
-
-
- {(integration?.identifier === 'linkedin' || - integration?.identifier === 'linkedin-page') && ( - - )} - - 1 ? 200 : 250} - value={val.content} - totalPosts={InPlaceValue.length} - commands={[ - // ...commands - // .getCommands() - // .filter((f) => f.name !== 'image'), - // newImage, - postSelector(date), - ...linkedinCompany( - integration?.identifier!, - integration?.id! - ), - ]} - preview="edit" - onPaste={pasteImages(index, val.image || [])} - // @ts-ignore - onChange={changeValue(index)} - /> - - {(!val.content || val.content.length < 6) && ( -
- {t( - 'the_post_should_be_at_least_6_characters_long', - 'The post should be at least 6 characters long' - )} -
- )} -
-
- -
-
- {InPlaceValue.length > 1 && ( -
-
- - - -
-
- {t('delete_post', 'Delete Post')} -
-
- )} -
-
-
-
- -
-
-
-
- -
-
- ))} -
- {InPlaceValue.length > 1 && ( -
- -
- )} -
- p.content)} - len={ - typeof maximumCharacters === 'number' - ? maximumCharacters - : 10000 - } - merge={separatePosts} - /> -
-
-
-
, - document.querySelector('#renderEditor')! - )} - {(showTab === 0 || showTab === 2) && ( -
- - {!!data?.internalPlugs?.length && ( - - )} -
- )} - {showTab === 0 && ( -
- - {(editInPlace ? InPlaceValue : props.value) - .map((p) => p.content) - .join('').length ? ( - CustomPreviewComponent ? ( - - ) : ( - - ) - ) : ( - <>{t('no_content_yet', 'No Content Yet')} - )} - -
- )} -
-
- ); - }; -}; diff --git a/apps/frontend/src/components/launches/providers/instagram/instagram.collaborators.tsx b/apps/frontend/src/components/launches/providers/instagram/instagram.collaborators.tsx deleted file mode 100644 index 4303108a..00000000 --- a/apps/frontend/src/components/launches/providers/instagram/instagram.collaborators.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { FC } from 'react'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { InstagramDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/instagram.dto'; -import { InstagramCollaboratorsTags } from '@gitroom/frontend/components/launches/providers/instagram/instagram.tags'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -const postType = [ - { - value: 'post', - label: 'Post / Reel', - }, - { - value: 'story', - label: 'Story', - }, -]; -const InstagramCollaborators: FC<{ - values?: any; -}> = (props) => { - const t = useT(); - const { watch, register, formState, control } = useSettings(); - const postCurrentType = watch('post_type'); - return ( - <> - - - {postCurrentType !== 'story' && ( - - )} - - ); -}; -export default withProvider( - InstagramCollaborators, - undefined, - InstagramDto, - async ([firstPost, ...otherPosts], settings) => { - if (!firstPost.length) { - return 'Instagram should have at least one media'; - } - if (firstPost.length > 1 && settings.post_type === 'story') { - return 'Instagram stories can only have one media'; - } - const checkVideosLength = await Promise.all( - firstPost - .filter((f) => f.path.indexOf('mp4') > -1) - .flatMap((p) => p.path) - .map((p) => { - return new Promise((res) => { - const video = document.createElement('video'); - video.preload = 'metadata'; - video.src = p; - video.addEventListener('loadedmetadata', () => { - res(video.duration); - }); - }); - }) - ); - for (const video of checkVideosLength) { - if (video > 60 && settings.post_type === 'story') { - return 'Instagram stories should be maximum 60 seconds'; - } - if (video > 180 && settings.post_type === 'post') { - return 'Instagram reel should be maximum 180 seconds'; - } - } - return true; - }, - 2200 -); diff --git a/apps/frontend/src/components/launches/providers/instagram/instagram.tags.tsx b/apps/frontend/src/components/launches/providers/instagram/instagram.tags.tsx deleted file mode 100644 index a219bc59..00000000 --- a/apps/frontend/src/components/launches/providers/instagram/instagram.tags.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { ReactTags } from 'react-tag-autocomplete'; -import interClass from '@gitroom/react/helpers/inter.font'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import clsx from 'clsx'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; - -export const InstagramCollaboratorsTags: FC<{ - name: string; - label: string; - onChange: (event: { - target: { - value: any[]; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name, label } = props; - const { getValues } = useSettings(); - const { integration } = useIntegration(); - const [tagValue, setTagValue] = useState([]); - const [suggestions, setSuggestions] = useState(''); - const t = useT(); - - const onDelete = useCallback( - (tagIndex: number) => { - const modify = tagValue.filter((_, i) => i !== tagIndex); - setTagValue(modify); - onChange({ - target: { - value: modify, - name, - }, - }); - }, - [tagValue] - ); - const onAddition = useCallback( - (newTag: any) => { - if (tagValue.length >= 3) { - return; - } - const modify = [...tagValue, newTag]; - setTagValue(modify); - onChange({ - target: { - value: modify, - name, - }, - }); - }, - [tagValue] - ); - useEffect(() => { - const settings = getValues()[props.name]; - if (settings) { - setTagValue(settings); - } - }, []); - const suggestionsArray = useMemo(() => { - return [ - ...tagValue, - { - label: suggestions, - value: suggestions, - }, - ].filter((f) => f.label); - }, [suggestions, tagValue]); - return ( -
-
-
- {label} -
- -
-
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/lemmy/lemmy.provider.tsx b/apps/frontend/src/components/launches/providers/lemmy/lemmy.provider.tsx deleted file mode 100644 index b2f6ac09..00000000 --- a/apps/frontend/src/components/launches/providers/lemmy/lemmy.provider.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { FC, useCallback } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useFieldArray } from 'react-hook-form'; -import { Button } from '@gitroom/react/form/button'; -import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; -import { Subreddit } from './subreddit'; -import { LemmySettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/lemmy.dto'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -const LemmySettings: FC = () => { - const { register, control } = useSettings(); - const { fields, append, remove } = useFieldArray({ - control, - // control props comes from useForm (optional: if you are using FormContext) - name: 'subreddit', // unique name for your Field Array - }); - const t = useT(); - - const addField = useCallback(() => { - append({}); - }, [fields, append]); - const deleteField = useCallback( - (index: number) => async () => { - if ( - !(await deleteDialog( - t( - 'are_you_sure_you_want_to_delete_this_subreddit', - 'Are you sure you want to delete this Subreddit?' - ) - )) - ) - return; - remove(index); - }, - [fields, remove] - ); - return ( - <> -
- {fields.map((field, index) => ( -
-
- x -
- -
- ))} -
- - {fields.length === 0 && ( -
- {t( - 'please_add_at_least_one_subreddit', - 'Please add at least one Subreddit' - )} -
- )} - - ); -}; -export default withProvider( - LemmySettings, - undefined, - LemmySettingsDto, - async (items) => { - const [firstItems] = items; - if ( - firstItems.length && - firstItems[0].path.indexOf('png') === -1 && - firstItems[0].path.indexOf('jpg') === -1 && - firstItems[0].path.indexOf('jpef') === -1 && - firstItems[0].path.indexOf('gif') === -1 - ) { - return 'You can set only one picture for a cover'; - } - return true; - }, - 10000 -); diff --git a/apps/frontend/src/components/launches/providers/lemmy/subreddit.tsx b/apps/frontend/src/components/launches/providers/lemmy/subreddit.tsx deleted file mode 100644 index d050ef72..00000000 --- a/apps/frontend/src/components/launches/providers/lemmy/subreddit.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { FC, FormEvent, useCallback, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Input } from '@gitroom/react/form/input'; -import { useDebouncedCallback } from 'use-debounce'; -import { useWatch } from 'react-hook-form'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -export const Subreddit: FC<{ - onChange: (event: { - target: { - name: string; - value: { - id: string; - subreddit: string; - title: string; - name: string; - url: string; - body: string; - media: any[]; - }; - }; - }) => void; - name: string; -}> = (props) => { - const { onChange, name } = props; - const state = useSettings(); - const split = name.split('.'); - const [loading, setLoading] = useState(false); - // @ts-ignore - const errors = state?.formState?.errors?.[split?.[0]]?.[split?.[1]]?.value; - const [results, setResults] = useState([]); - const func = useCustomProviderFunction(); - const value = useWatch({ - name, - }); - const [searchValue, setSearchValue] = useState(''); - const setResult = (result: { id: string; name: string }) => async () => { - setLoading(true); - setSearchValue(''); - onChange({ - target: { - name, - value: { - id: String(result.id), - subreddit: result.name, - title: '', - name: '', - url: '', - body: '', - media: [], - }, - }, - }); - setLoading(false); - }; - const setTitle = useCallback( - (e: any) => { - onChange({ - target: { - name, - value: { - ...value, - title: e.target.value, - }, - }, - }); - }, - [value] - ); - const setURL = useCallback( - (e: any) => { - onChange({ - target: { - name, - value: { - ...value, - url: e.target.value, - }, - }, - }); - }, - [value] - ); - const search = useDebouncedCallback( - useCallback(async (e: FormEvent) => { - // @ts-ignore - setResults([]); - // @ts-ignore - if (!e.target.value) { - return; - } - // @ts-ignore - const results = await func.get('subreddits', { word: e.target.value }); - // @ts-ignore - setResults(results); - }, []), - 500 - ); - return ( -
- {value?.subreddit ? ( - <> - - - - - ) : ( -
- { - // @ts-ignore - setSearchValue(e.target.value); - await search(e); - }} - /> - {!!results.length && !loading && ( -
- {results.map((r: { id: string; name: string }) => ( -
- {r.name} -
- ))} -
- )} -
- )} -
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/linkedin/linkedin.provider.tsx b/apps/frontend/src/components/launches/providers/linkedin/linkedin.provider.tsx deleted file mode 100644 index 39a42e59..00000000 --- a/apps/frontend/src/components/launches/providers/linkedin/linkedin.provider.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { Checkbox } from '@gitroom/react/form/checkbox'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { LinkedinDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/linkedin.dto'; - -const LinkedInSettings = () => { - const t = useT(); - const { watch, register, formState, control } = useSettings(); - - return ( -
- -
- ); -}; -export default withProvider( - LinkedInSettings, - undefined, - LinkedinDto, - async (posts, vals) => { - const [firstPost, ...restPosts] = posts; - - if ( - vals.post_as_images_carousel && - (firstPost.length < 2 || - firstPost.some((p) => p.path.indexOf('mp4') > -1)) - ) { - return 'LinkedIn carousel can only be created with 2 or more images and no videos.'; - } - - if ( - firstPost.length > 1 && - firstPost.some((p) => p.path.indexOf('mp4') > -1) - ) { - return 'LinkedIn can have maximum 1 media when selecting a video.'; - } - if (restPosts.some((p) => p.length > 0)) { - return 'LinkedIn comments can only contain text.'; - } - return true; - }, - 3000 -); diff --git a/apps/frontend/src/components/launches/providers/mastodon/mastodon.provider.tsx b/apps/frontend/src/components/launches/providers/mastodon/mastodon.provider.tsx deleted file mode 100644 index 538c72c9..00000000 --- a/apps/frontend/src/components/launches/providers/mastodon/mastodon.provider.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { FC } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -export default withProvider(null, undefined, undefined, undefined, 500); diff --git a/apps/frontend/src/components/launches/providers/medium/fonts/Charter Bold Italic.ttf b/apps/frontend/src/components/launches/providers/medium/fonts/Charter Bold Italic.ttf deleted file mode 100755 index 8bf24218da1d78da0bc22b1306ef20da4a2f3dd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40436 zcmeFacYIsb`9FTnl_lAhC0UYf*;>|~*0wC~y^}a`_TCc`ASCP%M%cTQQD$fhv_OG$ z&<2MOg_d0?6gnv_p)GrqwzQ?Rk-qQe-YZK^;Pd%>f3M$vzhB@!_v+~C-gBPwoM)fM zj5Ee`>|CZ`Yv(SAr>>fNZVh96D_Yks9-Omur}Fgk8B?yrad^Xybti3pbRWLbbTU@< z(S}oZJK1+sKV;1CF&ZtKPuj9Wwd~d`W7SP~#;z^f&)EEr#-*DWGgdLScjMMg>o(?x zp4*LkKfuwl6%FcCc>?!(@!7j|$L`ZV)0?ix=VusGT(|wi4eOp-_BOt|<|MQ|zhm9$ zCkaOcJFZ7@zw?B3J2qYN&zrx^*tO_S#kWs7ao6q*k92w%y9NCbgp*F*bQ1SJk9QgF z!2J`9#wsxOy6Q_mTBGm$JF8HGY=f>^Ipure-6oO#H-HCB2UCBES^ebN~x?_w_I{I?){hCaNCz7h7sd-zAfeq1~8(I+1ZS%fcO zA>q%gO&Dhlit|}kc$JyBlJ)XCSwFus|6~3MTc_w_d$>3MH1B1V+|TOx8~ICdza7V1 zVLX2X=PI0YIM?84#4(Pe9!G*NXDPls{|=sU9zBQ7`~xV{|4U=;rchsD_n@* zgqT?v#WVhkjSAbCRdExG2y62{#QQBmXa3LpahB$9uv-3j{+F1=XE7#*G0qk`nNetB zR{jvH76$PBOBnl5ezTy=|3O&5YIrxZ^HBZ-Ae%5QT{vpXBflVERJ`+h;s+Vzk~zt=vxdp`#bwa zzF%0zDslZd|0MqpVKwuy2U!UHo!~zLzANd-|4rC|ew~uvjC~XdAfLa1^M~^FGdQ>7xB(()o`G7YZxp{e=7)aXx8Ik3MLAX>Lmnac*gT zLmonp>LJ(nFqCasFryk2+{R#kr*UEF3hKCCBtU(p;7tG?z4wrAJ{N6-joo zVlV3v=~zCCblVG>M4y1S7x@^grSF9#=%hdY6I@@RxRj;n;QLs!_#J2mpUd$X2WSO! zBCb+S|5z3Kv^>wsS$RH(HC~ZF!axIn8m0lPVpV`zrp^BcyjTaQXL`VDRt;!ihWx*o zkr@F^%mi4&Y5;3lEnpq1%YVkq%nVr1>H!;A1E7Uj^8aF1W(Bk{8=#%p0UgYd|CBYd zMnETX0=k$B(9PWWe=?5o z0mfJqFwSE6PgsJ*0h25Nm|{u5G)v|G#+q3gFvFSwTUZ7#%US?iSvLPy*2Y=^+gTf6 z2WtoHWF7gxurAgK*v+~CdssJMFYC#F%=%a_U_a{v9AN!`gKQxGXEr3lVK#{C5jF%k z%7y{Q*hu~(HqJ%?XR$HB*=!te4x5$#5K>|`;9NEba2}fgoMdzJAF%ms9^e8t3Am8W z2VBG!g>i{>h^?;k$2Efg1WBzTng>3@dD#C4SGp>(gTk>zQG?mfJ?sp?v)P$|d)Zll=deA1=d!c&Z?N;&UcmF&Ie`1vxquh2 z^YVw;h3tI5i`YKEi`fN$m#_=-ud_?pMSz!y@N#xBuCHL1{I7wo(20l@FE2LT^q2LQj%z76;T_MQCC*+KSQz=zrQ0H@ePfQQ)k^RKW+*be~z ziyZ`flsydiLpGIvnLWl10Y1(i0sImBFTfwONAo{pPp}^XKFJ;fe2P5|_%!}TvJfG@M>0bgM+0REi) zH2(to1$z#&p*rFVuu0WW^Vw#!~OvHF8d?kd+bm7 zXW0AfO~4P>TYw+3w*fz5@8q9me`fCje$3tj{0n;@@UMVRvA?ko03jm*|IR)F{0IAU z{z>*v_A%h6>@R@-Vt)nvjQtJp-|Un86YM|i?|?_xKLB&=pMZJxY5vFH?+WQql*>As z4K2{jxEqHG-~A8&xS%Lgs?=L6Dm7JFoxa*&G}YABnd=)YR-4_?=ybU~UY|b@422_2 z(O5i@Or@JME!oz#_Kwc3?w;N~{R4wT!y}_(CB)w=bYckjCX zXD|Nr?0xLAD={x@mH7Zl~XwaJD-KU2eDW-$Fi* zCphuTAbz=9UUxdy#%ovyXMuO! z0A6+rIN8nMkhg+E-3E@e9~|kc;80)3`nwDK=Wg($d%=x<3!eEPaCtv_0ITum;D`@_ z&wLl$TRd-p+)IfZS5%s3SiW+$Y{|3AzBUzlZ(6Kk4v zkX6iE`fbjyT6U1I(>b(l@Bm+n4?+_f!Y*7Xnw-N26u#m4 zOFhe+mpLyR+jyCC*tvDx#sg(O@r*AvUA8RlJirz#-3GXDsp~-RGVAo^re(|8@tiVx z4t|2$FI$Eu949{kXR#@M1UD(0W;qWi{PUJhEncWcm^;rbdaAr4-do1a3ziO{r>Z#m&KHmO%MULe&?WrXY=!OdY{Pq*0=|23+lQ zoV9sBWYoJ%4G)4&_?;-p1nBYq;(p;F=iXPUc(yPIpv!YPNVT>TZh zUuSMKSOYq<<0-zOzpv4zb(?dW{dPm6Stmhqj)eHvctm&(mXejNImm4BgRB~d4X;wX zgag+MXNI$)`e8U>gij8#O0-ncow!SjYprbD7BSK(}VDUme! zn={SnRIQEcxhG2>TBK3nW0=R{+-o|QH`LWNa9j!JD=UoT=T0GqpR=cdkxn&FXZmM?3;qj~YiNEglM-_&u{Po6|e{(%WKR{r+Un?2G32 z%)R1{rkfv}H*sP7V&QwgeB1ELu8X@qss0oG$HhCjg%?wAVNrfXXcXQ7#Wlf(`}#rF z3|uDS4}m(q~}6gdd4?#EEQp2_5;U!B^5? zqz0ozSmIA=si9VC;Fw}y4==98m0i3dOa#ycJI+xN6Ln^_CmV?IfLf$IaWVthwAx%} z&WdE%!__)oTVqyq^Gvfpz^~KIp5y8*tI{>tsU5hjN zhIIRoG20XH3Ga-RS--loQmGPNZ`~Q4)9zDl+op2eeOiT4@oxJ`;jvb)V*ET+PqfFD z+pq4Ay3#th4`JVaqL>iw!@@Gb?oPsvz3mXjEx@cLLdfDODqbmY1*HjX4Y(pQnSwi@ zoB4p*DIi9}8gNxumyD1D@8R^i3{yjxuyqLZ#v!rkQEptNaD`a_-fDn1dMJ1T9(9m~ z(bgum8S&FLw1J*xtXn1baHU&BS~}G&WSW&TzBU)W$`V3(MbD_SZB7%x*+Tu1w`L30 z+~Ovi!H5;+F!8VSjJo8n=eQ$ijz=8TCgHw`q0WtC!8tuWTgHP`N7f1ZT|>bY@de)g z71{Z3&yl|D?b$LKY#IuzN=y#W;BEUO*3% zu0Z#|Y^zA6Zd~=^idL#h?ErghN!J3QV2lBk#~lMsTO{I?8K=3MXX8ARR;p@i96~yk zRkVOsJ#Ksy9v*HU@r)$O)MXu24chpy zHo0QfuI&6BL3b$22P;<0PA7Om#f3n4i6!3c?ceMi8Vn3JJLdLut*g7=kPRBtiF9(p z8h4o@+>%)nigl#YKr_bN%P;3u0#Q!wA<&@!vWA410*zIJuYrHIWIb4464TTP>fT+- zPEFk74%8=xWBi`pWd@Tc8TK{yb~MAK&f&2+8NTtKf-Soa;UNMR2cAcdCcha?UmdOx zaKN*OOdtin5Ktr?5&tQ6l#J*ySpX>#CoD!f*u7GEZDi|nTDXEsz zy55PZ)5^-vZ=551>Fl$+uI&}7Xa8VM-JXhyvuo!}*!8@JBo2pV!h|P~kf1j5lyMBv9=X z8U)}9J*3faac+R3EN?L6jNH9`J=(|@`T*=84RasDj|2*+OlvPHTD&S*rjUXn>L#L2 z(z4#!)Z}c8HeDZextgL*XACdFcrMLGENAK0H&IRe!clQsCwRiP+CKfIV_w}7I^sQy*h`4}Hl<|jzdm!=?M6XJk z3%SQ-)WI@|EmmO~NL~?T(MUyRr)cE0u1pU%1=N`=e`r_bs@&bjRj<}u^}cY=k^R-G zRI|#!|E4r1Mw6 zaMr-d+csp9treH(UA9Qb7j9_k@vVP)7g1qV{_lbn^V`j~9DbooeKmWD>@Z3hHcK z3L-@wt0-1T-HGpc?}|J0j$XYTXzWSThfyXv{AY$#kHd& zgzF^IBt6?B_JZ^u@DSiwffkiGRXVgmS3;W~KVWDh7VJ{XMhsampM!Fh+9U)_x#vCp zPV*hJpJtyyYYIKb$cU9w%ckTjPYA|%U#5czCzZW)Q zzAErq*;FH2vUH}D;GbL#X3kw81z}@lZjG>m-<11v2?uxP`Jn5+8yM}kjy z01U>D_|fUo{M#_4hk!Il2XXc3arTO1)noM~MSN93t4N}43d_jGD#UL?_|`0bYmwUu zROBKYx@eUig24ll6N!ef4-z8fP1FHIEv(K=>Va(9&eYwYqsdD%Ch+yaa5|js?>V8j zJ2<|%d;6}1lS}*qtFo&$&H7~VK&vg`G1Z2<`B|1ZP4R4hbGW_PIh=~k@A9mf=vZfs zFOSS=cP$v`Tt3#mtgRo~oUPvHbOONwqH9kHQRuyT-~@CN0G*IM901*riP(TqLQ4Zv zB+J+(j@Jl^aRCPyuOGLH3&lZWc1UB^O^?|jkC|+a8m7Zb_{Lfk_V z8G#FONtj9`zUY#W#6io$&ZsE;?apY_+1M1}Z$SmXr8Am)FzOPoNFfmN@8l=t{@7Tu zv_IzQ{+Q7p1NCPL2tzyo;y~)gQLjHr6DoA!-c$6QRnUlnq!AVSapb1jUDb8Ic-Rw| z-9yR|hn8g)9uvATL?1bbApbB@Qq`0%iQWxTmL#Qx7Czptto3DlwV(25jyx{(@bJ{K z4<~uWgJn}w z%Rj_V$Kjj$C1kAy*6EUiECRw+$}1S3@Jv5?>PL&Cgc@WARnao`5Se?3J(8!2*eU4? z9{k)&DxpVIm;4c!8E%hT5}qV+^)oHuXZsqKuFSS5`r+*9wKb2&R&3n6x6|%}Gs|d! zOUv>2#rEU+W2v1yS>NQYoj*Fc*MGU})Up{G>vb5F{|jCUFV`C0!M$y`F|s&(y@J+JVMi@d@L&N{UzHWU9v1K~|5!k~T)q zs2A4`&>e#wLCZLuf-|HQbT^E4YA>#+HzI zJQ4Q=CkC>^S>KkHc-lBvp;7zFl(qVrXpPeonzgO(mThOISDrujqP>QBH;pX1w*90p zb$)f_>^;j8t^RGPd3=iV#@310aXnAxCKkmuIm?P zU@4cXuaXT!in=6*fi{z@&IUYcTzR04FU;D)@C~VO2k`3|LPXNw#iTVY8cJ z1J2{u_iY;wt!}w&b& zL$E@~nrtZP?J+Y^LEVQ`A}ho=jd5Akk}NbGk8rYr2+2Tkf!FZ0H{H_P+4hw!|LWIm zs_fkmnsuDd8(F=$Mc9A-*-P)}Y)cbP>-5URk(=Y`)aB!AHp4c35B(cN|KQLnQ1&r> zDq>LL-8zx7i4u^bDC3f70(77TGT}Dv;n2sk0gpnwDv*RQ=;-B|N1|uy8`_#$1nn8A zKj{4Zt|R$A-KL6OVgId*^dIZS-<_q){abhZcM~eTP*bf;l5F83owuQ%*8irTrG7P% zF-P~4JZOZ|WBZ8(sGja+o2y5tJdileXlaXP1>LF9s)4fHJN??tm3_kgZ?4yVRyFJW ziK-9u%2YzF6Y90f1m5L`-o0PAAO1SK2R)$$Pc~q$KJF+Xi*{(_#qa_{$4$8zt)HNCmF zd#g89b_@FxO6}p_>s4`_kG!i_C%{er{cl5AGO4Tvt}xvb8R1;}d$RPjBV_C43)!iXv+NMSVJk7R-bwxF)9~3UY)7 z4Tp#ii;DzLo5rCTSCBuzp%*v|$arijj3Z55PlE_d4u$CSrh&x-VmUL2p2^n^6sxpyIcDtm83UvK zoUa>Xi!Ktm{!VxHlL?hpus|S!K9Fy&xCZ@jBAerj=0a9aitDn9<^r+G>A5JHIPx=O zEf9B*@2N_3UP%5oiL9$I2)NTRIXX;?4jR5ezKe{M!u=Fjq=iet#YS=BtkRrKd+)eM z!$pNhl3{$w_$UAF)vvAW&i%Dtw>J0V(KTDEI$!VAZ>xaA!;wq!m#s;q?#O$3RU)O- z36>*Y6_y`)Plq{E>jhIa*e`JM7UbC5z)1r#Ouh&wvg@{p6Aj@+Q-YHs^CA>zWE7|{ za7k+@e`yL@L!o^pw<^bg>*WEDqO6nK7X&*rgUJlb;YqV7$jxJY03+T4Ma z15WRPzUX|n-6MP}IJ&ue;;Qzc@!;6zo{1|u2gY-sY}|fQ^F_n!PiSpRUPx;RHZZ^l z=F5UHO;Ye$KsSmK^O)Wjsr3-~t1$;8F^%ZGK^#X7NRIf3M;^6~75%w)h%a7LMPN2 zpp|}^Z(4C0vMG?=yb|{Fx1cF!*`9-}6>}5A(F$Uq(7T>Kqg&*?#V1_(OZ0GAu__Ye zjNk(Kw~FjU3cO10Pa;Ti_CUQRR;H+SXZJ)aHM@T23O4CZt{&S9I8@pHhhF`lvdU(7#za)hBeIflg0uwgQINiA@2VL8tGfM__S{43HdM5d;#-}I@n2}m60wRS*9)t) zYLer~Q)7xBqhDs^jDAtSj!7VsMO(3>dRh(e;D5fdQ_^$2DB`D}%}ZBUX%O*-=}!d} z+RD?#0cqqhMY=T3!)w!r%G-b5ll$}X%ttHYm03)J%77@-+qr6fzfPHmRUWxXP#ifT ztgNCDlCJVY(EqgSBLT<$LkYpBs2AYCuSy!Pzj$UMbMhv8Oy1gD# zLmnGqj83IJQW4)uM+hdf)4-{3HPG@TY-l z@5vRUaI18=|8QQdO2#WHa^HVRtAgXL`iFc)xk{eDKVv-PGtq%xq<*s@y@Fz_2#b`91vC z!V@4?Gx8T`e<&r*9F@s{NT|!ie_eU=1vgjZ{`wW+iPj^5tODuh$VAD1oqvjcBLY_F zw?I^d1P76-;JQ|Nc$$AYH@AIq73CiA{4ep&GiSULzI*wd^mdF!;mW2>$e=j$#@yd3 zZ{BxvrSQam4r0G3w(xT7srTfk7cU@rflWXqr3$wa1iJ*wg>~ zXZj!8`1gPGBVHqpndNJ+qj4+xti_m%@d71c1^km-760Ueh4h};$R}zjM|^K{3pv&~6+oPVgB z)$_Gfjm4(%dB&9U)+{-GWm~Vdsy@N}gKOG$)th+*(UyQ6e*fhE5e{RJZnoqQoKFJO z?4mv{i{sB5o|Nl@sf9jH^4Td4Rt+bnQ&iB%>qfQ)Vn-P%Ab|Luls1832CRk51Gr!_ z_cfJOlzUbT+mqhfOk(c&tLJR5b_MKhQQJayyKtk&U(*@-;c!E&KQwe+Vs4YL<;cUf z;P9H(-5#QW>ij?WP5eXfH+Wi!1}NfMn6YCfs3;>Ooq{Gv&#dS(s6|eDY01h8BV~KQ zmTy^I}&kgYNTn$@`kXz zy2 zBq~J-MfqotlsOy7WEC+vbOQ%Hh$^rO6lM3XZ4Cz&&FP+(4W2RT1L_|*fN+eXBViAD z5?vAD@R3(q4Q8S!e^{|-{gQ2qyZa6IY2AU`8=MD+*S5BGwsJzh2{iQ}e;YQ6al6x^PuntAAy* zqwm7K<@)eIya5?2qkk;dt9u7Lo~}q}cPk}(8o4|^x!?mqyPuE+t=#?9>A@tMx!wC@qnJ-123OtU%tC{a(%+K&q&tjwHZb5o!;S&bay*{vANo&4GlLtYK�bxEJ2 zEn*$-NDSM{tVxT0FcuzZcGy?Wu|zxFvm2T^b1%4CVm&dZk5VczrW)AD3Gjq4J6Xy_ zDdoJfOQ1;iMIWlX5Q<*bL*x|zA_+y53o4}~kyDkz9^|Dfw2=ovRs%`yNEsK?p;}P@ zWtw}qoF=SRcwm-fxueop;XZw=safMtswCMnS?;Z9FxT~ly7%l`!oMRN4lRn^vmqU| zWiD&*R*76<#N@s^Qg5?6-MM>(t1F!W;)B>l&V9l!z;m6fUGfW*W?2@;L|OyoUr+`g z7iAJQFQE72_L-RsVWv3*9}`)&Xf=Vuz2@{FDZ|&))~ie+hO!_yt}JVrf1mIRkKGyZ z*j$l!au3+FSzX9fGof|YaIMzsL;vz8V7=OeSI|E<3zhUw;==VJiVGb>98p}VGrOaJ zv@0>NGtu&uM#?eNQ-?b6=WB z`|XZsRl60s^Tq*JdBCo-2Cdhoo)oSrcVUL9uc!sU>(N&;<$6{@=PBlT7Ok05^?{5R zNkt}ApD%4_8qy-oI$7nheD3NJQq7Npn(_K$hCvX0tZV#6E;big5c+c?Ls9I97HXyNin8Q8>1+wj_|rTb$>Cn zt@lTgLhBk&EK^qI)YOwG&rX(=`O8!0Zdb=y?TWHgO^?6p%!zsT@(1-C_*5(K8N%-V|200nge`9gwo0SP zK|D1eW2;s+>?kr%4n0a1E3{D(uv1#_g-pt$nU#bY=*ZLfsOel62~4x9l^v5xg}1_D zuImYQoHK910si5JWGWN2HeYH1qq1uJ?h%cp`tFF?hTX%td-)9-7n~8qt4#U7^S@)< zwGdy>K1hdgPy64!CECpAvNhXIlO`a?(=RCa$LLjrogw9QQU=o(j`bMzQkJ{L zu@?1B3T_qrkdz2Z`XpHoS{4v>64FHEIR%?lh$E#Ky~x7E5Peqdho8QXTu=6#LS@j* zTb_HnTN79^*gq%W4{mKw^+wOdcEGNvw$4x)4Ve?RDF4{GrY9FM_=8otS4Y<@?K?4= zz}ijlPD8Z0)z;owSI4oHQ}ns;ABi+O{)J;chWC|n+dCM8u=EZK8E3B<^7~@GtW;BxR^t<9PeVn1NzdmTyJDNu$ zp4LE}+tS$3RUc|J+3ISmoEe|1BhnCZS=_>M&fR8n&}wXS1sdF)QA@SWUuSchiOc0b zz2*<6hpVM? zv30FF)xQ|Eqt0#ryQ8MZ7_6;Z<8bqGg*S2n@c~#$$bIj`u3bNyBWX6Jxhh4?OJ3u4 z!myn%T&h&q(K(8VPC=~O<-ALiq=12(vomFP7jgha^3Rfv@#psPOkJmc@U#w6BJKXn zgk@I8Drd4qm7I4!{HDK%RJWKL_*z}=IZ>=@e8!qN*ksa@taI|Rsz&H%JpXAv&wmYG zW`{~BceE6XAOHwha!(--&5X@t0ZGMGsXb!Wbp}KLw{-S~#_F<$6-jerW25)ts~0O( zyjH0xpS+!aSdnPT{pqAl*ERT@Ex)~ZKD+m#vlrLIRwY(f)GfH0f0X<3(t8$_4?TMJm6JDE{Lb#@Z{y3B-M6Tb z@2PV6McT-}id^YD#?@TRbUbEUHlhe5C6nh_i3`$lq`VC>ZKcl`ASgr%O`0ItrWG1> z09zJC&68*XYf~nT7EwW#X62q*ySb(+wkTrrxEcc;&DCa$tHEk(>NDFzjrEnu1rdAL z?T9pXTI$@o6_@gl>Y4^(ix+!smQY2;vZG~Qa|1M7U2SwYv3yy;QXeSK)Q)F{me;7= zNW{;7Cm$3z#^`~mBu_+9vPp4Piu_37W!ZJ*K*|Da?6eshEfsQ-E4qyQYxq!zlCE&N zH15V(@y59w_IOjwe!&^uM5A?JaMIsdrY&D`Gyh06d-TVn$3IK%!Xh&_?A9q%9lL9wgePLYApR047Kx z!gU0-5+B67NI~Hc@Qv=E>RgF7ltEx*)wgWAJq_uK%_QbHpmh=ga z8-oLhg~J`ZP1l(6PBxD;nRrI)NO;HQEUePbpV#e<+jU&t>$`;gTzH?K1KAfKYhEgt zKupd|BO^tF(i+I=EbTFepd%8M3lnwk(beHTs5p zP0Q2V=k^#3&Y*wAuu-Em`+duS%0e9qcy-AmOj()qqQaU#Cd5{>Opuj`?ol0zTAZtC z(}xr{5LF0lM<(M`R_IOmYJJ7(6WUDfw*LM`o6cQFB$$PDkR1Wq zk3xHn$f1CKP1iOkE^%q<8}YqVmVgR7aI6kea|+=khy(C{e*iTIDDxKk3_P-zi>edQ z4o)+_-IN%vvvdg#&upWw#@=fkom(qXUBla=Ix3!#F~V48_IN=^Osc%x$V5X zeEB72Vav9v6Bl-DotIW^yjk5eusGEU<1aRPO`_1>Kfm1eOxa$|^%K9$Ttd zLTi9SM;cCHrzIKwQr;pl07@aFjl^OAj|@5_6GOt02yuzqFtNcRO?tE#ML;G`fZwg| zAFldd`9l>0oeF2l$SbOH<_b^JX;clV2Q^pic4q^%O@1iT!p?mccMh$0s>+0ovsA8@ ziA?7$Uo+T%5g%9!&-VkMTmT5gNwi9PO$ziP*PDRYBhrxe>hg8Dz%c&}_Uh7)Ffyvv zdbw~bbgK&rzbk4~#0?70O!%+B*of@OeI%tSQ#h;;*QE79sj<{XG0tLYBrR^*i$o;wf`ot_*Z~|Aop0^ZEc$j?^103n&-v!? z&wgds_2+&&Qfq(tXU-eW>uMElO{z3UKB?9ulA7=3J&+c;Rvc|{`e~{uEKO5QB~!5I(MNHrrxzFIya&XbhG>$cQ*Di! ze+T(A)iK0|!F@4|12LvIAG-s>fik9*e0p;@#{OIWvleAESRZnLwZ&|$nR#O&zpHa`%f#&ZHbo@T5Ox@9{LPJt=vDc?v-rl6mdFjdqy~Sy)ZEUa@Ed8dOJY=K6bazfw-y_GAB#e0Nnvc*fC2EE8vJ0EA3Vj z^V$x<+LpEoNrnumQQ)26;AT{mf%T;}L;nM7M@1P}!`VQVgob%ha(-R6P5&n8=@OCgG0?5qZ@-kfaamW%*JT$ zANF*>Y!0MxyT7i^j{BzET7y;G%q4GCUHi5YFjl>lCURuXT zF5FX6u191M6No+kQ;a=(2}iU)zYz!Rxs}qC3b~rJ{e1=2}mdU!Ycqxf#r`=D%3dh@Z*lOI%g0)7gf zOqE@qFZ`BxGJY-nme@1q2-PW2-{Se|XZ7d+w@7cM-wG6W6P5_S#{l}-F4`m*#ZRW7 zUgJz7l6h4pnKYdYkvF-aXyZs4S6D<;!Q+n%8(C4a0Z9dqu1(&qPfDBQwg4XxeGZbU zfZ88vxV2~4?=Y4FWWLE9PY&c|iqU4lWOs)gHgEXZsAFnPQ)w9E88N)KCFTf*j&HDP zBmETJn-d5ptQO&C9-AZNwl;=6Eq7UR4>VLuAr76Z223{hFFEYjWNP!AwOkDQbt3HN zM>ZLxJK>!0wj93u4pgF*QPN5{YAwN0sliPfoN3qCA#g$tZI$GE!GR$~)>}maqsmGW zTNN3;8e=~?Xd?zEX2v%q;}EV65ijPfuu!SwtCXr_Z8|$qv%Flj!XKTi3+T_iSVYOz zm;<2z!buZw67QQGYO$Oy9JbiYa&`8gHeDU4GcGqKocvdc#H8hf1?{=d26u>Y&{|hT z5hJVnJq`rPun*=5{#Wh*@lXy*L4>3KP)7J)4LMaccPw8{cq>EQ;&XUzx;{${_$Guj zY8Q~$r;;>NScRY-;DUaS(kyx*kX6!BQk&t&&+_f#hT7q-vKzbR@$=?iq`2X(+6#^L zg~It)TrvAkrbrh5BBsRLyK>9;H|}EU{M*RSDScl9v`UY-N6Lk_l9EBHqr{D+_m|`S z0^Tq6M7pZST_oV9pvFm8$M%jotDrhEa&N)H`SGLGrh)E~&YBnNEz4#rzJlJLzu=;> z>+doS`bXu?hcYcKnUE<_HyPbYSvWd+ zmRHvnv%d&`kU9MNqO2@P9dfuJk4I!>95|#Jfs|fSXd|tCT8AJpS0bO3GsV+pnYZLL zpiL{KRg7FE%dGVJRJpnl-%+?Y;plotQMv9>;Y>VHP4()^ehb^6P_M2JThdptR}Z0} zdZALC4_6c72p8dss;nJCa;1Qx=X6E9fPB<5>)1{F-`BB|G0{$vtX*!gl?5 z3vR-ifLj7Hi^xYwVY@N0jSAb1i4;JqDFqDn<2(=NF`So>B|{jT*4+Mwf_EZ{i#N|G zf9IO37cEBOH}YJ_-sPgNKrWjinc4VJImncXrcgB_ zLak)pf6@m zfIB+}P7&UE^ikaKDenK5ct7Li-8&nI6 zWEL!BP#1W=^oT;K3+a9Iklo{RG8-qpjOUzvHof-(p`E`eybKJ9@5P2Tk{q=VP2zh= zwTwX&QRstwCU6DwH!C|L=Ag%>36*CnI-BbJZo4*IA-vo_q%-Pz`iJ!feGlGGeO$xe z5WbFXxeFaScIKvKC@Dm5ROKG3623k-DE|H%FkF5o)+0jgwJLN9eIo-v(uN?@RW)M$ zmu^()n6~;~=g0^P+6>CHZqfXKZiOKHR8ysJ)R!9@&3tks)>3Ifh5-9e=*3>$XTMNi z5SJmWO^Un1c@qd&Ex~~BY|w5C2JH5rh~LYE0pwIag=d&q4|pMHwiZV{2#>b$R)AWi z97Re?03RmXO|k-rO-Kxsn5hxVzEnRE9fk6{pSAe?7K_jKu6XwQg{RPyfZuBK`)yV~ zo$*MJ%QK*d`xKNW+{n^Y2NfPa97-$zCtjgPe`r6M`88nBg7Ft?3{nay=tEo^lGZ^f zZm8cT;+C?wcw2qgVKh3z^>8N`4UM6CbjV`y`xF}bfM}-CD4h){uT|uW5WpCsbo1|cZ)iEBvBG6jkw4Xz+zRlq>mYnTNE8cACr?2}WJ zO!+cmzE~nIS|(Q<>bQve{xtAST5wpP_{Z_rHk_#9k3S~G%#vIo&znqGwRI`Z`Um)@F-FlZh5vr$bkx7*u;4fdxK1^FblN{~)}H{`d;rB0T}!lh!dA zyM>Z9jOYY~QJ_u#r+L$yYnP4*Z(4!nrzBsi_6~S+n(k`PtCy8^ztPXXUfwnP zP=~Ppwnh3s>qp-n!+s0Ydx)#6zyFZFJdw}}cAYwryMe>m#&j_4Z^l@i$d^W5dI(LW zwWN=c92(_GZ&aPhXO*MdHv(L8-9BJvD8vuvfUfvbpJGLxb8_Q*NnGD_RG-#`}WN%5sC7 zTN3@jNf(^oVvPlHPkBSp&OT;LrI{zBn!uKXYElL{D=DIsgF?IFC}XP7Mh;+duGUlC z2-Hu2`)zuwxj^P7xqY$Q+_m0vN!#>}^H5*i#<;xe{K0HuR_-Nf=lN^CWZS=_?Z{Yn zzWjsOk4$+)J~%-yJ;;(+lTmO=!~r1blX$feuQsB^BeqDPsVUqJk2jD%g`Y`R1?rW3 zFFAMG* znY^yEf55e=ab5WM&Ik5%4>YX2&6R3SUp6|>5sPg~UOqQGND4Y?fhgXB9%O)yd8L%m zn*tdY#wzF}lab&b8e>Ic!?MlACduHBVs(<~CaGa|c3m9X7kyk{AfBx5WEH8^INUd1d~e!ned+iC$z&JWPQA0Y#&UtD>hY#Ns{X=CNg zjPXxOU99u(;~#!bf;i8Aj9j)^@Q=D!r{u4pvNq&Ct7Dpy`7HivgF~1_$r(q{eJR|D z1xccZ$}<;GSx8=oKQJI>OL3D5*j!$>$1mkQXXjZa1;IU9vn9LafNW^wsqbmC zS0^PvFW1yoO$DO}7ie5!9<~BLv3vR7g)D;1ZlubAUq`{O!_%uOid9wEkK+{iwG_3O z!tK~_DpG8dd{w}#tXvf7v~<5VsShx#L2;;h&T8=hX=fO8CA2lkZN#s|e7pj?7Skie zP!Vx!+L$q2l{UbCot_tq_}8_>JXvpQek?NQ)R?nnX}!mh37M}Nq94S3l>mI3}i+u-40T#;ml*^Dd7=Ao{5Sw`$Y09TD7cF7XyA>CI*8(6!TPiqD; zk6OB9kpzxn?S+j_yb+niby2@1>8p$ETePL6=hAacyfrzvbjSL{h%vAt8yZSlqe1`r z^p1%T>eDvV`bYVce{fy<;IMyaP5a=8W3n?bx&&o_dxpolmj*n3uRSv>+Iw<15cz|` z>8K4xHEvAf;q=244BJ-FSjZt!q z3D$C*db`tZ4%!X&=8>?cHB{%ZTN?~kw?C{wL7_y;#Bi0y>mHt0rtcO9jST0C7*i^1+SHF_Hc>I03{^~f)Ew+7ngX?z`KfAIVZa{n1R zF+McgXNwqHeHX6dRz5y&$kLC$QS}H6$c>6S@E0rHz^@t=yXNDsyB*uUcSifU)A#S2 z(O!Jc9%^T0^7DTp+NLQG^_5gTH373ml6ulcWINUiY3EXOTrU!71}*lIRdUQ4h|x60 zB>6=goiz4C2+$#BD_#{WU1<%FMk5vJjDjqtBT4^_Qb1 z5vR%IjMT#tw^#%Isx8_Uss7@M3bFp;W#11eeqwYsHCQ4pqY3ARCa1C44<|yCQi6tti>nJAvpwS4qL@JJi2}F zjCPts>Hd8)+G!4@_C0d@2SD#*;`77O^YIt$h(@UW!jksACGGna^nB_5eI@NXOYYwz zx4#7%d|N@|jf>Ae2m3_ue5rnsct35Rr*WPCx$S#rw9|W~`}fUgr*TQ`duFuLd!_bs z8yWL}?@V|NA@P71K)}`om10*Z*>pd_+vJafIpB?7%?O&3ff1UJvYM)=y zzPF@(yZC(R{(U9wzLNX*$nE0(FoDK9SA70CsY3t%E*Qo8=SlBvm~Mw&O7tqV@14<3 z00r@BQ-UAnBL2Wz)F!zWcNd zs^?Vr_>*_v{Ry3)Q(+br_}k1sRg4M0ff5nJ-%TDm1W_iiS)z`ilJVq#FG-9lKsSIF zgqRNL5tLGU2s$9g>Y%H6xJu&+qY(3nX&bC)_#)3(a&y36F1m>1WMj!k6yqjOK(pPcihY^J@dJ$w1&_!X^fZEdaDYbJ)yhA(+z`i!BWvl7YX=0sxe zs*K*@a<_%d=1{B4;56u)y`!G?RsCM?z^b;!;jr+V&eoP|=FYmht);D_we^a*6PLHO zb~I&@>9dBe-k3_KQ|Uc}L+2zCnOuIZ(V83%hX<3E^72JzYpXonOPbS5x;+~F(Fq#; z9(Dk=*zbZG4L>T?r8&ke&DA4IP*CXec^Pv**nu>*Hb((lSj@Erxd*Rq=q0owwQ zM<_%EGWzjDDO6>yvc=>*X_oej-HK9v`N9;7_L@{4_$(*G4Y{k zoR^69OeY>P8+11tYJV55=iqt{u2_Y z1Y8W2lqGUC1TyC0Up+wqxX+!^!LyUe^t#Pg4V{@xHm75Wa}u|Ab=tjk`f{zyuMC@# zje28Mxk}d*s%n3}IeR_oj?&-REh|@k!PGXVl6(5EUB5M*O6?gMJUfwU*}Fa3rcu>3 z`s-X)pQ@&^-s;f%UDs%Q-YUMN%JV#r1cFTz7y#DxaE>`%h*cu~T_XxJ0`CfZgP9~c z7w1>3rOy{2ZtynffND|K!jFoqZHlUsBk?E+UvxtjZF(t_NJ>(slw;y0lyXeGglfJ( zM~7BU4ma7OF4~<~OjM~_p!{99n@tFMVB?QGClM|etiEx}XZ^awq-K7oviFYjs?JM_ zg{zy^%q(1;@BA$l&U>RX_jeSpzG8g!X2O9W*8L0$Hz9>3$QDcW?>!}BD)qk*%4iix zo*2o($EFz|gN$zS$w+?^Nh-H2`*r(OR&p0JCani81v8J-3 z4@HRe8!Nj{g@w3c{Uu7RO1LSe(zeZ8+Ol%cFSMd^X;P^bj0R;aXXBezo{YaW3`~;l zNIIpYJDyFtBPQy_{37frp-EFyJ%YlDmRLKnescKZZ#EzXhJx5@14ayF0O`VhuWxmGWOkX2anfU!47Q^2c z3qaJ-u8pijrIJ6F0(?{!x&r40`pXa1aJETOkRpMUCR3=xFeCDdRUrO}LGpc2B>1bg zfZuNS2YC-IjofSUM{jqoRMv?SY(j1S-`jw6MB zkPx-fXHbunH(rQ!FmzwasihiE^j9nk>rCEiEIRX@GX0S#_sPy#%E)Sx+!XY8Cj(eJ zNVG)&r;tD{x#h{ZWBxzIU3qYu#T8#2mgFNoWZANOt}pqL6dAxOBv+*i&3!tU-o#spC4yI7%p4 z;gBM4Lu2F==AIDD!j6+hU}_Yy2!~cmBiaX+&g-Stj2hnL$a0UjYjlMst3{_b81$Lh z+4X%5HdW&_EuOUOCD~?+*^+Ci$X3msvKR7dSH}hHD3s?Fm~9#PIq5l>?Uq58bE3n& zI<~U5*qqNMQn?E z&xCHop~NORBV|ylkT+Vy%E4*F4UeHi@{&j8FhVIIm zitNH%BQBgTHuu(g`nGJrOh@aLdoM!2qpbsm!Qvsy^BF4k z;*RP?Np}9NGq#x-+nF=)Dx!hQrOHxq+(EL0!GD4Lt%QB3Jle~=kmQf~6#zFcXm1r? zrSCd5n9*&x;oIuH=kH0^mRD#qR85+UGUcp`FXAre7u2hT{9T?Z3H*ziv)3>};3;l+ zOiEkXwwdOXvZWG{js~OTU60^4cp0@h^XbGs<-W&{#H3{Z+C6*L?)mu82*z=7HU;)m z${;F(@}4P;%gNTeOXQYm2NcA1r1ieHcL^lXZ|uAW_)I-5d0SJ__p@+Xg{&{Sb3=Hu~s$5WsI4T9(QVmZ?Z z70C+r>W?8>W$({JxX^b%NDmL5-2!J1_}d5mX3(YhgzTWSZV^Yf1Ijm$4Jqjl0ic{S zNk3(iFg3TEZvxp3{^}9(gt`M6Lq5g4XhDxC&?|27B@ZAuB=0EFUd~gj2dVne-raZ( zpw#`=qtEDBGIflG~!iJ7&PtS7IvqD0BqKBzI(5*1rO?jsJVq=l6OPl7b_i7qc z_G(MHzE`Ww&(0|;%C=Wmx9=rsHLvS|8mcr^K>aAlJ}BR;Tm$mZgbc1e3#gx@v~oHS zC@p)v$>el_=j!C)@N$H~P_A1@8X6Ymqsl1H++;;r=}^75uf&vPG-T!*99{L+bW@fg z&7f^xX61PWOUz4*h32Ntn$F&S)jPT?Ee?~Zz*d@X(JfC)b2pV&s?|1CtF^e&Fqm%2 z&8@KHI%{ivLcUx$5BahI@`ckrD(UfQ!k4U5>aI+AX)XIsrLM=sw(e!F#}t)S#;EaX5}GG8?`yesNc(y1SGD`nveWw0cIm2gBf4kw zjrukEK>>&TyLx&t$(<|&~UCX(D=p1 z`x>8WJl&*gay6}Q+TC>8R&Kk(cC&4_ZMNCke1G#<`_`r9OA{^bmRQS6ts@SjoM)ZqTn3lP#a%X6hpXSU#&x|b=t{V@y6$xC zay{ajbv^BRscl=^&bHlc``Qk)J=b=m?aj7RZD-rgxeacUo4al94tKwMjr)3c(4BB^ zb>HdU)oyJ++dxPFHzBRr?XHn<=&J$h5UH2>-Uv|9P+D$4m zBRc`PBmUGbJmfHLv&SzvjN@F@J|(PSW$HmC3?B^jm=cEng?f_`)-j{{b|tK5UFvTt zVFU8Mftj01i(^l$9fNx-4!?)_k8hBrHYI7_!5lrw_PluP~e@x;*DJG3><`Xf0Bq0U(loXo`#p9u9gil8TQjGh<;d!8@ zV$rEsNJ?zxqP#dyMEP_aAjg1$jZa1cp>aIp)1%?gm=vLyxD*cCxIYr$F)0uNN}336xhKYvAiPPf5I$N2e3vP(gzzX>iTMN4q(8QiAo<5OMxrxe36u|Tf1JmI(U}Mz zmBP`PB;@IcAY2FuQiUjWRmh@{M3BPEt9pmmUA1mxVEJm^H?(|Y-N1+_2^E|Gh0&sc zc{l*!i^vIHs8VR%8x05eaKewKa@bp1T72N5xKD{}rdT;L*);Rgua{ziN06_%)!uSx zp8pBKh3I~Qburr-gI<Z#P^AJqXJR@uq5$zHTIY6NO>*Fna0yEa&wdi#kz>RAY`Ey~T0v zLp;%jC=f%MdVEv+tOFKA4Qdq*%m^Og5)tpl@rI~IbxPteza(niX+R=65Y$f(jUZDF zf=cw85^$#Qmg=1V)g0?FEsAx3UHpMXHEvI%df4FiI1l+%w?GJS|{9OXqt zKB6{9YI+w&cwD5TnkSHlU=uxvFOs|K%H4GW3URw% zU_6OujBNxY87IPFqri4X;3xAuae-gtj0>vF2nIJMS^xR>z{8jjjV7;*%*LhICA3|sZ?*{Ols*~J;6QYhXFUlA#MhBU~ zmr^bz7jX5XXyGJZ_oDV;QNv-;igK@VKti;Le;@daWKkRr%?oojqZV@B`8gM+p`NuE z{PmzJ!A!~#xjd3?RPI6;i`A20g7zXCij!RE%Z$)Go1l6r#L~40c5lU4UzTFwQ4ZA#hfcZ*#_==rdyKt^``G%}UF=QvTa||W zj=jb1W^ZF|`+GLWPO=}eo$NvO4*Le1We>53*>Bh%*mv0X*&Xa<_A?0d@1k=)Aq2up z?C0zic7*+c{gS;3@$wq`6$Y}`+4tBf_6GYk82=cw@~6Re8^QE9DIJ}Lr8xTn*nbnm z!8E%W41X*1>9@eX~qQv%j*xus^Zeu+lpN|Kqdl oAMBs(Lv}BFpZ$yd9iB4pWn<16iUu%U6f+myq<<_H#X*Aq0i6UM*Z=?k diff --git a/apps/frontend/src/components/launches/providers/medium/fonts/Charter Bold.ttf b/apps/frontend/src/components/launches/providers/medium/fonts/Charter Bold.ttf deleted file mode 100755 index c8f7e857a216d54a141e0e22ee9c8edd0b2fa423..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41036 zcmeFacX(q*)dxItWm~Q)mSx$N)h)@EY+05p%e{MTuh-kW&D)E&m-N1yO@Z`E5&|h~ z5>iNmB_Xg`hmb%BX{3=5NP!LMZvq5JBV?uTcV@0EdA;!R{`Wo4_ib|LUXQNsojK>s z>2t(5V@$`+Vj8w~-dKI)vbksFGRC){ckPn?(PhVe{Zxgq?3FkUZP>Z)*i8?gi;oK0 z8O!?1hLcZpvPW}%&Y1CIbXIIScJt1h@f+fd8EWy26E^QSZByT-`yXShxR9~43%6`s zH<8@+)MniK5ss!U=*V?sEyul8_`7P$&J#~fuJfLQzn@@CbM=m6Hmq|*x^aC~8Ty{t zx$e|smBWe$*F(79xoh3djRjBNdx}(Ff%Du}_oBlO9Im_3zlzjz57pne$(Y@+HRbD#k|86Zi1%xMnOAv-#aNPs`8{j}4lnI>iVTZ z9>=r4V0OM9#|x|wFt95QX4Ra4cf5k*W86O?&VJ0vp)|8LWd$=RkFpZwjO2%!`+(3r z0ML3oe?F__lk5VF`JXrkfW;>^Yn}G5@6mcfh6%N08l-T&|2I|B35D+!In(GcWrAp7$Dy@JE>kYr6XwGE=bnv}wNPISrmEi9R{9TE|NpvDsDW`v|kbRMxWVtLinE+qOOCDzVEFWzF zD?nSw3egs^B78^3bZGTVkJi8pXpPL6{1+=`#b`~;gtmm0pfxiy+EP}U{E}Ii1#KBC zLtDsT$?5UWF5&qB#hSeVtLZD3)v5!Qe< z$|A{sutpX|8)J=Vn^+8OT(r%sDfxHS!s2LKSu@%;)`GU3wI=_@I#?UpPS%dLi*=yw zW}V58Sr6+%+snGq_OTwc{j4|nS2n=<(9UB0Xb0H<+95Uz?Jyfm{)NqELug0XFxok6 zHri1(lKeBI#2mEq*eKfhY%babY+mvswotTVY(B0Ru?1)svxUhI*%CH}b}3tgb{SiY zcAPCq{tsKumZDw3mZ4qA#?h`~%h9f8E0Q0uHEbo?wQLpIb!;`-^=wV@eYSzEMLWUP zq20*VqusF^ z+N;=QXs>3MqrHY*k$fFo@=CPVvTvaM7P|`Vx7pRn*VuLJ8noB5Z=$_{U5oZc_O0Zr z>^tn+X!o(}(B8zZM|(570qrg9#^mqWcSU3)(x` zchTO(ZcV;G53wJk{VDqi+J{B^Gj<^P zB71~Ai1tx-5be*|B-&rFhmtR_$JkHN{*pb6_Hp(zw7+7HpnZZpntYx;$$pOZDfSDr zPqW9+KEr;Qe2)E^J&yKS_A9i{u_w^t-sH3F1@;u$7unNjf5V~*y7us4!VvUk}Z(7wn1i1vMU2<->#O|<{R{*-)zeaPNI`w@E^ z?Vs5@X#c|AP5z4gmA!}dWA;AUzp)R{{+<0#@^SVL_95C&MEfcG2-lynKPP|5K4*VH z`vv+AVqc1%*XAy}?*)DlwN@%E~LOl{UM>>2iCjygq+*O(0lX7pf08 zM52wcrg(EpYg>CqXIJ;`-oE~US%X8vvq$EP&Yd@Z!NRdcirWMoq8Jk_VssNcJ(nAZat+Z_jl}>{TtZ!9Xod& zcl=2wpMLFkzPazFn{WB0!MrfTy7iI(hK01uK>btf!6n6eVhQE{B^8{%fWZwz#4fI-1ghxXV-#j zeGB~SBJi!7z_q>uZgnf>eG9nLZ@`uA1W&pH{O5aEU6+E>+yl<@eXPcpz!4t+pSd60 z=W_8^G#%rCT)>;_CGRz+5SiRt*-HL z+?6vmQjB=d)-rX>T8ud-fX{Q~Q^uC<@3!t|;}=~-&m3FkaqU0rqKm8-VIJz=2iPM= zbZ~ZLN4MGmNZ=WO#J~Z5)_gn+Cy&cY9Uhm*g>jDe4HIg91(TpX@W`9@r%nY-|!=SAg6sJRr|-fEl01QIA>R+Jb9KJq>SQ z*#TBkZ+#F?&g&dkJ94NahiOE|>$m}5DSSQL5Ra6aOL9DJU#zhy?$Lxe&QZ~)y~|Ns z>#*0=w#ModO^wG>qbOI_Ii10v(^(he8;UD(eKmpVT#JFcBsKgN9#o!!s8f0B5~= zrm^MYZ!^wXoCy_lUpdayUx_pI+c9>ojm9n7sM#Y9f83+R5sQjLgA>1b_Sffh%|7qC z+8ghi+dXp5{I1apZ>YWY?ztmpht5@g^xOA}U+z4={S(96pBBH>etzfsiLvuRI~rJD z*C}S@T~J^U_T8nEAVLL3Ulyig0wK_JYS7~nlOW{Vo3uLk3}u$j|q~C$ILo>WHEJu0R6l_u(ZCX*xt2$ldWl9B!1eWzLJVI z*TmW_>uQ3FqO}dHly`@@uIRR7i?e@QxpKtU7pu~4-keo&@5#DC{&vO6k&%g_+2`j* zeY49Gw`yAhbIai>gx&m!W{q+;aH@xW?tztj<0O!+01kv?zX~6@%1T9FG5Tn|9Rw-n zF)N^Q5Do!(m0D|zKmm8>)LOGshh4&^1hB~wk1E4e6|MkLK*j*b&_nTuK!6>6HKI?4 zuhyUsbe^#`v$=<7yUiuhNUSkCqu=7rk)2P^S+RU{bbPtem{>iF-;!9--#?4rB|4X{ znC+?>7*OuswPE6zV~r0E+ikbLcg*^UUAxd#JGSt)+it^fKufXYC(28L z=QP5)zj+e#RRA4=Q3I|t0v>VnmLL#6->vg_8o+x=3x!^GzFtt0!i&rVRR7Q zgfc;(MnK3QAXE!zV9kL=5Nn|IWyiVvb$W$?8S!9xg}efN5z+WO1c_2hQ@ozXqGoN5 z*10TbHM+vs3$t9UE5=?7tUa!N zH14=~g*`sEzHTsL9iDS~liAhLv(JGVOVycNmg`8mq7pk$Y%*Ft(;no~{U z6WBfI1bk>|m0HXp4KaCs&g!uxD+YGXsk#0V<@%zBetiFf1yN1w&Kov9`vzG^9P8wG zK8$A@j(Bz+KBHkzio5jU*(P;G#{>@iG4F-fSI^nezj|!ZD&<-2>rZd|&dxSXv~co) zA59iSu?AzX6CTF1vp`fju%gI+yKN&Ue$<5ns9-UjM<6RXrkKJJMzf=|h z#_>tKP{Dg>`DKBWNEVS;$$K6!6S7=iCcqF8}VN(YK-!y{`Idh{LjZ0 zBw%SQ-~ca&zit66g|opMfmh(`6kUU&-+!AdD$ z?zD!GT6xn2|8#+Wg{!{a7vW2WCO@IWZ9z8<7ALYqH)Z`PZ z$X7)T_y9O4sS3CP2PJ7D*04^I>$+31xQ&Kr#Ax8&*42GgReh^lTUYf~RrRiFJNe|3 zmAmW5&sjKj_OklW_}OD)XOGu6Ck`cE#ppd^uJF+@{#WHrpstAsL0y;X*s^FS&;>}y z72;D;28ezh1ZZebIYc5x@EKREiyQsgSe&0%usU(uL}A`#zf$QyMCH8G#sa-9m3Eii<#%-~ZHg>taRe9d9ow|*;dvd~)-JE_8!kM% z*ynUK2g)iNhl1hdtJb$*s_-H!1u#TfqZi1vFmdGSQMcmTuMD;|)GnUsn-HRB3Al5i`zi9{_iLI*F6MmoX2iM?xMrIBc) z>8KOV;d586^ABz54vjS0{LVa6fzxlVY^XBN?k;eY zhpR)oXdo~Wcb0hS%57CySv&M*U(^=wS2RPsr#04Fc#_UnHIc;*5f5NJZD;W8yFcf^5KAu#R0Zu8A7? zFONI!q{Nea_FrFDZcD70_tHxX_`bv%ZXvA0`~JC7g!Nd%){#=GK(-PSCR>28lEOgd z8Wk%^PZ-ck3}oXuQb!~01DpinT7#Z!feStQ>=FZJml=R3F_~Io5)XDhg$S*Ye~@^h zr@3)ao3m#2*6!dyxT40LTU_8Sv=rK7{?e6W?H$U#Eq9iJqG}^cIz1*=u)M;Xr8!Qc zl=@?izPUP%ATzcLBEb`kC-7=jg*lo>f$d4CQdVrF07pscl!EQ zH@B?n@wDx_VO`=7=K~!LT|*tM%2`>tXB-=KwayPWt>~$$nS1Qu+8d7POk8QPYfm|4 z>D<|i1n%Y}|DXhcyF7RzRWpdx=S*B>gP(FUm^yc9JuxMicxXHCP5e>ctL*DJd_$$O zaMd#eD-G7<-xRBIFG!#UF&XHtxd5O|&;seM2vuXwb?C_zbFRY*Efa8y;WNMJi=hwN z2asQY&vfXcH7&o9q9ZrK(w(uAP1Io`;2vOZ01~t$9$;c_^#SsV%!mi!pA#!tE>oeB zOEhm4H++h_eb41$>A+#nN&R zNE`$sDH+Uw{Q>5{cSvm|Q_{=|@f~0`LphB`c)XLxbvz}zQVUJXugT8tZ)xZq=?^3l zb!$(ptQzvxjx;&E18dvk%e&n1Z8uEt9!o>T#MY&wbH@^Y%B?+lo~gvq0_t1dlnTKjCD>i$2HIg{>9%1iY;tjS|gx2Nf}JO12gd`F&C8wBR_I5Q6Zen{vPu2A9!A$LlFqdI)OSb>06Mu zcpIsJ+0P3v1Swz#1!Rd^VgT7@Z_I1{fb*^qRs-{ z0~etCYCO}6k$TYs{bWkM&+sUzY(j8_5)eLSgs;2t^-3TK4h`Y}L9Wel3-3}&Gtu)5 z>-DXkEBiY&b#Tad{NQ#!;%4j8* zF;M>`g4-OJDKo>mV$nkuFSC%oIyJ8nMKq zI=H8V!SaDaeU8gH4ukdee?$|g~9SI+I?}D$biVj!T z1zVc8-}ltH@wU*SlLwDmWUF(+y~h+}5HRIN<#t%BC5Ypzt2C{isvSiH%pxgV({_W$>jc)|UxcfGD1gpd;0mh+ z>oE(`PyXcqp^{@k!QhDUQ*+9c%tzQGlccX^s1~K-v1FN$Mh+0*iu^hUm=zB$!VBCq z&j=7pA~44z%mlb6OsXDB#%RBo|;Qa85oOccFMF5N=59AYN9P8W5 z`X(W}rrR_siqhUHg>VLbLhQc?Gcb!85Lg_z3O9I(s{PVS2fYc7ym}68oQR$zcb5`1 zE8`n?Hm&l`T^5V3xpCv>*(P0$FS@AR>FOMBF0ay;50zC}O6$L~ZuFdnmEJqH8}+{7 zt-XEQhW&Z^)9wK(@p{7LodTB?Y%u@`o>U4BByC44K&b;rb?7nucetV(Q#dIX^N@BU zG>$YHU^Wtq;yp{xTUmcb{Rtz9*Ej%-B07K0DKJ?ua&L(Ka5v3NRJpV*`RnP=sZ1ghKZMh+K)bNGug=Yc7vgt ze>R{mdh|Rw>hp}V62DK4`Frb%{#i8q!En(B0JVTI`4jGg4eDd39AJJ>gd6yW9|te? z<8=j~hys#bxGtt^49k{59jZ-`hJM-=lJ=&Mhf#VK8m|>INUklyU^|ccXe#2}&yCGZmK}~ekIdezP zT;AZiYg@6wH?+C;f@?I-VEqzq?7+<%z>SCfP+C7Zm=(Fw9hj8^b0#ewY!rVHz~N;Q zpg)QZm!4}LQ5q84rj$A(bs)Ym)nTO$tE5G;4$0vyc^FxT!c!&N{_5uH|y#|!y zeE84u{MA?TELNRdZ-5belKWuJj!a^)$n}=u*)!Iej^?JLxn)u+*)4KjM6E>`)T)l$ z-fJ-Q@?f9A(3f~QMVCO|;SVKA0!oF+Px$i~hlR#LQii~m8i&eC(?HMkWf4b}kR?Ts zq(%y=&?x;9d=!a8T*Lt#iG+gj<5}F-Vc2=btl?pcE-N>yKcZ|UNa+%HU;6d3AAPNe zZ{5Y0q-f|SjLXR`p9F_V@gwrO#Qix998Mr7Q&=+K^*i5rqh?8=`SHF^YJ^Hj7I>$>0Nk>ZZG+l2n|jGE)~-{m*HBlJ@9HH?;JPr@eQk#yF{HLfa%w2ZD=FX=>y~4JkF7 zS6_10%GQpiSm?yAxqFv4@Ug%^w9*zCsIGzMq_SavkKMLr>DAy^k(buQoT zAKunCuye%kpS`V@&T?*q&t~AW1QP57l2j6_q*F6lXLX&WEu-ws3qp?%wD`=N+STsp8j;zz(`9ens#A7CxOWg|2X z^6=v?V6+CHuYm=X4aXVTzT_gL&q7nuWrpRH$!!IsyaXw)R5=;|7$hOWLd(XPV#QJw zgIbKIR^e@a90atu0F`hXz>cDv0XuKw$QKZHiN+t&1bL>qk+QBxv!8d;$@f$>8ZBm> zp)pca5w$p*ic8821v!Of?ugH5=t#UPOf8Vcg3*!Tkg{*-qKlom_A=L~uf`V6$};No zPM4>+s?lwDQ&mcY+4XbYGtk*fu;a*r|5V9_y%nXXS0f;oOV9(%WPVNxQWWqA0%j=* zFoSNw1fHS{yY{tX@B_4QAms@KH=HLX^?qtZ6$4GhKX?pwC# zwAxs}(@>_f*(yit>fntu7{z=k;b#G8#Y7oNIam#}OjEO(K?SNNDpd;12Ya!AU}E*i z(Zv<1@ub3&fhYU|($Y!kj~*oT#FPaCM*XSAp2W*N##0T30cGD0w-+5IC4d&QvuOJd z2@fT(7k-R!IoYmB3{J+@WaPK`LgoNBFp~Yd;G=B1Z6k_8Yturmg zO}SSDZWAP&714IenSiAC#}cgtx8GdQ{#wr;Hok=rL_@Yd(afLF1Jp%_Z&W4nX+CdJ@mpirLEoOj{nx$UpEJ#6StywqoS zq?_opF!8COAly)p_~~o9>_{YA_Y1x#kEC`|3bkc@>+6 zX&z7VA8Txg&*m^IMKdTd5-|}9v8I9~8bX!Ful1Os8e8=9&!eAhG;p^3inV0f^KV*C>m7R)Dh^JEyDxsb-+UN?p`jm!aBOOdRwq1;3&2?MRHafOUwaRi7D6@P8`-{*YfOq zv(;1XsfITNFv`OYS`RXfP2g~Q4=^WYPF9%{Lri7rlt?H5E~Lo=FOVY~3yC7kskNj6 zAq|zxC_pi8Ck0wY0Z4C`AvT+U3;CO+ztd!d;Ubdrv^hcU2Q|j0^f;uq{CYumaH!Ef ze{S>f)?Y89%%2ah z3O6By?HgFrJa=ie(^a9*uLxI}7tQLKT~}eP>RHj$vSz^76|(tF+cXv7f#8aXxM`m0r4@roKqQr!3W)?* z5soOsT8k{pJgjh!zz``tY8G!S9u;I6OOr09Zi$&OZBjoe%*ETU3F)Gf!BJmeu+ir0 zU(y8iGgLso4wbn340ruGekzU=H<{;1!$eDTWsJaz8;Bkb|D zq-l~op!z8~q*Y85N;-@dpOC-cptxP1L6ho4(=$&;IVen&3h7BV1JNY8@F`$VFd(;R zD)N!?{Fd6dOD;yg%teaw4>xXWUV+#<5V>Jz;=v^&^Ol@b7pQAdeimt~>Rs8=vZmj6 z(oU0R>Du@&y1E9*SP;HmeuMHJV7gsKzbR{jbR8JBm{B>-39zxLryaN{pDK%{9(I$_a@*Szx9YQzA*jKQWIuL1{0$th9lLg4kQ#O? zhA@ewT(~@NMR7Ou0H6oipn7$H4FX@3`*#p&Wi_l(fV&HQl*w}t`8l%hAjn=`rRX?B zd^eQAcU9kYHpNj0s#2oCpNdp98U{>8&@jP-mIg%}3!y%`@F`_m(+l!gT)aL6m_bJX z%&fTT6?lg{29RJy1-KuC?cjFsVPRBJ{w$^F#wi>o>@RJK^ufe6autYlH9%-bsVzRQ zL95Hn)$}(lj92<+O|(yJkB5t_l^tES=6R96!ApFhP?aYX+7#%CT5BD~rY8PUi_c%x zQCrTFI8;jda$xW?L=gb>+r+O}=jAs}*;|Te^E%nmQ5-JmH!)eTCcP zwP6hrZ8K#y_=l6-aDch6UUWEI00eDBs06&pvj*b8Uph=0UTi?0!&ga>(G<*8-&1-8 zW%{y@P;BLrq69zbmIBikPt0P)0?6d-M)EM;NvMztEkwGJ0_A4OQ@Ugdw>I?`(d$c1 zW9|!!VxI2+juz8 z;IOVY>GU;jM*ur}g8bY5aN_up<7$0@YI~VCdqu_i*?jlMu0YV`2-E-$cnfN*C~cr6 z8`%T!P2xYoGVv$vlwLGLj;hHb(f}nNSti4RYeQ(Gw69<$>msp>Km%xnbP!@-#1GR< z44K#&#t#zwMHInP-l!YCE>L>8w)UBxI7!F=ms{)ORdq|C+C zXrjacqZu4%Al2E_U$iiyX1bq$+CE-+aZ&8Epe_(G1WkmIJMGg6}8!2Kuaa)a{>Q5 zc-^-oucM4n;&svkP0@DZb)+p&&Zx|N6!t|1bX8oZdEJa)X*vv+60sC*ro@6&I%F=` zO}SXNM6=`>BDz)MDpN2x8n<&qb^TX_n-;k)5WEf$Y17qy4&Ekac{E-Ja`7g=P&}}2 zNOy-dLb|&RJWb|HI57fRJ(Oz?#b%1jsaAV>p3`_bCX~*#ufWuR=V^(+lxwdldcZNS zZdujq@%F84Yev33&he(s&RBD27yn09AF?-BP!j&i79{0+W1H4(*t~K5hRwuN5Hd}A zl`zI$3G3`G85411{1g*OVXbTmYiE1GS@N* ze7Tkhm*kqKcND1U>4ZgcyAah#7pz5cc}dKv1Zj#oXk8{!ekI*onsfu-sH>aftsaQl zyaVeyTn+jzp7``(r?Yp#V288*UNEIdb$z?T>F!$E*uH+in{$&cE5t3@&C3@oA-APB z=~LPO9}5ytFQZI6a2sG!`r^G97kNpFsTbE}bd51)W<#sY}Lu-i(tDHpV`0S;^Qk;JFn`o-OW;YRy+zwI7f zperk!J2uj*t198|Mzx0@)MeF$vUI>4vTfXIa}E*@f9ocTr<$usnpY(nsn--DHcFa&Ek+sxt8=L_MZ}*x#r8I`I8E zwhD0);EPsi2rnnLS`CbnJuMk5SurVIA0);d%;5ED@;$(UKn3Q6uMtvI%S>iuVQJbG z3+bxBjL0I8R2fo4xBz&v@Qd5?3*Anyzp%_x>T2?tx38PMqN5<+UsqFW@-*0*n>VkT zGs2gQ6d0V921`kCfuYjrx6TbEUX_ZJDW5QxmG9>LW(-_ zhZEc>rJ3Xct)5I>FcaKD(M>Cda!;_dEC~KGmXUH_%Cv7XdZgV^1{J|1;{tIZ2Bl0S z^BH@>px*`?AqIOc3+Wnv8lGQ$Vb7)fABm^hV!64z3!2#|$SCe`-TkFs#FA0-49v3> zwZ>+~0@Adv`rOkUX_Fri$B>~oVr~DIv4Afc3$`4e8-2L-p5-^S^Y=p8MTytBN0%K6 zX%ln#{W-K@3{^d#-vlwPQdFx@u|7l6WD`+i>-!W3n!&YaIL@a92Qo%39pe-YNV&+# zhg<~CV4UhP6X-=`V|ow(-s8_33KpC+v2&R=_S5DIHXd`z#Mv}61OX254T&4MOP3>O zw>j}`F+XqXf1IA5%9YY8a5|_&;MWN^I0ZlD6-W_NltvO6Wt34$ zTenm9l}z17+hU06(=w}6r)h~}y<@tn2IkjNeoYreb&|g9`Aee*;%8kG`yWr%venU_ zw_S2^3x6+=Q*g?jyxNfV_E++1{dxK4U6fy2TX6rcatWot=~s}^WvE7Aoe_6RPjLpV zsVJ0UW(LOOY9m~UP5c5oYTSvIgtT3n;y}@t(fl1d^J0%QJ?h;M@ith?m)3aiYv=C< zb99M!c!fSE7|crq$Jf-^N~?<6UE}=WJnSEXhk)@HFlIe=$EbKx1z&p1nP{O*0$L8z z3?|qkZ(X|hU1ly*Ekj(nr6|9LUy}IzL49F=VpS(UUN?4aW8yr+%3JB3${&`>T+A=Hs%!z z?mBBhS!`jeS-Fhs>>+p8ys@IfvC-kGu)Qe8O|^rK3#uXxU5n1%;8_&zt%1=;eDpc^ z?tR$WsbNNPv(RQXX&+%+*$7#1-_oTYQ4K?U&0TQjD4#Z(V?je31r$iCK~5ke0)Gg%j3*|+Kz)XmNF4c+spj-lB6vsuna3)|z-s zXAgUZN5=|_#^!ao>uow7m9SXKUQ#|p9lReg9_3!Q$7pm``&P^q`*cV+Erum=vWyxaCb9M~LTC=!sMygB zA`|Ozss;$iO%w2Vs=1<+Oceo1+-S5GcmlP4DgvS)58^uhg)#v;u4boALZeo|KBP|r zl_G%F5{y$yeX^fPg@N{?p55Tz)wrJ&GR&d`1S5oRIweT$Nb^zY1tGr(t(jE*UaHyz zAaBH`j3^Wdsy9K|H56;XpR^gCZ>burYSUwLcNH>I?L&ch^NMbdyK7}jb5~E3GBLq* zx+~V_=O&KVZ@IRhK-s({tEP8ZV{Ca}P0pr$hAj(5HbeSw=xI!;RPF!;Bd?n1-i_g; zu%PCj-O! zec^KwiwF5V2u7mH1bzRX_|6Jk`nXO;Gl&~d1~<7F$hslqQI;49MlZ_;1yE@WlX_)P z`y`;qo<9hS%qzTP2jNeVSE&*G?~&Jvh0D!qIvln=a8O_-@bH*o65LD?g$ zDev6#bDN)U-uSg!Vz0bxn3Z_B-}uU}8*VsrHTK!2Bi|21);8QOW8b$otd0B_(Ql&B z!sHIcg8ZZ)n=9=p%3}k^z$i*EzLKe`LFt5zNqCM>+(1Bv0t_-aoYpI?-%^|dq~3dEprNv2qqF!}ew=A! zYn3+;a@5+^I2N_%1ghH2e$(x+h~-CWg0T{B%sJTK)!NvwZQb03ytSyluCCEi+u=Rs z9t56&NL#kI(KHV9$0q6$pV^{*i^U(s z?Y`1d9}4-wKIXTu^F+<4I+;tK-YQR2Mv*=$n?#Z#zh3ObB(aOJXV!mG3qEC(c@i)} zJ^`N;`2-$<5$!1_>$?iiqeL^>NtCv}u}6yPP03sXxwpYa3gdO`8^7 zf&b(QFvojQKbhWZBXWSp8{{D4kEn<^Ng8Kjw=9W3 zfg>}jVfbS&-m_x|uaE-}c!4imS*d&gQQyeEBfaiaNQRVS6ju;qA&yGHONud2l`5=W zbw_&*pi)n`QdI#DNgoeO$3<16GHrCF1@1wl0Yxx0>4lIxIti|n;zQP>ty+>*NT*|RQ~V=434YAU@BU$xC%?FY;WW}5*sKien0rIfuQ zeHi33B`+oITc@3IlDf%#Z=dqOs1h*^r78kjRR-A7bxu^kX6jfJRh1bWnT1cFMS@&Y zwkQcd3eik$05YPkSq`8lW6WfWk^>}_-yB!$2$X!@WTvPJ>8^|F-7Su2JCmfr@v4+xdV2lEKk;pBwuUJ7TOUC4x z{H>{)LnR;sh--{q=$EPn0}D~+ppjb;87@L{(B5CV!Xv3Nk=6_rnXSb_(^`-!8Rzx2 z#!yr76@!EP;^9j#y*3gtHZ&;bTyn{rw@uZJ_*ZSJ8@WBPjDPQTj8%(q?4CA`ayV^0 zs9h}s7e|an>Lw(CY1jC_9~CGxjqFcrKs zBWRi`JH+?ZyPWl?6M%>)J;RjzA%7BjVi60`R(8rYBZh=pK%{Sq5`q-zN^5x1d?$o! zsY;X4<0d7TKiSbT%lN@bdz5{_{KJFF!-;F3+O-bP|0a8j|3t~cLNQSWDS54gR6&Up zk}4vgpYrR6ly6%6F+1(U7H3p7;U~(!8qr%#y)&mt{s>FBkIG zimOo9Yh?BnE%TAKR$8e_3DR$>k_-7g;(1eYi*m9^ZslT~)5@n97FIlH!b!X^RYNQ- zw`RUGK4TPBls)IeC`M;LkuEeQ2UKErdgJw7+nn}RN~X`8Z)8*>_d3-Z# zoy{Cy7;<&y`1qX=q`6ro4irMG@7n6Li@ZOKSN@6d1tC{&Q03}?l&hL4Zb^1>HlRpS zR%#WJzBtx+N*^HI96NaF11ZTsTqMb``02!NxOc~nvJ9!FN>>mQD$9SNxl+{OqUwSZ zRDw-GY?q`P?H(b;D`Rb_{73arrA5{>wcv#uuX?rqSL#gb5x;AZ{3Poyup6jeVmZvL1|;(Iu~#RNMw_ZZL>YB0VqTrN zl5U(DT=h=PRqlf$=}sI$)={MLhO&+#U8SUXdR?oaagv;Js>UTjqLw;P(1Bv|lTUZkiSJ0CRF##DXr0_NEAffj;)ubPik3K*!f^!?rah$tJ;md$vy5J%O z_A*N@X2Ld`0;06x$d$S{N*zYG*UO((%QN!V)RK&eNz`PV#fOhxnQ`IR!i8#W#tpk< zjm8bTWR1pDp+*J20PzL*8R2KDjtAul$~Ylu2DFQ&3O!^U{aYxfL)!#EkQh8ew7-** zc)(gSKw>dd^tX-2n^1-eiVykTL~X?wFQrA#7CDX)jW#&rN}NLw~o{+j~KJiV5s_>$>Q<9xUT=( z%DWFgjGLduckfPpmzWf^+9?l3ruIYMg(Q#jyRYk8C%!D+y%yiU8sE=h?UVLtE#^f8cp!m#nV)Yr2~`N62@;l5p?qjTo&!t?j+d6?$5RB7ecD=%UVLGEzSp^!V} z!ih-2i{f=;aoG?Ql1`jxq=WP8>#NIxUVDKzUKc2>sd5(il@|@I9lBy&EZ^ALp*QN| zl;ldVTgh)$zDuy9=M&pHV$|?JrDY|Qqni^CDBm3%#LerKIKK+^G~^e_M3m4Gdg3`fXOfuhQnnBQX3iJmV(R<)!*XUEp)1XyTx#e;z10P2&`T6SPfkDcC}S z1xUwx4sI?!Vo3|4RXv+mRd~G>6+YklbhcJ`mB)RRRv(7rOP%FdzNWbOaT+~z2J8rw zHlz(>$;Kja;uU&~M~}ZPuR{YRMnv97sf*Ia31TT}je;DInHdycmIs}tVrOkR&c(&f zV7b-rw^sW78a@4y`C%glRb7q2VNe{uTT#JJ!c_(BEucN<6jZ?bQ(0nimjStK!VReA zCKoHs8ww44H6l*|K51S8QR)wLHF_8885mcA9I8*~eb^vS~;3GktL(2wh28GY!Jbq>CYVJ7D zyO&lb7Pgq{{-l%7$CZIur0f)X&7=`Wu*M9@50lzON&YAf*fkfFSSuT29=9c09@F$| zL$%H!N(*Fb6+hPcJD`>>TEj#%v}SPrH)~y}&EQm23 zwfG2Sc%@4AP=pcX3pJf6Me@)oy8PDGeBCLp>rjg1(+3-O zq$+`s{CA2^NsxJ`EZ}rq&4YL_xlG6_=*F392B6@rfDUQYv*UxrW&15xZ;Z0j(tbDZ^Pp?)Nx?J&-& zSgY$6`xbxDQ@14XJnA0+mCuIjQ5Zl}Ga)^=CV8*&tnxRIUlmkB?^@jt^-dof?9^io`SOq@RoWq6&9EKzNS~4NUtwhiXgp-Un<7J zR!C{U)8+afmTt602kQa@5vw&iR8w7F?+?_6l{?lh@^{ylqt0D*bzi8$JJ>%kJUB2g z1c=j``AqpEa+bnCZV&s3lm_jBe`61pT8obA+Eocek%UOa)uq3Ze1Hd71Nv*G_}+{J zjTwpB>W;QFUATxYT#_!@K^LT293)LcxM1nW0Zgo25Tpwf(jsVuI7=6KRoX4W^Nf>r10fPu&QyDRM?tM*q&3Eb6UH#Vs_i`?4iz@ z<{D?QJ>HPBdU1i->ZV<9&+7JEj5(1aP{lun{{6qyd?wi-!^@ejPfRnF14&NJH&WUD z{Nrg!{v5w7h~Gs;et8L-MGA|o8Ue`;9FbSQ5NE@YxDvK4mCmE6B>X)9E#x;AB;}i1 zIq_(9XT0Fhc>k+>u45PFoww=+D%TBNiwzRLjn~adJT0B5Z#9JaP(K}I1z^wLi~W9W za2Prv=E0Y#`l)YfB?QEHFedcK9XU?22LxZPQLj=QM^!!2c{M7j2|^;}g3?6~;yt;{ zEU1Mhf*oh*t5N%iFRMnRPmMi^9W{a}!_Z9EJK%@vkH>boxT~$Qsitv)vWx5M8^&x^ zO})i7YpAuSP_K9v&H4t_|IRB|V_h+PLF?+?D*dvnN;j_VX^ptnuMQ3Z>9o#}H?5)E z+5*sVBil!Q1nHTO+NJ!J17aE}!Z)!fCXkx9>VZhlTdmoU?wGNn+_a*gYmn1|GJwb~ zfH(v^B&VeWXDS*it#3V;eg*hc7%v5c$g3cukG^bm-x-A2)Pf>CCAC9MtT-Fz716f# zXtcGBZx8sYqnhvE$H#^OgTC>J9kcw)nwpk%c|6_An@;E-*tlXde|XcniA|K5eP(CZ ztiIT?H5C=JTj$mIP(B@*+r3ru=AXC&8+k#F$Tx>ci(hiQNcuTxw~x$t@QJGkU`C!G zP!#B>6!cv>6<6*e5Oie(9A+eS#ORI~0ZC>95cwQnT>uRgN;$w{xM~zvR0}YUr^hKd zYAPvWYKIp6s)z(wD(w~VX<_k9rQREbqZg!?qg0^8Vr{tAV-Goum65@qwa3?)TW0sw zl~hF?E^m8Nc6OxZj4bC{&H4VJiS`wnbNDNqSG!yubFs53Sm|!7Ezc{se3d@nDs@#_ zi%o5w`oW?ypDxz%*TlKlw}2#Pe)7<9b8FTuw1gOb|BUw6->A7+@qr}B$F>K*bvb#I z{xhfbpFMT|xzqa7&)H4=EK7aR)p3K;C(8TCRnzc5MbS(wyhMK}6vWY$;uKR8My(J9zp zItAms62_3p6;wwP{Z#^2U&n8*0f$(fOlcB0Bzv527$zLf=s$B>KjBc`f9|w?!lCTn zt@e|A+8~}Ekk3yZ5YI0||D25eGu3|Nr}AYQdcM5>T(ut_89tnG|8BLv9OHjnL-VD; zix$5lcf5GMs8uEIr}!Gp>&&C}pE<3c-Yf4vcUnKqOZM-c)=%%1{d?7ZQ9nm>6Z(-B zfcIViiXnK4dM;u-^xJ>Q0k>B1{Bz+bruSmk zmf{oRX;a4&68)m4fbuS$Lwk91*q&0HaQ~70XHM&XeCqylr}d|wvzz*19Es?e%jyR7SpizOofxBd7SoXMX;ua#F{48vPb+Dk6RQ~KEQgh%A2st|MSW= zQF<~g=akGkTHynfKo$}&&P&oO-dSu?S3Eq1w^7A|e_sz_PpTNgbT1knW@_}>;9aY% z^c|i+F@*n6ETJQ#Ou`g?U!20@UKNiX_~B4n0R8=f9==X4P~4CG`}`w8C$mKV9*RaB zrT@%n{X{47{&T1G6P?KZ-D*GahY|7oE9LWVlFvuW8#DUPl>PWMXU4lxdC!Mm?j^cC zSMC1{{Z$$F@0R^?Pn|;ZohR;(y^P1j&=Cpo#ue|@QKfPD>?^XN7J{sj6^rKV=#(%+k^1Wi8hZxTiIiAST`_G)#PvepIpF6Fe#v}W8 z%YK;yFW^T0I>3$G?U-)}aCc5;~JgMg5ffPcCt~mx?}+ zdx#Pc>FmOp`bpN(-#+#4YMkl2L7ao6I7!o-b_v8|qNa_@Y>86|D6{N?V^h6C$a9HZ zs|~pKdIDOM89J`D?O3Ptgvy1EdG=Kfhw{zYwb{?-l$Yl`pItk<=+5uyDsrC8DKFFh z>fLvLMcq$jSCHP_nS55$to$AfEd=ZiOrp%3f*<}S4J1c}lO5`@h(1td3M#NiuI5yx zUI(uFMc-UpMR7&EhH|PYS5NrsQs(hbEEYH&wS9$tkc$r?hAO z(8y&?jVO$@#_BhW>u=^luQ^7>S%QYvAA5mp0YZPX#C9hu*R zJ)&oUQ}MeGd<^J9g1M-PUIIIMuS^o6JWsjD*9FiLizoz`X}2+zEuq?>|ItUBw$jPL zl&Y^u4kXItqC{m2&Sa~D4uwUU+Waatc3Hxn(#@&jvx(BXQZ>}Om!7{OeBg(PH`)!$ zmmAt&xb)JDD(W|XA70{rbx@h-#2-5npQq}mE0`Hm+7SaO2fIYA8_EW!I-*{6NM_7e z=DUywoWjyFYm+iKDyDoVX!B_#@^_ixLcCh}K2Y5h^mV^zxn72{a^+H~8?ssm;E6yhuxgoZC`{olh z9hqe#VV{5JYEB4O?T!8YZ$W!PDUk z7Qri`9^e8wP-0ik(xrTuAOF>L{CHv?X8t{tDSr|+p^IXewAY%pSCH=L#*yA`durYNO8=i}_5hGM(}yrB2ymehYr|$&Md} zvRvV7q>uIGE|LkmSqSpd4{@l6zbKy0jX}Hv<06F6E|+r3#xWoTT}ny{*^yBzWrW}> zGBl0YAFZIwR1JP}rQc_>`KoyrEvv-q>Ys|gx{@N!mDP#Y7Tn~Q*U&cTw^2UFZ!EnJ z?YEwtBqJBJb2p4}kg%oSB_P+h5i5<>uvKKD?PVs1xlg32OCJZkpKjBsWjmb|O zvQ7=kyg*8m`&amY{q#F0(i6O7V?%zGGZ-ms+7#F1l$Q9)bF{g++5(-fy04~|2bP6f zvUNo|OSz@oP>ziQ``-?gIz5fe$;4MWyU}c^%{S@u^ab(qS&h-n%}t}nk9aFArjAA1 z`+yzL$R+qK<)112|&Y#q`0BdASYYE!;*-7QRmP3bH-aJI@A*CNzt#7{B zdg#rTLqw|sXeN|f5jiu$uX61q)EHT_LuRW`bbyEy0X887>9>z{Fp(P2N58U_qKg@u zT+=b!^iK@ZLV(D}BPWR_;K?DLMN1+FBxuH2howtiRtiPXOU&XWs$*JY+xn5MMk!3D z%wGx2N&QS-%aU%>w?_Ut@d=u12onbT+uROJ@umz0#0&l~6(*|Al* zHE~y-Qdz0V=Ox<0%9?E2+H?52hHbU(wx(!>uO>?~ly5HfMA{o-8@dU)1IfQ?PFLYo zi5c83cb=4qNs$_Jbco4aDaEj6Z7Sqs-iO>-lRItSe;SsVprgDnnRAx{Vj6V%DbUG~ z7VSr)408wA31R7|02F)DJ&<{EZ8SCmU_(R0k3E0w#YY8D;`I;ePChyG{s%XJ;4rKq zUdRXW+kyD)u{70y=cWdloZB#mTD4IZT6feK`Jnb1tM`0M|D z^*lrws#KQFk@Y-swB_-l;cIKB7xd`niBG7Y$HJkGVt*+rdT6}Zu>Zo*OM0NNT^6el z>)|%ITbmHy>t}CHqIjAj6l&7I;rbS4U`#|CC~zXLAS?hq=Xfj(?oR;#6uW-mX7Ki*6HYT9yp zv9+TN;nKE&@{+=$k_uy0Lw&WbytpnL^b{8tfjy1%bj{{xN#3O{MgHfku&=DfQ5>i= znzA}_>s$_>rn<^$_iB4`OO5vWSfKw#;$Iod6Lo}mHXp~@j8R=as$%EH)G4>#t=6e4 z`+thN`rxRpDt?k(vLS?oZayF(gv$cShU_lMvYSmdAx$=56KXOwq$t>F-H#Xc!RGDu zy|;wm*r{!;T1TeiAB=;wgVABIj##m3r=!?1SP`|-T4}9_h!n9RDk9_L560iQ@1;pf zbe!=IcV~Cc-j8$7`Q7vGyZ4;?-m@{E##vZuv&PXj=PGNx>p4|d;^eFU|f0t z&-SXPpmmQg?)GUt?THKQ##)YB*Zc5v1<_HSu2?4+`>s!O`ja0*+g$3s^-@}EZm4uG zb63}F?T-!BwU0y!2EzLKEn0h1vukkC(u#(*-q4D+_D;k^FfW$(9*};W9Y76!R`$Et zuMs+0P+4%eFj{!YQR;{~(vGJcXB<;bw=?S8=6u$9WkJ`1Q$>YExuOfMBG-}P+TwKa zvEnxuIv1{6xW8mm$^J#Pi_AqoEnQRkQ0eu>k1ak`R$2CB+3V$_gS2 zx3~}B5`p(u9ItGzoUA-oMOAfGJyjp6GOM1d4pbkio?5zh>6K+$YHDi^)?BUasXbbI zaru*VrFFaNrdI4*alU@2{@}`@mBTAfh%RwJoLSYqYGl<(4|%qE&a95DPOR~)`PABy zwc6UJ)?RJ!HuN{78w(rvH%>NQ_KtY>cn^Eec>med-}L#Wv+KHX>pQdgbIr$^FZ$dF zRDH;|&-bFg#2@oN>_6gv%YQAfH*jo8hKx2IC6hvS7cA*k;wkY!N}prvB>er>B!mk zRQps%b;sq7ThUzfT6C(@)2Ven-xcjT)OB*>eH$-#S9cG0U%KOXzB9 zr{WWXy#cX3n-_6i5otwN5))#l9@k7IC31>BrW%Ht)kI!PDY}SfGP79a^lVO76>~z! z_6%WWMcx3*Bt-Cuv202m#jlZ1WYnahagL#6GCmR4QbJc!DnwEfc~cQ)S`ndHocq#o z-9&p{y-AErzUp~!0Es+k5e z2*AxJO=#CCpvoRKrKEfiC2rzNHH4NmA+`XOQASOnYGyoX3Shw~Kt)wCM0OPFCDU`H zLj8B)ZUiWLJf)1q_1(-Vp4_cv$1@6$Pl>o8jC6Kf6A2}g9iQf$*CcQ%3d}TO>uSSd zLn5Jw3QufcWb4TA=H5Zk*WWulvUymx1O;~jVf1KfmJAU1UE!oHcxV7 zk=BaXe>*;YNp)bF<3nl;B}_8#(Mh2=9=0yvCe*+uAoKfVT0(M4ftMmv2QfhkpyYP6 zlgDpd))r_#c}EI%RXG0-X097R3OGf*ypwp5f-Ai;DU{$&}s49m`PGcsJ) zLPwNE0)>bp+KfqP{SQn(LO z5;v|HM=1**#to1AKq;=rXbb#uS_br}EXSIgsKdM&54MYGTd;bOb>%u))UbLliB<&u z&5xDU{_WP?D7mn;$ECz$_|<7QI9W2W47;VY<5E7$=GhA3vZf(X8J7|!AX5hIk0W=k z%xu#$7RRzPhxs&_+plx2Wp2ODXc`4C502ac^!!$QhT;0?MQoXm`+iWvNZX9>8J(;i z+$nXmY|)ZvJ{&BBZ%1xsT=1Zs*^OzBJEohXAlWC{FSZg`9FWG}Q(Hd-?Z@`Xg zFNU6V@K*V73JAb&*aAp{SlEWJqH2R*n@#-7ZE3amY$|V^alN&zC_=oPt%X-M;MyFj>GJzJhV^IY5EDS z{QVidLO;hqafV*SDd`vV4Z1|H(=TDdXW`ko3`5%u^W9}1vV4Lu=s^rbdvIXqX)g@< zqws_8gYW-s?1p)mK91cuFVG+0xBLu!g`S|l&>!i~^e4JPk77mk4z4c!E8U=f(BE(` fx@&Zk{!Z8FY8mE;YBq)Got$YDjm49CRwMcs`(g+? diff --git a/apps/frontend/src/components/launches/providers/medium/fonts/Charter Italic.ttf b/apps/frontend/src/components/launches/providers/medium/fonts/Charter Italic.ttf deleted file mode 100755 index a65012142b936d695290fe0530c82d86d7edc421..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40796 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 diff --git a/apps/frontend/src/components/launches/providers/medium/fonts/stylesheet.css b/apps/frontend/src/components/launches/providers/medium/fonts/stylesheet.css deleted file mode 100755 index 2c0106c2..00000000 --- a/apps/frontend/src/components/launches/providers/medium/fonts/stylesheet.css +++ /dev/null @@ -1,37 +0,0 @@ -/* Generated by Font Squirrel (http://www.fontsquirrel.com) on July 10, 2013 */ - -@font-face { - font-family: 'charterbold_italic'; - src: url('charter_bold_italic-webfont.eot'); - src: url('charter_bold_italic-webfont.eot?#iefix') format('embedded-opentype'), - url('charter_bold_italic-webfont.woff') format('woff'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'charterbold'; - src: url('charter_bold-webfont.eot'); - src: url('charter_bold-webfont.eot?#iefix') format('embedded-opentype'), - url('charter_bold-webfont.woff') format('woff'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'charteritalic'; - src: url('charter_italic-webfont.eot'); - src: url('charter_italic-webfont.eot?#iefix') format('embedded-opentype'), - url('charter_italic-webfont.woff') format('woff'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'charterregular'; - src: url('charter_regular-webfont.eot'); - src: url('charter_regular-webfont.eot?#iefix') format('embedded-opentype'), - url('charter_regular-webfont.woff') format('woff'); - font-weight: normal; - font-style: normal; -} diff --git a/apps/frontend/src/components/launches/providers/medium/medium.provider.tsx b/apps/frontend/src/components/launches/providers/medium/medium.provider.tsx deleted file mode 100644 index bc085e91..00000000 --- a/apps/frontend/src/components/launches/providers/medium/medium.provider.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { FC } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { Input } from '@gitroom/react/form/input'; -import { MediumPublications } from '@gitroom/frontend/components/launches/providers/medium/medium.publications'; -import { MediumTags } from '@gitroom/frontend/components/launches/providers/medium/medium.tags'; -import { MediumSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/medium.settings.dto'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import clsx from 'clsx'; -import MDEditor from '@uiw/react-md-editor'; -import localFont from 'next/font/local'; -import { Canonical } from '@gitroom/react/form/canonical'; -import interClass from '@gitroom/react/helpers/inter.font'; -const charter = localFont({ - src: [ - { - path: './fonts/Charter Regular.ttf', - weight: 'normal', - style: 'normal', - }, - { - path: './fonts/Charter Italic.ttf', - weight: 'normal', - style: 'italic', - }, - { - path: './fonts/Charter Bold.ttf', - weight: '700', - style: 'normal', - }, - { - path: './fonts/Charter Bold Italic.ttf', - weight: '700', - style: 'italic', - }, - ], -}); -const MediumPreview: FC = () => { - const { value } = useIntegration(); - const settings = useSettings(); - const [title, subtitle] = settings.watch(['title', 'subtitle']); - return ( -
-
-
{title}
-
- {subtitle} -
-
-
- p.content).join('\n')} - /> -
-
- ); -}; -const MediumSettings: FC = () => { - const form = useSettings(); - const { date } = useIntegration(); - return ( - <> - - - -
- -
-
- -
- - ); -}; -export default withProvider(MediumSettings, MediumPreview, MediumSettingsDto); diff --git a/apps/frontend/src/components/launches/providers/medium/medium.publications.tsx b/apps/frontend/src/components/launches/providers/medium/medium.publications.tsx deleted file mode 100644 index 9ae07e55..00000000 --- a/apps/frontend/src/components/launches/providers/medium/medium.publications.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const MediumPublications: FC<{ - name: string; - onChange: (event: { - target: { - value: string; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name } = props; - const t = useT(); - - const customFunc = useCustomProviderFunction(); - const [publications, setOrgs] = useState([]); - const { getValues } = useSettings(); - const [currentMedia, setCurrentMedia] = useState(); - const onChangeInner = (event: { - target: { - value: string; - name: string; - }; - }) => { - setCurrentMedia(event.target.value); - onChange(event); - }; - useEffect(() => { - customFunc.get('publications').then((data) => setOrgs(data)); - const settings = getValues()[props.name]; - if (settings) { - setCurrentMedia(settings); - } - }, []); - if (!publications.length) { - return null; - } - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/providers/medium/medium.tags.tsx b/apps/frontend/src/components/launches/providers/medium/medium.tags.tsx deleted file mode 100644 index b8c3fab2..00000000 --- a/apps/frontend/src/components/launches/providers/medium/medium.tags.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { ReactTags } from 'react-tag-autocomplete'; -import interClass from '@gitroom/react/helpers/inter.font'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; - -export const MediumTags: FC<{ - name: string; - label: string; - onChange: (event: { - target: { - value: any[]; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name, label } = props; - const { getValues } = useSettings(); - const [tagValue, setTagValue] = useState([]); - const [suggestions, setSuggestions] = useState(''); - const t = useT(); - - const onDelete = useCallback( - (tagIndex: number) => { - const modify = tagValue.filter((_, i) => i !== tagIndex); - setTagValue(modify); - onChange({ - target: { - value: modify, - name, - }, - }); - }, - [tagValue] - ); - const onAddition = useCallback( - (newTag: any) => { - if (tagValue.length >= 3) { - return; - } - const modify = [...tagValue, newTag]; - setTagValue(modify); - onChange({ - target: { - value: modify, - name, - }, - }); - }, - [tagValue] - ); - useEffect(() => { - const settings = getValues()[props.name]; - if (settings) { - setTagValue(settings); - } - }, []); - const suggestionsArray = useMemo(() => { - return [ - ...tagValue, - { - label: suggestions, - value: suggestions, - }, - ].filter((f) => f.label); - }, [suggestions, tagValue]); - return ( -
-
{label}
- -
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/nostr/nostr.provider.tsx b/apps/frontend/src/components/launches/providers/nostr/nostr.provider.tsx deleted file mode 100644 index e4b05986..00000000 --- a/apps/frontend/src/components/launches/providers/nostr/nostr.provider.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -export default withProvider( - null, - undefined, - undefined, - async () => { - return true; - }, - undefined -); diff --git a/apps/frontend/src/components/launches/providers/pinterest/pinterest.board.tsx b/apps/frontend/src/components/launches/providers/pinterest/pinterest.board.tsx deleted file mode 100644 index 1618e2cf..00000000 --- a/apps/frontend/src/components/launches/providers/pinterest/pinterest.board.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const PinterestBoard: FC<{ - name: string; - onChange: (event: { - target: { - value: string; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name } = props; - const t = useT(); - - const customFunc = useCustomProviderFunction(); - const [orgs, setOrgs] = useState(); - const { getValues } = useSettings(); - const [currentMedia, setCurrentMedia] = useState(); - const onChangeInner = (event: { - target: { - value: string; - name: string; - }; - }) => { - setCurrentMedia(event.target.value); - onChange(event); - }; - useEffect(() => { - customFunc.get('boards').then((data) => setOrgs(data)); - const settings = getValues()[props.name]; - if (settings) { - setCurrentMedia(settings); - } - }, []); - if (!orgs) { - return null; - } - if (!orgs.length) { - return 'No boards found, you have to create a board first'; - } - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/providers/pinterest/pinterest.provider.tsx b/apps/frontend/src/components/launches/providers/pinterest/pinterest.provider.tsx deleted file mode 100644 index ee97a378..00000000 --- a/apps/frontend/src/components/launches/providers/pinterest/pinterest.provider.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { FC } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { PinterestBoard } from '@gitroom/frontend/components/launches/providers/pinterest/pinterest.board'; -import { PinterestSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/pinterest.dto'; -import { Input } from '@gitroom/react/form/input'; -import { ColorPicker } from '@gitroom/react/form/color.picker'; -const PinterestSettings: FC = () => { - const { register, control } = useSettings(); - return ( -
- - - - -
- ); -}; -export default withProvider( - PinterestSettings, - undefined, - PinterestSettingsDto, - async ([firstItem, ...otherItems]) => { - const isMp4 = firstItem?.find((item) => item.path.indexOf('mp4') > -1); - const isPicture = firstItem?.find( - (item) => item.path.indexOf('mp4') === -1 - ); - if (firstItem.length === 0) { - return 'Pinterest requires at least one media'; - } - if (isMp4 && firstItem.length !== 2 && !isPicture) { - return 'If posting a video to Pinterest you have to also include a cover image as second media'; - } - if (isMp4 && firstItem.length > 2) { - return 'If posting a video to Pinterest you can only have two media items'; - } - if (otherItems.length) { - return 'Pinterest can only have one post'; - } - if ( - firstItem.length > 1 && - firstItem.every((p) => p.path.indexOf('mp4') == -1) - ) { - const loadAll: Array<{ - width: number; - height: number; - }> = (await Promise.all( - firstItem.map((p) => { - return new Promise((resolve, reject) => { - const url = new Image(); - url.onload = function () { - // @ts-ignore - resolve({ width: this.width, height: this.height }); - }; - url.src = p.path; - }); - }) - )) as any; - const checkAllTheSameWidthHeight = loadAll.every((p, i, arr) => { - return p.width === arr[0].width && p.height === arr[0].height; - }); - if (!checkAllTheSameWidthHeight) { - return 'Pinterest requires all images to have the same width and height'; - } - } - return true; - }, - 500 -); diff --git a/apps/frontend/src/components/launches/providers/reddit/reddit.provider.tsx b/apps/frontend/src/components/launches/providers/reddit/reddit.provider.tsx deleted file mode 100644 index 287ffe14..00000000 --- a/apps/frontend/src/components/launches/providers/reddit/reddit.provider.tsx +++ /dev/null @@ -1,219 +0,0 @@ -import { FC, useCallback } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { useFormatting } from '@gitroom/frontend/components/launches/helpers/use.formatting'; -import { Subreddit } from '@gitroom/frontend/components/launches/providers/reddit/subreddit'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useFieldArray, useWatch } from 'react-hook-form'; -import { Button } from '@gitroom/react/form/button'; -import { - RedditSettingsDto, - RedditSettingsValueDto, -} from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/reddit.dto'; -import clsx from 'clsx'; -import { useMediaDirectory } from '@gitroom/react/helpers/use.media.directory'; -import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; -import MDEditor from '@uiw/react-md-editor'; -import interClass from '@gitroom/react/helpers/inter.font'; -import Image from 'next/image'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -const RenderRedditComponent: FC<{ - type: string; - images?: Array<{ - id: string; - path: string; - }>; -}> = (props) => { - const { value: topValue } = useIntegration(); - const showMedia = useMediaDirectory(); - const t = useT(); - - const { type, images } = props; - const [firstPost] = topValue; - switch (type) { - case 'self': - return ( - - ); - case 'link': - return ( -
- {t('link', 'Link')} -
- ); - case 'media': - return ( -
- ); - } - return <>; -}; -const RedditPreview: FC = (props) => { - const { value: topValue, integration } = useIntegration(); - const settings = useWatch({ - name: 'subreddit', - }) as Array; - const [, ...restOfPosts] = useFormatting(topValue, { - removeMarkdown: true, - saveBreaklines: true, - specialFunc: (text: string) => { - return text.slice(0, 280); - }, - }); - if (!settings || !settings.length) { - return <>Please add at least one Subreddit from the settings; - } - return ( -
- {settings - .filter(({ value }) => value?.subreddit) - .map(({ value }, index) => ( -
-
-
-
-
-
- {value.subreddit} -
-
{integration?.name}
-
-
-
- {value.title} -
- -
- {restOfPosts.map((p, index) => ( -
-
- x - x -
-
-
- {integration?.name} -
- -
-
- ))} -
-
-
- ))} -
- ); -}; -const RedditSettings: FC = () => { - const { register, control } = useSettings(); - const { fields, append, remove } = useFieldArray({ - control, - // control props comes from useForm (optional: if you are using FormContext) - name: 'subreddit', // unique name for your Field Array - }); - const t = useT(); - - const addField = useCallback(() => { - append({}); - }, [fields, append]); - const deleteField = useCallback( - (index: number) => async () => { - if ( - !(await deleteDialog( - t( - 'are_you_sure_you_want_to_delete_this_subreddit', - 'Are you sure you want to delete this Subreddit?' - ) - )) - ) - return; - remove(index); - }, - [fields, remove] - ); - return ( - <> -
- {fields.map((field, index) => ( -
-
- x -
- -
- ))} -
- - {fields.length === 0 && ( -
- {t( - 'please_add_at_least_one_subreddit', - 'Please add at least one Subreddit' - )} -
- )} - - ); -}; -export default withProvider( - RedditSettings, - RedditPreview, - RedditSettingsDto, - undefined, - 10000 -); diff --git a/apps/frontend/src/components/launches/providers/reddit/subreddit.tsx b/apps/frontend/src/components/launches/providers/reddit/subreddit.tsx deleted file mode 100644 index 4eb104e2..00000000 --- a/apps/frontend/src/components/launches/providers/reddit/subreddit.tsx +++ /dev/null @@ -1,283 +0,0 @@ -import { FC, FormEvent, useCallback, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Input } from '@gitroom/react/form/input'; -import { useDebouncedCallback } from 'use-debounce'; -import { Button } from '@gitroom/react/form/button'; -import clsx from 'clsx'; -import { MultiMediaComponent } from '@gitroom/frontend/components/media/media.component'; -import { useWatch } from 'react-hook-form'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { Canonical } from '@gitroom/react/form/canonical'; -import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const RenderOptions: FC<{ - options: Array<'self' | 'link' | 'media'>; - onClick: (current: 'self' | 'link' | 'media') => void; - value: 'self' | 'link' | 'media'; -}> = (props) => { - const { options, onClick, value } = props; - const mapValues = useMemo(() => { - return options.map((p) => ({ - children: ( - <> - {p === 'self' - ? 'Post' - : p === 'link' - ? 'Link' - : p === 'media' - ? 'Media' - : ''} - - ), - id: p, - onClick: () => onClick(p), - })); - }, [options]); - return ( -
- {mapValues.map((p) => ( -
- ); -}; -export const Subreddit: FC<{ - onChange: (event: { - target: { - name: string; - value: { - id: string; - name: string; - }; - }; - }) => void; - name: string; -}> = (props) => { - const { onChange, name } = props; - const state = useSettings(); - const t = useT(); - - const { date } = useIntegration(); - const split = name.split('.'); - const [loading, setLoading] = useState(false); - // @ts-ignore - const errors = state?.formState?.errors?.[split?.[0]]?.[split?.[1]]?.value; - const [results, setResults] = useState([]); - const func = useCustomProviderFunction(); - const value = useWatch({ - name, - }); - const [searchValue, setSearchValue] = useState(''); - const setResult = (result: { id: string; name: string }) => async () => { - setLoading(true); - setSearchValue(''); - const restrictions = await func.get('restrictions', { - subreddit: result.name, - }); - onChange({ - target: { - name, - value: { - ...restrictions, - type: restrictions.allow[0], - media: [], - }, - }, - }); - setLoading(false); - }; - const setTitle = useCallback( - (e: any) => { - onChange({ - target: { - name, - value: { - ...value, - title: e.target.value, - }, - }, - }); - }, - [value] - ); - const setType = useCallback( - (e: string) => { - onChange({ - target: { - name, - value: { - ...value, - type: e, - }, - }, - }); - }, - [value] - ); - const setMedia = useCallback( - (e: any) => { - onChange({ - target: { - name, - value: { - ...value, - media: e.target.value.map((p: any) => p), - }, - }, - }); - }, - [value] - ); - const setURL = useCallback( - (e: any) => { - onChange({ - target: { - name, - value: { - ...value, - url: e.target.value, - }, - }, - }); - }, - [value] - ); - const setFlair = useCallback( - (e: any) => { - onChange({ - target: { - name, - value: { - ...value, - flair: value.flairs.find((p: any) => p.id === e.target.value), - }, - }, - }); - }, - [value] - ); - const search = useDebouncedCallback( - useCallback(async (e: FormEvent) => { - // @ts-ignore - setResults([]); - // @ts-ignore - if (!e.target.value) { - return; - } - // @ts-ignore - const results = await func.get('subreddits', { word: e.target.value }); - // @ts-ignore - setResults(results); - }, []), - 500 - ); - return ( -
- {value?.subreddit ? ( - <> - -
- -
- - - {value.type === 'link' && ( - - )} - {value.type === 'media' && ( -
-
-
- -
-
- )} - - ) : ( -
- { - // @ts-ignore - setSearchValue(e.target.value); - await search(e); - }} - /> - {!!results.length && !loading && ( -
- {results.map((r: { id: string; name: string }) => ( -
- {r.name} -
- ))} -
- )} -
- )} -
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/show.all.providers.tsx b/apps/frontend/src/components/launches/providers/show.all.providers.tsx deleted file mode 100644 index 445f496e..00000000 --- a/apps/frontend/src/components/launches/providers/show.all.providers.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import { FC } from 'react'; -import { Integrations } from '@gitroom/frontend/components/launches/calendar.context'; -import DevtoProvider from '@gitroom/frontend/components/launches/providers/devto/devto.provider'; -import XProvider from '@gitroom/frontend/components/launches/providers/x/x.provider'; -import LinkedinProvider from '@gitroom/frontend/components/launches/providers/linkedin/linkedin.provider'; -import RedditProvider from '@gitroom/frontend/components/launches/providers/reddit/reddit.provider'; -import MediumProvider from '@gitroom/frontend/components/launches/providers/medium/medium.provider'; -import HashnodeProvider from '@gitroom/frontend/components/launches/providers/hashnode/hashnode.provider'; -import FacebookProvider from '@gitroom/frontend/components/launches/providers/facebook/facebook.provider'; -import InstagramProvider from '@gitroom/frontend/components/launches/providers/instagram/instagram.collaborators'; -import YoutubeProvider from '@gitroom/frontend/components/launches/providers/youtube/youtube.provider'; -import TiktokProvider from '@gitroom/frontend/components/launches/providers/tiktok/tiktok.provider'; -import PinterestProvider from '@gitroom/frontend/components/launches/providers/pinterest/pinterest.provider'; -import DribbbleProvider from '@gitroom/frontend/components/launches/providers/dribbble/dribbble.provider'; -import ThreadsProvider from '@gitroom/frontend/components/launches/providers/threads/threads.provider'; -import DiscordProvider from '@gitroom/frontend/components/launches/providers/discord/discord.provider'; -import SlackProvider from '@gitroom/frontend/components/launches/providers/slack/slack.provider'; -import MastodonProvider from '@gitroom/frontend/components/launches/providers/mastodon/mastodon.provider'; -import BlueskyProvider from '@gitroom/frontend/components/launches/providers/bluesky/bluesky.provider'; -import LemmyProvider from '@gitroom/frontend/components/launches/providers/lemmy/lemmy.provider'; -import WarpcastProvider from '@gitroom/frontend/components/launches/providers/warpcast/warpcast.provider'; -import TelegramProvider from '@gitroom/frontend/components/launches/providers/telegram/telegram.provider'; -import NostrProvider from '@gitroom/frontend/components/launches/providers/nostr/nostr.provider'; -import VkProvider from '@gitroom/frontend/components/launches/providers/vk/vk.provider'; -export const Providers = [ - { - identifier: 'devto', - component: DevtoProvider, - }, - { - identifier: 'x', - component: XProvider, - }, - { - identifier: 'linkedin', - component: LinkedinProvider, - }, - { - identifier: 'linkedin-page', - component: LinkedinProvider, - }, - { - identifier: 'reddit', - component: RedditProvider, - }, - { - identifier: 'medium', - component: MediumProvider, - }, - { - identifier: 'hashnode', - component: HashnodeProvider, - }, - { - identifier: 'facebook', - component: FacebookProvider, - }, - { - identifier: 'instagram', - component: InstagramProvider, - }, - { - identifier: 'instagram-standalone', - component: InstagramProvider, - }, - { - identifier: 'youtube', - component: YoutubeProvider, - }, - { - identifier: 'tiktok', - component: TiktokProvider, - }, - { - identifier: 'pinterest', - component: PinterestProvider, - }, - { - identifier: 'dribbble', - component: DribbbleProvider, - }, - { - identifier: 'threads', - component: ThreadsProvider, - }, - { - identifier: 'discord', - component: DiscordProvider, - }, - { - identifier: 'slack', - component: SlackProvider, - }, - { - identifier: 'mastodon', - component: MastodonProvider, - }, - { - identifier: 'bluesky', - component: BlueskyProvider, - }, - { - identifier: 'lemmy', - component: LemmyProvider, - }, - { - identifier: 'wrapcast', - component: WarpcastProvider, - }, - { - identifier: 'telegram', - component: TelegramProvider, - }, - { - identifier: 'nostr', - component: NostrProvider, - }, - { - identifier: 'vk', - component: VkProvider, - }, -]; -export const ShowAllProviders: FC<{ - integrations: Integrations[]; - hideEditOnlyThis: boolean; - value: Array<{ - content: string; - id?: string; - }>; - selectedProvider?: Integrations; -}> = (props) => { - const { integrations, value, selectedProvider, hideEditOnlyThis } = props; - return ( - <> - {integrations.map((integration) => { - const { component: ProviderComponent } = Providers.find( - (provider) => provider.identifier === integration.identifier - ) || { - component: null, - }; - if ( - !ProviderComponent || - integrations.map((p) => p.id).indexOf(selectedProvider?.id!) === -1 - ) { - return null; - } - return ( - - ); - })} - - ); -}; diff --git a/apps/frontend/src/components/launches/providers/slack/slack.channel.select.tsx b/apps/frontend/src/components/launches/providers/slack/slack.channel.select.tsx deleted file mode 100644 index 33207c60..00000000 --- a/apps/frontend/src/components/launches/providers/slack/slack.channel.select.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const SlackChannelSelect: FC<{ - name: string; - onChange: (event: { - target: { - value: string; - name: string; - }; - }) => void; -}> = (props) => { - const { onChange, name } = props; - const t = useT(); - const customFunc = useCustomProviderFunction(); - const [publications, setOrgs] = useState([]); - const { getValues } = useSettings(); - const [currentMedia, setCurrentMedia] = useState(); - const onChangeInner = (event: { - target: { - value: string; - name: string; - }; - }) => { - setCurrentMedia(event.target.value); - onChange(event); - }; - useEffect(() => { - customFunc.get('channels').then((data) => setOrgs(data)); - const settings = getValues()[props.name]; - if (settings) { - setCurrentMedia(settings); - } - }, []); - if (!publications.length) { - return null; - } - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/providers/slack/slack.provider.tsx b/apps/frontend/src/components/launches/providers/slack/slack.provider.tsx deleted file mode 100644 index 19e4d2ce..00000000 --- a/apps/frontend/src/components/launches/providers/slack/slack.provider.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { FC } from 'react'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { SlackChannelSelect } from '@gitroom/frontend/components/launches/providers/slack/slack.channel.select'; -import { SlackDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/slack.dto'; -const SlackComponent: FC = () => { - const form = useSettings(); - return ( -
- -
- ); -}; -export default withProvider( - SlackComponent, - undefined, - SlackDto, - undefined, - 280 -); diff --git a/apps/frontend/src/components/launches/providers/telegram/telegram.provider.tsx b/apps/frontend/src/components/launches/providers/telegram/telegram.provider.tsx deleted file mode 100644 index 8b10b657..00000000 --- a/apps/frontend/src/components/launches/providers/telegram/telegram.provider.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -export default withProvider( - null, - undefined, - undefined, - async () => { - return true; - }, - 4096 -); diff --git a/apps/frontend/src/components/launches/providers/threads/threads.provider.tsx b/apps/frontend/src/components/launches/providers/threads/threads.provider.tsx deleted file mode 100644 index cde5fbd6..00000000 --- a/apps/frontend/src/components/launches/providers/threads/threads.provider.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { ThreadFinisher } from '@gitroom/frontend/components/launches/finisher/thread.finisher'; -const SettingsComponent = () => { - return ; -}; - -export default withProvider( - SettingsComponent, - undefined, - undefined, - async () => { - return true; - }, - 500 -); diff --git a/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx b/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx deleted file mode 100644 index ff8908c5..00000000 --- a/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx +++ /dev/null @@ -1,370 +0,0 @@ -import { - FC, - ReactEventHandler, - useCallback, - useEffect, - useMemo, - useState, -} from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { Select } from '@gitroom/react/form/select'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Checkbox } from '@gitroom/react/form/checkbox'; -import clsx from 'clsx'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; - -const CheckTikTokValidity: FC<{ - picture: string; -}> = (props) => { - const { register } = useSettings(); - const t = useT(); - - const func = useCustomProviderFunction(); - const [maxVideoLength, setMaxVideoLength] = useState(0); - const [isValidVideo, setIsValidVideo] = useState( - undefined - ); - const registerVideo = register('isValidVideo'); - const video = useMemo(() => { - return props.picture; - }, [props.picture]); - useEffect(() => { - loadStats(); - }, []); - const loadStats = useCallback(async () => { - const { maxDurationSeconds } = await func.get('maxVideoLength'); - // setMaxVideoLength(5); - setMaxVideoLength(maxDurationSeconds); - }, []); - const loadVideo: ReactEventHandler = useCallback( - (e) => { - // @ts-ignore - setIsValidVideo(e.target.duration <= maxVideoLength); - registerVideo.onChange({ - target: { - name: 'isValidVideo', - // @ts-ignore - value: String(e.target.duration <= maxVideoLength), - }, - }); - }, - [maxVideoLength, registerVideo] - ); - if (!maxVideoLength || !video || video.indexOf('mp4') === -1) { - return null; - } - return ( - <> - {isValidVideo === false && ( -
- {t( - 'video_length_is_invalid_must_be_up_to', - 'Video length is invalid, must be up to' - )} - {maxVideoLength} - {t('seconds', 'seconds')} -
- )} - - - ); -}; -const TikTokSettings: FC<{ - values?: any; -}> = (props) => { - const { watch, register, formState, control } = useSettings(); - const t = useT(); - - const disclose = watch('disclose'); - const brand_organic_toggle = watch('brand_organic_toggle'); - const brand_content_toggle = watch('brand_content_toggle'); - const content_posting_method = watch('content_posting_method'); - const isUploadMode = content_posting_method === 'UPLOAD'; - - const privacyLevel = [ - { - value: 'PUBLIC_TO_EVERYONE', - label: t('public_to_everyone', 'Public to everyone'), - }, - { - value: 'MUTUAL_FOLLOW_FRIENDS', - label: t('mutual_follow_friends', 'Mutual follow friends'), - }, - { - value: 'FOLLOWER_OF_CREATOR', - label: t('follower_of_creator', 'Follower of creator'), - }, - { - value: 'SELF_ONLY', - label: t('self_only', 'Self only'), - }, - ]; - const contentPostingMethod = [ - { - value: 'DIRECT_POST', - label: t( - 'post_content_directly_to_tiktok', - 'Post content directly to TikTok' - ), - }, - { - value: 'UPLOAD', - label: t( - 'upload_content_to_tiktok_without_posting', - 'Upload content to TikTok without posting it' - ), - }, - ]; - const yesNo = [ - { - value: 'yes', - label: t('yes', 'Yes'), - }, - { - value: 'no', - label: t('no', 'No'), - }, - ]; - - return ( -
- - -
- {t( - 'choose_upload_without_posting_description', - `Choose upload without posting if you want to review and edit your content within TikTok's app before publishing. - This gives you access to TikTok's built-in editing tools and lets you make final adjustments before posting.` - )} -
- - -
- {t( - 'this_feature_available_only_for_photos', - 'This feature available only for photos, it will add a default music that\n you can change later.' - )} -
-
-
- {t('allow_user_to', 'Allow User To:')} -
-
- - - -
-
-
- - {disclose && ( -
-
- - - -
-
- {t( - 'your_video_will_be_labeled_promotional', - 'Your video will be labeled "Promotional Content".' - )} -
- {t( - 'this_cannot_be_changed_once_posted', - 'This cannot be changed once your video is posted.' - )} -
-
- )} -
- {t( - 'turn_on_to_disclose_video_promotes', - 'Turn on to disclose that this video promotes goods or services in\n exchange for something of value. You video could promote yourself, a\n third party, or both.' - )} -
-
-
- -
- {t( - 'you_are_promoting_yourself', - 'You are promoting yourself or your own brand.' - )} -
- {t( - 'this_video_will_be_classified_brand_organic', - 'This video will be classified as Brand Organic.' - )} -
- -
- {t( - 'you_are_promoting_another_brand', - 'You are promoting another brand or a third party.' - )} -
- {t( - 'this_video_will_be_classified_branded_content', - 'This video will be classified as Branded Content.' - )} -
- {(brand_organic_toggle || brand_content_toggle) && ( -
- {t( - 'by_posting_you_agree_to_tiktoks', - "By posting, you agree to TikTok's" - )} - {[ - brand_organic_toggle || brand_content_toggle ? ( - - {t('music_usage_confirmation', 'Music Usage Confirmation')} - - ) : undefined, - brand_content_toggle ? <> {t('and', 'and')} : undefined, - brand_content_toggle ? ( - - {t('branded_content_policy', 'Branded Content Policy')} - - ) : undefined, - ].filter((f) => f)} -
- )} -
-
- ); -}; -export default withProvider( - TikTokSettings, - undefined, - TikTokDto, - async (items) => { - const [firstItems] = items; - if (items.length !== 1) { - return 'Tiktok items should be one'; - } - if (firstItems.length === 0) { - return 'No video / images selected'; - } - if ( - firstItems.length > 1 && - firstItems?.some((p) => p?.path?.indexOf('mp4') > -1) - ) { - return 'Only pictures are supported when selecting multiple items'; - } else if ( - firstItems?.length !== 1 && - firstItems?.[0]?.path?.indexOf('mp4') > -1 - ) { - return 'You need one media'; - } - return true; - }, - 2000 -); diff --git a/apps/frontend/src/components/launches/providers/vk/vk.provider.tsx b/apps/frontend/src/components/launches/providers/vk/vk.provider.tsx deleted file mode 100644 index dc3939fd..00000000 --- a/apps/frontend/src/components/launches/providers/vk/vk.provider.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -export default withProvider( - null, - undefined, - undefined, - async (posts) => { - return true; - }, - 2048 -); diff --git a/apps/frontend/src/components/launches/providers/warpcast/subreddit.tsx b/apps/frontend/src/components/launches/providers/warpcast/subreddit.tsx deleted file mode 100644 index bbacbe2c..00000000 --- a/apps/frontend/src/components/launches/providers/warpcast/subreddit.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { FC, FormEvent, useCallback, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; -import { Input } from '@gitroom/react/form/input'; -import { useDebouncedCallback } from 'use-debounce'; -import { useWatch } from 'react-hook-form'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -export const Subreddit: FC<{ - onChange: (event: { - target: { - name: string; - value: { - id: string; - subreddit: string; - title: string; - name: string; - url: string; - body: string; - media: any[]; - }; - }; - }) => void; - name: string; -}> = (props) => { - const { onChange, name } = props; - const state = useSettings(); - const split = name.split('.'); - const [loading, setLoading] = useState(false); - // @ts-ignore - const errors = state?.formState?.errors?.[split?.[0]]?.[split?.[1]]?.value; - const [results, setResults] = useState([]); - const func = useCustomProviderFunction(); - const value = useWatch({ - name, - }); - const [searchValue, setSearchValue] = useState(''); - const setResult = (result: { id: string; name: string }) => async () => { - setLoading(true); - setSearchValue(''); - onChange({ - target: { - name, - value: { - id: String(result.id), - subreddit: result.name, - title: '', - name: '', - url: '', - body: '', - media: [], - }, - }, - }); - setLoading(false); - }; - const setTitle = useCallback( - (e: any) => { - onChange({ - target: { - name, - value: { - ...value, - title: e.target.value, - }, - }, - }); - }, - [value] - ); - const setURL = useCallback( - (e: any) => { - onChange({ - target: { - name, - value: { - ...value, - url: e.target.value, - }, - }, - }); - }, - [value] - ); - const search = useDebouncedCallback( - useCallback(async (e: FormEvent) => { - // @ts-ignore - setResults([]); - // @ts-ignore - if (!e.target.value) { - return; - } - // @ts-ignore - const results = await func.get('subreddits', { word: e.target.value }); - // @ts-ignore - setResults(results); - }, []), - 500 - ); - return ( -
- {value?.subreddit ? ( - <> - - - ) : ( -
- { - // @ts-ignore - setSearchValue(e.target.value); - await search(e); - }} - /> - {!!results.length && !loading && ( -
- {results.map((r: { id: string; name: string }) => ( -
- {r.name} -
- ))} -
- )} -
- )} -
- ); -}; diff --git a/apps/frontend/src/components/launches/providers/warpcast/warpcast.provider.tsx b/apps/frontend/src/components/launches/providers/warpcast/warpcast.provider.tsx deleted file mode 100644 index f2714669..00000000 --- a/apps/frontend/src/components/launches/providers/warpcast/warpcast.provider.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { FC, useCallback } from 'react'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { useFieldArray } from 'react-hook-form'; -import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; -import { Button } from '@gitroom/react/form/button'; -import { Subreddit } from './subreddit'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -const WrapcastProvider: FC = () => { - const { register, control } = useSettings(); - const { fields, append, remove } = useFieldArray({ - control, - // control props comes from useForm (optional: if you are using FormContext) - name: 'subreddit', // unique name for your Field Array - }); - const t = useT(); - - const addField = useCallback(() => { - append({}); - }, [fields, append]); - const deleteField = useCallback( - (index: number) => async () => { - if ( - !(await deleteDialog( - t( - 'are_you_sure_you_want_to_delete_this_subreddit', - 'Are you sure you want to delete this Subreddit?' - ) - )) - ) - return; - remove(index); - }, - [fields, remove] - ); - return ( - <> -
- {fields.map((field, index) => ( -
-
- x -
- -
- ))} -
- - - ); -}; -export default withProvider( - WrapcastProvider, - undefined, - undefined, - async (list) => { - if ( - list.some((item) => item.some((field) => field.path.indexOf('mp4') > -1)) - ) { - return 'Warpcast can only accept images'; - } - return true; - }, - 800 -); diff --git a/apps/frontend/src/components/launches/providers/x/fonts/Chirp-Bold.woff2 b/apps/frontend/src/components/launches/providers/x/fonts/Chirp-Bold.woff2 deleted file mode 100644 index ed3a03d90aa33a1811ce8054dfcd7fe9f530e5d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45016 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

8A z|2<2;w??n-1zm*;y80IGM{%7~ye1j=|6uVw{LapLx&Ob~sD26k;iaIW*$;8yBj4I@ z$5E#)c4S}wzv9=xDTc8&GVo;TL5}1TnLRnUUUc#*UEY+*{`w7arv@fr1+1bKvcR)L%HCEcD}$BtO6URkk=*qsHiZaXMEA(zs=oU*|Bs&%zFx*!|5Q`q<*DE17|GAb z@$Lrm;N6dq%vc;>2Y!0-hzWgdJ+|6H-r(~%k{REZ>1ohLm6TEWP<8a!=fsVcD7_zv zauCcVf2rJ>XmhIm-20j&5-}I&?trL-ty zRn3l8Se%^qW?YOv*XV@xzM z6PN|@?2n&1_p=-bvhs>IiHE0e3S!j}k1 z#9r-7?q>U$5B5Q=9Bepnd`ND~GS%uiPEI_n6@@Kq#Of&RBj=0vtno_!cB^aj@mztv z8A`!d>L@VU+61}?sMJMu_&Yw4g7OTdAeTCzc#c3xKm{d{+y5jwi@t3He+_c{l$&be z{uzVjq>e`QJ|7=H`r)D)e5{{9_0*tY8;RW`_;P%7fvvpSPlNH}ptUxZ{|bAz`uYkx?8(IrZ|IWV!aH=&&UTO8Q+Mn3-;)53{cN7Tmc=fok>0-k z?sk;W>He#)zSZ>Kl`QcJZ^t!X?iB+R+U>lr#z2N^IOjm-ys6BFv^1pJaJ~DH+s{rT zZe?UABX= McMZR(H|V`S0F|4%2LJ#7 diff --git a/apps/frontend/src/components/launches/providers/x/x.provider.tsx b/apps/frontend/src/components/launches/providers/x/x.provider.tsx deleted file mode 100644 index 9573fc3a..00000000 --- a/apps/frontend/src/components/launches/providers/x/x.provider.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { ThreadFinisher } from '@gitroom/frontend/components/launches/finisher/thread.finisher'; -import { Select } from '@gitroom/react/form/select'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { XDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/x.dto'; -import { Input } from '@gitroom/react/form/input'; - -const whoCanReply = [ - { - label: 'Everyone', - value: 'everyone', - }, - { - label: 'Accounts you follow', - value: 'following', - }, - { - label: 'Mentioned accounts', - value: 'mentionedUsers', - }, - { - label: 'Subscribers', - value: 'subscribers', - }, - { - label: 'Verified accounts', - value: 'verified', - } -] - -const SettingsComponent = () => { - const t = useT(); - const { register, watch, setValue } = useSettings(); - - return ( - <> - - - - - - - ); -}; - -export default withProvider( - SettingsComponent, - undefined, - XDto, - async (posts, settings, additionalSettings: any) => { - const premium = additionalSettings?.find((p: any) => p?.title === 'Verified')?.value || false; - if (posts.some((p) => p.length > 4)) { - return 'There can be maximum 4 pictures in a post.'; - } - if ( - posts.some( - (p) => p.some((m) => m.path.indexOf('mp4') > -1) && p.length > 1 - ) - ) { - return 'There can be maximum 1 video in a post.'; - } - for (const load of posts.flatMap((p) => p.flatMap((a) => a.path))) { - if (load.indexOf('mp4') > -1) { - const isValid = await checkVideoDuration(load, premium); - if (!isValid) { - return 'Video duration must be less than or equal to 140 seconds.'; - } - } - } - return true; - }, - (settings) => { - if (settings?.[0]?.value) { - return 4000; - } - return 280; - } -); -const checkVideoDuration = async (url: string, isPremium = false): Promise => { - return new Promise((resolve, reject) => { - const video = document.createElement('video'); - video.src = url; - video.preload = 'metadata'; - video.onloadedmetadata = () => { - // Check if the duration is less than or equal to 140 seconds - const duration = video.duration; - if ((!isPremium && duration <= 140) || isPremium) { - resolve(true); // Video duration is acceptable - } else { - resolve(false); // Video duration exceeds 140 seconds - } - }; - video.onerror = () => { - reject(new Error('Failed to load video metadata.')); - }; - }); -}; diff --git a/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx b/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx deleted file mode 100644 index e636c93c..00000000 --- a/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { FC } from 'react'; -import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider'; -import { YoutubeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/youtube.settings.dto'; -import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; -import { Input } from '@gitroom/react/form/input'; -import { MediumTags } from '@gitroom/frontend/components/launches/providers/medium/medium.tags'; -import { MediaComponent } from '@gitroom/frontend/components/media/media.component'; -import { Select } from '@gitroom/react/form/select'; -const type = [ - { - label: 'Public', - value: 'public', - }, - { - label: 'Private', - value: 'private', - }, - { - label: 'Unlisted', - value: 'unlisted', - }, -]; -const YoutubeSettings: FC = () => { - const { register, control } = useSettings(); - return ( -

- - - -
- -
-
- ); -}; -export default withProvider( - YoutubeSettings, - undefined, - YoutubeSettingsDto, - async (items) => { - const [firstItems] = items; - if (items.length !== 1) { - return 'Youtube items should be one'; - } - if (items[0].length !== 1) { - return 'You need one media'; - } - if (firstItems[0].path.indexOf('mp4') === -1) { - return 'Item must be a video'; - } - return true; - }, - 5000 -); diff --git a/apps/frontend/src/components/launches/submitted.tsx b/apps/frontend/src/components/launches/submitted.tsx deleted file mode 100644 index daf899e7..00000000 --- a/apps/frontend/src/components/launches/submitted.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React, { FC, ReactNode, useCallback } from 'react'; -import { Button } from '@gitroom/react/form/button'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const Submitted: FC<{ - children: ReactNode; - postId: string; - status: 'YES' | 'NO' | 'WAITING_CONFIRMATION'; - updateOrder: () => void; -}> = (props) => { - const { postId, updateOrder, status, children } = props; - const fetch = useFetch(); - const t = useT(); - const cancel = useCallback(async () => { - if ( - !(await deleteDialog( - 'Are you sure you want to cancel this publication?', - 'Yes' - )) - ) { - return; - } - await fetch(`/marketplace/posts/${postId}/cancel`, { - method: 'POST', - }); - updateOrder(); - }, [postId]); - if (!status || status === 'NO') { - return <>{children}; - } - return ( - - ); -}; diff --git a/apps/frontend/src/components/launches/u.text.tsx b/apps/frontend/src/components/launches/u.text.tsx deleted file mode 100644 index aa268a15..00000000 --- a/apps/frontend/src/components/launches/u.text.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import { FC, useCallback } from 'react'; -import { Editor, Transforms } from 'slate'; -import { ReactEditor } from 'slate-react'; -const underlineMap = { - a: 'a̲', - b: 'b̲', - c: 'c̲', - d: 'd̲', - e: 'e̲', - f: 'f̲', - g: 'g̲', - h: 'h̲', - i: 'i̲', - j: 'j̲', - k: 'k̲', - l: 'l̲', - m: 'm̲', - n: 'n̲', - o: 'o̲', - p: 'p̲', - q: 'q̲', - r: 'r̲', - s: 's̲', - t: 't̲', - u: 'u̲', - v: 'v̲', - w: 'w̲', - x: 'x̲', - y: 'y̲', - z: 'z̲', - A: 'A̲', - B: 'B̲', - C: 'C̲', - D: 'D̲', - E: 'E̲', - F: 'F̲', - G: 'G̲', - H: 'H̲', - I: 'I̲', - J: 'J̲', - K: 'K̲', - L: 'L̲', - M: 'M̲', - N: 'N̲', - O: 'O̲', - P: 'P̲', - Q: 'Q̲', - R: 'R̲', - S: 'S̲', - T: 'T̲', - U: 'U̲', - V: 'V̲', - W: 'W̲', - X: 'X̲', - Y: 'Y̲', - Z: 'Z̲', - '1': '1̲', - '2': '2̲', - '3': '3̲', - '4': '4̲', - '5': '5̲', - '6': '6̲', - '7': '7̲', - '8': '8̲', - '9': '9̲', - '0': '0̲', -}; -const reverseMap = Object.fromEntries( - Object.entries(underlineMap).map(([key, value]) => [value, key]) -); -export const UText: FC<{ - editor: any; - currentValue: string; -}> = ({ editor }) => { - const mark = () => { - const selectedText = Editor.string(editor, editor.selection); - const setUnderline = selectedText.indexOf('̲') === -1; - const newText = Array.from( - !selectedText - ? prompt('What do you want to write?') || '' - : selectedText.replace(/̲/g, '') - ) - .map((char) => { - // @ts-ignore - return ((setUnderline ? underlineMap?.[char] : reverseMap?.[char]) || char); - }) - .join(''); - Transforms.insertText(editor, newText); - ReactEditor.focus(editor); - }; - return ( -
- - - - - - - - - - - -
- ); -}; diff --git a/apps/frontend/src/components/layout/continue.provider.tsx b/apps/frontend/src/components/layout/continue.provider.tsx index 4bed9d6c..a5ef400c 100644 --- a/apps/frontend/src/components/layout/continue.provider.tsx +++ b/apps/frontend/src/components/layout/continue.provider.tsx @@ -1,11 +1,11 @@ import React, { FC, useCallback, useMemo } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; -import { continueProviderList } from '@gitroom/frontend/components/launches/providers/continue-provider/list'; import { IntegrationContext } from '@gitroom/frontend/components/launches/helpers/use.integration'; import dayjs from 'dayjs'; import useSWR, { useSWRConfig } from 'swr'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; +import { continueProviderList } from '@gitroom/frontend/components/new-launch/providers/continue-provider/list'; export const Null: FC<{ closeModal: () => void; existingId: string[]; diff --git a/apps/frontend/src/components/marketplace/preview.popup.dynamic.tsx b/apps/frontend/src/components/marketplace/preview.popup.dynamic.tsx index 92322b0b..4b445458 100644 --- a/apps/frontend/src/components/marketplace/preview.popup.dynamic.tsx +++ b/apps/frontend/src/components/marketplace/preview.popup.dynamic.tsx @@ -1,7 +1,7 @@ import 'reflect-metadata'; import { FC } from 'react'; import { Post as PrismaPost } from '.prisma/client'; -import { Providers } from '@gitroom/frontend/components/launches/providers/show.all.providers'; +import { Providers } from '@gitroom/frontend/components/new-launch/providers/show.all.providers'; export const PreviewPopupDynamic: FC<{ postId: string; providerId: string; @@ -15,17 +15,5 @@ export const PreviewPopupDynamic: FC<{ const { component: ProviderComponent } = Providers.find( (p) => p.identifier === props.providerId )!; - return ( - ({ - id: p.id, - content: p.content, - image: p.image, - }))} - /> - ); + return null; }; diff --git a/apps/frontend/src/components/new-launch/add.edit.modal.inner.tsx b/apps/frontend/src/components/new-launch/add.edit.modal.inner.tsx deleted file mode 100644 index c7f53d08..00000000 --- a/apps/frontend/src/components/new-launch/add.edit.modal.inner.tsx +++ /dev/null @@ -1,99 +0,0 @@ -'use client'; - -import React, { FC, Fragment, useRef } from 'react'; -import { AddEditModalProps } from '@gitroom/frontend/components/new-launch/add.edit.modal'; -import clsx from 'clsx'; -import { TopTitle } from '@gitroom/frontend/components/new-launch/helpers/top.title.component'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -import { PicksSocialsComponent } from '@gitroom/frontend/components/new-launch/picks.socials.component'; -import { - Editor, - EditorWrapper, -} from '@gitroom/frontend/components/new-launch/editor'; -import { SelectCurrent } from '@gitroom/frontend/components/new-launch/select.current'; -import { ShowAllProviders } from '@gitroom/frontend/components/new-launch/providers/show.all.providers'; - -export const AddEditModalInnerInner: FC = () => { - const t = useT(); - const ref = useRef(null); - - return ( -
-
-
- -
asd
-
- - -
- -
-
- -
-
media
-
-
-
-
-
-
-
-
-
-
-
{ - console.log(await ref.current.checkAllValid()); - }} - > - test -
-
-
-
-
-
-
-
- - - - - -
-
- -
-
-
- ); -}; diff --git a/apps/frontend/src/components/new-launch/add.edit.modal.tsx b/apps/frontend/src/components/new-launch/add.edit.modal.tsx index 64b24c1b..d679a6be 100644 --- a/apps/frontend/src/components/new-launch/add.edit.modal.tsx +++ b/apps/frontend/src/components/new-launch/add.edit.modal.tsx @@ -3,11 +3,12 @@ import 'reflect-metadata'; import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; import dayjs from 'dayjs'; import type { CreatePostDto } from '@gitroom/nestjs-libraries/dtos/posts/create.post.dto'; -import { FC, useEffect, useState } from 'react'; -import { useExistingData } from '@gitroom/frontend/components/new-launch/helpers/use.existing.data'; +import { FC, useEffect } from 'react'; import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; -import { AddEditModalInnerInner } from '@gitroom/frontend/components/new-launch/add.edit.modal.inner'; +import { ManageModal } from '@gitroom/frontend/components/new-launch/manage.modal'; import { Integrations } from '@gitroom/frontend/components/launches/calendar.context'; +import { useShallow } from 'zustand/react/shallow'; +import { useExistingData } from '@gitroom/frontend/components/launches/helpers/use.existing.data'; export interface AddEditModalProps { date: dayjs.Dayjs; @@ -30,14 +31,22 @@ export interface AddEditModalProps { } export const AddEditModal: FC = (props) => { - const setAllIntegrations = useLaunchStore( - (state) => state.setAllIntegrations + const { setAllIntegrations, setDate, setIsCreateSet } = useLaunchStore( + useShallow((state) => ({ + setAllIntegrations: state.setAllIntegrations, + setDate: state.setDate, + setIsCreateSet: state.setIsCreateSet, + })) ); const integrations = useLaunchStore((state) => state.integrations); useEffect(() => { - setAllIntegrations(props.integrations || []); + setDate(props.date || dayjs()); + setAllIntegrations( + (props.integrations || []).filter((f) => !f.inBetweenSteps && !f.disabled) + ); + setIsCreateSet(!!props.addEditSets); }, []); if (!integrations.length) { @@ -49,48 +58,118 @@ export const AddEditModal: FC = (props) => { export const AddEditModalInner: FC = (props) => { const existingData = useExistingData(); - const reset = useLaunchStore((state) => state.reset); - - const addOrRemoveSelectedIntegration = useLaunchStore( - (state) => state.addOrRemoveSelectedIntegration - ); - - const addGlobalValue = useLaunchStore((state) => state.addGlobalValue); - const addInternalValue = useLaunchStore((state) => state.addInternalValue); - const selectedIntegrations = useLaunchStore((state) => state.selectedIntegrations); - const global = useLaunchStore((state) => state.global); - const internal = useLaunchStore((state) => state.internal); + const { addOrRemoveSelectedIntegration, selectedIntegrations, integrations } = + useLaunchStore( + useShallow((state) => ({ + integrations: state.integrations, + selectedIntegrations: state.selectedIntegrations, + addOrRemoveSelectedIntegration: state.addOrRemoveSelectedIntegration, + })) + ); useEffect(() => { + if (props?.set?.posts?.length) { + for (const post of props?.set?.posts) { + if (post.integration) { + const integration = integrations.find( + (i) => i.id === post.integration.id + ); + addOrRemoveSelectedIntegration(integration, post.settings); + } + } + } + if (existingData.integration) { - const integration = props.integrations.find( + const integration = integrations.find( (i) => i.id === existingData.integration ); addOrRemoveSelectedIntegration(integration, existingData.settings); + } + }, []); - addInternalValue(0, existingData.settings, existingData.posts.map((post) => ({ - content: post.content, - id: post.id, + if (existingData.integration && selectedIntegrations.length === 0) { + return null; + } + + return ; +}; + +export const AddEditModalInnerInner: FC = (props) => { + const existingData = useExistingData(); + const { + reset, + addGlobalValue, + addInternalValue, + global, + setCurrent, + internal, + setTags, + } = useLaunchStore( + useShallow((state) => ({ + reset: state.reset, + addGlobalValue: state.addGlobalValue, + addInternalValue: state.addInternalValue, + setCurrent: state.setCurrent, + global: state.global, + internal: state.internal, + setTags: state.setTags, + })) + ); + + useEffect(() => { + if (existingData.integration) { + setTags( // @ts-ignore - media: post.image as any[], - }))); - } - else { - addGlobalValue(0, [{ - content: '', - id: makeId(10), - media: [], - }]); + existingData?.posts?.[0]?.tags?.map((p: any) => ({ + label: p.tag.name, + value: p.tag.name, + })) || [] + ); + addInternalValue( + 0, + existingData.integration, + existingData.posts.map((post) => ({ + content: post.content, + id: post.id, + // @ts-ignore + media: post.image as any[], + })) + ); + setCurrent(existingData.integration); } + addGlobalValue( + 0, + props.onlyValues?.length + ? props.onlyValues.map((p) => ({ + content: p.content, + id: makeId(10), + media: p.image || [], + })) + : props.set?.posts?.length + ? props.set.posts[0].value.map((p) => ({ + id: makeId(10), + content: p.content, + // @ts-ignore + media: p.media, + })) + : [ + { + content: '', + id: makeId(10), + media: [], + }, + ] + ); + return () => { reset(); }; }, []); - if (!selectedIntegrations.length && !global.length && !internal.length) { + if (!global.length && !internal.length) { return null; } - return ; + return ; }; diff --git a/apps/frontend/src/components/new-launch/bold.text.tsx b/apps/frontend/src/components/new-launch/bold.text.tsx index 06dd7db0..14617649 100644 --- a/apps/frontend/src/components/new-launch/bold.text.tsx +++ b/apps/frontend/src/components/new-launch/bold.text.tsx @@ -90,7 +90,7 @@ export const BoldText: FC<{ return (
({ internal: state.internal.find((p) => p.integration.id === state.current), + internalFromAll: state.integrations.find(p => p.id === state.current), global: state.global, current: state.current, addRemoveInternal: state.addRemoveInternal, @@ -38,9 +66,29 @@ export const EditorWrapper: FC<{ setGlobalValueText: state.setGlobalValueText, addInternalValue: state.addInternalValue, addGlobalValue: state.addGlobalValue, + setGlobalValueMedia: state.setGlobalValueMedia, + setInternalValueMedia: state.setInternalValueMedia, + changeOrderGlobal: state.changeOrderGlobal, + changeOrderInternal: state.changeOrderInternal, + isCreateSet: state.isCreateSet, + deleteGlobalValue: state.deleteGlobalValue, + deleteInternalValue: state.deleteInternalValue, + setGlobalValue: state.setGlobalValue, + setInternalValue: state.setInternalValue, })) ); + const existingData = useExistingData(); + const [loaded, setLoaded] = useState(true); + + useEffect(() => { + if (loaded) { + return; + } + + setLoaded(true); + }, [loaded]); + const canEdit = useMemo(() => { return current === 'global' || !!internal; }, [current, internal]); @@ -53,6 +101,46 @@ export const EditorWrapper: FC<{ return global; }, [current, internal, global]); + const setValue = useCallback( + (value: string[]) => { + const newValue = value.map((p, index) => { + return { + id: makeId(10), + ...(items?.[index]?.media + ? { media: items[index].media } + : { media: [] }), + content: p, + }; + }); + if (internal) { + return setInternalValue(current, newValue); + } + + return setGlobalValue(newValue); + }, + [internal, items] + ); + + useCopilotReadable({ + description: 'Current content of posts', + value: items.map((p) => p.content), + }); + + useCopilotAction({ + name: 'setPosts', + description: 'a thread of posts', + parameters: [ + { + name: 'content', + type: 'string[]', + description: 'a thread of posts', + }, + ], + handler: async ({ content }) => { + setValue(content); + }, + }); + const changeValue = useCallback( (index: number) => (value: string) => { if (internal) { @@ -64,6 +152,41 @@ export const EditorWrapper: FC<{ [current, global, internal] ); + const changeImages = useCallback( + (index: number) => (value: any[]) => { + if (internal) { + return setInternalValueMedia(current, index, value); + } + + return setGlobalValueMedia(index, value); + }, + [current, global, internal] + ); + + const changeOrder = useCallback( + (index: number) => (direction: 'up' | 'down') => { + if (internal) { + changeOrderInternal(current, index, direction); + return setLoaded(false); + } + + changeOrderGlobal(index, direction); + setLoaded(false); + }, + [changeOrderInternal, changeOrderGlobal, current, global, internal] + ); + + const goBackToGlobal = useCallback(async () => { + if ( + await deleteDialog( + 'This action is irreversible. Are you sure you want to go back to global mode?' + ) + ) { + setLoaded(false); + addRemoveInternal(current); + } + }, []); + const addValue = useCallback( (index: number) => () => { if (internal) { @@ -87,25 +210,115 @@ export const EditorWrapper: FC<{ [current, global, internal] ); + const deletePost = useCallback( + (index: number) => async () => { + if ( + !(await deleteDialog( + 'Are you sure you want to delete this post?', + 'Yes, delete it!' + )) + ) { + return; + } + + if (internal) { + deleteInternalValue(current, index); + return setLoaded(false); + } + + deleteGlobalValue(index); + setLoaded(false); + }, + [current, global, internal] + ); + + if (!loaded) { + return null; + } + return items.map((g, index) => (
- {!canEdit && ( + {!canEdit && !isCreateSet && (
addRemoveInternal(current)} + onClick={() => { + if (index !== 0) { + return; + } + + setLoaded(false); + addRemoveInternal(current); + }} className="select-none cursor-pointer absolute w-full h-full left-0 top-0 bg-red-600/10 z-[100]" > -
- Edit -
+ {index === 0 && ( +
+ Edit +
+ )}
)} -
- +
+
+ +
+
+ + {index === 0 && + current !== 'global' && + canEdit && + !existingData.integration && ( + + + + )} + {items.length > 1 && ( + + + + )} +
{canEdit && } @@ -116,8 +329,24 @@ export const EditorWrapper: FC<{ export const Editor: FC<{ totalPosts: number; value: string; + num?: number; + pictures?: any[]; + allValues?: any[]; onChange: (value: string) => void; + setImages?: (value: any[]) => void; + autoComplete?: boolean; + validateChars?: boolean; + identifier?: string; }> = (props) => { + const { + allValues, + pictures, + setImages, + num, + autoComplete, + validateChars, + identifier, + } = props; const user = useUser(); const [id] = useState(makeId(10)); const newRef = useRef(null); @@ -136,6 +365,38 @@ export const Editor: FC<{ return ( <>
+
+ + + +
setEmojiPickerOpen(!emojiPickerOpen)} + > + {'\uD83D\uDE00'} +
+ {identifier === 'linkedin' || identifier === 'linkedin-page' ? ( + + ) : null} +
+
+ { + addText(e.emoji); + setEmojiPickerOpen(false); + }} + open={emojiPickerOpen} + /> +
+
+
+ {validateChars && props.value.length < 6 && ( +
+ {t( + 'the_post_should_be_at_least_6_characters_long', + 'The post should be at least 6 characters long' + )} +
+ )}
-
- - - -
setEmojiPickerOpen(!emojiPickerOpen)} - > - {t('', '\uD83D\uDE00')} -
-
-
- { - addText(e.emoji); - setEmojiPickerOpen(false); - }} - open={emojiPickerOpen} - /> +
+ {setImages && ( + { + setImages(value.target.value); + }} + onOpen={() => {}} + onClose={() => {}} + /> + )}
); diff --git a/apps/frontend/src/components/new-launch/finisher/thread.finisher.tsx b/apps/frontend/src/components/new-launch/finisher/thread.finisher.tsx index e659fa1a..77c7f252 100644 --- a/apps/frontend/src/components/new-launch/finisher/thread.finisher.tsx +++ b/apps/frontend/src/components/new-launch/finisher/thread.finisher.tsx @@ -3,9 +3,9 @@ import { Slider } from '@gitroom/react/form/slider'; import clsx from 'clsx'; import { Editor } from '@gitroom/frontend/components/new-launch/editor'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; export const ThreadFinisher = () => { const integration = useIntegration(); @@ -50,10 +50,7 @@ export const ThreadFinisher = () => { setValue('thread_finisher', val)} value={value} - height={150} totalPosts={1} - order={1} - preview="edit" />
diff --git a/apps/frontend/src/components/new-launch/helpers/date.picker.tsx b/apps/frontend/src/components/new-launch/helpers/date.picker.tsx deleted file mode 100644 index 6d3a812c..00000000 --- a/apps/frontend/src/components/new-launch/helpers/date.picker.tsx +++ /dev/null @@ -1,102 +0,0 @@ -'use client'; - -import { FC, useCallback, useState } from 'react'; -import dayjs from 'dayjs'; -import { Calendar, TimeInput } from '@mantine/dates'; -import { useClickOutside } from '@mantine/hooks'; -import { Button } from '@gitroom/react/form/button'; -import { isUSCitizen } from './isuscitizen.utils'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const DatePicker: FC<{ - date: dayjs.Dayjs; - onChange: (day: dayjs.Dayjs) => void; -}> = (props) => { - const { date, onChange } = props; - const [open, setOpen] = useState(false); - const t = useT(); - - const changeShow = useCallback(() => { - setOpen((prev) => !prev); - }, []); - const ref = useClickOutside(() => { - setOpen(false); - }); - const changeDate = useCallback( - (type: 'date' | 'time') => (day: Date) => { - onChange( - dayjs( - type === 'time' - ? date.format('YYYY-MM-DD') + ' ' + dayjs(day).format('HH:mm:ss') - : dayjs(day).format('YYYY-MM-DD') + ' ' + date.format('HH:mm:ss') - ) - ); - }, - [date] - ); - return ( -
-
- {date.format(isUSCitizen() ? 'MM/DD/YYYY hh:mm A' : 'DD/MM/YYYY HH:mm')} -
-
- - - -
- {open && ( -
e.stopPropagation()} - className="animate-normalFadeDown absolute top-[100%] mt-[16px] end-0 bg-sixth border border-tableBorder text-textColor rounded-[16px] z-[300] p-[16px] flex flex-col" - > - { - if (modifiers.weekend) { - return '!text-customColor28'; - } - if (modifiers.outside) { - return '!text-gray'; - } - if (modifiers.selected) { - return '!text-white !bg-seventh !outline-none'; - } - return '!text-textColor'; - }} - classNames={{ - day: 'hover:bg-seventh', - calendarHeaderControl: 'text-textColor hover:bg-third', - calendarHeaderLevel: 'text-textColor hover:bg-third', // cell: 'child:!text-textColor' - }} - /> - - -
- )} -
- ); -}; diff --git a/apps/frontend/src/components/new-launch/helpers/dnd.provider.tsx b/apps/frontend/src/components/new-launch/helpers/dnd.provider.tsx deleted file mode 100644 index 82ff70c9..00000000 --- a/apps/frontend/src/components/new-launch/helpers/dnd.provider.tsx +++ /dev/null @@ -1,10 +0,0 @@ -'use client'; - -import { FC, ReactNode } from 'react'; -import { HTML5Backend } from 'react-dnd-html5-backend'; -import { DndProvider } from 'react-dnd'; -export const DNDProvider: FC<{ - children: ReactNode; -}> = ({ children }) => { - return {children}; -}; diff --git a/apps/frontend/src/components/new-launch/helpers/isuscitizen.utils.tsx b/apps/frontend/src/components/new-launch/helpers/isuscitizen.utils.tsx deleted file mode 100644 index 3490b57d..00000000 --- a/apps/frontend/src/components/new-launch/helpers/isuscitizen.utils.tsx +++ /dev/null @@ -1,6 +0,0 @@ -'use client'; - -export const isUSCitizen = () => { - const userLanguage = navigator.language || navigator.languages[0]; - return userLanguage.startsWith('en-US'); -}; diff --git a/apps/frontend/src/components/new-launch/helpers/linkedin.component.tsx b/apps/frontend/src/components/new-launch/helpers/linkedin.component.tsx deleted file mode 100644 index ef5883a8..00000000 --- a/apps/frontend/src/components/new-launch/helpers/linkedin.component.tsx +++ /dev/null @@ -1,189 +0,0 @@ -'use client'; - -import { EventEmitter } from 'events'; -import React, { FC, useCallback, useEffect, useState } from 'react'; -import { TopTitle } from '@gitroom/frontend/components/new-launch/helpers/top.title.component'; -import { - executeCommand, - ExecuteState, - ICommand, - selectWord, - TextAreaTextApi, -} from '@uiw/react-md-editor'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { Input } from '@gitroom/react/form/input'; -import { Button } from '@gitroom/react/form/button'; -import { useToaster } from '@gitroom/react/toaster/toaster'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -const postUrlEmitter = new EventEmitter(); -export const ShowLinkedinCompany = () => { - const [showPostSelector, setShowPostSelector] = useState(false); - const [id, setId] = useState(''); - const [callback, setCallback] = useState<{ - callback: (tag: string) => void; - // eslint-disable-next-line @typescript-eslint/no-empty-function - } | null>({ - callback: (tag: string) => {}, - } as any); - useEffect(() => { - postUrlEmitter.on( - 'show', - (params: { id: string; callback: (url: string) => void }) => { - setCallback(params); - setId(params.id); - setShowPostSelector(true); - } - ); - return () => { - setShowPostSelector(false); - setCallback(null); - setId(''); - postUrlEmitter.removeAllListeners(); - }; - }, []); - const close = useCallback(() => { - setShowPostSelector(false); - setCallback(null); - setId(''); - }, []); - if (!showPostSelector) { - return <>; - } - return ( - - ); -}; -export const showPostSelector = (id: string) => { - return new Promise((resolve) => { - postUrlEmitter.emit('show', { - id, - callback: (tag: string) => { - resolve(tag); - }, - }); - }); -}; -export const LinkedinCompany: FC<{ - onClose: () => void; - onSelect: (tag: string) => void; - id: string; -}> = (props) => { - const { onClose, onSelect, id } = props; - const fetch = useFetch(); - const [company, setCompany] = useState(null); - const toast = useToaster(); - const t = useT(); - const getCompany = async () => { - if (!company) { - return; - } - try { - const { options } = await ( - await fetch('/integrations/function', { - method: 'POST', - body: JSON.stringify({ - id, - name: 'company', - data: { - url: company, - }, - }), - }) - ).json(); - onSelect(options.value); - onClose(); - } catch (e) { - toast.show('Failed to load profile', 'warning'); - } - }; - return ( -
-
-
-
- -
- -
-
- setCompany(e.target.value)} - placeholder="https://www.linkedin.com/company/gitroom" - /> - -
-
-
- ); -}; -export const linkedinCompany = (identifier: string, id: string): ICommand[] => { - if (identifier !== 'linkedin' && identifier !== 'linkedin-page') { - return []; - } - return [ - { - name: 'linkedinCompany', - keyCommand: 'linkedinCompany', - shortcuts: 'ctrlcmd+p', - prefix: '', - suffix: '', - buttonProps: { - 'aria-label': 'Add Post Url', - title: 'Add Post Url', - }, - icon: ( - - - - ), - execute: async (state: ExecuteState, api: TextAreaTextApi) => { - const newSelectionRange = selectWord({ - text: state.text, - selection: state.selection, - prefix: state.command.prefix!, - suffix: state.command.suffix, - }); - const state1 = api.setSelectionRange(newSelectionRange); - const media = await showPostSelector(id); - executeCommand({ - api, - selectedText: state1.selectedText, - selection: state.selection, - prefix: media, - suffix: '', - }); - }, - }, - ]; -}; diff --git a/apps/frontend/src/components/new-launch/helpers/new.image.component.tsx b/apps/frontend/src/components/new-launch/helpers/new.image.component.tsx deleted file mode 100644 index d539b430..00000000 --- a/apps/frontend/src/components/new-launch/helpers/new.image.component.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client'; - -import React from 'react'; -import { - executeCommand, - ExecuteState, - ICommand, - selectWord, - TextAreaTextApi, -} from '@uiw/react-md-editor'; -import { showMediaBox } from '@gitroom/frontend/components/media/media.component'; -import { loadVars } from '@gitroom/react/helpers/variable.context'; -export const newImage: ICommand = { - name: 'image', - keyCommand: 'image', - shortcuts: 'ctrlcmd+k', - prefix: '![image](', - suffix: ')', - buttonProps: { - 'aria-label': 'Add image (ctrl + k)', - title: 'Add image (ctrl + k)', - }, - icon: ( - - - - ), - execute: (state: ExecuteState, api: TextAreaTextApi) => { - const { uploadDirectory, backendUrl } = loadVars(); - let newSelectionRange = selectWord({ - text: state.text, - selection: state.selection, - prefix: state.command.prefix!, - suffix: state.command.suffix, - }); - let state1 = api.setSelectionRange(newSelectionRange); - if ( - state1.selectedText.includes('http') || - state1.selectedText.includes('www') || - state1.selectedText.includes('(post:') - ) { - executeCommand({ - api, - selectedText: state1.selectedText, - selection: state.selection, - prefix: state.command.prefix!, - suffix: state.command.suffix, - }); - return; - } - newSelectionRange = selectWord({ - text: state.text, - selection: state.selection, - prefix: '![', - suffix: ']()', - }); - state1 = api.setSelectionRange(newSelectionRange); - showMediaBox((media) => { - if (media) { - if (state1.selectedText.length > 0) { - executeCommand({ - api, - selectedText: state1.selectedText, - selection: state.selection, - prefix: '![', - suffix: `](${ - media.path.indexOf('http') === -1 - ? `${backendUrl}/${uploadDirectory}` - : `` - }${media.path})`, - }); - return; - } - executeCommand({ - api, - selectedText: state1.selectedText, - selection: state.selection, - prefix: '![image', - suffix: `](${ - media.path.indexOf('http') === -1 - ? `${backendUrl}/${uploadDirectory}` - : `` - }${media.path})`, - }); - } - }); - }, -}; diff --git a/apps/frontend/src/components/new-launch/helpers/top.title.component.tsx b/apps/frontend/src/components/new-launch/helpers/top.title.component.tsx deleted file mode 100644 index ee45eab5..00000000 --- a/apps/frontend/src/components/new-launch/helpers/top.title.component.tsx +++ /dev/null @@ -1,68 +0,0 @@ -'use client'; - -import { FC, ReactNode } from 'react'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; - -export const TopTitle: FC<{ - title: string; - shouldExpend?: boolean; - removeTitle?: boolean; - expend?: () => void; - collapse?: () => void; - children?: ReactNode; -}> = (props) => { - const { title, removeTitle, children, shouldExpend, expend, collapse } = - props; - const t = useT(); - - // Translate the title using a key derived from the title itself - // This creates a consistent key pattern for each title - const translatedTitle = t( - // Convert to lowercase, replace spaces with underscores - `top_title_${title - .toLowerCase() - .replace(/\s+/g, '_') - .replace(/[^\w]/g, '')}`, - title - ); - - return ( -
- {!removeTitle &&
{translatedTitle}
} - {children} - {shouldExpend !== undefined && ( -
- {!shouldExpend ? ( - - - - ) : ( - - - - )} -
- )} -
- ); -}; diff --git a/apps/frontend/src/components/new-launch/helpers/use.custom.provider.function.ts b/apps/frontend/src/components/new-launch/helpers/use.custom.provider.function.ts deleted file mode 100644 index 0f012ac5..00000000 --- a/apps/frontend/src/components/new-launch/helpers/use.custom.provider.function.ts +++ /dev/null @@ -1,29 +0,0 @@ -'use client'; - -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; -import { useCallback } from 'react'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -export const useCustomProviderFunction = () => { - const { integration } = useIntegration(); - const fetch = useFetch(); - const get = useCallback( - async (funcName: string, customData?: any) => { - const load = await fetch('/integrations/function', { - method: 'POST', - body: JSON.stringify({ - name: funcName, - id: integration?.id!, - data: customData, - }), - }); - if (load.status > 299 && load.status < 200) { - throw new Error('Failed to fetch'); - } - return load.json(); - }, - [integration] - ); - return { - get, - }; -}; diff --git a/apps/frontend/src/components/new-launch/helpers/use.existing.data.tsx b/apps/frontend/src/components/new-launch/helpers/use.existing.data.tsx deleted file mode 100644 index c2a3eae5..00000000 --- a/apps/frontend/src/components/new-launch/helpers/use.existing.data.tsx +++ /dev/null @@ -1,21 +0,0 @@ -'use client'; - -import { createContext, FC, ReactNode, useContext } from 'react'; -import { Post } from '@prisma/client'; -const ExistingDataContext = createContext({ - integration: '', - group: undefined as undefined | string, - posts: [] as Post[], - settings: {} as any, -}); -export const ExistingDataContextProvider: FC<{ - children: ReactNode; - value: any; -}> = ({ children, value }) => { - return ( - - {children} - - ); -}; -export const useExistingData = () => useContext(ExistingDataContext); diff --git a/apps/frontend/src/components/new-launch/helpers/use.expend.tsx b/apps/frontend/src/components/new-launch/helpers/use.expend.tsx deleted file mode 100644 index 3b392b29..00000000 --- a/apps/frontend/src/components/new-launch/helpers/use.expend.tsx +++ /dev/null @@ -1,31 +0,0 @@ -'use client'; - -import EventEmitter from 'events'; -import { useEffect, useState } from 'react'; -const emitter = new EventEmitter(); -export const useExpend = () => { - const [expend, setExpend] = useState(false); - useEffect(() => { - const hide = () => { - setExpend(false); - }; - const show = () => { - setExpend(true); - }; - emitter.on('hide', hide); - emitter.on('show', show); - return () => { - emitter.off('hide', hide); - emitter.off('show', show); - }; - }, []); - return { - expend, - hide: () => { - emitter.emit('hide'); - }, - show: () => { - emitter.emit('show'); - }, - }; -}; diff --git a/apps/frontend/src/components/new-launch/helpers/use.formatting.ts b/apps/frontend/src/components/new-launch/helpers/use.formatting.ts deleted file mode 100644 index 2f6b13d7..00000000 --- a/apps/frontend/src/components/new-launch/helpers/use.formatting.ts +++ /dev/null @@ -1,49 +0,0 @@ -'use client'; - -import { useMemo } from 'react'; -export const useFormatting = ( - text: Array<{ - content: string; - image?: Array<{ - id: string; - path: string; - }>; - id?: string; - }>, - params: { - removeMarkdown?: boolean; - saveBreaklines?: boolean; - specialFunc?: (text: string) => any; - beforeSpecialFunc?: (text: string) => string; - } -) => { - return useMemo(() => { - return text.map((value) => { - let newText = value.content; - if (params.beforeSpecialFunc) { - newText = params.beforeSpecialFunc(newText); - } - if (params.saveBreaklines) { - newText = newText.replace('\n', '𝔫𝔢𝔴𝔩𝔦𝔫𝔢'); - } - newText = newText.replace(/@\w{1,15}/g, function (match) { - return `${match}`; - }); - if (params.saveBreaklines) { - newText = newText.replace('𝔫𝔢𝔴𝔩𝔦𝔫𝔢', '\n'); - } - if (params.specialFunc) { - newText = params.specialFunc(newText); - } - return { - id: value.id, - text: newText, - images: value.image, - count: - params.removeMarkdown && params.saveBreaklines - ? newText.replace(/\n/g, ' ').length - : newText.length, - }; - }); - }, [text]); -}; diff --git a/apps/frontend/src/components/new-launch/helpers/use.hide.top.editor.tsx b/apps/frontend/src/components/new-launch/helpers/use.hide.top.editor.tsx deleted file mode 100644 index 5ba28014..00000000 --- a/apps/frontend/src/components/new-launch/helpers/use.hide.top.editor.tsx +++ /dev/null @@ -1,31 +0,0 @@ -'use client'; - -import EventEmitter from 'events'; -import { useEffect, useState } from 'react'; -const emitter = new EventEmitter(); -export const useHideTopEditor = () => { - const [hideTopEditor, setHideTopEditor] = useState(false); - useEffect(() => { - const hide = () => { - setHideTopEditor(true); - }; - const show = () => { - setHideTopEditor(false); - }; - emitter.on('hide', hide); - emitter.on('show', show); - return () => { - emitter.off('hide', hide); - emitter.off('show', show); - }; - }, []); - return { - hideTopEditor, - hide: () => { - emitter.emit('hide'); - }, - show: () => { - emitter.emit('show'); - }, - }; -}; diff --git a/apps/frontend/src/components/new-launch/helpers/use.integration.tsx b/apps/frontend/src/components/new-launch/helpers/use.integration.tsx deleted file mode 100644 index edbc22df..00000000 --- a/apps/frontend/src/components/new-launch/helpers/use.integration.tsx +++ /dev/null @@ -1,27 +0,0 @@ -'use client'; - -import { createContext, useContext } from 'react'; -import dayjs from 'dayjs'; -import { Integrations } from '@gitroom/frontend/components/launches/calendar.context'; - -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(), - allIntegrations: [], -}); - -const useIntegration = () => useContext(IntegrationContext); -export {IntegrationContext, useIntegration}; \ No newline at end of file diff --git a/apps/frontend/src/components/new-launch/helpers/use.move.to.integration.tsx b/apps/frontend/src/components/new-launch/helpers/use.move.to.integration.tsx deleted file mode 100644 index 3aa00952..00000000 --- a/apps/frontend/src/components/new-launch/helpers/use.move.to.integration.tsx +++ /dev/null @@ -1,47 +0,0 @@ -'use client'; - -import EventEmitter from 'events'; -import { useCallback, useEffect } from 'react'; -const emitter = new EventEmitter(); -export const useMoveToIntegration = () => { - return useCallback( - ({ - identifier, - toPreview, - }: { - identifier: string; - toPreview?: boolean; - }) => { - emitter.emit('moveToIntegration', { - identifier, - toPreview, - }); - }, - [] - ); -}; -export const useMoveToIntegrationListener = ( - useEffectParams: any[], - enabled: boolean, - callback: ({ - identifier, - toPreview, - }: { - identifier: string; - toPreview: boolean; - }) => void -) => { - useEffect(() => { - if (!enabled) { - return; - } - return load(); - }, useEffectParams); - const load = useCallback(() => { - emitter.off('moveToIntegration', callback); - emitter.on('moveToIntegration', callback); - return () => { - emitter.off('moveToIntegration', callback); - }; - }, useEffectParams); -}; diff --git a/apps/frontend/src/components/new-launch/helpers/use.values.ts b/apps/frontend/src/components/new-launch/helpers/use.values.ts deleted file mode 100644 index 209c160b..00000000 --- a/apps/frontend/src/components/new-launch/helpers/use.values.ts +++ /dev/null @@ -1,96 +0,0 @@ -'use client'; - -import { useEffect, useMemo } from 'react'; -import { useForm, useFormContext } from 'react-hook-form'; -import { classValidatorResolver } from '@hookform/resolvers/class-validator'; -import { IsOptional } from 'class-validator'; - -class Empty { - @IsOptional() - empty: string; -} - -const finalInformation = {} as { - [key: string]: { - posts: Array<{ - id?: string; - content: string; - media?: Array; - }>; - settings: () => object; - trigger: () => Promise; - isValid: boolean; - checkValidity?: ( - value: Array< - Array<{ - path: string; - }> - >, - settings: any, - additionalSettings: any, - ) => Promise; - maximumCharacters?: number; - }; -}; -export const useValues = ( - initialValues: object, - integration: string, - identifier: string, - value: Array<{ - id?: string; - content: string; - media?: Array; - }>, - dto: any, - checkValidity?: ( - value: Array< - Array<{ - path: string; - }> - >, - settings: any, - additionalSettings: any, - ) => Promise, - maximumCharacters?: number -) => { - - const form = useForm({ - resolver: classValidatorResolver(dto || Empty), - values: initialValues, - mode: 'onChange', - criteriaMode: 'all', - }); - - const getValues = useMemo(() => { - return () => ({ - ...form.getValues(), - __type: identifier, - }); - }, [form, integration]); - - // @ts-ignore - finalInformation[integration] = finalInformation[integration] || {}; - finalInformation[integration].posts = value; - finalInformation[integration].isValid = form.formState.isValid; - finalInformation[integration].settings = getValues; - finalInformation[integration].trigger = form.trigger; - if (checkValidity) { - finalInformation[integration].checkValidity = checkValidity; - } - if (maximumCharacters) { - finalInformation[integration].maximumCharacters = maximumCharacters; - } - useEffect(() => { - return () => { - delete finalInformation[integration]; - }; - }, []); - return form; -}; -export const useSettings = () => useFormContext(); -export const getValues = () => finalInformation; -export const resetValues = () => { - Object.keys(finalInformation).forEach((key) => { - delete finalInformation[key]; - }); -}; diff --git a/apps/frontend/src/components/new-launch/manage.modal.tsx b/apps/frontend/src/components/new-launch/manage.modal.tsx new file mode 100644 index 00000000..076fa334 --- /dev/null +++ b/apps/frontend/src/components/new-launch/manage.modal.tsx @@ -0,0 +1,445 @@ +'use client'; + +import React, { FC, useCallback, useRef, useState } from 'react'; +import { AddEditModalProps } from '@gitroom/frontend/components/new-launch/add.edit.modal'; +import clsx from 'clsx'; +import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { PicksSocialsComponent } from '@gitroom/frontend/components/new-launch/picks.socials.component'; +import { EditorWrapper } from '@gitroom/frontend/components/new-launch/editor'; +import { SelectCurrent } from '@gitroom/frontend/components/new-launch/select.current'; +import { ShowAllProviders } from '@gitroom/frontend/components/new-launch/providers/show.all.providers'; +import { useExistingData } from '@gitroom/frontend/components/launches/helpers/use.existing.data'; +import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; +import { DatePicker } from '@gitroom/frontend/components/launches/helpers/date.picker'; +import { useShallow } from 'zustand/react/shallow'; +import { RepeatComponent } from '@gitroom/frontend/components/launches/repeat.component'; +import { TagsComponent } from '@gitroom/frontend/components/launches/tags.component'; +import { Button } from '@gitroom/react/form/button'; +import { useToaster } from '@gitroom/react/toaster/toaster'; +import { weightedLength } from '@gitroom/helpers/utils/count.length'; +import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; +import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; +import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; +import { useModals } from '@mantine/modals'; +import { capitalize } from 'lodash'; +import { usePreventWindowUnload } from '@gitroom/react/helpers/use.prevent.window.unload'; +// @ts-ignore +import useKeypress from 'react-use-keypress'; +import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; +import { SelectCustomer } from '@gitroom/frontend/components/launches/select.customer'; +import { CopilotPopup } from '@copilotkit/react-ui'; + +function countCharacters(text: string, type: string): number { + if (type !== 'x') { + return text.length; + } + return weightedLength(text); +} + +export const ManageModal: FC = (props) => { + const t = useT(); + const fetch = useFetch(); + const ref = useRef(null); + const existingData = useExistingData(); + const [loading, setLoading] = useState(false); + const toaster = useToaster(); + const modal = useModals(); + usePreventWindowUnload(true); + + const { addEditSets, mutate, customClose } = props; + + const { + selectedIntegrations, + hide, + date, + setDate, + repeater, + setRepeater, + tags, + setTags, + integrations, + setSelectedIntegrations, + } = useLaunchStore( + useShallow((state) => ({ + hide: state.hide, + date: state.date, + setDate: state.setDate, + repeater: state.repeater, + setRepeater: state.setRepeater, + tags: state.tags, + setTags: state.setTags, + selectedIntegrations: state.selectedIntegrations, + integrations: state.integrations, + setSelectedIntegrations: state.setSelectedIntegrations, + })) + ); + + const deletePost = useCallback(async () => { + if ( + !(await deleteDialog( + 'Are you sure you want to delete this post?', + 'Yes, delete it!' + )) + ) { + setLoading(false); + return; + } + await fetch(`/posts/${existingData.group}`, { + method: 'DELETE', + }); + mutate(); + modal.closeAll(); + return; + }, [existingData, mutate, modal]); + + const askClose = useCallback(async () => { + if ( + await deleteDialog( + t( + 'are_you_sure_you_want_to_close_this_modal_all_data_will_be_lost', + 'Are you sure you want to close this modal? (all data will be lost)' + ), + t('yes_close_it', 'Yes, close it!') + ) + ) { + if (customClose) { + customClose(); + return; + } + modal.closeAll(); + } + }, []); + + const changeCustomer = useCallback( + (customer: string) => { + const neededIntegrations = integrations.filter( + (p) => p?.customer?.id === customer + ); + setSelectedIntegrations( + neededIntegrations.map((p) => ({ + settings: {}, + selectedIntegrations: p, + })) + ); + }, + [integrations] + ); + + useKeypress('Escape', askClose); + + const schedule = useCallback( + (type: 'draft' | 'now' | 'schedule') => async () => { + const checkAllValid = await ref.current.checkAllValid(); + if (type !== 'draft') { + const notEnoughChars = checkAllValid.filter((p: any) => { + return p.values.some((a: any) => { + return ( + countCharacters(a.content, p?.integration?.identifier || '') < 6 + ); + }); + }); + + for (const item of notEnoughChars) { + console.log('no enough'); + toaster.show( + '' + + item.integration.name + + ' post is too short, it must be at least 6 characters', + 'warning' + ); + item.preview(); + return; + } + + for (const item of checkAllValid) { + if (item.valid === false) { + toaster.show('Some fields are not valid', 'warning'); + item.fix(); + return; + } + + if (item.errors !== true) { + toaster.show( + `${capitalize(item.integration.identifier.split('-')[0])} (${ + item.integration.name + }): ${item.errors}`, + 'warning' + ); + item.preview(); + return; + } + } + + const sliceNeeded = checkAllValid.filter((p: any) => { + return p.values.some((a: any) => { + return ( + countCharacters(a.content, p?.integration?.identifier || '') > + (p.maximumCharacters || 1000000) + ); + }); + }); + + for (const item of sliceNeeded) { + if ( + !(await deleteDialog( + `${item?.integration?.name} (${item?.integration?.identifier}) post is too long, it will be cropped, do you want to continue?`, + 'Yes, continue' + )) + ) { + item.preview(); + return; + } + } + } + + const shortLinkUrl = await ( + await fetch('/posts/should-shortlink', { + method: 'POST', + body: JSON.stringify({ + messages: checkAllValid.flatMap((p: any) => + p.values.flatMap((a: any) => a.content) + ), + }), + }) + ).json(); + + const shortLink = !shortLinkUrl.ask + ? false + : await deleteDialog( + 'Do you want to shortlink the URLs? it will let you get statistics over clicks', + 'Yes, shortlink it!' + ); + + const group = existingData.group || makeId(10); + const data = { + type, + inter: repeater || undefined, + tags, + shortLink, + date: date.utc().format('YYYY-MM-DDTHH:mm:ss'), + posts: checkAllValid.map((p: any) => ({ + integration: p.integration, + group, + settings: p.settings, + value: p.values.map((a: any) => ({ + ...a, + image: a.media || [], + content: a.content.slice(0, p.maximumCharacters || 1000000), + })), + })), + }; + + addEditSets + ? addEditSets(data) + : await fetch('/posts', { + method: 'POST', + body: JSON.stringify(data), + }); + + if (!addEditSets) { + mutate(); + toaster.show( + !existingData.integration + ? 'Added successfully' + : 'Updated successfully' + ); + } + if (customClose) { + setTimeout(() => { + customClose(); + }, 2000); + } + + if (!addEditSets) { + modal.closeAll(); + } + }, + [ref, repeater, tags, date, addEditSets] + ); + + return ( + <> +
+
+
+ +
+ + +
+
+ + +
+ {!existingData.integration && } +
+
+ {!hide && } +
+
+
+
+
+
+
+
+ {!!existingData.integration && ( + + )} + + {!addEditSets && ( + + )} + + {addEditSets && ( + + )} + {!addEditSets && ( + + )} +
+
+
+
+
+
+
+ +
+
+ setTags(e.target.value)} + /> +
+ +
+ + + +
+
+
+ +
+
+
+ + + ); +}; diff --git a/apps/frontend/src/components/new-launch/picks.socials.component.tsx b/apps/frontend/src/components/new-launch/picks.socials.component.tsx index eb17c34d..e33b8010 100644 --- a/apps/frontend/src/components/new-launch/picks.socials.component.tsx +++ b/apps/frontend/src/components/new-launch/picks.socials.component.tsx @@ -5,38 +5,46 @@ import clsx from 'clsx'; import Image from 'next/image'; import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; import { useShallow } from 'zustand/react/shallow'; +import { useExistingData } from '@gitroom/frontend/components/launches/helpers/use.existing.data'; export const PicksSocialsComponent: FC<{ toolTip?: boolean }> = ({ toolTip, }) => { - const { addOrRemoveSelectedIntegration, integrations, selectedIntegrations } = + const exising = useExistingData(); + + const { locked, addOrRemoveSelectedIntegration, integrations, selectedIntegrations } = useLaunchStore( useShallow((state) => ({ integrations: state.integrations, selectedIntegrations: state.selectedIntegrations, addOrRemoveSelectedIntegration: state.addOrRemoveSelectedIntegration, + locked: state.locked, })) ); + return ( -
+
-
+
{integrations .filter((f) => !f.inBetweenSteps) .map((integration) => (
- addOrRemoveSelectedIntegration(integration, {}) - } + onClick={() => { + if (exising.integration) { + return; + } + addOrRemoveSelectedIntegration(integration, {}); + }} className={clsx( 'cursor-pointer relative w-[34px] h-[34px] rounded-full flex justify-center items-center bg-fifth filter transition-all duration-500', selectedIntegrations.findIndex( diff --git a/apps/frontend/src/components/new-launch/providers/bluesky/bluesky.provider.tsx b/apps/frontend/src/components/new-launch/providers/bluesky/bluesky.provider.tsx index 6cf97f1d..6ef5e119 100644 --- a/apps/frontend/src/components/new-launch/providers/bluesky/bluesky.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/bluesky/bluesky.provider.tsx @@ -2,10 +2,8 @@ import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; import { ThreadFinisher } from '@gitroom/frontend/components/new-launch/finisher/thread.finisher'; -import { useFormContext } from 'react-hook-form'; const SettingsComponent = () => { - const form = useFormContext(); return ; }; diff --git a/apps/frontend/src/components/new-launch/providers/continue-provider/facebook/facebook.continue.tsx b/apps/frontend/src/components/new-launch/providers/continue-provider/facebook/facebook.continue.tsx index a7738e73..a1c9d72c 100644 --- a/apps/frontend/src/components/new-launch/providers/continue-provider/facebook/facebook.continue.tsx +++ b/apps/frontend/src/components/new-launch/providers/continue-provider/facebook/facebook.continue.tsx @@ -1,13 +1,13 @@ 'use client'; import { FC, useCallback, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; import useSWR from 'swr'; import clsx from 'clsx'; import { Button } from '@gitroom/react/form/button'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; export const FacebookContinue: FC<{ closeModal: () => void; existingId: string[]; diff --git a/apps/frontend/src/components/new-launch/providers/continue-provider/instagram/instagram.continue.tsx b/apps/frontend/src/components/new-launch/providers/continue-provider/instagram/instagram.continue.tsx index 2ce5def6..4798d85c 100644 --- a/apps/frontend/src/components/new-launch/providers/continue-provider/instagram/instagram.continue.tsx +++ b/apps/frontend/src/components/new-launch/providers/continue-provider/instagram/instagram.continue.tsx @@ -1,13 +1,13 @@ 'use client'; import { FC, useCallback, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; import useSWR from 'swr'; import clsx from 'clsx'; import { Button } from '@gitroom/react/form/button'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; export const InstagramContinue: FC<{ closeModal: () => void; existingId: string[]; diff --git a/apps/frontend/src/components/new-launch/providers/continue-provider/linkedin/linkedin.continue.tsx b/apps/frontend/src/components/new-launch/providers/continue-provider/linkedin/linkedin.continue.tsx index f1bb48a0..e66b0ff6 100644 --- a/apps/frontend/src/components/new-launch/providers/continue-provider/linkedin/linkedin.continue.tsx +++ b/apps/frontend/src/components/new-launch/providers/continue-provider/linkedin/linkedin.continue.tsx @@ -1,13 +1,13 @@ 'use client'; import { FC, useCallback, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; import useSWR from 'swr'; import clsx from 'clsx'; import { Button } from '@gitroom/react/form/button'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; export const LinkedinContinue: FC<{ closeModal: () => void; existingId: string[]; diff --git a/apps/frontend/src/components/new-launch/providers/devto/devto.provider.tsx b/apps/frontend/src/components/new-launch/providers/devto/devto.provider.tsx index 886d612b..b4320897 100644 --- a/apps/frontend/src/components/new-launch/providers/devto/devto.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/devto/devto.provider.tsx @@ -3,7 +3,6 @@ import { FC } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; import { DevToSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/dev.to.settings.dto'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; import { Input } from '@gitroom/react/form/input'; import { MediaComponent } from '@gitroom/frontend/components/media/media.component'; import { SelectOrganization } from '@gitroom/frontend/components/new-launch/providers/devto/select.organization'; @@ -12,8 +11,10 @@ import { useMediaDirectory } from '@gitroom/react/helpers/use.media.directory'; import clsx from 'clsx'; import localFont from 'next/font/local'; import MDEditor from '@uiw/react-md-editor'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; import { Canonical } from '@gitroom/react/form/canonical'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; + const font = localFont({ src: [ { diff --git a/apps/frontend/src/components/new-launch/providers/devto/devto.tags.tsx b/apps/frontend/src/components/new-launch/providers/devto/devto.tags.tsx index f61a875a..131cb9e9 100644 --- a/apps/frontend/src/components/new-launch/providers/devto/devto.tags.tsx +++ b/apps/frontend/src/components/new-launch/providers/devto/devto.tags.tsx @@ -1,10 +1,10 @@ 'use client'; import { FC, useCallback, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; import { ReactTags } from 'react-tag-autocomplete'; import interClass from '@gitroom/react/helpers/inter.font'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; export const DevtoTags: FC<{ name: string; label: string; diff --git a/apps/frontend/src/components/new-launch/providers/devto/select.organization.tsx b/apps/frontend/src/components/new-launch/providers/devto/select.organization.tsx index 8451fa23..49cbbb80 100644 --- a/apps/frontend/src/components/new-launch/providers/devto/select.organization.tsx +++ b/apps/frontend/src/components/new-launch/providers/devto/select.organization.tsx @@ -1,10 +1,10 @@ 'use client'; import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; export const SelectOrganization: FC<{ name: string; onChange: (event: { diff --git a/apps/frontend/src/components/new-launch/providers/discord/discord.channel.select.tsx b/apps/frontend/src/components/new-launch/providers/discord/discord.channel.select.tsx index ce282790..a9a8a28a 100644 --- a/apps/frontend/src/components/new-launch/providers/discord/discord.channel.select.tsx +++ b/apps/frontend/src/components/new-launch/providers/discord/discord.channel.select.tsx @@ -1,9 +1,9 @@ 'use client'; import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; export const DiscordChannelSelect: FC<{ name: string; diff --git a/apps/frontend/src/components/new-launch/providers/discord/discord.provider.tsx b/apps/frontend/src/components/new-launch/providers/discord/discord.provider.tsx index 1fdf9f60..904fd0a2 100644 --- a/apps/frontend/src/components/new-launch/providers/discord/discord.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/discord/discord.provider.tsx @@ -4,7 +4,7 @@ import { withProvider } from '@gitroom/frontend/components/new-launch/providers/ import { FC } from 'react'; import { DiscordDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/discord.dto'; import { DiscordChannelSelect } from '@gitroom/frontend/components/new-launch/providers/discord/discord.channel.select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; const DiscordComponent: FC = () => { const form = useSettings(); return ( diff --git a/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.provider.tsx b/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.provider.tsx index a2dd6024..ce76011e 100644 --- a/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.provider.tsx @@ -2,7 +2,7 @@ import { FC } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { Input } from '@gitroom/react/form/input'; import { DribbbleTeams } from '@gitroom/frontend/components/new-launch/providers/dribbble/dribbble.teams'; import { DribbbleDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/dribbble.dto'; diff --git a/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.teams.tsx b/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.teams.tsx index d6457372..a948b76c 100644 --- a/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.teams.tsx +++ b/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.teams.tsx @@ -1,9 +1,9 @@ 'use client'; import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; export const DribbbleTeams: FC<{ name: string; diff --git a/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.provider.tsx b/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.provider.tsx index c1614075..36050b7c 100644 --- a/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.provider.tsx @@ -2,12 +2,12 @@ import { FC } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { Input } from '@gitroom/react/form/input'; import { HashnodePublications } from '@gitroom/frontend/components/new-launch/providers/hashnode/hashnode.publications'; import { HashnodeTags } from '@gitroom/frontend/components/new-launch/providers/hashnode/hashnode.tags'; import { HashnodeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/hashnode.settings.dto'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; import { useMediaDirectory } from '@gitroom/react/helpers/use.media.directory'; import clsx from 'clsx'; import MDEditor from '@uiw/react-md-editor'; diff --git a/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.publications.tsx b/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.publications.tsx index 9e6b8139..d6052f15 100644 --- a/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.publications.tsx +++ b/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.publications.tsx @@ -1,9 +1,9 @@ 'use client'; import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; export const HashnodePublications: FC<{ name: string; diff --git a/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.tags.tsx b/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.tags.tsx index 2bcebcce..352b76dd 100644 --- a/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.tags.tsx +++ b/apps/frontend/src/components/new-launch/providers/hashnode/hashnode.tags.tsx @@ -1,8 +1,8 @@ 'use client'; import { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { ReactTags } from 'react-tag-autocomplete'; import interClass from '@gitroom/react/helpers/inter.font'; export const HashnodeTags: FC<{ diff --git a/apps/frontend/src/components/new-launch/providers/high.order.provider.tsx b/apps/frontend/src/components/new-launch/providers/high.order.provider.tsx index 83188e33..f7885dcd 100644 --- a/apps/frontend/src/components/new-launch/providers/high.order.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/high.order.provider.tsx @@ -1,27 +1,31 @@ 'use client'; -import React, { FC, forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react'; +import React, { + FC, + forwardRef, + useCallback, + useImperativeHandle, + useMemo, +} from 'react'; import { useForm, FormProvider } from 'react-hook-form'; import { IsOptional } from 'class-validator'; import { classValidatorResolver } from '@hookform/resolvers/class-validator'; import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; -import { IntegrationContext } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; import { useShallow } from 'zustand/react/shallow'; -import { timer } from '@gitroom/helpers/utils/timer'; +import { GeneralPreviewComponent } from '@gitroom/frontend/components/launches/general.preview.component'; +import { IntegrationContext } from '@gitroom/frontend/components/launches/helpers/use.integration'; +import { Button } from '@gitroom/react/form/button'; +import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; +import useSWR from 'swr'; +import { InternalChannels } from '@gitroom/frontend/components/launches/internal.channels'; +import { capitalize } from 'lodash'; class Empty { @IsOptional() empty: string; } -export const TriggerComponent: FC<{form: any}> = ({ form }) => { - useEffect(() => { - form.trigger(); - }, []); - - return null; -} - export const withProvider = function ( SettingsComponent: FC<{ values?: any; @@ -42,52 +46,122 @@ export const withProvider = function ( maximumCharacters?: number | ((settings: any) => number) ) { return forwardRef((props: { id: string }, ref) => { + const t = useT(); + const fetch = useFetch(); const { current, integrations, selectedIntegration, + setCurrent, internal, global, date, + isGlobal, + tab, + setTab, } = useLaunchStore( useShallow((state) => ({ date: state.date, + tab: state.tab, + setTab: state.setTab, global: state.global, internal: state.internal.find((p) => p.integration.id === props.id), integrations: state.selectedIntegrations, current: state.current === props.id, + isGlobal: state.current === 'global', + setCurrent: state.setCurrent, selectedIntegration: state.selectedIntegrations.find( (p) => p.integration.id === props.id ), })) ); + const getInternalPlugs = useCallback(async () => { + return ( + await fetch( + `/integrations/${selectedIntegration.integration.identifier}/internal-plugs` + ) + ).json(); + }, [selectedIntegration.integration.identifier]); + const { data, isLoading } = useSWR( + `internal-${selectedIntegration.integration.identifier}`, + getInternalPlugs, + { + revalidateOnReconnect: true, + } + ); + const value = useMemo(() => { - if (internal) { + if (internal?.integrationValue?.length) { return internal.integrationValue; } return global; - }, []); + }, [internal, global, isGlobal]); const form = useForm({ resolver: classValidatorResolver(dto || Empty), - values: {...selectedIntegration.settings}, + ...(Object.keys(selectedIntegration.settings).length > 0 + ? { values: { ...selectedIntegration.settings } } + : {}), mode: 'all', criteriaMode: 'all', + reValidateMode: 'onChange', }); - useImperativeHandle(ref, () => ({ - isValid: async () => { - return { - id: props.id, - identifier: selectedIntegration.integration.identifier, - valid: form.formState.isValid, - values: form.getValues(), - errors: form.formState.errors, - }; - }, - }), [form, props.id, selectedIntegration]); + useImperativeHandle( + ref, + () => ({ + isValid: async () => { + const settings = form.getValues(); + return { + id: props.id, + identifier: selectedIntegration.integration.identifier, + integration: selectedIntegration.integration, + valid: await form.trigger(), + errors: checkValidity + ? await checkValidity( + value.map((p) => p.media || []), + settings, + JSON.parse( + selectedIntegration.integration.additionalSettings || '[]' + ) + ) + : true, + settings, + values: value, + maximumCharacters: + typeof maximumCharacters === 'number' + ? maximumCharacters + : maximumCharacters( + JSON.parse( + selectedIntegration.integration.additionalSettings || '[]' + ) + ), + fix: () => { + setTab(1); + setCurrent(props.id); + }, + preview: () => { + setTab(0); + setCurrent(props.id); + }, + }; + }, + getValues: () => { + return { + id: props.id, + identifier: selectedIntegration.integration.identifier, + values: value, + settings: form.getValues(), + }; + }, + trigger: () => { + return form.trigger(); + }, + }), + [value] + ); return ( ( date, integration: selectedIntegration.integration, allIntegrations: integrations.map((p) => p.integration), - value: value, + value: value.map((p) => ({ + id: p.id, + content: p.content, + image: p.media, + })), }} > -
+
+
+
+ +
+ {!!SettingsComponent && ( +
+ +
+ )} +
+ + {(tab === 0 || !SettingsComponent) && + !value?.[0]?.content?.length && ( +
{t('start_writing_your_post', 'Start writing your post for a preview')}
+ )} + {(tab === 0 || !SettingsComponent) && + !!value?.[0]?.content?.length && + (CustomPreviewComponent ? ( + + ) : ( + + ))} {SettingsComponent && ( -
+
+ {!!data?.internalPlugs?.length && ( + + )}
)} - +
); diff --git a/apps/frontend/src/components/new-launch/providers/instagram/instagram.collaborators.tsx b/apps/frontend/src/components/new-launch/providers/instagram/instagram.collaborators.tsx index d36abc8d..d4c2bdac 100644 --- a/apps/frontend/src/components/new-launch/providers/instagram/instagram.collaborators.tsx +++ b/apps/frontend/src/components/new-launch/providers/instagram/instagram.collaborators.tsx @@ -3,7 +3,7 @@ import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; import { FC } from 'react'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { InstagramDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/instagram.dto'; import { InstagramCollaboratorsTags } from '@gitroom/frontend/components/new-launch/providers/instagram/instagram.tags'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; diff --git a/apps/frontend/src/components/new-launch/providers/instagram/instagram.tags.tsx b/apps/frontend/src/components/new-launch/providers/instagram/instagram.tags.tsx index e9d65f1a..8b7f9572 100644 --- a/apps/frontend/src/components/new-launch/providers/instagram/instagram.tags.tsx +++ b/apps/frontend/src/components/new-launch/providers/instagram/instagram.tags.tsx @@ -1,10 +1,10 @@ 'use client'; import { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { ReactTags } from 'react-tag-autocomplete'; import interClass from '@gitroom/react/helpers/inter.font'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; import clsx from 'clsx'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; diff --git a/apps/frontend/src/components/new-launch/providers/lemmy/lemmy.provider.tsx b/apps/frontend/src/components/new-launch/providers/lemmy/lemmy.provider.tsx index 172e2f24..cee55028 100644 --- a/apps/frontend/src/components/new-launch/providers/lemmy/lemmy.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/lemmy/lemmy.provider.tsx @@ -2,7 +2,7 @@ import { FC, useCallback } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useFieldArray } from 'react-hook-form'; import { Button } from '@gitroom/react/form/button'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; diff --git a/apps/frontend/src/components/new-launch/providers/lemmy/subreddit.tsx b/apps/frontend/src/components/new-launch/providers/lemmy/subreddit.tsx index e4b3a473..0e4c170c 100644 --- a/apps/frontend/src/components/new-launch/providers/lemmy/subreddit.tsx +++ b/apps/frontend/src/components/new-launch/providers/lemmy/subreddit.tsx @@ -1,11 +1,11 @@ 'use client'; import { FC, FormEvent, useCallback, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Input } from '@gitroom/react/form/input'; import { useDebouncedCallback } from 'use-debounce'; import { useWatch } from 'react-hook-form'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; export const Subreddit: FC<{ onChange: (event: { target: { diff --git a/apps/frontend/src/components/new-launch/providers/linkedin/linkedin.provider.tsx b/apps/frontend/src/components/new-launch/providers/linkedin/linkedin.provider.tsx index ecdd7940..379285b3 100644 --- a/apps/frontend/src/components/new-launch/providers/linkedin/linkedin.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/linkedin/linkedin.provider.tsx @@ -3,7 +3,7 @@ import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; import { Checkbox } from '@gitroom/react/form/checkbox'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { LinkedinDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/linkedin.dto'; const LinkedInSettings = () => { diff --git a/apps/frontend/src/components/new-launch/providers/medium/medium.provider.tsx b/apps/frontend/src/components/new-launch/providers/medium/medium.provider.tsx index 5b552d96..d35a4b69 100644 --- a/apps/frontend/src/components/new-launch/providers/medium/medium.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/medium/medium.provider.tsx @@ -2,12 +2,12 @@ import { FC } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { Input } from '@gitroom/react/form/input'; import { MediumPublications } from '@gitroom/frontend/components/new-launch/providers/medium/medium.publications'; import { MediumTags } from '@gitroom/frontend/components/new-launch/providers/medium/medium.tags'; import { MediumSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/medium.settings.dto'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; import clsx from 'clsx'; import MDEditor from '@uiw/react-md-editor'; import localFont from 'next/font/local'; diff --git a/apps/frontend/src/components/new-launch/providers/medium/medium.publications.tsx b/apps/frontend/src/components/new-launch/providers/medium/medium.publications.tsx index c12c456b..12e7f856 100644 --- a/apps/frontend/src/components/new-launch/providers/medium/medium.publications.tsx +++ b/apps/frontend/src/components/new-launch/providers/medium/medium.publications.tsx @@ -1,9 +1,9 @@ 'use client'; import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; export const MediumPublications: FC<{ name: string; diff --git a/apps/frontend/src/components/new-launch/providers/medium/medium.tags.tsx b/apps/frontend/src/components/new-launch/providers/medium/medium.tags.tsx index 0363170a..53d0d165 100644 --- a/apps/frontend/src/components/new-launch/providers/medium/medium.tags.tsx +++ b/apps/frontend/src/components/new-launch/providers/medium/medium.tags.tsx @@ -1,7 +1,7 @@ 'use client'; import { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { ReactTags } from 'react-tag-autocomplete'; import interClass from '@gitroom/react/helpers/inter.font'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; diff --git a/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.board.tsx b/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.board.tsx index 30e9ab89..d48570de 100644 --- a/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.board.tsx +++ b/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.board.tsx @@ -1,9 +1,9 @@ 'use client'; import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; export const PinterestBoard: FC<{ name: string; diff --git a/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.provider.tsx b/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.provider.tsx index cfb2371e..a43ccb2b 100644 --- a/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.provider.tsx @@ -2,7 +2,7 @@ import { FC } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { PinterestBoard } from '@gitroom/frontend/components/new-launch/providers/pinterest/pinterest.board'; import { PinterestSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/pinterest.dto'; import { Input } from '@gitroom/react/form/input'; diff --git a/apps/frontend/src/components/new-launch/providers/reddit/reddit.provider.tsx b/apps/frontend/src/components/new-launch/providers/reddit/reddit.provider.tsx index f0427d97..dca11b33 100644 --- a/apps/frontend/src/components/new-launch/providers/reddit/reddit.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/reddit/reddit.provider.tsx @@ -2,10 +2,9 @@ import { FC, useCallback } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; -import { useFormatting } from '@gitroom/frontend/components/new-launch/helpers/use.formatting'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; import { Subreddit } from '@gitroom/frontend/components/new-launch/providers/reddit/subreddit'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useFieldArray, useWatch } from 'react-hook-form'; import { Button } from '@gitroom/react/form/button'; import { @@ -19,6 +18,7 @@ import MDEditor from '@uiw/react-md-editor'; import interClass from '@gitroom/react/helpers/inter.font'; import Image from 'next/image'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { useFormatting } from '@gitroom/frontend/components/launches/helpers/use.formatting'; const RenderRedditComponent: FC<{ type: string; images?: Array<{ diff --git a/apps/frontend/src/components/new-launch/providers/reddit/subreddit.tsx b/apps/frontend/src/components/new-launch/providers/reddit/subreddit.tsx index 07704150..8d14bc24 100644 --- a/apps/frontend/src/components/new-launch/providers/reddit/subreddit.tsx +++ b/apps/frontend/src/components/new-launch/providers/reddit/subreddit.tsx @@ -1,7 +1,7 @@ 'use client'; import { FC, FormEvent, useCallback, useMemo, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Input } from '@gitroom/react/form/input'; import { useDebouncedCallback } from 'use-debounce'; import { Button } from '@gitroom/react/form/button'; @@ -9,9 +9,9 @@ import clsx from 'clsx'; import { MultiMediaComponent } from '@gitroom/frontend/components/media/media.component'; import { useWatch } from 'react-hook-form'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { Canonical } from '@gitroom/react/form/canonical'; -import { useIntegration } from '@gitroom/frontend/components/new-launch/helpers/use.integration'; +import { useIntegration } from '@gitroom/frontend/components/launches/helpers/use.integration'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; export const RenderOptions: FC<{ options: Array<'self' | 'link' | 'media'>; diff --git a/apps/frontend/src/components/new-launch/providers/show.all.providers.tsx b/apps/frontend/src/components/new-launch/providers/show.all.providers.tsx index 62d7ea20..292d01cd 100644 --- a/apps/frontend/src/components/new-launch/providers/show.all.providers.tsx +++ b/apps/frontend/src/components/new-launch/providers/show.all.providers.tsx @@ -24,7 +24,12 @@ import NostrProvider from '@gitroom/frontend/components/new-launch/providers/nos import VkProvider from '@gitroom/frontend/components/new-launch/providers/vk/vk.provider'; import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; import { useShallow } from 'zustand/react/shallow'; -import { createRef, FC, forwardRef, useImperativeHandle } from 'react'; +import React, { createRef, FC, forwardRef, useImperativeHandle } from 'react'; +import { GeneralPreviewComponent } from '@gitroom/frontend/components/launches/general.preview.component'; +import { IntegrationContext } from '@gitroom/frontend/components/launches/helpers/use.integration'; +import { Button } from '@gitroom/react/form/button'; +import { useT } from '@gitroom/react/translation/get.transation.service.client'; + export const Providers = [ { identifier: 'devto', @@ -124,12 +129,18 @@ export const Providers = [ }, ]; export const ShowAllProviders = forwardRef((props, ref) => { - const { current, selectedIntegrations } = useLaunchStore( - useShallow((state) => ({ - selectedIntegrations: state.selectedIntegrations, - current: state.current, - })) - ); + const { date, current, global, selectedIntegrations, allIntegrations } = + useLaunchStore( + useShallow((state) => ({ + date: state.date, + selectedIntegrations: state.selectedIntegrations, + allIntegrations: state.integrations, + current: state.current, + global: state.global, + })) + ); + + const t = useT(); useImperativeHandle(ref, () => ({ checkAllValid: async () => { @@ -137,10 +148,48 @@ export const ShowAllProviders = forwardRef((props, ref) => { selectedIntegrations.map(async (p) => await p.ref?.current.isValid()) ); }, + getAllValues: async () => { + return Promise.all( + selectedIntegrations.map(async (p) => await p.ref?.current.getValues()) + ); + }, + triggerAll: () => { + return selectedIntegrations.map(async (p) => await p.ref?.current.trigger()); + } })); return ( - <> +
+ {current === 'global' && ( + p.integration), + value: global.map((p) => ({ + id: p.id, + content: p.content, + image: p.media, + })), + }} + > +
+
+ +
+
+ {global?.[0]?.content?.length === 0 ? ( +
{t('start_writing_your_post', 'Start writing your post for a preview')}
+ ) : ( + + )} +
+ )} {selectedIntegrations.map((integration) => { const { component: ProviderComponent } = Providers.find( (provider) => @@ -157,7 +206,7 @@ export const ShowAllProviders = forwardRef((props, ref) => { /> ); })} - +
); }); diff --git a/apps/frontend/src/components/new-launch/providers/slack/slack.channel.select.tsx b/apps/frontend/src/components/new-launch/providers/slack/slack.channel.select.tsx index 510bf891..6de498e3 100644 --- a/apps/frontend/src/components/new-launch/providers/slack/slack.channel.select.tsx +++ b/apps/frontend/src/components/new-launch/providers/slack/slack.channel.select.tsx @@ -1,9 +1,9 @@ 'use client'; import { FC, useEffect, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Select } from '@gitroom/react/form/select'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; export const SlackChannelSelect: FC<{ name: string; diff --git a/apps/frontend/src/components/new-launch/providers/slack/slack.provider.tsx b/apps/frontend/src/components/new-launch/providers/slack/slack.provider.tsx index 3393f5f5..1ff82a6f 100644 --- a/apps/frontend/src/components/new-launch/providers/slack/slack.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/slack/slack.provider.tsx @@ -2,7 +2,7 @@ import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; import { FC } from 'react'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { SlackChannelSelect } from '@gitroom/frontend/components/new-launch/providers/slack/slack.channel.select'; import { SlackDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/slack.dto'; const SlackComponent: FC = () => { diff --git a/apps/frontend/src/components/new-launch/providers/tiktok/tiktok.provider.tsx b/apps/frontend/src/components/new-launch/providers/tiktok/tiktok.provider.tsx index d0cea233..879afdef 100644 --- a/apps/frontend/src/components/new-launch/providers/tiktok/tiktok.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/tiktok/tiktok.provider.tsx @@ -10,9 +10,9 @@ import { } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { Select } from '@gitroom/react/form/select'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Checkbox } from '@gitroom/react/form/checkbox'; import clsx from 'clsx'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; diff --git a/apps/frontend/src/components/new-launch/providers/warpcast/subreddit.tsx b/apps/frontend/src/components/new-launch/providers/warpcast/subreddit.tsx index 56239784..3bcf2e02 100644 --- a/apps/frontend/src/components/new-launch/providers/warpcast/subreddit.tsx +++ b/apps/frontend/src/components/new-launch/providers/warpcast/subreddit.tsx @@ -1,11 +1,11 @@ 'use client'; import { FC, FormEvent, useCallback, useState } from 'react'; -import { useCustomProviderFunction } from '@gitroom/frontend/components/new-launch/helpers/use.custom.provider.function'; +import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function'; import { Input } from '@gitroom/react/form/input'; import { useDebouncedCallback } from 'use-debounce'; import { useWatch } from 'react-hook-form'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; export const Subreddit: FC<{ onChange: (event: { target: { diff --git a/apps/frontend/src/components/new-launch/providers/warpcast/warpcast.provider.tsx b/apps/frontend/src/components/new-launch/providers/warpcast/warpcast.provider.tsx index 27c12622..9f23cdae 100644 --- a/apps/frontend/src/components/new-launch/providers/warpcast/warpcast.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/warpcast/warpcast.provider.tsx @@ -2,7 +2,7 @@ import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; import { FC, useCallback } from 'react'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { useFieldArray } from 'react-hook-form'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { Button } from '@gitroom/react/form/button'; diff --git a/apps/frontend/src/components/new-launch/providers/x/x.provider.tsx b/apps/frontend/src/components/new-launch/providers/x/x.provider.tsx index d8b824b4..b3297879 100644 --- a/apps/frontend/src/components/new-launch/providers/x/x.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/x/x.provider.tsx @@ -4,7 +4,7 @@ import { withProvider } from '@gitroom/frontend/components/new-launch/providers/ import { ThreadFinisher } from '@gitroom/frontend/components/new-launch/finisher/thread.finisher'; import { Select } from '@gitroom/react/form/select'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { XDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/x.dto'; import { Input } from '@gitroom/react/form/input'; diff --git a/apps/frontend/src/components/new-launch/providers/youtube/youtube.provider.tsx b/apps/frontend/src/components/new-launch/providers/youtube/youtube.provider.tsx index f790a9bd..32975129 100644 --- a/apps/frontend/src/components/new-launch/providers/youtube/youtube.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/youtube/youtube.provider.tsx @@ -3,7 +3,7 @@ import { FC } from 'react'; import { withProvider } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; import { YoutubeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/youtube.settings.dto'; -import { useSettings } from '@gitroom/frontend/components/new-launch/helpers/use.values'; +import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values'; import { Input } from '@gitroom/react/form/input'; import { MediumTags } from '@gitroom/frontend/components/new-launch/providers/medium/medium.tags'; import { MediaComponent } from '@gitroom/frontend/components/media/media.component'; diff --git a/apps/frontend/src/components/new-launch/select.current.tsx b/apps/frontend/src/components/new-launch/select.current.tsx index befc7ad3..a18596b0 100644 --- a/apps/frontend/src/components/new-launch/select.current.tsx +++ b/apps/frontend/src/components/new-launch/select.current.tsx @@ -1,70 +1,151 @@ 'use client'; -import { FC } from 'react'; +import { + FC, + RefObject, + useEffect, + useRef, + useState, +} from 'react'; import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store'; import clsx from 'clsx'; import Image from 'next/image'; import { useShallow } from 'zustand/react/shallow'; +export function useHasScroll(ref: RefObject): boolean { + const [hasHorizontalScroll, setHasHorizontalScroll] = useState(false); + + useEffect(() => { + if (!ref.current) return; + + const checkScroll = () => { + const el = ref.current; + if (el) { + setHasHorizontalScroll(el.scrollWidth > el.clientWidth); + } + }; + + checkScroll(); // initial check + + const resizeObserver = new ResizeObserver(checkScroll); + resizeObserver.observe(ref.current); + + const mutationObserver = new MutationObserver(checkScroll); + mutationObserver.observe(ref.current, { + childList: true, + subtree: true, + characterData: true, + }); + + return () => { + resizeObserver.disconnect(); + mutationObserver.disconnect(); + }; + }, [ref]); + + return hasHorizontalScroll; +} + export const SelectCurrent: FC = () => { - const { selectedIntegrations, current, setCurrent } = useLaunchStore( - useShallow((state) => ({ - selectedIntegrations: state.selectedIntegrations, - current: state.current, - setCurrent: state.setCurrent, - })) - ); + const { selectedIntegrations, current, setCurrent, locked, setHide, hide } = + useLaunchStore( + useShallow((state) => ({ + selectedIntegrations: state.selectedIntegrations, + current: state.current, + setCurrent: state.setCurrent, + locked: state.locked, + hide: state.hide, + setHide: state.setHide, + })) + ); + + const contentRef = useRef(null); + const hasScroll = useHasScroll(contentRef); + console.log(hasScroll); + + useEffect(() => { + if (!hide) { + return; + } + + setHide(false); + }, [hide]); return ( -
-
setCurrent('global')} - className="cursor-pointer flex gap-[8px] items-center bg-customColor2 p-[10px] rounded-tl-[4px] rounded-tr-[4px]" - > + <> +
setCurrent('global')} - className={clsx(current !== 'global' ? 'opacity-40' : '')} - > - T -
-
- {selectedIntegrations.map(({ integration }) => ( -
setCurrent(integration.id)} - key={integration.id} - className="cursor-pointer flex gap-[8px] items-center bg-customColor2 p-[10px] rounded-tl-[4px] rounded-tr-[4px]" + ref={contentRef} + className={clsx( + 'flex gap-[3px] w-full overflow-x-auto scrollbar scrollbar-thumb-tableBorder scrollbar-track-secondary', + locked && 'opacity-50 pointer-events-none' + )} >
{ + setHide(true); + setCurrent('global'); + }} + className="cursor-pointer flex gap-[8px] items-center bg-customColor2 p-[10px] rounded-tl-[4px] rounded-tr-[4px]" > - {integration.identifier} - {integration.identifier === 'youtube' ? ( - - ) : ( - {integration.identifier} - )} +
+ + + +
+ {selectedIntegrations.map(({ integration }) => ( +
{ + setHide(true); + setCurrent(integration.id); + }} + key={integration.id} + className="cursor-pointer flex gap-[8px] items-center bg-customColor2 p-[10px] rounded-tl-[4px] rounded-tr-[4px]" + > +
+ {integration.identifier} + {integration.identifier === 'youtube' ? ( + + ) : ( + {integration.identifier} + )} +
+
+ ))}
- ))} -
+
+
+ ); }; diff --git a/apps/frontend/src/components/new-launch/store.ts b/apps/frontend/src/components/new-launch/store.ts index 86403e8d..a66c897f 100644 --- a/apps/frontend/src/components/new-launch/store.ts +++ b/apps/frontend/src/components/new-launch/store.ts @@ -4,6 +4,7 @@ import { create } from 'zustand'; import dayjs from 'dayjs'; import { Integrations } from '@gitroom/frontend/components/launches/calendar.context'; import { createRef, RefObject } from 'react'; +import { arrayMoveImmutable } from 'array-move'; interface Values { id: string; @@ -24,7 +25,14 @@ interface SelectedIntegrations { interface StoreState { date: dayjs.Dayjs; + repeater?: number; + isCreateSet: boolean; + tags: { label: string; value: string }[]; + tab: 0 | 1; current: string; + locked: boolean; + hide: boolean; + setLocked: (locked: boolean) => void; integrations: Integrations[]; selectedIntegrations: SelectedIntegrations[]; global: Values[]; @@ -35,16 +43,27 @@ interface StoreState { integrationId: string, value: Values[] ) => void; + setGlobalValue: (value: Values[]) => void; + setInternalValue: (integrationId: string, value: Values[]) => void; deleteGlobalValue: (index: number) => void; deleteInternalValue: (integrationId: string, index: number) => void; addRemoveInternal: (integrationId: string) => void; - changeOrderGlobal: (fromIndex: number, toIndex: number) => void; + changeOrderGlobal: (index: number, direction: 'up' | 'down') => void; changeOrderInternal: ( integrationId: string, - fromIndex: number, - toIndex: number + index: number, + direction: 'up' | 'down' ) => void; setGlobalValueText: (index: number, content: string) => void; + setGlobalValueMedia: ( + index: number, + media: { id: string; path: string }[] + ) => void; + setInternalValueMedia: ( + integrationId: string, + index: number, + media: { id: string; path: string }[] + ) => void; addGlobalValueMedia: ( index: number, media: { id: string; path: string }[] @@ -72,11 +91,25 @@ interface StoreState { settings: any ) => void; reset: () => void; + setSelectedIntegrations: ( + params: { selectedIntegrations: Integrations; settings: any }[] + ) => void; + setTab: (tab: 0 | 1) => void; + setHide: (hide: boolean) => void; + setDate: (date: dayjs.Dayjs) => void; + setRepeater: (repeater: number) => void; + setTags: (tags: { label: string; value: string }[]) => void; + setIsCreateSet: (isCreateSet: boolean) => void; } const initialState = { date: dayjs(), + tags: [] as { label: string; value: string }[], + tab: 0 as 0, + isCreateSet: false, current: 'global', + locked: false, + hide: false, integrations: [] as Integrations[], selectedIntegrations: [] as SelectedIntegrations[], global: [] as Values[], @@ -122,7 +155,6 @@ export const useLaunchStore = create()((set) => ({ return { global: state.global.reduce((acc, item, i) => { - console.log(i, index); acc.push(item); if (i === index) { acc.push(...value); @@ -131,18 +163,44 @@ export const useLaunchStore = create()((set) => ({ }, []), }; }), - // Add value after index + // Add value after index, similar to addGlobalValue, but for a speciic integration (index starts from 0) addInternalValue: (index: number, integrationId: string, value: Values[]) => set((state) => { - const newInternal = state.internal.map((i) => { - if (i.integration.id === integrationId) { - const newIntegrationValue = [...i.integrationValue]; - newIntegrationValue.splice(index + 1, 0, ...value); - return { ...i, integrationValue: newIntegrationValue }; - } - return i; - }); - return { internal: newInternal }; + const integrationIndex = state.internal.findIndex( + (i) => i.integration.id === integrationId + ); + + if (integrationIndex === -1) { + return { + internal: [ + ...state.internal, + { + integration: state.selectedIntegrations.find( + (i) => i.integration.id === integrationId + )!.integration, + integrationValue: value, + }, + ], + }; + } + + const updatedIntegration = state.internal[integrationIndex]; + const newValues = updatedIntegration.integrationValue.reduce( + (acc, item, i) => { + acc.push(item); + if (i === index) { + acc.push(...value); + } + return acc; + }, + [] as Values[] + ); + + return { + internal: state.internal.map((i, idx) => + idx === integrationIndex ? { ...i, integrationValue: newValues } : i + ), + }; }), deleteGlobalValue: (index: number) => set((state) => ({ @@ -191,29 +249,38 @@ export const useLaunchStore = create()((set) => ({ ], }; }), - changeOrderGlobal: (fromIndex: number, toIndex: number) => + changeOrderGlobal: (index: number, direction: 'up' | 'down') => set((state) => { - const updatedGlobal = [...state.global]; - const [movedItem] = updatedGlobal.splice(fromIndex, 1); - updatedGlobal.splice(toIndex, 0, movedItem); - return { global: updatedGlobal }; + return { + global: arrayMoveImmutable( + state.global, + index, + direction === 'up' ? index - 1 : index + 1 + ), + }; }), changeOrderInternal: ( integrationId: string, - fromIndex: number, - toIndex: number + index: number, + direction: 'up' | 'down' ) => set((state) => { - const updatedInternal = state.internal.map((i) => { - if (i.integration.id === integrationId) { - const updatedValues = [...i.integrationValue]; - const [movedItem] = updatedValues.splice(fromIndex, 1); - updatedValues.splice(toIndex, 0, movedItem); - return { ...i, integrationValue: updatedValues }; - } - return i; - }); - return { internal: updatedInternal }; + return { + internal: state.internal.map((item) => { + if (item.integration.id === integrationId) { + return { + ...item, + integrationValue: arrayMoveImmutable( + item.integrationValue, + index, + direction === 'up' ? index - 1 : index + 1 + ), + }; + } + + return item; + }), + }; }), setGlobalValueText: (index: number, content: string) => set((state) => ({ @@ -221,6 +288,30 @@ export const useLaunchStore = create()((set) => ({ i === index ? { ...item, content } : item ), })), + setInternalValueMedia: ( + integrationId: string, + index: number, + media: { id: string; path: string }[] + ) => { + return set((state) => ({ + internal: state.internal.map((item) => + item.integration.id === integrationId + ? { + ...item, + integrationValue: item.integrationValue.map((v, i) => + i === index ? { ...v, media } : v + ), + } + : item + ), + })); + }, + setGlobalValueMedia: (index: number, media: { id: string; path: string }[]) => + set((state) => ({ + global: state.global.map((item, i) => + i === index ? { ...item, media } : item + ), + })), addGlobalValueMedia: (index: number, media: { id: string; path: string }[]) => set((state) => ({ global: state.global.map((item, i) => @@ -242,7 +333,7 @@ export const useLaunchStore = create()((set) => ({ integrationId: string, index: number, content: string - ) => + ) => { set((state) => ({ internal: state.internal.map((item) => item.integration.id === integrationId @@ -254,7 +345,8 @@ export const useLaunchStore = create()((set) => ({ } : item ), - })), + })); + }, addInternalValueMedia: ( integrationId: string, index: number, @@ -303,4 +395,54 @@ export const useLaunchStore = create()((set) => ({ set((state) => ({ integrations: integrations, })), + setTab: (tab: 0 | 1) => + set((state) => ({ + tab: tab, + })), + setLocked: (locked: boolean) => + set((state) => ({ + locked: locked, + })), + setHide: (hide: boolean) => + set((state) => ({ + hide: hide, + })), + setDate: (date: dayjs.Dayjs) => + set((state) => ({ + date, + })), + setRepeater: (repeater: number) => + set((state) => ({ + repeater, + })), + setTags: (tags: { label: string; value: string }[]) => + set((state) => ({ + tags, + })), + setIsCreateSet: (isCreateSet: boolean) => + set((state) => ({ + isCreateSet, + })), + setSelectedIntegrations: ( + params: { selectedIntegrations: Integrations; settings: any }[] + ) => + set((state) => ({ + selectedIntegrations: params.map((p) => ({ + integration: p.selectedIntegrations, + settings: p.settings, + ref: createRef(), + })), + })), + setGlobalValue: (value: Values[]) => + set((state) => ({ + global: value, + })), + setInternalValue: (integrationId: string, value: Values[]) => + set((state) => ({ + internal: state.internal.map((item) => + item.integration.id === integrationId + ? { ...item, integrationValue: value } + : item + ), + })), })); diff --git a/apps/frontend/src/components/new-launch/u.text.tsx b/apps/frontend/src/components/new-launch/u.text.tsx index b014ecba..6ea6acae 100644 --- a/apps/frontend/src/components/new-launch/u.text.tsx +++ b/apps/frontend/src/components/new-launch/u.text.tsx @@ -93,7 +93,7 @@ export const UText: FC<{ return (
{ const fetch = useFetch(); const params = usePathname(); diff --git a/i18n.lock b/i18n.lock index 7d13037a..66a384a2 100644 --- a/i18n.lock +++ b/i18n.lock @@ -165,6 +165,7 @@ checksums: repeat_post_every: 0969cb627a580ec4afc19efd11958f4e use_this_media: 6aeb1e22711eafe7f3dca7e496b52931 create_new_post: d0eba99343fb56e2baf90486eb68e70f + update_post: f24fceedd97a09c9b26bd7e1f8ce202c merge_comments_into_one_post: 2f672bd0b317afb250671ad97ca881f6 accounts_that_will_engage: adb190c89e1a6f75cc883d904791581d day: 47648cd60fc313bc3f05b70357a1d675 @@ -190,6 +191,8 @@ checksums: please_add_the_following_command_in_your_chat: 91cf09291659b1293786f0cf5ac50408 copy: 627c00d2c850b9b45f7341a6ac01b6bb settings: 8df6777277469c1fd88cc18dde2f1cc3 + integrations: 0ccce343287704cd90150c32e2fcad36 + add_integration: 1b83c3002a8e84ba9449055de0f7e5ee you_are_now_editing_only: 92478fd454abceccc5e47ddb543d9fec tag_a_company: 6f8a005436febb76a4270a0ea6db432c video_length_is_invalid_must_be_up_to: d5ab83e0f9d8c0f6e9c9ffdf7ad80c1d @@ -425,7 +428,7 @@ checksums: enable_color_picker: 299af76a76f4bf348425e16cbef55cfa cancel_the_color_picker: bb5a774d8367a5154e29ba7ee0615a12 no_content_yet: bdde7a6b531b27bd921bdbd26a0fada7 - write_your_reply: b77b3540c5eb362704ec103120943d8a + write_your_reply: 0f4d124dbef4685590d5a95af3b5df64 add_a_tag: 1e529e5b2e62a9b521ded77f2f2cd53e add_to_calendar: 40f6e2b51467f0abf819e69dcb3df2a1 select_channels_from_circles: ecde8aa1d62c31366127aa7b7a69b028 @@ -488,3 +491,8 @@ checksums: change_language: c798f65b78e23b2cf8fc29a1a24a182f that_a_wrap: 0ecf5b5a1fbac9c2653f2642baf5d4a5 post_as_images_carousel: 2f82f0f6adbf03abfeec3389800d7232 + save_set: e9c633bf57da897086a7bfd5108e445b + separate_post: 8c4bbcbabb5200898d1dec0fbdbc96a0 + label_who_can_reply_to_this_post: 4d8913296a1fc3f197cb0aead34af73d + delete_integration: ccc879ccfcf7f85bcfe09f2bc3fa0dd3 + start_writing_your_post: 471efc4f2a7e2cf02a065a2de34e7213 diff --git a/libraries/react-shared-libraries/src/translation/locales/ar/translation.json b/libraries/react-shared-libraries/src/translation/locales/ar/translation.json index b80ad6d3..b7ecc267 100644 --- a/libraries/react-shared-libraries/src/translation/locales/ar/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/ar/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "تكرار النشر كل...", "use_this_media": "استخدم هذه الوسائط", "create_new_post": "إنشاء منشور جديد", + "update_post": "تحديث المنشور الحالي", "merge_comments_into_one_post": "دمج التعليقات في منشور واحد", "accounts_that_will_engage": "الحسابات التي ستتفاعل:", "day": "يوم", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "يرجى إضافة الأمر التالي في الدردشة الخاصة بك:", "copy": "نسخ", "settings": "الإعدادات", + "integrations": "التكاملات", + "add_integration": "إضافة تكامل", "you_are_now_editing_only": "أنت الآن تقوم بالتحرير فقط", "tag_a_company": "الإشارة إلى شركة", "video_length_is_invalid_must_be_up_to": "مدة الفيديو غير صالحة، يجب أن تكون حتى", @@ -421,7 +424,7 @@ "enable_color_picker": "تفعيل منتقي الألوان", "cancel_the_color_picker": "إلغاء منتقي الألوان", "no_content_yet": "لا يوجد محتوى بعد", - "write_your_reply": "اكتب ردك...", + "write_your_reply": "اكتب منشورك...", "add_a_tag": "أضف وسمًا", "add_to_calendar": "أضف إلى التقويم", "select_channels_from_circles": "اختر القنوات من الدوائر أعلاه", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "ابدأ تجربة مجانية لمدة 7 أيام", "change_language": "تغيير اللغة", "that_a_wrap": "انتهينا!\n\nإذا أعجبك هذا التسلسل:\n\n1. تابعني على @{{username}} للمزيد من هذه المواضيع\n2. أعد تغريد التغريدة أدناه لمشاركة هذا التسلسل مع جمهورك\n", - "post_as_images_carousel": "انشر كعرض شرائح للصور" + "post_as_images_carousel": "انشر كعرض شرائح للصور", + "save_set": "حفظ المجموعة", + "separate_post": "فصل المنشور إلى عدة منشورات", + "label_who_can_reply_to_this_post": "من يمكنه الرد على هذا المنشور؟", + "delete_integration": "حذف التكامل", + "start_writing_your_post": "ابدأ بكتابة منشورك لمعاينة" } diff --git a/libraries/react-shared-libraries/src/translation/locales/bn/translation.json b/libraries/react-shared-libraries/src/translation/locales/bn/translation.json index 423c74db..16c4004f 100644 --- a/libraries/react-shared-libraries/src/translation/locales/bn/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/bn/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "প্রতি পোস্ট পুনরাবৃত্তি করুন...", "use_this_media": "এই মিডিয়া ব্যবহার করুন", "create_new_post": "নতুন পোস্ট তৈরি করুন", + "update_post": "বিদ্যমান পোস্ট আপডেট করুন", "merge_comments_into_one_post": "মন্তব্যগুলি একটি পোস্টে একত্রিত করুন", "accounts_that_will_engage": "যে অ্যাকাউন্টগুলি এনগেজ করবে:", "day": "দিন", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "অনুগ্রহ করে আপনার চ্যাটে নিম্নলিখিত কমান্ড যোগ করুন:", "copy": "কপি করুন", "settings": "সেটিংস", + "integrations": "ইন্টিগ্রেশনসমূহ", + "add_integration": "ইন্টিগ্রেশন যোগ করুন", "you_are_now_editing_only": "আপনি এখন শুধুমাত্র সম্পাদনা করছেন", "tag_a_company": "একটি কোম্পানি ট্যাগ করুন", "video_length_is_invalid_must_be_up_to": "ভিডিওর দৈর্ঘ্য অবৈধ, সর্বোচ্চ হতে হবে", @@ -421,7 +424,7 @@ "enable_color_picker": "কলর পিকার সক্রিয় করা", "cancel_the_color_picker": "কলর পিকার বাতিল করা", "no_content_yet": "কন্টেন্ট নেই", - "write_your_reply": "আপনার উত্তর লিখুন", + "write_your_reply": "আপনার পোস্ট লিখুন...", "add_a_tag": "ট্যাগ যোগ করুন", "add_to_calendar": "ক্যালেন্ডারে যোগ করুন", "select_channels_from_circles": "বলার মাধ্যমে চ্যানেল নির্বাচন করুন", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "৭ দিনের বিনামূল্যে ট্রায়াল শুরু করুন", "change_language": "ভাষা পরিবর্তন করুন", "that_a_wrap": "এটাই শেষ!\n\nযদি আপনি এই থ্রেডটি উপভোগ করে থাকেন:\n\n১. আরও এমন পোস্টের জন্য আমাকে @{{username}} ফলো করুন\n২. আপনার অডিয়েন্সের সাথে এই থ্রেডটি শেয়ার করতে নিচের টুইটটি রিটুইট করুন\n", - "post_as_images_carousel": "ছবির ক্যারোসেল হিসেবে পোস্ট করুন" + "post_as_images_carousel": "ছবির ক্যারোসেল হিসেবে পোস্ট করুন", + "save_set": "সেট সংরক্ষণ করুন", + "separate_post": "একটি পোস্টকে একাধিক পোস্টে ভাগ করুন", + "label_who_can_reply_to_this_post": "এই পোস্টে কে উত্তর দিতে পারবে?", + "delete_integration": "ইন্টিগ্রেশন মুছে ফেলুন", + "start_writing_your_post": "প্রিভিউর জন্য আপনার পোস্ট লেখা শুরু করুন" } diff --git a/libraries/react-shared-libraries/src/translation/locales/de/translation.json b/libraries/react-shared-libraries/src/translation/locales/de/translation.json index 63f68358..99dd66ad 100644 --- a/libraries/react-shared-libraries/src/translation/locales/de/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/de/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Beitrag wiederholen alle...", "use_this_media": "Dieses Medium verwenden", "create_new_post": "Neuen Beitrag erstellen", + "update_post": "Vorhandenen Beitrag aktualisieren", "merge_comments_into_one_post": "Kommentare zu einem Beitrag zusammenfassen", "accounts_that_will_engage": "Konten, die interagieren werden:", "day": "Tag", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "Bitte fügen Sie den folgenden Befehl in Ihrem Chat hinzu:", "copy": "Kopieren", "settings": "Einstellungen", + "integrations": "Integrationen", + "add_integration": "Integration hinzufügen", "you_are_now_editing_only": "Sie bearbeiten jetzt nur", "tag_a_company": "Unternehmen markieren", "video_length_is_invalid_must_be_up_to": "Videolänge ist ungültig, sie darf maximal", @@ -421,7 +424,7 @@ "enable_color_picker": "Farbwähler aktivieren", "cancel_the_color_picker": "Farbwähler abbrechen", "no_content_yet": "Noch kein Inhalt", - "write_your_reply": "Schreibe deine Antwort...", + "write_your_reply": "Schreibe deinen Beitrag...", "add_a_tag": "Tag hinzufügen", "add_to_calendar": "Zum Kalender hinzufügen", "select_channels_from_circles": "Wähle Kanäle aus den obigen Kreisen aus", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "7-tägige kostenlose Testversion starten", "change_language": "Sprache ändern", "that_a_wrap": "Das war's!\n\nWenn dir dieser Thread gefallen hat:\n\n1. Folge mir @{{username}} für mehr davon\n2. Retweete den untenstehenden Tweet, um diesen Thread mit deinem Publikum zu teilen\n", - "post_as_images_carousel": "Als Bilderkarussell posten" + "post_as_images_carousel": "Als Bilderkarussell posten", + "save_set": "Set speichern", + "separate_post": "Beitrag in mehrere Beiträge aufteilen", + "label_who_can_reply_to_this_post": "Wer kann auf diesen Beitrag antworten?", + "delete_integration": "Integration löschen", + "start_writing_your_post": "Beginne, deinen Beitrag für eine Vorschau zu schreiben" } diff --git a/libraries/react-shared-libraries/src/translation/locales/en/translation.json b/libraries/react-shared-libraries/src/translation/locales/en/translation.json index a085748a..92c27898 100644 --- a/libraries/react-shared-libraries/src/translation/locales/en/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/en/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Repeat Post Every...", "use_this_media": "Use this media", "create_new_post": "Create New Post", + "update_post": "Update Existing Post", "merge_comments_into_one_post": "Merge comments into one post", "accounts_that_will_engage": "Accounts that will engage:", "day": "Day", @@ -423,7 +424,7 @@ "enable_color_picker": "Enable color picker", "cancel_the_color_picker": "Cancel the color picker", "no_content_yet": "No Content Yet", - "write_your_reply": "Write your reply...", + "write_your_reply": "Write your post...", "add_a_tag": "Add a tag", "add_to_calendar": "Add to Calendar", "select_channels_from_circles": "Select channels from the circles above", @@ -489,5 +490,6 @@ "save_set": "Save Set", "separate_post": "Separate post to multiple posts", "label_who_can_reply_to_this_post": "Who can reply to this post?", - "delete_integration": "Delete Integration" + "delete_integration": "Delete Integration", + "start_writing_your_post": "Start writing your post for a preview" } diff --git a/libraries/react-shared-libraries/src/translation/locales/es/translation.json b/libraries/react-shared-libraries/src/translation/locales/es/translation.json index c293f1f5..8b25d338 100644 --- a/libraries/react-shared-libraries/src/translation/locales/es/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/es/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Repetir publicación cada...", "use_this_media": "Usar este medio", "create_new_post": "Crear nueva publicación", + "update_post": "Actualizar publicación existente", "merge_comments_into_one_post": "Unir comentarios en una sola publicación", "accounts_that_will_engage": "Cuentas que interactuarán:", "day": "Día", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "Por favor agrega el siguiente comando en tu chat:", "copy": "Copiar", "settings": "Configuración", + "integrations": "Integraciones", + "add_integration": "Agregar integración", "you_are_now_editing_only": "Ahora solo estás editando", "tag_a_company": "Etiquetar una empresa", "video_length_is_invalid_must_be_up_to": "La duración del video no es válida, debe ser de hasta", @@ -421,7 +424,7 @@ "enable_color_picker": "Habilitar selector de color", "cancel_the_color_picker": "Cancelar el selector de color", "no_content_yet": "Aún no hay contenido", - "write_your_reply": "Escribe tu respuesta...", + "write_your_reply": "Escribe tu publicación...", "add_a_tag": "Agregar una etiqueta", "add_to_calendar": "Agregar al calendario", "select_channels_from_circles": "Selecciona canales de los círculos de arriba", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "Comienza la prueba gratuita de 7 días", "change_language": "Cambiar idioma", "that_a_wrap": "¡Eso es todo!\n\nSi te gustó este hilo:\n\n1. Sígueme en @{{username}} para más contenido como este\n2. Haz RT al tuit de abajo para compartir este hilo con tu audiencia\n", - "post_as_images_carousel": "Publicar como carrusel de imágenes" + "post_as_images_carousel": "Publicar como carrusel de imágenes", + "save_set": "Guardar conjunto", + "separate_post": "Separar publicación en varias publicaciones", + "label_who_can_reply_to_this_post": "¿Quién puede responder a esta publicación?", + "delete_integration": "Eliminar integración", + "start_writing_your_post": "Comienza a escribir tu publicación para obtener una vista previa" } diff --git a/libraries/react-shared-libraries/src/translation/locales/fr/translation.json b/libraries/react-shared-libraries/src/translation/locales/fr/translation.json index 54b1d1c4..bde57da5 100644 --- a/libraries/react-shared-libraries/src/translation/locales/fr/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/fr/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Répéter la publication tous les...", "use_this_media": "Utiliser ce média", "create_new_post": "Créer une nouvelle publication", + "update_post": "Mettre à jour le post existant", "merge_comments_into_one_post": "Fusionner les commentaires en une seule publication", "accounts_that_will_engage": "Comptes qui vont interagir :", "day": "Jour", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "Veuillez ajouter la commande suivante dans votre chat :", "copy": "Copier", "settings": "Paramètres", + "integrations": "Intégrations", + "add_integration": "Ajouter une intégration", "you_are_now_editing_only": "Vous modifiez maintenant uniquement", "tag_a_company": "Taguer une entreprise", "video_length_is_invalid_must_be_up_to": "La durée de la vidéo est invalide, elle doit être au maximum de", @@ -421,7 +424,7 @@ "enable_color_picker": "Activer le sélecteur de couleurs", "cancel_the_color_picker": "Annuler le sélecteur de couleurs", "no_content_yet": "Pas encore de contenu", - "write_your_reply": "Écrivez votre réponse...", + "write_your_reply": "Écrivez votre post...", "add_a_tag": "Ajouter une étiquette", "add_to_calendar": "Ajouter au calendrier", "select_channels_from_circles": "Sélectionnez des canaux à partir des cercles ci-dessus", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "Commencez l’essai gratuit de 7 jours", "change_language": "Changer de langue", "that_a_wrap": "C'est terminé !\n\nSi vous avez aimé ce fil :\n\n1. Suivez-moi @{{username}} pour en voir d'autres\n2. Retweetez le tweet ci-dessous pour partager ce fil avec votre audience\n", - "post_as_images_carousel": "Publier en carrousel d’images" + "post_as_images_carousel": "Publier en carrousel d’images", + "save_set": "Enregistrer l'ensemble", + "separate_post": "Séparer le post en plusieurs publications", + "label_who_can_reply_to_this_post": "Qui peut répondre à ce post ?", + "delete_integration": "Supprimer l'intégration", + "start_writing_your_post": "Commencez à écrire votre post pour un aperçu" } diff --git a/libraries/react-shared-libraries/src/translation/locales/he/translation.json b/libraries/react-shared-libraries/src/translation/locales/he/translation.json index a4b41ccd..a5d61c01 100644 --- a/libraries/react-shared-libraries/src/translation/locales/he/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/he/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "חזור על הפוסט כל...", "use_this_media": "השתמש במדיה זו", "create_new_post": "צור פוסט חדש", + "update_post": "עדכן פוסט קיים", "merge_comments_into_one_post": "מזג תגובות לפוסט אחד", "accounts_that_will_engage": "חשבונות שיתקשרו:", "day": "יום", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "אנא הוסף את הפקודה הבאה בצ'אט שלך:", "copy": "העתק", "settings": "הגדרות", + "integrations": "אינטגרציות", + "add_integration": "הוסף אינטגרציה", "you_are_now_editing_only": "אתה עורך כעת רק", "tag_a_company": "תייג חברה", "video_length_is_invalid_must_be_up_to": "אורך הווידאו לא תקין, חייב להיות עד", @@ -421,7 +424,7 @@ "enable_color_picker": "הפעל בורר צבעים", "cancel_the_color_picker": "בטל את בורר הצבעים", "no_content_yet": "אין תוכן עדיין", - "write_your_reply": "כתוב את התשובה שלך...", + "write_your_reply": "כתוב את הפוסט שלך...", "add_a_tag": "הוסף תגית", "add_to_calendar": "הוסף ליומן", "select_channels_from_circles": "בחר ערוצים מהעיגולים למעלה", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "התחל תקופת ניסיון חינם ל-7 ימים", "change_language": "שנה שפה", "that_a_wrap": "זה הסוף!\n\nאם נהנית מהשרשור הזה:\n\n1. עקוב אחרי @{{username}} לעוד תכנים כאלה\n2. רטווט את הציוץ למטה כדי לשתף את השרשור עם הקהל שלך\n", - "post_as_images_carousel": "פרסם כתמונות בגלריה" + "post_as_images_carousel": "פרסם כתמונות בגלריה", + "save_set": "שמור סט", + "separate_post": "פצל פוסט למספר פוסטים", + "label_who_can_reply_to_this_post": "מי יכול להגיב לפוסט הזה?", + "delete_integration": "מחק אינטגרציה", + "start_writing_your_post": "התחל לכתוב את הפוסט שלך לתצוגה מקדימה" } diff --git a/libraries/react-shared-libraries/src/translation/locales/it/translation.json b/libraries/react-shared-libraries/src/translation/locales/it/translation.json index 65e18d2e..90629388 100644 --- a/libraries/react-shared-libraries/src/translation/locales/it/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/it/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Ripeti post ogni...", "use_this_media": "Usa questo media", "create_new_post": "Crea nuovo post", + "update_post": "Aggiorna post esistente", "merge_comments_into_one_post": "Unisci i commenti in un unico post", "accounts_that_will_engage": "Account che interagiranno:", "day": "Giorno", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "Per favore aggiungi il seguente comando nella tua chat:", "copy": "Copia", "settings": "Impostazioni", + "integrations": "Integrazioni", + "add_integration": "Aggiungi integrazione", "you_are_now_editing_only": "Ora stai modificando solo", "tag_a_company": "Tagga un'azienda", "video_length_is_invalid_must_be_up_to": "La durata del video non è valida, deve essere fino a", @@ -421,7 +424,7 @@ "enable_color_picker": "Abilita selettore colore", "cancel_the_color_picker": "Annulla il selettore colore", "no_content_yet": "Nessun contenuto ancora", - "write_your_reply": "Scrivi la tua risposta...", + "write_your_reply": "Scrivi il tuo post...", "add_a_tag": "Aggiungi un'etichetta", "add_to_calendar": "Aggiungi al calendario", "select_channels_from_circles": "Seleziona i canali dai cerchi sopra", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "Inizia la prova gratuita di 7 giorni", "change_language": "Cambia lingua", "that_a_wrap": "È tutto!\n\nSe ti è piaciuto questo thread:\n\n1. Seguimi su @{{username}} per altri contenuti come questo\n2. Ritwitta il tweet qui sotto per condividere questo thread con il tuo pubblico\n", - "post_as_images_carousel": "Pubblica come carosello di immagini" + "post_as_images_carousel": "Pubblica come carosello di immagini", + "save_set": "Salva set", + "separate_post": "Separa il post in più post", + "label_who_can_reply_to_this_post": "Chi può rispondere a questo post?", + "delete_integration": "Elimina integrazione", + "start_writing_your_post": "Inizia a scrivere il tuo post per un'anteprima" } diff --git a/libraries/react-shared-libraries/src/translation/locales/ja/translation.json b/libraries/react-shared-libraries/src/translation/locales/ja/translation.json index 93ea8f94..666fae61 100644 --- a/libraries/react-shared-libraries/src/translation/locales/ja/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/ja/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "投稿を繰り返す間隔...", "use_this_media": "このメディアを使用", "create_new_post": "新しい投稿を作成", + "update_post": "既存の投稿を更新", "merge_comments_into_one_post": "コメントを1つの投稿にまとめる", "accounts_that_will_engage": "エンゲージするアカウント:", "day": "日", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "チャットに次のコマンドを追加してください:", "copy": "コピー", "settings": "設定", + "integrations": "連携", + "add_integration": "連携を追加", "you_are_now_editing_only": "現在、次のみを編集しています", "tag_a_company": "会社をタグ付け", "video_length_is_invalid_must_be_up_to": "動画の長さが無効です。最大", @@ -421,7 +424,7 @@ "enable_color_picker": "カラーピッカーを有効にする", "cancel_the_color_picker": "カラーピッカーをキャンセル", "no_content_yet": "まだコンテンツがありません", - "write_your_reply": "返信を書いてください...", + "write_your_reply": "投稿内容を入力してください...", "add_a_tag": "タグを追加", "add_to_calendar": "カレンダーに追加", "select_channels_from_circles": "上のサークルからチャンネルを選択してください", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "7日間の無料トライアルを開始", "change_language": "言語を変更", "that_a_wrap": "以上で終了です!\n\nこのスレッドを楽しんでいただけたなら:\n\n1. @{{username}} をフォローして、さらに多くの投稿をご覧ください\n2. 下のツイートをリツイートして、このスレッドをあなたのフォロワーと共有してください\n", - "post_as_images_carousel": "画像カルーセルとして投稿" + "post_as_images_carousel": "画像カルーセルとして投稿", + "save_set": "セットを保存", + "separate_post": "投稿を複数に分割", + "label_who_can_reply_to_this_post": "この投稿に返信できる人", + "delete_integration": "連携を削除", + "start_writing_your_post": "プレビュー用に投稿を書き始めてください" } diff --git a/libraries/react-shared-libraries/src/translation/locales/ko/translation.json b/libraries/react-shared-libraries/src/translation/locales/ko/translation.json index 99fb60b7..6038987b 100644 --- a/libraries/react-shared-libraries/src/translation/locales/ko/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/ko/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "게시 반복 주기...", "use_this_media": "이 미디어 사용", "create_new_post": "새 게시물 만들기", + "update_post": "기존 게시물 업데이트", "merge_comments_into_one_post": "댓글을 하나의 게시물로 합치기", "accounts_that_will_engage": "참여할 계정:", "day": "일", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "채팅에 다음 명령어를 추가해 주세요:", "copy": "복사", "settings": "설정", + "integrations": "통합", + "add_integration": "통합 추가", "you_are_now_editing_only": "현재 이 항목만 편집 중입니다", "tag_a_company": "회사 태그하기", "video_length_is_invalid_must_be_up_to": "영상 길이가 잘못되었습니다. 최대", @@ -421,7 +424,7 @@ "enable_color_picker": "색상 선택기 활성화", "cancel_the_color_picker": "색상 선택기 취소", "no_content_yet": "아직 콘텐츠가 없습니다", - "write_your_reply": "답글을 작성하세요...", + "write_your_reply": "게시글을 작성하세요...", "add_a_tag": "태그 추가", "add_to_calendar": "캘린더에 추가", "select_channels_from_circles": "위의 원에서 채널을 선택하세요", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "7일 무료 체험 시작하기", "change_language": "언어 변경", "that_a_wrap": "여기까지입니다!\n\n이 스레드가 유익하셨다면:\n\n1. 더 많은 정보를 원하시면 @{{username}}를 팔로우하세요\n2. 아래 트윗을 리트윗해서 이 스레드를 여러분의 팔로워들과 공유하세요\n", - "post_as_images_carousel": "이미지 캐러셀로 게시" + "post_as_images_carousel": "이미지 캐러셀로 게시", + "save_set": "세트 저장", + "separate_post": "게시물을 여러 개로 분리", + "label_who_can_reply_to_this_post": "이 게시물에 누가 답글을 달 수 있나요?", + "delete_integration": "통합 삭제", + "start_writing_your_post": "미리보기를 위해 게시글 작성을 시작하세요" } diff --git a/libraries/react-shared-libraries/src/translation/locales/pt/translation.json b/libraries/react-shared-libraries/src/translation/locales/pt/translation.json index add488d8..0435ae61 100644 --- a/libraries/react-shared-libraries/src/translation/locales/pt/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/pt/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Repetir postagem a cada...", "use_this_media": "Usar esta mídia", "create_new_post": "Criar nova postagem", + "update_post": "Atualizar postagem existente", "merge_comments_into_one_post": "Mesclar comentários em uma postagem", "accounts_that_will_engage": "Contas que irão interagir:", "day": "Dia", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "Por favor, adicione o seguinte comando no seu chat:", "copy": "Copiar", "settings": "Configurações", + "integrations": "Integrações", + "add_integration": "Adicionar integração", "you_are_now_editing_only": "Agora você está editando apenas", "tag_a_company": "Marcar uma empresa", "video_length_is_invalid_must_be_up_to": "A duração do vídeo é inválida, deve ser de até", @@ -421,7 +424,7 @@ "enable_color_picker": "Ativar seletor de cores", "cancel_the_color_picker": "Cancelar o seletor de cores", "no_content_yet": "Ainda não há conteúdo", - "write_your_reply": "Escreva sua resposta...", + "write_your_reply": "Escreva sua postagem...", "add_a_tag": "Adicionar uma tag", "add_to_calendar": "Adicionar ao calendário", "select_channels_from_circles": "Selecione os canais dos círculos acima", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "Comece o teste gratuito de 7 dias", "change_language": "Mudar idioma", "that_a_wrap": "É isso aí!\n\nSe você gostou deste fio:\n\n1. Siga-me @{{username}} para ver mais conteúdos como este\n2. Dê RT no tweet abaixo para compartilhar este fio com seu público\n", - "post_as_images_carousel": "Publicar como carrossel de imagens" + "post_as_images_carousel": "Publicar como carrossel de imagens", + "save_set": "Salvar conjunto", + "separate_post": "Separar postagem em várias postagens", + "label_who_can_reply_to_this_post": "Quem pode responder a esta postagem?", + "delete_integration": "Excluir integração", + "start_writing_your_post": "Comece a escrever sua postagem para visualizar" } diff --git a/libraries/react-shared-libraries/src/translation/locales/ru/translation.json b/libraries/react-shared-libraries/src/translation/locales/ru/translation.json index 1547ddd7..5ed57368 100644 --- a/libraries/react-shared-libraries/src/translation/locales/ru/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/ru/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Повторять публикацию каждые...", "use_this_media": "Использовать этот медиафайл", "create_new_post": "Создать новый пост", + "update_post": "Обновить существующий пост", "merge_comments_into_one_post": "Объединить комментарии в один пост", "accounts_that_will_engage": "Аккаунты, которые будут взаимодействовать:", "day": "День", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "Пожалуйста, добавьте следующую команду в ваш чат:", "copy": "Копировать", "settings": "Настройки", + "integrations": "Интеграции", + "add_integration": "Добавить интеграцию", "you_are_now_editing_only": "Сейчас вы редактируете только", "tag_a_company": "Отметить компанию", "video_length_is_invalid_must_be_up_to": "Недопустимая длина видео, должно быть не более", @@ -421,7 +424,7 @@ "enable_color_picker": "Включить выбор цвета", "cancel_the_color_picker": "Отменить выбор цвета", "no_content_yet": "Пока нет контента", - "write_your_reply": "Напишите свой ответ...", + "write_your_reply": "Напишите свой пост...", "add_a_tag": "Добавить тег", "add_to_calendar": "Добавить в календарь", "select_channels_from_circles": "Выберите каналы из кругов выше", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "Начать 7-дневную бесплатную пробную версию", "change_language": "Сменить язык", "that_a_wrap": "На этом всё!\n\nЕсли вам понравилась эта серия:\n\n1. Подпишитесь на меня @{{username}}, чтобы не пропустить новые посты\n2. Ретвитните твит ниже, чтобы поделиться этой серией со своей аудиторией\n", - "post_as_images_carousel": "Опубликовать как карусель изображений" + "post_as_images_carousel": "Опубликовать как карусель изображений", + "save_set": "Сохранить набор", + "separate_post": "Разделить пост на несколько постов", + "label_who_can_reply_to_this_post": "Кто может отвечать на этот пост?", + "delete_integration": "Удалить интеграцию", + "start_writing_your_post": "Начните писать свой пост для предварительного просмотра" } diff --git a/libraries/react-shared-libraries/src/translation/locales/tr/translation.json b/libraries/react-shared-libraries/src/translation/locales/tr/translation.json index 054f97e5..24b495cc 100644 --- a/libraries/react-shared-libraries/src/translation/locales/tr/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/tr/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Gönderiyi Her ... Tekrarla", "use_this_media": "Bu medyayı kullan", "create_new_post": "Yeni Gönderi Oluştur", + "update_post": "Mevcut Gönderiyi Güncelle", "merge_comments_into_one_post": "Yorumları tek gönderide birleştir", "accounts_that_will_engage": "Etkileşime Geçecek Hesaplar:", "day": "Gün", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "Lütfen sohbetinize aşağıdaki komutu ekleyin:", "copy": "Kopyala", "settings": "Ayarlar", + "integrations": "Entegrasyonlar", + "add_integration": "Entegrasyon Ekle", "you_are_now_editing_only": "Şu anda yalnızca düzenliyorsunuz", "tag_a_company": "Bir şirket etiketle", "video_length_is_invalid_must_be_up_to": "Video uzunluğu geçersiz, en fazla", @@ -421,7 +424,7 @@ "enable_color_picker": "Renk seçiciyi etkinleştir", "cancel_the_color_picker": "Renk seçiciyi iptal et", "no_content_yet": "Henüz İçerik Yok", - "write_your_reply": "Yanıtınızı yazın...", + "write_your_reply": "Gönderinizi yazın...", "add_a_tag": "Etiket ekle", "add_to_calendar": "Takvime Ekle", "select_channels_from_circles": "Yukarıdaki dairelerden kanalları seçin", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "7 gün ücretsiz denemeyi başlat", "change_language": "Dili Değiştir", "that_a_wrap": "Bu iş burada bitti!\n\nEğer bu diziyi beğendiyseniz:\n\n1. Daha fazlası için beni @{{username}} hesabından takip edin\n2. Aşağıdaki tweet'i RT'leyerek bu diziyi kendi kitlenizle paylaşın\n", - "post_as_images_carousel": "Görselleri kaydırmalı gönder olarak paylaş" + "post_as_images_carousel": "Görselleri kaydırmalı gönder olarak paylaş", + "save_set": "Seti Kaydet", + "separate_post": "Gönderiyi birden fazla gönderiye ayır", + "label_who_can_reply_to_this_post": "Bu gönderiye kim yanıt verebilir?", + "delete_integration": "Entegrasyonu Sil", + "start_writing_your_post": "Önizleme için gönderinizi yazmaya başlayın" } diff --git a/libraries/react-shared-libraries/src/translation/locales/vi/translation.json b/libraries/react-shared-libraries/src/translation/locales/vi/translation.json index 8e601f7f..82c54d82 100644 --- a/libraries/react-shared-libraries/src/translation/locales/vi/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/vi/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "Lặp lại bài đăng mỗi...", "use_this_media": "Sử dụng phương tiện này", "create_new_post": "Tạo bài đăng mới", + "update_post": "Cập nhật bài viết hiện có", "merge_comments_into_one_post": "Gộp bình luận vào một bài đăng", "accounts_that_will_engage": "Các tài khoản sẽ tương tác:", "day": "Ngày", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "Vui lòng thêm lệnh sau vào cuộc trò chuyện của bạn:", "copy": "Sao chép", "settings": "Cài đặt", + "integrations": "Tích hợp", + "add_integration": "Thêm tích hợp", "you_are_now_editing_only": "Bạn hiện chỉ đang chỉnh sửa", "tag_a_company": "Gắn thẻ công ty", "video_length_is_invalid_must_be_up_to": "Độ dài video không hợp lệ, phải tối đa", @@ -421,7 +424,7 @@ "enable_color_picker": "Bật bộ chọn màu", "cancel_the_color_picker": "Hủy bộ chọn màu", "no_content_yet": "Chưa có nội dung", - "write_your_reply": "Viết phản hồi của bạn...", + "write_your_reply": "Viết bài của bạn...", "add_a_tag": "Thêm thẻ", "add_to_calendar": "Thêm vào lịch", "select_channels_from_circles": "Chọn kênh từ các vòng tròn phía trên", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "Bắt đầu dùng thử miễn phí 7 ngày", "change_language": "Thay đổi ngôn ngữ", "that_a_wrap": "Kết thúc rồi!\n\nNếu bạn thích chuỗi bài này:\n\n1. Hãy theo dõi tôi @{{username}} để xem thêm nhiều nội dung như vậy\n2. Retweet bài bên dưới để chia sẻ chuỗi này với mọi người\n", - "post_as_images_carousel": "Đăng dưới dạng băng chuyền hình ảnh" + "post_as_images_carousel": "Đăng dưới dạng băng chuyền hình ảnh", + "save_set": "Lưu bộ", + "separate_post": "Tách bài viết thành nhiều bài", + "label_who_can_reply_to_this_post": "Ai có thể trả lời bài viết này?", + "delete_integration": "Xóa tích hợp", + "start_writing_your_post": "Bắt đầu viết bài của bạn để xem trước" } diff --git a/libraries/react-shared-libraries/src/translation/locales/zh/translation.json b/libraries/react-shared-libraries/src/translation/locales/zh/translation.json index 852765ab..dd0f9169 100644 --- a/libraries/react-shared-libraries/src/translation/locales/zh/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/zh/translation.json @@ -161,6 +161,7 @@ "repeat_post_every": "每隔...重复发布", "use_this_media": "使用此媒体", "create_new_post": "创建新帖子", + "update_post": "更新已有帖子", "merge_comments_into_one_post": "将评论合并为一条帖子", "accounts_that_will_engage": "将参与的账号:", "day": "天", @@ -186,6 +187,8 @@ "please_add_the_following_command_in_your_chat": "请在您的聊天中添加以下命令:", "copy": "复制", "settings": "设置", + "integrations": "集成", + "add_integration": "添加集成", "you_are_now_editing_only": "您现在仅在编辑", "tag_a_company": "标记公司", "video_length_is_invalid_must_be_up_to": "视频时长无效,最长不得超过", @@ -421,7 +424,7 @@ "enable_color_picker": "启用取色器", "cancel_the_color_picker": "取消取色器", "no_content_yet": "暂无内容", - "write_your_reply": "写下你的回复...", + "write_your_reply": "写下你的帖子...", "add_a_tag": "添加标签", "add_to_calendar": "添加到日历", "select_channels_from_circles": "从上方的圈子中选择频道", @@ -483,5 +486,10 @@ "start_7_days_free_trial": "开始7天免费试用", "change_language": "切换语言", "that_a_wrap": "本帖到此结束!\n\n如果你喜欢这个话题:\n\n1. 关注我 @{{username}},获取更多类似内容\n2. 转发下方推文,与更多人分享本帖\n", - "post_as_images_carousel": "以图片轮播的形式发布" + "post_as_images_carousel": "以图片轮播的形式发布", + "save_set": "保存设置", + "separate_post": "将帖子拆分为多个帖子", + "label_who_can_reply_to_this_post": "谁可以回复此帖子?", + "delete_integration": "删除集成", + "start_writing_your_post": "开始写你的帖子以预览" } diff --git a/package.json b/package.json index dc4d71b6..1e718cdb 100644 --- a/package.json +++ b/package.json @@ -177,7 +177,7 @@ "react-dnd-html5-backend": "^16.0.1", "react-dom": "18.3.1", "react-dropzone": "^14.3.5", - "react-hook-form": "^7.50.1", + "react-hook-form": "^7.58.1", "react-i18next": "^15.5.2", "react-loading": "^2.0.3", "react-tag-autocomplete": "^7.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d19d8d4..12d7d5f6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,7 +35,7 @@ importers: version: 1.8.9(@aws-crypto/sha256-js@5.2.0)(@aws-sdk/client-s3@3.802.0)(@aws-sdk/credential-provider-node@3.799.0)(@browserbasehq/sdk@2.5.0)(@browserbasehq/stagehand@1.14.0(@playwright/test@1.52.0)(bufferutil@4.0.9)(deepmerge@4.3.1)(dotenv@16.5.0)(openai@4.97.0(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.24.4))(utf-8-validate@5.0.10)(zod@3.24.4))(@ibm-cloud/watsonx-ai@1.6.4(@langchain/core@0.3.51(openai@4.97.0(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.24.4))))(@smithy/util-utf8@2.3.0)(axios@1.9.0)(cheerio@1.0.0)(crypto-js@4.2.0)(fast-xml-parser@4.5.3)(google-auth-library@9.15.1)(googleapis@137.1.0)(html-to-text@9.0.5)(ibm-cloud-sdk-core@5.3.2)(ignore@5.3.2)(ioredis@5.6.1)(jsdom@22.1.0(bufferutil@4.0.9)(canvas@2.11.2)(utf-8-validate@5.0.10))(jsonwebtoken@9.0.2)(lodash@4.17.21)(playwright@1.52.0)(redis@4.7.0)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@hookform/resolvers': specifier: ^3.3.4 - version: 3.10.0(react-hook-form@7.56.2(react@18.3.1)) + version: 3.10.0(react-hook-form@7.58.1(react@18.3.1)) '@langchain/community': specifier: ^0.3.40 version: 0.3.42(9a70403282cad7df9fe3853e78fee122) @@ -409,8 +409,8 @@ importers: specifier: ^14.3.5 version: 14.3.8(react@18.3.1) react-hook-form: - specifier: ^7.50.1 - version: 7.56.2(react@18.3.1) + specifier: ^7.58.1 + version: 7.58.1(react@18.3.1) react-i18next: specifier: ^15.5.2 version: 15.5.2(i18next@25.2.1(typescript@5.5.4))(react-dom@18.3.1(react@18.3.1))(react-native@0.79.2(@babel/core@7.27.1)(@types/react@18.3.1)(bufferutil@4.0.9)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(typescript@5.5.4) @@ -13071,8 +13071,8 @@ packages: react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} - react-hook-form@7.56.2: - resolution: {integrity: sha512-vpfuHuQMF/L6GpuQ4c3ZDo+pRYxIi40gQqsCmmfUBwm+oqvBhKhwghCuj2o00YCgSfU6bR9KC/xnQGWm3Gr08A==} + react-hook-form@7.58.1: + resolution: {integrity: sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -18168,9 +18168,9 @@ snapshots: react-dom: 18.3.1(react@18.3.1) use-sync-external-store: 1.5.0(react@18.3.1) - '@hookform/resolvers@3.10.0(react-hook-form@7.56.2(react@18.3.1))': + '@hookform/resolvers@3.10.0(react-hook-form@7.58.1(react@18.3.1))': dependencies: - react-hook-form: 7.56.2(react@18.3.1) + react-hook-form: 7.58.1(react@18.3.1) '@humanwhocodes/config-array@0.11.14': dependencies: @@ -19623,6 +19623,21 @@ snapshots: - typescript - verdaccio + '@nrwl/js@19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(typescript@5.5.4)': + dependencies: + '@nx/js': 19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(typescript@5.5.4) + transitivePeerDependencies: + - '@babel/traverse' + - '@swc-node/register' + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - debug + - nx + - supports-color + - typescript + - verdaccio + '@nrwl/nest@19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(chokidar@3.5.3)(eslint@8.57.0)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(ts-node@10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.5.4))(typescript@5.5.4)': dependencies: '@nx/nest': 19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(chokidar@3.5.3)(eslint@8.57.0)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(ts-node@10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.5.4))(typescript@5.5.4) @@ -19969,7 +19984,7 @@ snapshots: '@babel/preset-env': 7.27.1(@babel/core@7.27.1) '@babel/preset-typescript': 7.27.1(@babel/core@7.27.1) '@babel/runtime': 7.27.1 - '@nrwl/js': 19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(typescript@5.4.5) + '@nrwl/js': 19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(typescript@5.5.4) '@nx/devkit': 19.7.2(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))) '@nx/workspace': 19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)) babel-plugin-const-enum: 1.2.0(@babel/core@7.27.1) @@ -32387,7 +32402,7 @@ snapshots: react-fast-compare@3.2.2: {} - react-hook-form@7.56.2(react@18.3.1): + react-hook-form@7.58.1(react@18.3.1): dependencies: react: 18.3.1