diff --git a/apps/frontend/src/components/launches/add.edit.model.tsx b/apps/frontend/src/components/launches/add.edit.model.tsx index 1417b187..4e6b7c88 100644 --- a/apps/frontend/src/components/launches/add.edit.model.tsx +++ b/apps/frontend/src/components/launches/add.edit.model.tsx @@ -45,6 +45,7 @@ import { PostToOrganization, } from '@gitroom/frontend/components/launches/post.to.organization'; import { Submitted } from '@gitroom/frontend/components/launches/submitted'; +import { capitalize } from 'lodash'; export const AddEditModal: FC<{ date: dayjs.Dayjs; @@ -241,6 +242,7 @@ export const AddEditModal: FC<{ } const values = getValues(); + const allKeys = Object.keys(values).map((v) => ({ integration: integrations.find((p) => p.id === v), value: values[v].posts, @@ -248,9 +250,46 @@ export const AddEditModal: FC<{ group: existingData?.group, trigger: values[v].trigger, settings: values[v].settings(), + firstCommentRequirements: values[v].firstCommentRequirements, + maximumMediaRequirements: values[v].maximumMediaRequirements, + minimumMediaRequirements: values[v].minimumMediaRequirements, })); for (const key of allKeys) { + // @ts-ignore + const images = key?.value[0].image; + if ( + (images?.length || 0) > (key.maximumMediaRequirements || 0) || + (images?.length || 0) < (key.minimumMediaRequirements || 0) + ) { + toaster.show( + `The amount of ${capitalize(key?.integration?.identifier)} media attached supposed to be ${ + key.maximumMediaRequirements === key.minimumMediaRequirements + ? key.minimumMediaRequirements + : `between ${key.minimumMediaRequirements} to ${key.maximumMediaRequirements}` + }`, + 'warning' + ); + return; + } + + if ( + key.firstCommentRequirements && + !images?.every((p: any) => + key.firstCommentRequirements === 'video' + ? p.name.includes('mp4') + : !p.name.includes('mp4') + ) + ) { + toaster.show( + `${capitalize(key?.integration?.identifier?.toUpperCase())} media should be a ${ + key.firstCommentRequirements === 'video' ? 'video' : 'image' + }`, + 'warning' + ); + return; + } + if (key.value.some((p) => !p.content || p.content.length < 6)) { setShowError(true); return; @@ -346,7 +385,10 @@ export const AddEditModal: FC<{ onChange={setSelectedIntegrations} /> )} -
+
{!existingData.integration && !showHide.hideTopEditor ? ( <>
You are in global editing mode
diff --git a/apps/frontend/src/components/launches/helpers/use.values.ts b/apps/frontend/src/components/launches/helpers/use.values.ts index 34ab1a50..0334285f 100644 --- a/apps/frontend/src/components/launches/helpers/use.values.ts +++ b/apps/frontend/src/components/launches/helpers/use.values.ts @@ -1,11 +1,28 @@ -import {useEffect, useMemo} from 'react'; -import {useForm, useFormContext} from 'react-hook-form'; -import {classValidatorResolver} from "@hookform/resolvers/class-validator"; +import { useEffect, useMemo } from 'react'; +import { useForm, useFormContext } from 'react-hook-form'; +import { classValidatorResolver } from '@hookform/resolvers/class-validator'; const finalInformation = {} as { - [key: string]: { posts: Array<{id?: string, content: string, media?: Array}>; settings: () => object; trigger: () => Promise; isValid: boolean }; + [key: string]: { + posts: Array<{ id?: string; content: string; media?: Array }>; + settings: () => object; + trigger: () => Promise; + isValid: boolean; + firstCommentRequirements?: 'video' | 'image'; + minimumMediaRequirements?: number; + maximumMediaRequirements?: number; + }; }; -export const useValues = (initialValues: object, integration: string, identifier: string, value: Array<{id?: string, content: string, media?: Array}>, dto: any) => { +export const useValues = ( + initialValues: object, + integration: string, + identifier: string, + value: Array<{ id?: string; content: string; media?: Array }>, + dto: any, + firstCommentRequirements?: 'video' | 'image', + minimumMediaRequirements?: number, + maximumMediaRequirements?: number +) => { const resolver = useMemo(() => { return classValidatorResolver(dto); }, [integration]); @@ -18,15 +35,28 @@ export const useValues = (initialValues: object, integration: string, identifier }); const getValues = useMemo(() => { - return () => ({...form.getValues(), __type: identifier}); + return () => ({ ...form.getValues(), __type: identifier }); }, [form, integration]); - finalInformation[integration]= finalInformation[integration] || {}; + finalInformation[integration] = finalInformation[integration] || {}; finalInformation[integration].posts = value; finalInformation[integration].isValid = form.formState.isValid; finalInformation[integration].settings = getValues; finalInformation[integration].trigger = form.trigger; + if (firstCommentRequirements) { + finalInformation[integration].firstCommentRequirements = + firstCommentRequirements; + } + if (minimumMediaRequirements) { + finalInformation[integration].minimumMediaRequirements = + minimumMediaRequirements; + } + if (maximumMediaRequirements) { + finalInformation[integration].maximumMediaRequirements = + maximumMediaRequirements; + } + useEffect(() => { return () => { delete finalInformation[integration]; diff --git a/apps/frontend/src/components/launches/providers/high.order.provider.tsx b/apps/frontend/src/components/launches/providers/high.order.provider.tsx index dc1d93b1..0ad00ab1 100644 --- a/apps/frontend/src/components/launches/providers/high.order.provider.tsx +++ b/apps/frontend/src/components/launches/providers/high.order.provider.tsx @@ -66,7 +66,10 @@ export const EditorWrapper: FC<{ children: ReactNode }> = ({ children }) => { export const withProvider = ( SettingsComponent: FC | null, PreviewComponent: FC, - dto?: any + dto?: any, + firstCommentRequirements?: 'video' | 'image', + minimumMediaRequirements?: number, + maximumMediaRequirements?: number, ) => { return (props: { identifier: string; @@ -117,7 +120,10 @@ export const withProvider = ( props.id, props.identifier, editInPlace ? InPlaceValue : props.value, - dto + dto, + firstCommentRequirements, + minimumMediaRequirements, + maximumMediaRequirements ); // change editor value diff --git a/apps/frontend/src/components/launches/providers/instagram/instagram.provider.tsx b/apps/frontend/src/components/launches/providers/instagram/instagram.provider.tsx index 4d2a0106..42f14098 100644 --- a/apps/frontend/src/components/launches/providers/instagram/instagram.provider.tsx +++ b/apps/frontend/src/components/launches/providers/instagram/instagram.provider.tsx @@ -109,4 +109,4 @@ const InstagramPreview: FC = (props) => { ); }; -export default withProvider(null, InstagramPreview); +export default withProvider(null, InstagramPreview, undefined, undefined, 1, 10); diff --git a/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx b/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx index 75b90ded..f925d7eb 100644 --- a/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx +++ b/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx @@ -22,6 +22,7 @@ const YoutubeSettings: FC = () => {
{ export default withProvider( YoutubeSettings, YoutubePreview, - YoutubeSettingsDto + YoutubeSettingsDto, + 'video', + 1, + 1 ); diff --git a/apps/frontend/src/components/media/media.component.tsx b/apps/frontend/src/components/media/media.component.tsx index aebed26b..b2507d33 100644 --- a/apps/frontend/src/components/media/media.component.tsx +++ b/apps/frontend/src/components/media/media.component.tsx @@ -50,9 +50,10 @@ export const showMediaBox = ( export const MediaBox: FC<{ setMedia: (params: { id: string; path: string }) => void; + type?: 'image' | 'video'; closeModal: () => void; }> = (props) => { - const { setMedia, closeModal } = props; + const { setMedia, type, closeModal } = props; const [pages, setPages] = useState(0); const [mediaList, setListMedia] = useState([]); const fetch = useFetch(); @@ -140,7 +141,13 @@ export const MediaBox: FC<{
)} - {mediaList.map((media) => ( -
- {media.path.indexOf('mp4') > -1 ? ( - - ) : ( - - )} -
- ))} + {mediaList + .filter((f) => { + if (type === 'video') { + return f.path.indexOf('mp4') > -1; + } else if (type === 'image') { + return f.path.indexOf('mp4') === -1; + } + return true; + }) + .map((media) => ( +
+ {media.path.indexOf('mp4') > -1 ? ( + + ) : ( + + )} +
+ ))}
@@ -340,8 +356,9 @@ export const MediaComponent: FC<{ onChange: (event: { target: { name: string; value?: { id: string; path: string } }; }) => void; + type?: 'image' | 'video'; }> = (props) => { - const { name, label, description, onChange, value } = props; + const { name, type, label, description, onChange, value } = props; const { getValues } = useSettings(); useEffect(() => { const settings = getValues()[props.name]; @@ -369,7 +386,9 @@ export const MediaComponent: FC<{ return (
- {modal && } + {modal && ( + + )}
{label}
{description}
{!!currentMedia && (