feat: more channels

This commit is contained in:
Nevo David 2024-05-27 11:25:35 +07:00
parent e51906d485
commit d2ba83d0b1
6 changed files with 133 additions and 32 deletions

View File

@ -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}
/>
)}
<div id="renderEditor" className={clsx(!showHide.hideTopEditor && 'hidden')} />
<div
id="renderEditor"
className={clsx(!showHide.hideTopEditor && 'hidden')}
/>
{!existingData.integration && !showHide.hideTopEditor ? (
<>
<div>You are in global editing mode</div>

View File

@ -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<string>}>; settings: () => object; trigger: () => Promise<boolean>; isValid: boolean };
[key: string]: {
posts: Array<{ id?: string; content: string; media?: Array<string> }>;
settings: () => object;
trigger: () => Promise<boolean>;
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<string>}>, dto: any) => {
export const useValues = (
initialValues: object,
integration: string,
identifier: string,
value: Array<{ id?: string; content: string; media?: Array<string> }>,
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];

View File

@ -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

View File

@ -109,4 +109,4 @@ const InstagramPreview: FC = (props) => {
);
};
export default withProvider(null, InstagramPreview);
export default withProvider(null, InstagramPreview, undefined, undefined, 1, 10);

View File

@ -22,6 +22,7 @@ const YoutubeSettings: FC = () => {
<MediumTags label="Tags" {...register('tags')} />
<div className="mt-[20px]">
<MediaComponent
type="image"
label="Thumbnail"
description="Thumbnail picture (optional)"
{...register('thumbnail')}
@ -134,5 +135,8 @@ const YoutubePreview: FC = (props) => {
export default withProvider(
YoutubeSettings,
YoutubePreview,
YoutubeSettingsDto
YoutubeSettingsDto,
'video',
1,
1
);

View File

@ -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<Media[]>([]);
const fetch = useFetch();
@ -140,7 +141,13 @@ export const MediaBox: FC<{
<input
type="file"
className="absolute left-0 top-0 w-full h-full opacity-0"
accept="image/*,video/mp4"
accept={
type === 'video'
? 'video/mp4'
: type === 'image'
? 'image/*'
: 'image/*,video/mp4'
}
onChange={uploadMedia}
/>
<button
@ -207,22 +214,31 @@ export const MediaBox: FC<{
</div>
</div>
)}
{mediaList.map((media) => (
<div
key={media.id}
className="w-[200px] h-[200px] border-tableBorder border-2 cursor-pointer"
onClick={setNewMedia(media)}
>
{media.path.indexOf('mp4') > -1 ? (
<VideoFrame url={mediaDirectory.set(media.path)} />
) : (
<img
className="w-full h-full object-cover"
src={mediaDirectory.set(media.path)}
/>
)}
</div>
))}
{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) => (
<div
key={media.id}
className="w-[200px] h-[200px] border-tableBorder border-2 cursor-pointer"
onClick={setNewMedia(media)}
>
{media.path.indexOf('mp4') > -1 ? (
<VideoFrame url={mediaDirectory.set(media.path)} />
) : (
<img
className="w-full h-full object-cover"
src={mediaDirectory.set(media.path)}
/>
)}
</div>
))}
</div>
</div>
</div>
@ -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 (
<div className="flex flex-col gap-[8px]">
{modal && <MediaBox setMedia={changeMedia} closeModal={showModal} />}
{modal && (
<MediaBox setMedia={changeMedia} closeModal={showModal} type={type} />
)}
<div className="text-[14px]">{label}</div>
<div className="text-[12px]">{description}</div>
{!!currentMedia && (