feat: limit fields

This commit is contained in:
Nevo David 2024-07-26 16:40:24 +07:00
parent c379247c28
commit b195608f3b
17 changed files with 69 additions and 29 deletions

View File

@ -14,6 +14,9 @@ html {
position: relative;
z-index: 2;
}
#tooltip {
z-index: 10000;
}
.box:after {
border-radius: 50px;
width: 100%;

View File

@ -260,18 +260,36 @@ export const AddEditModal: FC<{
group: existingData?.group,
trigger: values[v].trigger,
settings: values[v].settings(),
checkValidity: values[v].checkValidity
checkValidity: values[v].checkValidity,
maximumCharacters: values[v].maximumCharacters,
}));
for (const key of allKeys) {
if (key.checkValidity) {
const check = await key.checkValidity(key?.value.map((p: any) => p.image || []));
const check = await key.checkValidity(
key?.value.map((p: any) => p.image || [])
);
if (typeof check === 'string') {
toaster.show(check, 'warning');
return;
}
}
if (
key.value.some(
(p) => p.content.length > (key.maximumCharacters || 1000000)
)
) {
if (
!(await deleteDialog(
`${key?.integration?.name} post is too long, it will be cropped, do you want to continue?`
))
) {
await key.trigger();
moveToIntegration({identifier: key?.integration?.id!, toPreview: true});
return;
}
}
if (key.value.some((p) => !p.content || p.content.length < 6)) {
setShowError(true);
@ -280,7 +298,7 @@ export const AddEditModal: FC<{
if (!key.valid) {
await key.trigger();
moveToIntegration(key?.integration?.id!);
moveToIntegration({identifier: key?.integration?.id!});
return;
}
}
@ -305,7 +323,14 @@ export const AddEditModal: FC<{
);
modal.closeAll();
},
[postFor, dateState, value, integrations, existingData, selectedIntegrations]
[
postFor,
dateState,
value,
integrations,
existingData,
selectedIntegrations,
]
);
const getPostsMarketplace = useCallback(async () => {
@ -373,7 +398,7 @@ export const AddEditModal: FC<{
{!existingData.integration && (
<PickPlatforms
integrations={integrations.filter(f => !f.disabled)}
integrations={integrations.filter((f) => !f.disabled)}
selectedIntegrations={[]}
singleSelect={false}
onChange={setSelectedIntegrations}

View File

@ -4,16 +4,17 @@ import { useFormatting } from '@gitroom/frontend/components/launches/helpers/use
import clsx from 'clsx';
import { VideoOrImage } from '@gitroom/react/helpers/video.or.image';
import { Chakra_Petch } from 'next/font/google';
import { FC } from 'react';
const chakra = Chakra_Petch({ weight: '400', subsets: ['latin'] });
export const GeneralPreviewComponent = () => {
export const GeneralPreviewComponent: FC<{maximumCharacters?: number}> = (props) => {
const { value: topValue, integration } = useIntegration();
const mediaDir = useMediaDirectory();
const newValues = useFormatting(topValue, {
removeMarkdown: true,
saveBreaklines: true,
specialFunc: (text: string) => {
return text.slice(0, 280);
return text.slice(0, props.maximumCharacters || 10000) + '<mark class="bg-red-500" data-tooltip-id="tooltip" data-tooltip-content="This text will be cropped">' + text?.slice(props.maximumCharacters || 10000) + '</mark>';
},
});
@ -61,9 +62,7 @@ export const GeneralPreviewComponent = () => {
@username
</div>
</div>
<pre className={clsx('text-wrap', chakra.className)}>
{value.text}
</pre>
<pre className={clsx('text-wrap', chakra.className)} dangerouslySetInnerHTML={{__html: value.text}} />
{!!value?.images?.length && (
<div className={clsx("w-full rounded-[16px] overflow-hidden mt-[12px]", value?.images?.length > 3 ? 'grid grid-cols-2 gap-[4px]' : 'flex gap-[4px]')}>
{value.images.map((image, index) => (

View File

@ -65,7 +65,7 @@ export const PickPlatforms: FC<{
useMoveToIntegrationListener(
[integrations],
props.singleSelect,
(identifier) => {
({identifier, toPreview}: {identifier: string, toPreview: boolean}) => {
const findIntegration = integrations.find((p) => p.id === identifier);
if (findIntegration) {

View File

@ -10,7 +10,7 @@ export const useFormatting = (
params: {
removeMarkdown?: boolean;
saveBreaklines?: boolean;
specialFunc?: (text: string) => string;
specialFunc?: (text: string) => any;
beforeSpecialFunc?: (text: string) => string;
}
) => {

View File

@ -5,15 +5,15 @@ import { useCallback, useEffect } from 'react';
const emitter = new EventEmitter();
export const useMoveToIntegration = () => {
return useCallback((identifier: string) => {
emitter.emit('moveToIntegration', identifier);
return useCallback(({identifier, toPreview}: {identifier: string, toPreview?: boolean}) => {
emitter.emit('moveToIntegration', {identifier, toPreview});
}, []);
};
export const useMoveToIntegrationListener = (
useEffectParams: any[],
enabled: boolean,
callback: (identifier: string) => void
callback: ({identifier, toPreview}: {identifier: string, toPreview: boolean}) => void
) => {
useEffect(() => {
if (!enabled) {

View File

@ -9,6 +9,7 @@ const finalInformation = {} as {
trigger: () => Promise<boolean>;
isValid: boolean;
checkValidity?: (value: Array<Array<{path: string}>>) => Promise<string|true>;
maximumCharacters?: number;
};
};
export const useValues = (
@ -18,6 +19,7 @@ export const useValues = (
value: Array<{ id?: string; content: string; media?: Array<string> }>,
dto: any,
checkValidity?: (value: Array<Array<{path: string}>>) => Promise<string|true>,
maximumCharacters?: number,
) => {
const resolver = useMemo(() => {
return classValidatorResolver(dto);
@ -45,6 +47,10 @@ export const useValues = (
checkValidity;
}
if (maximumCharacters) {
finalInformation[integration].maximumCharacters = maximumCharacters;
}
useEffect(() => {
return () => {
delete finalInformation[integration];

View File

@ -129,4 +129,4 @@ const FacebookPreview: FC = (props) => {
);
};
export default withProvider(null, FacebookPreview);
export default withProvider(null, FacebookPreview, undefined, undefined, 63206);

View File

@ -72,7 +72,8 @@ export const withProvider = (
SettingsComponent: FC | null,
PreviewComponent: FC,
dto?: any,
checkValidity?: (value: Array<Array<{path: string}>>) => Promise<string|true>
checkValidity?: (value: Array<Array<{path: string}>>) => Promise<string|true>,
maximumCharacters?: number
) => {
return (props: {
identifier: string;
@ -115,9 +116,9 @@ export const withProvider = (
}, [SettingsComponent]);
// in case there is an error on submit, we change to the settings tab for the specific provider
useMoveToIntegrationListener([props.id], true, (identifier) => {
useMoveToIntegrationListener([props.id], true, ({identifier, toPreview}) => {
if (identifier === props.id) {
setShowTab(2);
setShowTab(toPreview ? 1 : 2);
}
});
@ -128,7 +129,8 @@ export const withProvider = (
props.identifier,
editInPlace ? InPlaceValue : props.value,
dto,
checkValidity
checkValidity,
maximumCharacters
);
// change editor value
@ -398,7 +400,7 @@ export const withProvider = (
{(editInPlace ? InPlaceValue : props.value)
.map((p) => p.content)
.join('').length ? (
<GeneralPreviewComponent />
<GeneralPreviewComponent maximumCharacters={maximumCharacters} />
) : (
<>No Content Yet</>
)}

View File

@ -138,5 +138,6 @@ export default withProvider(
}
return true;
}
},
2200
);

View File

@ -129,4 +129,4 @@ const LinkedinPreview: FC = (props) => {
);
};
export default withProvider(null, LinkedinPreview);
export default withProvider(null, LinkedinPreview, undefined, undefined, 3000);

View File

@ -203,5 +203,6 @@ export default withProvider(
}
return true;
}
},
500
);

View File

@ -202,4 +202,4 @@ const RedditSettings: FC = () => {
);
};
export default withProvider(RedditSettings, RedditPreview, RedditSettingsDto);
export default withProvider(RedditSettings, RedditPreview, RedditSettingsDto, undefined, 10000);

View File

@ -134,5 +134,6 @@ export default withProvider(
undefined,
async ([firstPost, ...otherPosts]) => {
return true;
}
},
500
);

View File

@ -276,5 +276,6 @@ export default withProvider(
}
return true;
}
},
2200
);

View File

@ -102,4 +102,4 @@ const XPreview: FC = (props) => {
);
};
export default withProvider(null, XPreview);
export default withProvider(null, XPreview, undefined, undefined, 280);

View File

@ -185,5 +185,6 @@ export default withProvider(
}
return true;
}
},
5000
);