feat: refactor for creation modal

This commit is contained in:
Nevo David 2025-12-25 18:29:12 +07:00
parent ec623a678e
commit 37c45743a8
36 changed files with 2522 additions and 913 deletions

View File

@ -1,7 +1,11 @@
:root {
.dark {
--new-back-drop: #000;
--new-settings: #242323;
--new-border: #252525;
--new-bgColor: #0e0e0e;
--new-bgColorInner: #1a1919;
--new-sep: #454444;
--new-bgLineColor: #212121;
--new-textItemFocused: #1a1919;
--new-textItemBlur: #999999;
@ -26,6 +30,10 @@
--popup-color: rgba(65, 64, 66, 0.3);
}
.light {
--new-back-drop: #2d1b57;
--new-settings: #ECEEF1;
--new-sep: #D5D9DD;
--new-border: #EAECEE;
--new-bgColor: #f0f2f4;
--new-bgColorInner: #ffffff;
--new-bgLineColor: #e7e9eb;

View File

@ -679,6 +679,9 @@ html[dir='rtl'] [dir='ltr'] {
.blur-xs {
filter: blur(4px);
}
.blur-s {
filter: blur(5px);
}
.agent {
.copilotKitInputContainer {
@ -736,7 +739,45 @@ html[dir='rtl'] [dir='ltr'] {
background: transparent !important;
}
//html body iframe[title="Stripe developer tools frame"] {
// display: none !important;
// height: 0 !important;
//}
.menu-shadow {
border-radius: 12px;
box-shadow: 0 8px 30px 0 rgba(0, 0, 0, 0.5);
}
.post-now {
box-shadow: -33px 57px 18px 0 rgba(0, 0, 0, 0.01), -21px 36px 17px 0 rgba(0, 0, 0, 0.06), -12px 20px 14px 0 rgba(0, 0, 0, 0.20), -5px 9px 11px 0 rgba(0, 0, 0, 0.34), -1px 2px 6px 0 rgba(0, 0, 0, 0.39);
}
.uppyChange .uppy-Dashboard-inner {
width: 100% !important;
}
.btnSub:disabled .arrow-change {
display: none !important;
}
.btnSub:disabled + button {
display: none !important;
}
.tiptap p.is-editor-empty:first-child::before {
color: #adb5bd;
content: attr(data-placeholder);
float: left;
height: 0;
pointer-events: none;
}
.w8-max {
width: calc(100% / 6);
max-width: calc(100% / 6);
}
.withp3 {
width: calc(100% + 9px);
height: calc(100% + 6px);
}
.forceChange .changeColor {
background: var(--new-btn-primary) !important;
color: #fff !important;
}

View File

@ -28,7 +28,7 @@ export const AiImage: FC<{
const t = useT();
const { value, onChange } = props;
const [loading, setLoading] = useState(false);
const setLocked = useLaunchStore(p => p.setLocked);
const setLocked = useLaunchStore((p) => p.setLocked);
const fetch = useFetch();
const generateImage = useCallback(
(type: string) => async () => {
@ -59,7 +59,7 @@ ${type}
);
return (
<div className="relative group">
<Button
<div
{...(value.length < 30
? {
'data-tooltip-id': 'tooltip',
@ -68,13 +68,13 @@ ${type}
}
: {})}
className={clsx(
'relative ms-[10px] rounded-[4px] gap-[8px] !text-primary justify-center items-center flex border border-dashed border-newBgLineColor bg-newColColor',
value.length < 30 && 'opacity-25'
'cursor-pointer h-[30px] rounded-[6px] justify-center items-center flex bg-newColColor px-[8px]',
value.length < 30 && 'opacity-50'
)}
>
{loading && (
<div className="absolute start-[50%] -translate-x-[50%]">
<Loading height={30} width={30} type="spin" color="#fff" />
<Loading height={15} width={15} type="spin" color="#fff" />
</div>
)}
<div
@ -86,24 +86,32 @@ ${type}
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M19.5 3H7.5C7.10218 3 6.72064 3.15804 6.43934 3.43934C6.15804 3.72064 6 4.10218 6 4.5V6H4.5C4.10218 6 3.72064 6.15804 3.43934 6.43934C3.15804 6.72064 3 7.10218 3 7.5V19.5C3 19.8978 3.15804 20.2794 3.43934 20.5607C3.72064 20.842 4.10218 21 4.5 21H16.5C16.8978 21 17.2794 20.842 17.5607 20.5607C17.842 20.2794 18 19.8978 18 19.5V18H19.5C19.8978 18 20.2794 17.842 20.5607 17.5607C20.842 17.2794 21 16.8978 21 16.5V4.5C21 4.10218 20.842 3.72064 20.5607 3.43934C20.2794 3.15804 19.8978 3 19.5 3ZM7.5 4.5H19.5V11.0044L17.9344 9.43875C17.6531 9.15766 17.2717 8.99976 16.8741 8.99976C16.4764 8.99976 16.095 9.15766 15.8137 9.43875L8.75344 16.5H7.5V4.5ZM16.5 19.5H4.5V7.5H6V16.5C6 16.8978 6.15804 17.2794 6.43934 17.5607C6.72064 17.842 7.10218 18 7.5 18H16.5V19.5ZM19.5 16.5H10.875L16.875 10.5L19.5 13.125V16.5ZM11.25 10.5C11.695 10.5 12.13 10.368 12.5 10.1208C12.87 9.87357 13.1584 9.52217 13.3287 9.11104C13.499 8.6999 13.5436 8.2475 13.4568 7.81105C13.37 7.37459 13.1557 6.97368 12.841 6.65901C12.5263 6.34434 12.1254 6.13005 11.689 6.04323C11.2525 5.95642 10.8001 6.00097 10.389 6.17127C9.97783 6.34157 9.62643 6.62996 9.37919 6.99997C9.13196 7.36998 9 7.80499 9 8.25C9 8.84674 9.23705 9.41903 9.65901 9.84099C10.081 10.2629 10.6533 10.5 11.25 10.5ZM11.25 7.5C11.3983 7.5 11.5433 7.54399 11.6667 7.6264C11.79 7.70881 11.8861 7.82594 11.9429 7.96299C11.9997 8.10003 12.0145 8.25083 11.9856 8.39632C11.9566 8.5418 11.8852 8.67544 11.7803 8.78033C11.6754 8.88522 11.5418 8.95665 11.3963 8.98559C11.2508 9.01453 11.1 8.99968 10.963 8.94291C10.8259 8.88614 10.7088 8.79001 10.6264 8.66668C10.544 8.54334 10.5 8.39834 10.5 8.25C10.5 8.05109 10.579 7.86032 10.7197 7.71967C10.8603 7.57902 11.0511 7.5 11.25 7.5Z"
fill="currentColor"
/>
<g clip-path="url(#clip0_2352_53053)">
<path
d="M8.33333 2.00033H5.2C4.07989 2.00033 3.51984 2.00033 3.09202 2.21831C2.71569 2.41006 2.40973 2.71602 2.21799 3.09234C2 3.52017 2 4.08022 2 5.20032V10.8003C2 11.9204 2 12.4805 2.21799 12.9083C2.40973 13.2846 2.71569 13.5906 3.09202 13.7823C3.51984 14.0003 4.07989 14.0003 5.2 14.0003H11.3333C11.9533 14.0003 12.2633 14.0003 12.5176 13.9322C13.2078 13.7472 13.7469 13.2081 13.9319 12.518C14 12.2636 14 11.9536 14 11.3337M7 5.66699C7 6.40337 6.40305 7.00033 5.66667 7.00033C4.93029 7.00033 4.33333 6.40337 4.33333 5.66699C4.33333 4.93061 4.93029 4.33366 5.66667 4.33366C6.40305 4.33366 7 4.93061 7 5.66699ZM9.99336 7.94576L4.3541 13.0724C4.03691 13.3607 3.87831 13.5049 3.86429 13.6298C3.85213 13.738 3.89364 13.8454 3.97546 13.9173C4.06985 14.0003 4.28419 14.0003 4.71286 14.0003H10.9707C11.9301 14.0003 12.4098 14.0003 12.7866 13.8391C13.2596 13.6368 13.6365 13.2599 13.8388 12.7869C14 12.4101 14 11.9304 14 10.971C14 10.6482 14 10.4867 13.9647 10.3364C13.9204 10.1475 13.8353 9.97056 13.7155 9.81792C13.6202 9.69646 13.4941 9.59562 13.242 9.39396L11.3772 7.9021C11.1249 7.70026 10.9988 7.59935 10.8599 7.56373C10.7374 7.53234 10.6086 7.53641 10.4884 7.57545C10.352 7.61975 10.2324 7.72842 9.99336 7.94576ZM13 1.01074L12.5932 1.82425C12.4556 2.09958 12.3868 2.23724 12.2948 2.35653C12.2132 2.46238 12.1183 2.55728 12.0125 2.63887C11.8932 2.73083 11.7555 2.79966 11.4802 2.93732L10.6667 3.34408L11.4802 3.75083C11.7555 3.88849 11.8932 3.95732 12.0125 4.04928C12.1183 4.13087 12.2132 4.22577 12.2948 4.33162C12.3868 4.45091 12.4556 4.58857 12.5932 4.8639L13 5.67741L13.4068 4.8639C13.5444 4.58857 13.6132 4.45091 13.7052 4.33162C13.7868 4.22577 13.8817 4.13087 13.9875 4.04928C14.1068 3.95732 14.2445 3.88849 14.5198 3.75083L15.3333 3.34408L14.5198 2.93732C14.2445 2.79966 14.1068 2.73083 13.9875 2.63887C13.8817 2.55728 13.7868 2.46238 13.7052 2.35653C13.6132 2.23724 13.5444 2.09958 13.4068 1.82425L13 1.01074Z"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_2352_53053">
<rect width="16" height="16" fill="currentColor" />
</clipPath>
</defs>
</svg>
</div>
<div className="text-[12px] font-[500] !text-current">
{t('ai', 'AI')} Image
</div>
<div className="text-[10px] font-[600] iconBreak:hidden block">{t('ai', 'AI')} Image</div>
</div>
</Button>
</div>
{value.length >= 30 && !loading && (
<div className="text-[12px] ms-[10px] -mt-[10px] w-[200px] absolute top-[100%] z-[500] start-0 hidden group-hover:block">
<div className="text-[12px] -mt-[10px] w-[200px] absolute bottom-[100%] z-[500] start-0 hidden group-hover:block">
<ul className="cursor-pointer rounded-[4px] border border-dashed mt-[3px] p-[5px] border-newBgLineColor bg-newColColor">
{list.map((p) => (
<li onClick={generateImage(p)} key={p} className="hover:bg-sixth">

View File

@ -44,9 +44,9 @@ export const Modal: FC<{
setLocked(true);
const customParams = form.getValues();
if (!await form.trigger()) {
if (!(await form.trigger())) {
toaster.show('Please fill all required fields', 'warning');
return ;
return;
}
try {
const image = await fetch(`/media/generate-video`, {
@ -199,7 +199,7 @@ export const AiVideo: FC<{
/>
)}
<div className="relative group">
<Button
<div
{...(value.length < 30
? {
'data-tooltip-id': 'tooltip',
@ -208,8 +208,8 @@ export const AiVideo: FC<{
}
: {})}
className={clsx(
'relative ms-[10px] rounded-[4px] gap-[8px] !text-primary justify-center items-center flex border border-dashed border-newBgLineColor bg-newColColor',
value.length < 30 && 'opacity-25'
'cursor-pointer h-[30px] rounded-[6px] justify-center items-center flex bg-newColColor px-[8px]',
value.length < 30 && 'opacity-50'
)}
>
{loading && (
@ -226,24 +226,32 @@ export const AiVideo: FC<{
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M19.5 3H7.5C7.10218 3 6.72064 3.15804 6.43934 3.43934C6.15804 3.72064 6 4.10218 6 4.5V6H4.5C4.10218 6 3.72064 6.15804 3.43934 6.43934C3.15804 6.72064 3 7.10218 3 7.5V19.5C3 19.8978 3.15804 20.2794 3.43934 20.5607C3.72064 20.842 4.10218 21 4.5 21H16.5C16.8978 21 17.2794 20.842 17.5607 20.5607C17.842 20.2794 18 19.8978 18 19.5V18H19.5C19.8978 18 20.2794 17.842 20.5607 17.5607C20.842 17.2794 21 16.8978 21 16.5V4.5C21 4.10218 20.842 3.72064 20.5607 3.43934C20.2794 3.15804 19.8978 3 19.5 3ZM7.5 4.5H19.5V11.0044L17.9344 9.43875C17.6531 9.15766 17.2717 8.99976 16.8741 8.99976C16.4764 8.99976 16.095 9.15766 15.8137 9.43875L8.75344 16.5H7.5V4.5ZM16.5 19.5H4.5V7.5H6V16.5C6 16.8978 6.15804 17.2794 6.43934 17.5607C6.72064 17.842 7.10218 18 7.5 18H16.5V19.5ZM19.5 16.5H10.875L16.875 10.5L19.5 13.125V16.5ZM11.25 10.5C11.695 10.5 12.13 10.368 12.5 10.1208C12.87 9.87357 13.1584 9.52217 13.3287 9.11104C13.499 8.6999 13.5436 8.2475 13.4568 7.81105C13.37 7.37459 13.1557 6.97368 12.841 6.65901C12.5263 6.34434 12.1254 6.13005 11.689 6.04323C11.2525 5.95642 10.8001 6.00097 10.389 6.17127C9.97783 6.34157 9.62643 6.62996 9.37919 6.99997C9.13196 7.36998 9 7.80499 9 8.25C9 8.84674 9.23705 9.41903 9.65901 9.84099C10.081 10.2629 10.6533 10.5 11.25 10.5ZM11.25 7.5C11.3983 7.5 11.5433 7.54399 11.6667 7.6264C11.79 7.70881 11.8861 7.82594 11.9429 7.96299C11.9997 8.10003 12.0145 8.25083 11.9856 8.39632C11.9566 8.5418 11.8852 8.67544 11.7803 8.78033C11.6754 8.88522 11.5418 8.95665 11.3963 8.98559C11.2508 9.01453 11.1 8.99968 10.963 8.94291C10.8259 8.88614 10.7088 8.79001 10.6264 8.66668C10.544 8.54334 10.5 8.39834 10.5 8.25C10.5 8.05109 10.579 7.86032 10.7197 7.71967C10.8603 7.57902 11.0511 7.5 11.25 7.5Z"
fill="currentColor"
/>
<g clip-path="url(#clip0_2352_53058)">
<path
d="M8.06916 14.1663V2.04134M4.97208 14.1663V11.1351M4.97208 5.07259V2.04134M11.1662 14.1663V11.1351M9.09973 2.02152L4.8482 2.04134C3.80748 2.04134 3.28712 2.04134 2.88962 2.23957C2.53997 2.41394 2.25569 2.69218 2.07754 3.0344C1.875 3.42345 1.875 3.93275 1.875 4.95134L1.875 11.2563C1.875 12.2749 1.875 12.7842 2.07754 13.1733C2.25569 13.5155 2.53997 13.7937 2.88962 13.9681C3.28712 14.1663 3.80748 14.1663 4.8482 14.1663H11.2901C12.3308 14.1663 12.8512 14.1663 13.2487 13.9681C13.5984 13.7937 13.8826 13.5155 14.0608 13.1733C14.2633 12.7842 14.2633 12.2749 14.2633 11.2563V7.61426M1.875 5.07259L9.09973 5.06116M1.875 11.1351H14.2633M12.8141 1.20801L12.3949 2.02152C12.253 2.29684 12.1821 2.4345 12.0873 2.55379C12.0032 2.65965 11.9054 2.75455 11.7963 2.83614C11.6734 2.92809 11.5315 2.99692 11.2478 3.13458L10.4094 3.54134L11.2478 3.9481C11.5315 4.08576 11.6734 4.15459 11.7963 4.24654C11.9054 4.32814 12.0032 4.42303 12.0873 4.52889C12.1821 4.64818 12.253 4.78584 12.3949 5.06116L12.8141 5.87467L13.2333 5.06116C13.3751 4.78584 13.4461 4.64818 13.5408 4.52889C13.6249 4.42303 13.7227 4.32814 13.8318 4.24654C13.9548 4.15459 14.0966 4.08576 14.3804 3.9481L15.2188 3.54134L14.3804 3.13458C14.0966 2.99692 13.9548 2.92809 13.8318 2.83614C13.7227 2.75455 13.6249 2.65965 13.5408 2.55379C13.4461 2.4345 13.3751 2.29684 13.2333 2.02152L12.8141 1.20801Z"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_2352_53058">
<rect width="16" height="16" fill="currentColor" />
</clipPath>
</defs>
</svg>
</div>
<div className="text-[12px] font-[500] !text-current">
{t('ai', 'AI')} Video
</div>
<div className="text-[10px] font-[600] iconBreak:hidden block">{t('ai', 'AI')} Video</div>
</div>
</Button>
</div>
{value.length >= 30 && !loading && (
<div className="text-[12px] ms-[10px] -mt-[10px] w-[200px] absolute top-[100%] z-[500] start-0 hidden group-hover:block">
<div className="text-[12px] -mt-[10px] w-[200px] absolute bottom-[100%] z-[500] start-0 hidden group-hover:block">
<ul className="cursor-pointer rounded-[4px] border border-dashed border-newBgLineColor bg-newColColor mt-[3px] p-[5px]">
{data.map((p: any) => (
<li

View File

@ -471,6 +471,7 @@ export const CalendarColumn: FC<{
closeOnEscape: false,
withCloseButton: false,
askClose: true,
fullScreen: true,
classNames: {
modal: 'w-[100%] max-w-[1400px] text-textColor',
},
@ -551,9 +552,10 @@ export const CalendarColumn: FC<{
closeOnEscape: false,
withCloseButton: false,
removeLayout: true,
fullScreen: true,
askClose: true,
classNames: {
modal: 'w-[100%] max-w-[1400px] text-textColor',
modal: 'fixed left-0 top-0 w-full h-full',
},
id: 'add-edit-modal',
children: (

View File

@ -49,7 +49,7 @@ export const GeneralPreviewComponent: FC<{
});
return (
<div className={clsx('w-full md:w-[555px] px-[16px]')}>
<div className={clsx('w-full md:w-[555px]')}>
<div className="w-full h-full relative flex flex-col">
{renderContent.map((value, index) => (
<div

View File

@ -34,31 +34,34 @@ export const DatePicker: FC<{
);
return (
<div
className="flex gap-[8px] items-center relative px-[16px] select-none"
className="px-[16px] border border-newTextColor/10 rounded-[8px] justify-center flex gap-[8px] items-center relative h-[44px] text-[15px] font-[600] ml-[7px] select-none flex-1"
onClick={changeShow}
ref={ref}
>
<div className="cursor-pointer">
{date.format(isUSCitizen() ? 'MM/DD/YYYY hh:mm A' : 'DD/MM/YYYY HH:mm')}
</div>
<div className="cursor-pointer">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="21"
viewBox="0 0 20 21"
width="17"
height="19"
viewBox="0 0 17 19"
fill="none"
>
<path
d="M16.25 3H14.375V2.375C14.375 2.20924 14.3092 2.05027 14.1919 1.93306C14.0747 1.81585 13.9158 1.75 13.75 1.75C13.5842 1.75 13.4253 1.81585 13.3081 1.93306C13.1908 2.05027 13.125 2.20924 13.125 2.375V3H6.875V2.375C6.875 2.20924 6.80915 2.05027 6.69194 1.93306C6.57473 1.81585 6.41576 1.75 6.25 1.75C6.08424 1.75 5.92527 1.81585 5.80806 1.93306C5.69085 2.05027 5.625 2.20924 5.625 2.375V3H3.75C3.41848 3 3.10054 3.1317 2.86612 3.36612C2.6317 3.60054 2.5 3.91848 2.5 4.25V16.75C2.5 17.0815 2.6317 17.3995 2.86612 17.6339C3.10054 17.8683 3.41848 18 3.75 18H16.25C16.5815 18 16.8995 17.8683 17.1339 17.6339C17.3683 17.3995 17.5 17.0815 17.5 16.75V4.25C17.5 3.91848 17.3683 3.60054 17.1339 3.36612C16.8995 3.1317 16.5815 3 16.25 3ZM16.25 6.75H3.75V4.25H5.625V4.875C5.625 5.04076 5.69085 5.19973 5.80806 5.31694C5.92527 5.43415 6.08424 5.5 6.25 5.5C6.41576 5.5 6.57473 5.43415 6.69194 5.31694C6.80915 5.19973 6.875 5.04076 6.875 4.875V4.25H13.125V4.875C13.125 5.04076 13.1908 5.19973 13.3081 5.31694C13.4253 5.43415 13.5842 5.5 13.75 5.5C13.9158 5.5 14.0747 5.43415 14.1919 5.31694C14.3092 5.19973 14.375 5.04076 14.375 4.875V4.25H16.25V6.75Z"
fill="#B69DEC"
d="M15.75 7.41667H0.75M11.5833 0.75V4.08333M4.91667 0.75V4.08333M4.75 17.4167H11.75C13.1501 17.4167 13.8502 17.4167 14.385 17.1442C14.8554 16.9045 15.2378 16.522 15.4775 16.0516C15.75 15.5169 15.75 14.8168 15.75 13.4167V6.41667C15.75 5.01654 15.75 4.31647 15.4775 3.78169C15.2378 3.31129 14.8554 2.92883 14.385 2.68915C13.8502 2.41667 13.1501 2.41667 11.75 2.41667H4.75C3.34987 2.41667 2.6498 2.41667 2.11502 2.68915C1.64462 2.92883 1.26217 3.31129 1.02248 3.78169C0.75 4.31647 0.75 5.01654 0.75 6.41667V13.4167C0.75 14.8168 0.75 15.5169 1.02248 16.0516C1.26217 16.522 1.64462 16.9045 2.11502 17.1442C2.6498 17.4167 3.34987 17.4167 4.75 17.4167Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="cursor-pointer">
{date.format(isUSCitizen() ? 'MM/DD/YYYY hh:mm A' : 'DD/MM/YYYY HH:mm')}
</div>
{open && (
<div
onClick={(e) => 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"
className="animate-fadeIn absolute bottom-[100%] mb-[16px] start-[50%] -translate-x-[50%] bg-sixth border border-tableBorder text-textColor rounded-[16px] z-[300] p-[16px] flex flex-col"
>
<Calendar
onChange={changeDate('date')}
@ -92,7 +95,7 @@ export const DatePicker: FC<{
defaultValue={date.toDate()}
/>
<Button className="mt-[12px]" onClick={changeShow}>
{t('save', 'Save')}
{t('close', 'Close')}
</Button>
</div>
)}

View File

@ -0,0 +1,205 @@
import React, { FC, Fragment, useMemo } from 'react';
import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store';
import { useShallow } from 'zustand/react/shallow';
import clsx from 'clsx';
import Image from 'next/image';
import { capitalize } from 'lodash';
const Valid: FC = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M6 7.33333L8 9.33333L14.6667 2.66667M10.6667 2H5.2C4.0799 2 3.51984 2 3.09202 2.21799C2.71569 2.40973 2.40973 2.71569 2.21799 3.09202C2 3.51984 2 4.07989 2 5.2V10.8C2 11.9201 2 12.4802 2.21799 12.908C2.40973 13.2843 2.71569 13.5903 3.09202 13.782C3.51984 14 4.07989 14 5.2 14H10.8C11.9201 14 12.4802 14 12.908 13.782C13.2843 13.5903 13.5903 13.2843 13.782 12.908C14 12.4802 14 11.9201 14 10.8V8"
stroke="#00EB75"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};
const Invalid: FC = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<g clip-path="url(#clip0_2482_97670)">
<path
d="M8.00049 6.00015V8.66682M8.00049 11.3335H8.00715M7.07737 2.59464L1.59411 12.0657C1.28997 12.591 1.1379 12.8537 1.16038 13.0693C1.17998 13.2573 1.2785 13.4282 1.4314 13.5394C1.60671 13.6668 1.91022 13.6668 2.51723 13.6668H13.4837C14.0908 13.6668 14.3943 13.6668 14.5696 13.5394C14.7225 13.4282 14.821 13.2573 14.8406 13.0693C14.8631 12.8537 14.711 12.591 14.4069 12.0657L8.92361 2.59463C8.62056 2.07119 8.46904 1.80947 8.27135 1.72157C8.09892 1.64489 7.90206 1.64489 7.72962 1.72157C7.53193 1.80947 7.38041 2.07119 7.07737 2.59464Z"
stroke="white"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_2482_97670">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
);
};
export const InformationComponent: FC<{
chars: Record<string, number>;
totalChars: number;
totalAllowedChars: number;
isPicture: boolean;
}> = ({ totalChars, totalAllowedChars, chars, isPicture }) => {
const { isGlobal, selectedIntegrations, internal } = useLaunchStore(
useShallow((state) => ({
isGlobal: state.current === 'global',
selectedIntegrations: state.selectedIntegrations,
internal: state.internal,
}))
);
const isInternal = useMemo(() => {
if (!isGlobal) {
return [];
}
return selectedIntegrations.map((p) => {
const findIt = internal.find(
(a) => a.integration.id === p.integration.id
);
return !!findIt;
});
}, [isGlobal, internal, selectedIntegrations]);
const isValid = useMemo(() => {
if (!isPicture && !totalChars) {
return false;
}
if (totalChars > totalAllowedChars && !isGlobal) {
return false;
}
if (totalChars <= totalAllowedChars && !isGlobal) {
return true;
}
if (
selectedIntegrations.some((p, index) => {
if (isInternal[index]) {
return false;
}
return totalChars > (chars?.[p.integration.id] || 0);
})
) {
return false;
}
return true;
}, [totalAllowedChars, totalChars, isInternal, isPicture]);
return (
<div
className={clsx(
'group rounded-[6px] gap-[4px] h-[30px] px-[6px] flex justify-center items-center relative',
isValid ? 'border border-newColColor' : 'bg-[#FF3F3F]'
)}
>
{isValid ? <Valid /> : <Invalid />}
{!isGlobal && (
<div className="text-[10px] font-[600] flex justify-center items-center">
{totalChars}/{totalAllowedChars}
</div>
)}
{((isGlobal && selectedIntegrations.length) || !isValid) && (
<svg
className="group-hover:rotate-180"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M5.4563 6L10.5437 6C10.9494 6 11.1526 6.56798 10.8657 6.90016L8.32201 9.84556C8.14417 10.0515 7.85583 10.0515 7.67799 9.84556L5.13429 6.90016C4.84741 6.56798 5.05059 6 5.4563 6Z"
fill="currentColor"
/>
</svg>
)}
{((isGlobal && selectedIntegrations.length) || !isValid) && (
<div
className={clsx(
'z-[300] hidden rounded-[12px] bg-newBgColorInner group-hover:flex absolute end-0 bottom-[100%] mb-[5px] p-[12px] flex-col',
isValid ? 'border border-newColColor' : 'border border-[#FF3F3F]'
)}
>
{!isPicture && !totalChars && (
<div
className={clsx(
'text-sm text-[#FF3F3F] whitespace-nowrap',
isGlobal && selectedIntegrations.length && 'mb-[12px]'
)}
>
Your post should have at least
<br />
one character or one image.
</div>
)}
{isGlobal && (
<div className="grid grid-cols-[auto_auto_auto] text-[14px] font-[500] gap-[8px] items-center">
{selectedIntegrations.map((p, index) => (
<Fragment key={p.integration.id}>
<div>
<Image
src={`/icons/platforms/${p.integration.identifier}.png`}
alt={p.integration.name}
className="rounded-[4px] w-[16px] h-[16px] min-w-[16px] min-h-[16px]"
width={16}
height={16}
/>
</div>
<div
className={clsx(
'whitespace-nowrap',
isInternal?.[index]
? ''
: totalChars > (chars?.[p.integration.id] || 0)
? 'text-[#FF3F3F]'
: ''
)}
>
{p.integration.name} (
{capitalize(p.integration.identifier.split('-')[0])}):
</div>
<div
className={clsx(
'whitespace-nowrap',
isInternal?.[index]
? ''
: totalChars > (chars?.[p.integration.id] || 0)
? 'text-[#FF3F3F]'
: ''
)}
>
{isInternal?.[index]
? 'Internal Edit'
: `${totalChars}/${chars?.[p.integration.id] || 0}`}
</div>
</Fragment>
))}
</div>
)}
</div>
)}
</div>
);
};

View File

@ -1,42 +1,49 @@
import { FC } from 'react';
import { FC, useMemo, useState } from 'react';
import { Select } from '@gitroom/react/form/select';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import { useClickOutside } from '@mantine/hooks';
import { isUSCitizen } from '@gitroom/frontend/components/launches/helpers/isuscitizen.utils';
import clsx from 'clsx';
const list = [
{
value: 1,
label: 'Every Day',
label: 'Day',
},
{
value: 2,
label: 'Every Two Days',
label: 'Two Days',
},
{
value: 3,
label: 'Every Three Days',
label: 'Three Days',
},
{
value: 4,
label: 'Every Four Days',
label: 'Four Days',
},
{
value: 5,
label: 'Every Five Days',
label: 'Five Days',
},
{
value: 6,
label: 'Every Six Days',
label: 'Six Days',
},
{
value: 7,
label: 'Every Week',
label: 'Week',
},
{
value: 14,
label: 'Every Two Weeks',
label: 'Two Weeks',
},
{
value: 30,
label: 'Every Month',
label: 'Month',
},
{
value: null,
label: 'Cancel',
},
];
export const RepeatComponent: FC<{
@ -45,21 +52,95 @@ export const RepeatComponent: FC<{
}> = (props) => {
const { repeat } = props;
const t = useT();
const [isOpen, setIsOpen] = useState(false);
const ref = useClickOutside(() => {
if (!isOpen) {
return;
}
setIsOpen(false);
});
const everyLabel = useMemo(() => {
if (!repeat) {
return '';
}
return list.find((p) => p.value === repeat)?.label;
}, [repeat]);
return (
<Select
disableForm={true}
label=""
hideErrors={true}
name="repeat"
value={repeat ? repeat : undefined}
onChange={(e) => props.onChange(Number(e.target.value))}
<div
ref={ref}
className={clsx(
'border rounded-[8px] justify-center flex items-center relative h-[44px] text-[15px] font-[600] select-none',
isOpen ? 'border-[#612BD3]' : 'border-newTextColor/10',
)}
>
<option>{t('repeat_post_every', 'Repeat Post Every...')}</option>
{list.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</Select>
<div
onClick={() => setIsOpen(!isOpen)}
className="px-[16px] justify-center flex gap-[8px] items-center h-full select-none flex-1"
>
<div className="cursor-pointer">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<g clip-path="url(#clip0_2403_67385)">
<path
d="M14.1667 1.66602L17.5 4.99935M17.5 4.99935L14.1667 8.33268M17.5 4.99935H6.5C5.09987 4.99935 4.3998 4.99935 3.86502 5.27183C3.39462 5.51152 3.01217 5.89397 2.77248 6.36437C2.5 6.89915 2.5 7.59922 2.5 8.99935V9.16602M2.5 14.9993H13.5C14.9001 14.9993 15.6002 14.9993 16.135 14.7269C16.6054 14.4872 16.9878 14.1047 17.2275 13.6343C17.5 13.0995 17.5 12.3995 17.5 10.9993V10.8327M2.5 14.9993L5.83333 18.3327M2.5 14.9993L5.83333 11.666"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_2403_67385">
<rect width="20" height="20" fill="currentColor" />
</clipPath>
</defs>
</svg>
</div>
<div className="cursor-pointer">
{repeat
? `Repeat Post Every ${everyLabel}`
: t('repeat_post_every', 'Repeat Post Every...')}
</div>
<div className="cursor-pointer">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
className={isOpen ? 'rotate-180' : ''}
>
<path
d="M7.4563 8L12.5437 8C12.9494 8 13.1526 8.56798 12.8657 8.90016L10.322 11.8456C10.1442 12.0515 9.85583 12.0515 9.67799 11.8456L7.13429 8.90016C6.84741 8.56798 7.05059 8 7.4563 8Z"
fill="currentColor"
/>
</svg>
</div>
</div>
{isOpen && (
<div className="z-[300] absolute left-0 bottom-[100%] w-[240px] bg-newBgColorInner p-[12px] menu-shadow -translate-y-[10px] flex flex-col">
{list.map((p) => (
<div
onClick={() => {
props.onChange(Number(p.value));
setIsOpen(false);
}}
key={p.label}
className="h-[40px] py-[8px] px-[20px] -mx-[12px] hover:bg-newBgColor"
>
{p.label}
</div>
))}
</div>
)}
</div>
);
};

View File

@ -1,43 +1,127 @@
import { Select } from '@gitroom/react/form/select';
import { uniqBy } from 'lodash';
import React, { FC, useMemo, useState } from 'react';
import React, { FC, useCallback, useMemo, useRef, useState } from 'react';
import { Integrations } from '@gitroom/frontend/components/launches/calendar.context';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import clsx from 'clsx';
import { useClickOutside } from '@mantine/hooks';
import { useToaster } from '@gitroom/react/toaster/toaster';
import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store';
import { useShallow } from 'zustand/react/shallow';
export const SelectCustomer: FC<{
onChange: (value: string) => void;
integrations: Integrations[];
customer?: string;
}> = (props) => {
const { onChange, integrations, customer: currentCustomer } = props;
const { setCurrent } = useLaunchStore(
useShallow((state) => ({
setCurrent: state.setCurrent,
}))
);
const toaster = useToaster();
const t = useT();
const [customer, setCustomer] = useState(currentCustomer || '');
const [pos, setPos] = useState<any>({});
const [open, setOpen] = useState(false);
const ref = useClickOutside(() => {
if (open) {
setOpen(false);
}
});
const openClose = useCallback(() => {
if (open) {
setOpen(false);
return;
}
const { x, y, width, height } = ref.current?.getBoundingClientRect();
setPos({ top: y + height, left: x });
setOpen(true);
}, [open]);
const totalCustomers = useMemo(() => {
return uniqBy(integrations, (i) => i?.customer?.id).length;
}, [integrations]);
if (totalCustomers <= 1) {
return null;
}
return (
<Select
hideErrors={true}
label=""
name="customer"
value={customer}
onChange={(e) => {
setCustomer(e.target.value);
onChange(e.target.value);
}}
disableForm={true}
>
<option value="">{t('selected_customer', 'Selected Customer')}</option>
{uniqBy(integrations, (u) => u?.customer?.name)
.filter((f) => f.customer?.name)
.map((p) => (
<option key={p.customer?.id} value={p.customer?.id}>
{t('customer', 'Customer:')}
{p.customer?.name}
</option>
))}
</Select>
<div className="relative select-none z-[500]" ref={ref}>
<div
data-tooltip-id="tooltip"
data-tooltip-content="Select Customer"
onClick={openClose}
className={clsx(
'relative z-[20] cursor-pointer h-[42px] rounded-[8px] pl-[16px] pr-[12px] gap-[8px] border flex items-center',
open ? 'border-[#612BD3]' : 'border-newColColor'
)}
>
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M16.6673 17.5C16.6673 16.337 16.6673 15.7555 16.5238 15.2824C16.2006 14.217 15.3669 13.3834 14.3016 13.0602C13.8284 12.9167 13.247 12.9167 12.084 12.9167H7.91732C6.75435 12.9167 6.17286 12.9167 5.6997 13.0602C4.63436 13.3834 3.80068 14.217 3.47752 15.2824C3.33398 15.7555 3.33398 16.337 3.33398 17.5M13.7507 6.25C13.7507 8.32107 12.0717 10 10.0007 10C7.92958 10 6.25065 8.32107 6.25065 6.25C6.25065 4.17893 7.92958 2.5 10.0007 2.5C12.0717 2.5 13.7507 4.17893 13.7507 6.25Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div>
<svg
className={clsx(open && 'rotate-180')}
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M12.5437 8L7.4563 8C7.05059 8 6.84741 8.56798 7.13429 8.90016L9.67799 11.8456C9.85583 12.0515 10.1442 12.0515 10.322 11.8456L12.8657 8.90016C13.1526 8.56798 12.9494 8 12.5437 8Z"
fill="currentColor"
/>
</svg>
</div>
</div>
{open && (
<div
style={pos}
className="flex flex-col fixed pt-[12px] bg-newBgColorInner menu-shadow min-w-[250px]"
>
<div className="text-[14px] font-[600] px-[12px] mb-[5px]">
Customers
</div>
{uniqBy(integrations, (u) => u?.customer?.name)
.filter((f) => f.customer?.name)
.map((p) => (
<div
onClick={() => {
toaster.show(
t('customer_socials_selected', 'Customer socials selected'),
'success'
);
setCustomer(p.customer?.id);
onChange(p.customer?.id);
setOpen(false);
setCurrent('global')
}}
key={p.customer?.id}
className="p-[12px] hover:bg-newBgColor text-[14px] font-[500] h-[32px] flex items-center"
>
{p.customer?.name}
</div>
))}
</div>
)}
</div>
);
};

View File

@ -8,6 +8,10 @@ import { ColorPicker } from '@gitroom/react/form/color.picker';
import { Button } from '@gitroom/react/form/button';
import { uniqBy } from 'lodash';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import { useClickOutside } from '@mantine/hooks';
import clsx from 'clsx';
import { useModals } from '@gitroom/frontend/components/layout/new-modal';
export const TagsComponent: FC<{
name: string;
label: string;
@ -18,6 +22,254 @@ export const TagsComponent: FC<{
name: string;
};
}) => void;
}> = (props) => {
const fetch = useFetch();
const loadTags = useCallback(async () => {
return (await fetch('/posts/tags')).json();
}, []);
const { data, isLoading, mutate } = useSWR('load-tags', loadTags);
if (isLoading) {
return null;
}
return <TagsComponentInner {...props} allTags={data} mutate={mutate} />;
};
export const TagsComponentInner: FC<{
name: string;
label: string;
initial: any[];
allTags: any;
mutate: () => Promise<any>;
onChange: (event: {
target: {
value: any[];
name: string;
};
}) => void;
}> = ({ initial, onChange, name, mutate, allTags: data }) => {
const t = useT();
const [isOpen, setIsOpen] = useState(false);
const [tagValue, setTagValue] = useState<any[]>(
(initial?.slice(0) || []).map((p: any) => {
return data?.tags.find((a: any) => a.name === p.value) || p;
})
);
const modals = useModals();
const ref = useClickOutside(() => {
if (!isOpen) {
return;
}
setIsOpen(false);
});
const addTag = useCallback(async () => {
const val: string | undefined = await new Promise((resolve) => {
modals.openModal({
title: 'Add new tag',
children: (close) => (
<ShowModal tag="" close={close} resolve={resolve} />
),
});
});
const newValues = await mutate();
if (!val) {
return;
}
const newTag = newValues.tags.find((p: any) => p.name === val);
if (newTag) {
const modify = [...tagValue, newTag];
setTagValue(modify);
onChange({
target: {
value: modify,
name,
},
});
}
}, []);
return (
<div
ref={ref}
className={clsx(
'border rounded-[8px] justify-center flex items-center relative h-[44px] text-[15px] font-[600] select-none',
isOpen ? 'border-[#612BD3]' : 'border-newTextColor/10'
)}
>
<div
onClick={() => setIsOpen(!isOpen)}
className="px-[16px] justify-center flex gap-[8px] items-center h-full select-none flex-1"
>
<div className="cursor-pointer">
<svg
xmlns="http://www.w3.org/2000/svg"
width="17"
height="19"
viewBox="0 0 17 19"
fill="none"
>
<path
d="M15.75 8.25L9.42157 1.92157C8.98919 1.48919 8.773 1.273 8.52071 1.1184C8.29703 0.981328 8.05317 0.880317 7.79808 0.819075C7.51036 0.75 7.20462 0.75 6.59314 0.75L3.25 0.75M0.75 6.33333L0.75 7.97876C0.75 8.38641 0.75 8.59024 0.79605 8.78205C0.836878 8.95211 0.904218 9.11469 0.9956 9.26381C1.09867 9.432 1.2428 9.57613 1.53105 9.86438L8.03105 16.3644C8.69108 17.0244 9.02109 17.3544 9.40164 17.4781C9.73638 17.5868 10.097 17.5868 10.4317 17.4781C10.8122 17.3544 11.1423 17.0244 11.8023 16.3644L13.8644 14.3023C14.5244 13.6423 14.8544 13.3122 14.9781 12.9317C15.0868 12.597 15.0868 12.2364 14.9781 11.9016C14.8544 11.5211 14.5244 11.1911 13.8644 10.531L7.78105 4.44772C7.4928 4.15946 7.34867 4.01534 7.18048 3.91227C7.03135 3.82089 6.86878 3.75354 6.69872 3.71272C6.50691 3.66667 6.30308 3.66667 5.89543 3.66667H3.41667C2.48325 3.66667 2.01654 3.66667 1.66002 3.84832C1.34641 4.00811 1.09145 4.26308 0.931656 4.57668C0.75 4.9332 0.75 5.39991 0.75 6.33333Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="cursor-pointer flex gap-[4px]">
{tagValue.length === 0 ? (
'Add New Tag'
) : (
<>
<div
className="h-full flex justify-center items-center px-[8px] rounded-[4px]"
style={{ backgroundColor: tagValue[0].color }}
>
<span className="mix-blend-difference text-[#fff]">
{tagValue[0].name}
</span>
</div>
{tagValue.length > 1 ? <span>+{tagValue.length - 1}</span> : null}
</>
)}
</div>
<div className="cursor-pointer">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
className={isOpen ? 'rotate-180' : ''}
>
<path
d="M7.4563 8L12.5437 8C12.9494 8 13.1526 8.56798 12.8657 8.90016L10.322 11.8456C10.1442 12.0515 9.85583 12.0515 9.67799 11.8456L7.13429 8.90016C6.84741 8.56798 7.05059 8 7.4563 8Z"
fill="currentColor"
/>
</svg>
</div>
</div>
{isOpen && (
<div className="z-[300] absolute left-0 bottom-[100%] w-[240px] bg-newBgColorInner p-[12px] menu-shadow -translate-y-[10px] flex flex-col">
{(data?.tags || []).map((p: any) => (
<div
onClick={() => {
const exists = !!tagValue.find((a) => a.id === p.id);
let modify = [];
if (exists) {
modify = tagValue.filter((a) => a.id !== p.id);
} else {
modify = [...tagValue, p];
}
setTagValue(modify);
onChange({
target: {
value: modify.map((p: any) => ({
label: p.name,
value: p.name,
})),
name,
},
});
}}
key={p.name}
className="h-[40px] py-[8px] px-[20px] -mx-[12px] flex gap-[8px]"
>
<Check
onChange={() => {}}
value={!!tagValue.find((a) => a.id === p.id)}
/>
<div
className="h-full flex justify-center items-center px-[8px] rounded-[8px]"
style={{ backgroundColor: p.color }}
>
<span className="mix-blend-difference text-[#fff]">
{p.name}
</span>
</div>
</div>
))}
<div
onClick={addTag}
className="cursor-pointer gap-[8px] flex w-full h-[34px] rounded-[8px] mt-[12px] px-[16px] justify-center items-center bg-[#612BD3] text-white"
>
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M8.00065 3.33301V12.6663M3.33398 7.99967H12.6673"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="text-[13px] font-[600]">Add New Tag</div>
</div>
</div>
)}
</div>
);
};
const Check: FC<{ value: boolean; onChange: (value: boolean) => void }> = ({
value,
onChange,
}) => {
return (
<div
onClick={() => onChange(!value)}
className={clsx(
'text-[10px] font-[500] text-center flex border border-btnSimple rounded-[6px] w-[20px] h-[20px] justify-center items-center',
value && 'bg-[#612BD3]'
)}
>
{value ? (
<svg
xmlns="http://www.w3.org/2000/svg"
width="11"
height="8"
viewBox="0 0 11 8"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10.7071 0.292893C11.0976 0.683417 11.0976 1.31658 10.7071 1.70711L4.70711 7.70711C4.31658 8.09763 3.68342 8.09763 3.29289 7.70711L0.292893 4.70711C-0.0976311 4.31658 -0.0976311 3.68342 0.292893 3.29289C0.683417 2.90237 1.31658 2.90237 1.70711 3.29289L4 5.58579L9.29289 0.292893C9.68342 -0.0976311 10.3166 -0.0976311 10.7071 0.292893Z"
fill="white"
/>
</svg>
) : (
''
)}
</div>
);
};
export const TagsComponentA: FC<{
name: string;
label: string;
initial: any[];
onChange: (event: {
target: {
value: any[];
name: string;
};
}) => void;
}> = (props) => {
const { onChange, name, initial } = props;
const fetch = useFetch();
@ -228,53 +480,28 @@ const ShowModal: FC<{
}),
});
resolve(tagName);
close();
}, [tagName, color, id]);
return (
<div className="bg-black/40 fixed start-0 top-0 w-full h-full z-[500]">
<div className="relative w-[500px] mx-auto flex gap-[20px] flex-col flex-1 rounded-[4px] border border-customColor6 bg-sixth p-[16px] pt-0">
<TopTitle title={`Create a new tag`} />
<button
className="outline-none absolute end-[20px] top-[15px] mantine-UnstyledButton-root mantine-ActionIcon-root hover:bg-tableBorder cursor-pointer mantine-Modal-close mantine-1dcetaa"
type="button"
>
<svg
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
onClick={close}
>
<path
d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z"
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
></path>
</svg>
</button>
<div>
<Input
name="name"
disableForm={true}
label="Name"
value={tagName}
onChange={(e) => setTagName(e.target.value)}
/>
<ColorPicker
onChange={(e) => setColor(e.target.value)}
label="Tag Color"
name="color"
value={color}
enabled={true}
canBeCancelled={false}
/>
<Button onClick={save} className="mt-[16px]">
{t('save', 'Save')}
</Button>
</div>
</div>
<div>
<Input
name="name"
disableForm={true}
label="Name"
value={tagName}
onChange={(e) => setTagName(e.target.value)}
/>
<ColorPicker
onChange={(e) => setColor(e.target.value)}
label="Tag Color"
name="color"
value={color}
enabled={true}
canBeCancelled={false}
/>
<Button onClick={save} className="mt-[16px]">
{t('save', 'Save')}
</Button>
</div>
);
};

View File

@ -7,17 +7,20 @@ const Arrow: FC<{
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="currentColor"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
style={{
transform: flip ? 'rotate(180deg)' : '',
transform: !flip ? 'rotate(180deg)' : '',
}}
>
<path
d="M13.354 6.35378L8.35403 11.3538C8.30759 11.4003 8.25245 11.4372 8.19175 11.4623C8.13105 11.4875 8.06599 11.5004 8.00028 11.5004C7.93457 11.5004 7.86951 11.4875 7.80881 11.4623C7.74811 11.4372 7.69296 11.4003 7.64653 11.3538L2.64653 6.35378C2.55271 6.25996 2.5 6.13272 2.5 6.00003C2.5 5.86735 2.55271 5.7401 2.64653 5.64628C2.74035 5.55246 2.8676 5.49976 3.00028 5.49976C3.13296 5.49976 3.26021 5.55246 3.35403 5.64628L8.00028 10.2932L12.6465 5.64628C12.693 5.59983 12.7481 5.56298 12.8088 5.53784C12.8695 5.5127 12.9346 5.49976 13.0003 5.49976C13.066 5.49976 13.131 5.5127 13.1917 5.53784C13.2524 5.56298 13.3076 5.59983 13.354 5.64628C13.4005 5.69274 13.4373 5.74789 13.4625 5.80859C13.4876 5.86928 13.5006 5.93434 13.5006 6.00003C13.5006 6.06573 13.4876 6.13079 13.4625 6.19148C13.4373 6.25218 13.4005 6.30733 13.354 6.35378Z"
fill="currentColor"
d="M15 12.5L10 7.5L5 12.5"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
@ -35,14 +38,14 @@ export const UpDownArrow: FC<{
[]
);
return (
<div className="flex flex-col">
<div className="flex flex-col gap-[8px] pt-[8px]">
<button
onClick={changePosition('up')}
className={clsx(
'outline-none rounded-tl-[20px] rounded-tr-[20px] w-[24px] h-[24px] flex justify-center items-center',
'outline-none w-[20px] h-[20px] flex justify-center items-center',
isUp
? 'bg-input hover:bg-seventh cursor-pointer'
: 'bg-customColor8 pointer-events-none text-textColor'
? 'cursor-pointer'
: 'pointer-events-none text-textColor opacity-50'
)}
>
<Arrow flip={true} />
@ -50,10 +53,10 @@ export const UpDownArrow: FC<{
<button
onClick={changePosition('down')}
className={clsx(
'outline-none rounded-bl-[20px] rounded-br-[20px] w-[24px] h-[24px] flex justify-center items-center',
'outline-none rounded-bl-[20px] w-[20px] h-[20px] flex justify-center items-center',
isDown
? 'bg-input hover:bg-seventh cursor-pointer'
: 'bg-customColor8 pointer-events-none text-textColor'
? 'cursor-pointer'
: 'pointer-events-none text-textColor opacity-50'
)}
>
<Arrow flip={false} />

View File

@ -1,8 +1,10 @@
import { useDropzone } from 'react-dropzone';
import { FC, ReactNode } from 'react';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import clsx from 'clsx';
export const DropFiles: FC<{
children: ReactNode;
className?: string;
onDrop: (files: File[]) => void;
}> = (props) => {
const t = useT();
@ -11,7 +13,7 @@ export const DropFiles: FC<{
onDrop: props.onDrop,
});
return (
<div {...getRootProps()} className="relative">
<div {...getRootProps()} className={clsx("relative", props.className)}>
{isDragActive && (
<div className="absolute start-0 top-0 w-full h-full bg-black/90 flex items-center justify-center z-[200] animate-normalFadeIn">
{t('drag_n_drop_some_files_here', 'Drag n drop some files here')}

View File

@ -20,6 +20,7 @@ interface OpenModalInterface {
title?: string;
closeOnClickOutside?: boolean;
removeLayout?: boolean;
fullScreen?: boolean;
closeOnEscape?: boolean;
withCloseButton?: boolean;
askClose?: boolean;
@ -131,14 +132,25 @@ export const Component: FC<{
<div
style={{ zIndex }}
className={clsx(
'fixed flex left-0 top-0 min-w-full min-h-full bg-popup transition-all animate-fadeIn overflow-y-auto pb-[50px] text-newTextColor',
!modal.fullScreen
? 'pb-[50px] min-w-full min-h-full'
: 'w-full h-full',
'fixed flex left-0 top-0 bg-popup transition-all animate-fadeIn overflow-y-auto text-newTextColor',
!isLast && '!overflow-hidden'
)}
>
<div className="relative flex-1">
<div className="absolute top-0 left-0 min-w-full min-h-full">
<div className={clsx(modal.fullScreen && 'flex', 'relative flex-1')}>
<div
className={clsx(
modal.fullScreen
? 'flex flex-1'
: 'absolute top-0 left-0 min-w-full min-h-full'
)}
>
<div
className="mx-auto py-[48px]"
className={clsx(
modal.fullScreen ? 'w-full h-full flex-1' : 'mx-auto py-[48px]'
)}
{...(modal.size && { style: { width: modal.size } })}
>
{typeof modal.children === 'function'
@ -156,17 +168,34 @@ export const Component: FC<{
<div
onClick={closeModalFunction}
style={{ zIndex }}
className="fixed flex left-0 top-0 min-w-full min-h-full bg-popup transition-all animate-fadeIn overflow-y-auto pb-[50px] text-newTextColor"
className={clsx(
'fixed flex left-0 top-0 min-w-full min-h-full bg-popup transition-all animate-fadeIn overflow-y-auto text-newTextColor',
!modal.fullScreen && 'pb-[50px]'
)}
>
<div className="relative flex-1">
<div className="absolute top-0 left-0 min-w-full min-h-full pt-[100px] pb-[100px]">
<div
className={clsx(
'absolute min-w-full',
!modal.fullScreen
? 'min-h-full pt-[100px] pb-[100px]'
: 'h-screen',
modal.size && modal.height ? 'flex justify-center items-center' : 'top-0 left-0'
)}
>
<div
className={clsx(
!modal.removeLayout && 'gap-[40px] p-[32px]',
'bg-newBgColorInner mx-auto flex flex-col w-fit rounded-[24px] relative',
modal.size ? '' : 'min-w-[600px]'
modal.size ? '' : 'min-w-[600px]',
modal.fullScreen && 'h-full',
)}
{...(modal.size && { style: { width: modal.size } })}
{...((!!modal.size || !!modal.height) && {
style: {
...(modal.size ? { width: modal.size } : {}),
...(modal.height ? { height: modal.height } : {}),
},
})}
onClick={(e) => e.stopPropagation()}
>
<div className="flex items-center">
@ -199,7 +228,7 @@ export const Component: FC<{
</div>
) : null}
</div>
<div className="whitespace-pre-line">{RenderComponent}</div>
<div className={clsx("whitespace-pre-line", !!modal.height && !!modal.size && 'flex flex-1 flex-col')}>{RenderComponent}</div>
</div>
</div>
</div>

View File

@ -19,6 +19,7 @@ export const Support = () => {
if (!discordUrl || !show) return null;
return (
<div
id="support-discord"
className="bg-customColor39 w-[194px] h-[58px] fixed end-[20px] bottom-[20px] z-[500] text-[16px] text-customColor40 rounded-[30px] !rounded-br-[0] cursor-pointer flex justify-center items-center gap-[10px]"
onClick={() => window.open(discordUrl)}
>

View File

@ -1,6 +1,7 @@
'use client';
import React, {
ChangeEvent,
ClipboardEvent,
FC,
Fragment,
@ -20,7 +21,10 @@ import EventEmitter from 'events';
import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component';
import clsx from 'clsx';
import { VideoFrame } from '@gitroom/react/helpers/video.frame';
import { MultipartFileUploader } from '@gitroom/frontend/components/media/new.uploader';
import {
MultipartFileUploader,
useUppyUploader,
} from '@gitroom/frontend/components/media/new.uploader';
import dynamic from 'next/dynamic';
import { useUser } from '@gitroom/frontend/components/layout/user.context';
import { AiImage } from '@gitroom/frontend/components/launches/ai.image';
@ -37,6 +41,8 @@ import {
import { useLaunchStore } from '@gitroom/frontend/components/new-launch/store';
import { AiVideo } from '@gitroom/frontend/components/launches/ai.video';
import { useModals } from '@gitroom/frontend/components/layout/new-modal';
import { Dashboard } from '@uppy/react';
import { timer } from '@gitroom/helpers/utils/timer';
const Polonto = dynamic(
() => import('@gitroom/frontend/components/launches/polonto')
);
@ -88,7 +94,7 @@ export const Pagination: FC<{
aria-current="page"
onClick={() => setPage(page)}
className={clsx(
'cursor-pointer inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border hover:bg-forth h-10 w-10 hover:text-white border-[#1F1F1F]',
'cursor-pointer inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border hover:bg-forth h-10 w-10 hover:text-white border-newBorder',
current === page
? 'bg-forth !text-white'
: 'text-textColor hover:text-white'
@ -163,96 +169,71 @@ export const MediaBox: FC<{
standalone?: boolean;
type?: 'image' | 'video';
closeModal: () => void;
}> = (props) => {
const { setMedia, type, closeModal } = props;
const [mediaList, setListMedia] = useState<Media[]>([]);
const setActivateExitButton = useLaunchStore((e) => e.setActivateExitButton);
const fetch = useFetch();
const mediaDirectory = useMediaDirectory();
}> = ({ type, standalone, setMedia }) => {
const [page, setPage] = useState(0);
const [pages, setPages] = useState(0);
const [selectedMedia, setSelectedMedia] = useState<Media[]>([]);
const ref = useRef<any>(null);
useEffect(() => {
setActivateExitButton(false);
return () => {
setActivateExitButton(true);
};
}, []);
const fetch = useFetch();
const modals = useModals();
const loadMedia = useCallback(async () => {
return (await fetch(`/media?page=${page + 1}`)).json();
}, [page]);
const { data, mutate, isLoading } = useSWR(`get-media-${page}`, loadMedia);
const [selected, setSelected] = useState([]);
const t = useT();
const uploaderRef = useRef<any>(null);
const mediaDirectory = useMediaDirectory();
const setNewMedia = useCallback(
(media: Media) => () => {
if (props.standalone) {
const uppy = useUppyUploader({
allowedFileTypes:
type == 'image'
? 'image/*'
: type == 'video'
? 'video/mp4'
: 'image/*,video/mp4',
onUploadSuccess: async (arr) => {
uppy.clear();
await mutate();
if (standalone) {
return;
}
setSelectedMedia(
selectedMedia.find((p) => p.id === media.id)
? selectedMedia.filter((f) => f.id !== media.id)
: [
...selectedMedia.map((p) => ({
...p,
})),
{
...media,
},
]
);
setSelected((prevSelected) => {
return [...prevSelected, ...arr];
});
},
[selectedMedia]
);
});
const addNewMedia = useCallback(
(media: Media[]) => () => {
if (props.standalone) {
const addRemoveSelected = useCallback(
(media: any) => () => {
if (standalone) {
return;
}
setSelectedMedia((currentMedia) => [...currentMedia, ...media]);
// closeModal();
const exists = selected.find((p: any) => p.id === media.id);
if (exists) {
setSelected(selected.filter((f: any) => f.id !== media.id));
return;
}
setSelected([...selected, media]);
},
[selectedMedia]
[selected]
);
const addMedia = useCallback(async () => {
if (props.standalone) {
if (standalone) {
return;
}
// @ts-ignore
setMedia(selectedMedia);
closeModal();
}, [selectedMedia]);
const { data, mutate } = useSWR(`get-media-${page}`, loadMedia);
setMedia(selected);
modals.closeCurrent();
}, [selected]);
const finishUpload = useCallback(
async (res: any) => {
const lastMedia = mediaList?.[0]?.id;
const newData = await mutate();
const untilLastMedia = newData.results.findIndex(
(f: any) => f.id === lastMedia
);
const onlyNewMedia = newData.results.slice(
0,
untilLastMedia === -1 ? newData.results.length : untilLastMedia
);
if (props.standalone) {
return;
}
addNewMedia(onlyNewMedia)();
},
[mutate, addNewMedia, mediaList, selectedMedia]
);
const addToUpload = useCallback(async (e: ChangeEvent<HTMLInputElement>) => {
const files = Array.from(e.target.files).slice(0, 5);
for (const file of files) {
uppy.addFile(file);
}
}, []);
const dragAndDrop = useCallback(
async (event: ClipboardEvent<HTMLDivElement> | File[]) => {
if (!ref?.current?.setOptions) {
return;
}
// @ts-ignore
const clipboardItems = event.map((p) => ({
kind: 'file',
@ -261,39 +242,26 @@ export const MediaBox: FC<{
if (!clipboardItems) {
return;
}
const files: File[] = [];
const files = [];
// @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
}
files.push(file);
}
}
}
if (files.length === 0) {
return;
for (const file of files.slice(0, 5)) {
uppy.addFile(file);
}
ref.current.setOptions({
autoProceed: false,
});
for (const file of files) {
ref.current.addFile(file);
await ref.current.upload();
ref.current.clear();
}
ref.current.setOptions({
autoProceed: true,
});
},
[mutate, addNewMedia, mediaList, selectedMedia]
[]
);
const removeItem = useCallback(
const deleteImage = useCallback(
(media: Media) => async (e: any) => {
e.stopPropagation();
if (
@ -314,212 +282,270 @@ export const MediaBox: FC<{
[mutate]
);
const refNew = useRef(null);
useEffect(() => {
if (data?.pages) {
setPages(data.pages);
}
if (data?.results && data?.results?.length) {
setListMedia([...data.results]);
}
}, [data]);
useEffect(() => {
refNew?.current?.scrollIntoView({
behavior: 'smooth',
});
const btn = useMemo(() => {
return (
<button
onClick={() => uploaderRef?.current?.click()}
className="cursor-pointer bg-btnSimple changeColor flex gap-[8px] h-[44px] px-[18px] justify-center items-center rounded-[8px]"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 14 14"
fill="none"
>
<path
d="M6.58333 0.75V12.4167M0.75 6.58333H12.4167"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
<div>Upload</div>
</button>
);
}, []);
const t = useT();
return (
<div
{...(props.standalone
? {
className:
'bg-newBgColorInner p-[20px] flex flex-col gap-[15px] transition-all',
}
: {
ref: refNew,
className:
'removeEditor fixed start-0 top-0 bg-primary/80 z-[300] w-full min-h-full p-4 md:p-[60px] animate-fade',
})}
>
<div
{...(props.standalone
? {}
: {
className:
'max-w-[1000px] w-full h-full bg-newBgColorInner border-tableBorder border-2 rounded-xl relative mx-auto',
})}
>
<DropFiles onDrop={dragAndDrop}>
<div className="pb-[20px] px-[20px] w-full h-full">
<div className="flex flex-col">
<div className="flex-1">
{!props.standalone ? (
<TopTitle title="Media Library" />
) : (
<div className="h-[100px]" />
)}
</div>
{!props.standalone ? (
<button
onClick={closeModal}
className="outline-none z-[300] absolute end-[20px] top-[15px] mantine-UnstyledButton-root mantine-ActionIcon-root bg-primary hover:bg-tableBorder cursor-pointer mantine-Modal-close mantine-1dcetaa"
type="button"
>
<svg
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
>
<path
d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z"
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
></path>
</svg>
</button>
) : (
<div />
)}
<div className="absolute flex justify-center mt-[55px] items-center pointer-events-none text-center h-[57px] w-full start-0 rounded-lg transition-all group text-sm font-semibold bg-transparent text-gray-800 hover:bg-gray-100 focus:text-primary-500">
{t(
'select_or_upload_pictures_maximum_5_at_a_time',
'Select or upload pictures (maximum 5 at a time)'
)}
<br />
{t(
'you_can_also_drag_drop_pictures',
'You can also drag & drop pictures'
)}
</div>
{!!mediaList.length && (
<>
<div className="flex absolute h-[57px] w-full start-0 top-0 rounded-lg transition-all group text-sm font-semibold bg-transparent text-gray-800 hover:bg-gray-100 focus:text-primary-500">
<div className="relative flex flex-1 pe-[55px] gap-2 items-center justify-center">
<div className="flex-1" />
<MultipartFileUploader
uppRef={ref}
onUploadSuccess={finishUpload}
allowedFileTypes={
type === 'video'
? 'video/mp4'
: type === 'image'
? 'image/*'
: 'image/*,video/mp4'
}
/>
</div>
</div>
</>
)}
<DropFiles className="flex flex-col flex-1" onDrop={dragAndDrop}>
<div className="flex flex-col flex-1">
<div
className={clsx(
'flex',
!isLoading && !data?.results?.length && 'hidden'
)}
>
{!isLoading && !!data?.results?.length && (
<div className="flex-1 text-[14px] font-[600] whitespace-pre-line">
Select or upload pictures (maximum 5 at a time).{'\n'}
You can also drag & drop pictures.
</div>
<div
className={clsx(
'flex flex-wrap gap-[10px] mt-[35px] pt-[20px]',
!!mediaList.length &&
'justify-center items-center text-textColor'
)}
>
{!mediaList.length ? (
<div className="flex flex-col text-center items-center justify-center mx-auto">
<div>
{t(
'you_don_t_have_any_assets_yet',
"You don't have any assets yet."
)}
</div>
<div>
{t(
'click_the_button_below_to_upload_one',
'Click the button below to upload one'
)}
</div>
<div className="mt-[10px] justify-center items-center flex flex-col-reverse gap-[10px]">
<MultipartFileUploader
onUploadSuccess={finishUpload}
allowedFileTypes={
type === 'video'
? 'video/mp4'
: type === 'image'
? 'image/*'
: 'image/*,video/mp4'
}
/>
</div>
)}
<input
type="file"
ref={uploaderRef}
onChange={addToUpload}
className="hidden"
multiple={true}
/>
{!isLoading && !!data?.results?.length && btn}
</div>
<div className="w-full pointer-events-none relative mt-[5px] mb-[5px]">
<div className="w-full h-[46px] overflow-hidden absolute left-0 bg-newBgColorInner uppyChange">
<Dashboard
height={46}
uppy={uppy}
id={`uploader`}
showProgressDetails={true}
hideUploadButton={true}
hideRetryButton={true}
hidePauseResumeButton={true}
hideCancelButton={true}
hideProgressAfterFinish={true}
/>
</div>
<div className="w-full h-[46px] uppyChange" />
</div>
<div
className={clsx(
'flex-1 relative',
!isLoading &&
!data?.results?.length &&
'bg-newTextColor/[0.02] rounded-[12px]'
)}
>
<div
className={clsx(
'absolute -left-[3px] -top-[3px] withp3 h-full overflow-x-hidden overflow-y-auto scrollbar scrollbar-thumb-newColColor scrollbar-track-newBgColorInner',
!isLoading &&
!data?.results?.length &&
'flex justify-center items-center gap-[20px] flex-col'
)}
>
{!isLoading && !data?.results?.length && (
<>
<svg
width="192"
height="151"
viewBox="0 0 192 151"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M109.75 59.0141C104.489 59.0141 113.46 -5.73557 91.0289 1.57563C69.7021 8.5269 99.5229 59.0141 94.5119 59.0141C89.5009 59.0141 54.4775 56.107 52.1458 71.9377C49.5418 89.6178 95.4225 79.7216 96.7894 81.9895C98.1563 84.2573 78.775 111.109 91.0289 119.324C103.724 127.835 119.934 96.3491 122.711 96.3491C125.489 96.3491 139.845 147.93 151.514 133.684C160.997 122.106 138.391 96.3491 142.873 96.3491C147.355 96.3491 180.793 98.9658 186.076 81.9895C192.534 61.2424 134.828 76.0575 131.352 71.9377C127.876 67.818 159.167 34.7484 142.873 25.987C126.785 17.3361 115.012 59.0141 109.75 59.0141Z"
stroke="white"
strokeOpacity="0.08"
strokeWidth="2"
strokeLinecap="round"
/>
<rect
x="22.6328"
y="62.541"
width="49.2079"
height="49.2079"
rx="12.6792"
transform="rotate(-16.275 22.6328 62.541)"
fill="#232222"
/>
<path
d="M66.8573 81.5379L60.538 73.8505C59.3847 72.4421 58.0986 71.8279 56.9172 72.1076C55.7477 72.3838 54.8664 73.5134 54.4627 75.298L53.377 80.0552C53.1492 81.0592 52.6158 81.7748 51.8894 82.0519C51.1544 82.3446 50.2829 82.1692 49.4433 81.5678L49.0813 81.3089C47.9176 80.4896 46.7111 80.2818 45.6626 80.705C44.6142 81.1282 43.9074 82.1418 43.6491 83.5323L42.7814 88.278C42.4752 89.995 43.055 91.7139 44.3442 92.8742C45.6334 94.0345 47.406 94.4417 49.0739 93.9549L64.3851 89.4863C65.9931 89.017 67.2584 87.7753 67.7541 86.1722C68.2738 84.5621 67.924 82.8282 66.8573 81.5379Z"
fill="white"
fillOpacity="0.4"
/>
<path
d="M45.8412 76.6818C48.0811 76.0281 49.367 73.6823 48.7133 71.4423C48.0595 69.2024 45.7137 67.9165 43.4738 68.5702C41.2338 69.2239 39.9479 71.5697 40.6017 73.8097C41.2554 76.0497 43.6012 77.3355 45.8412 76.6818Z"
fill="white"
fillOpacity="0.4"
/>
<rect
x="64.8125"
y="70.6133"
width="66.3578"
height="66.3578"
rx="18.1132"
fill="#2C2B2B"
/>
<path
d="M80.1261 117.087L80.0882 117.125C79.5762 116.006 79.2538 114.735 79.1211 113.332C79.2538 114.716 79.6141 115.968 80.1261 117.087Z"
fill="white"
fillOpacity="0.4"
/>
<path
d="M92.3022 100.72C94.7948 100.72 96.8154 98.6991 96.8154 96.2065C96.8154 93.714 94.7948 91.6934 92.3022 91.6934C89.8097 91.6934 87.7891 93.714 87.7891 96.2065C87.7891 98.6991 89.8097 100.72 92.3022 100.72Z"
fill="white"
fillOpacity="0.4"
/>
<path
d="M105.936 84.8301H90.0448C83.1423 84.8301 79.0273 88.945 79.0273 95.8476V111.739C79.0273 113.805 79.3876 115.607 80.0893 117.124C81.7201 120.727 85.2093 122.756 90.0448 122.756H105.936C112.838 122.756 116.953 118.641 116.953 111.739V107.396V95.8476C116.953 88.945 112.838 84.8301 105.936 84.8301ZM113.862 104.741C112.383 103.471 109.994 103.471 108.515 104.741L100.626 111.511C99.147 112.781 96.7577 112.781 95.2786 111.511L94.6339 110.98C93.2875 109.804 91.1447 109.691 89.6276 110.715L82.5355 115.474C82.1183 114.412 81.8718 113.18 81.8718 111.739V95.8476C81.8718 90.5 84.6973 87.6745 90.0448 87.6745H105.936C111.283 87.6745 114.109 90.5 114.109 95.8476V104.95L113.862 104.741Z"
fill="white"
fillOpacity="0.4"
/>
</svg>
<div className="text-[20px] font-[600]">
You don't have any media yet
</div>
) : (
<>
{selectedMedia.length > 0 && (
<div className="flex justify-center absolute top-[7px] text-white">
<Button
onClick={props.standalone ? () => {} : addMedia}
className="!text-white"
>
<span className="!text-white">
{t('add_selected_media', 'Add selected media')}
</span>
</Button>
</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 className="whitespace-pre-line text-newTextColor/[0.6] text-center">
Select or upload pictures (maximum 5 at a time). {'\n'}
You can also drag & drop pictures.
</div>
<div className="forceChange">{btn}</div>
</>
)}
{isLoading && (
<>
{[...new Array(16)].map((_, i) => (
<div
key={media.id}
className={clsx(
'w-[120px] h-[120px] flex select-none relative cursor-pointer',
selectedMedia.find((p) => p.id === media.id)
? 'border-4 border-forth'
: 'border-tableBorder border-2'
'px-[3px] py-[3px] float-left rounded-[6px] cursor-pointer w8-max aspect-square'
)}
onClick={props.standalone ? () => {} : setNewMedia(media)}
key={i}
>
<div
onClick={removeItem(media)}
className="border border-red-400 !text-white flex justify-center items-center absolute w-[20px] z-[100] h-[20px] rounded-full bg-red-700 -top-[5px] -end-[5px]"
>
X
</div>
{media.path.indexOf('mp4') > -1 ? (
<VideoFrame url={mediaDirectory.set(media.path)} />
) : (
<Image
width={120}
height={120}
className="w-full h-full object-cover"
src={mediaDirectory.set(media.path)}
alt="media"
/>
)}
<div className="w-full h-full bg-newSep rounded-[6px] animate-pulse" />
</div>
))}
</div>
{(pages || 0) > 1 && (
<Pagination current={page} totalPages={pages} setPage={setPage} />
</>
)}
{data?.results
?.filter((f: any) => {
if (type === 'video') {
return f.path.indexOf('mp4') > -1;
} else if (type === 'image') {
return f.path.indexOf('mp4') === -1;
}
return true;
})
.map((media: any) => (
<div
className={clsx(
'group px-[3px] py-[3px] float-left rounded-[6px] w8-max aspect-square',
!standalone && 'cursor-pointer'
)}
key={media.id}
>
<div
className={clsx(
'w-full h-full rounded-[6px] border-[4px] relative',
!!selected.find((p) => p.id === media.id)
? 'border-[#612BD3]'
: 'border-transparent'
)}
onClick={addRemoveSelected(media)}
>
{!!selected.find((p: any) => p.id === media.id) ? (
<div className="flex justify-center items-center text-[14px] font-[500] w-[24px] h-[24px] rounded-full bg-[#612BD3] absolute -bottom-[10px] -end-[10px]">
{selected.findIndex((z: any) => z.id === media.id) + 1}
</div>
) : (
<svg
className="cursor-pointer hidden z-[100] group-hover:block absolute -top-[5px] -end-[5px]"
onClick={deleteImage(media)}
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
>
<ellipse
cx="9.96484"
cy="9.10742"
rx="6"
ry="5.5"
fill="white"
/>
<path
d="M9 1.5C4.8675 1.5 1.5 4.8675 1.5 9C1.5 13.1325 4.8675 16.5 9 16.5C13.1325 16.5 16.5 13.1325 16.5 9C16.5 4.8675 13.1325 1.5 9 1.5ZM11.52 10.725C11.7375 10.9425 11.7375 11.3025 11.52 11.52C11.4075 11.6325 11.265 11.685 11.1225 11.685C10.98 11.685 10.8375 11.6325 10.725 11.52L9 9.795L7.275 11.52C7.1625 11.6325 7.02 11.685 6.8775 11.685C6.735 11.685 6.5925 11.6325 6.48 11.52C6.2625 11.3025 6.2625 10.9425 6.48 10.725L8.205 9L6.48 7.275C6.2625 7.0575 6.2625 6.6975 6.48 6.48C6.6975 6.2625 7.0575 6.2625 7.275 6.48L9 8.205L10.725 6.48C10.9425 6.2625 11.3025 6.2625 11.52 6.48C11.7375 6.6975 11.7375 7.0575 11.52 7.275L9.795 9L11.52 10.725Z"
fill="#FF3535"
/>
</svg>
)}
<div className="w-full h-full rounded-[6px] overflow-hidden">
{media.path.indexOf('mp4') > -1 ? (
<VideoFrame url={mediaDirectory.set(media.path)} />
) : (
<img
width="100%"
height="100%"
className="w-full h-full object-cover"
src={mediaDirectory.set(media.path)}
alt="media"
/>
)}
</div>
</div>
</div>
))}
</div>
</div>
{(data?.pages || 0) > 1 && (
<Pagination
current={page}
totalPages={data?.pages}
setPage={setPage}
/>
)}
{!standalone && (
<div className="flex justify-end mt-[32px] gap-[8px]">
<button
onClick={() => modals.closeCurrent()}
className="cursor-pointer h-[52px] px-[20px] items-center justify-center border border-newTextColor/10 flex rounded-[10px]"
>
Cancel
</button>
{!isLoading && !!data?.results?.length && (
<button
onClick={standalone ? () => {} : addMedia}
disabled={selected.length === 0}
className="cursor-pointer text-white disabled:opacity-80 disabled:cursor-not-allowed h-[52px] px-[20px] items-center justify-center bg-[#612BD3] flex rounded-[10px]"
>
{t('add_selected_media', 'Add selected media')}
</button>
)}
</div>
</DropFiles>
)}
</div>
</div>
</DropFiles>
);
};
export const MultiMediaComponent: FC<{
@ -543,6 +569,8 @@ export const MultiMediaComponent: FC<{
error?: any;
onOpen?: () => void;
onClose?: () => void;
toolBar?: React.ReactNode;
information?: React.ReactNode;
onChange: (event: {
target: {
name: string;
@ -557,8 +585,6 @@ export const MultiMediaComponent: FC<{
}) => void;
}> = (props) => {
const {
onOpen,
onClose,
name,
error,
text,
@ -566,6 +592,8 @@ export const MultiMediaComponent: FC<{
value,
allData,
dummy,
toolBar,
information,
} = props;
const user = useUser();
const modals = useModals();
@ -574,7 +602,7 @@ export const MultiMediaComponent: FC<{
setCurrentMedia(value);
}
}, [value]);
const [mediaModal, setMediaModal] = useState(false);
const [currentMedia, setCurrentMedia] = useState(value);
const mediaDirectory = useMediaDirectory();
const changeMedia = useCallback(
@ -603,7 +631,12 @@ export const MultiMediaComponent: FC<{
);
const showModal = useCallback(() => {
modals.openModal({
title: 'Media Library',
askClose: false,
closeOnEscape: true,
fullScreen: true,
size: 'calc(100% - 80px)',
height: 'calc(100% - 80px)',
children: (close) => (
<MediaBox setMedia={changeMedia} closeModal={close} />
),
@ -637,40 +670,12 @@ export const MultiMediaComponent: FC<{
}
}, [changeMedia]);
const mediaSettings = useMediaSettings();
const t = useT();
return (
<>
<div className="b1 flex flex-col gap-[8px] bg-bigStrip rounded-bl-[8px] select-none w-full">
<div className="flex gap-[10px]">
<Button
onClick={showModal}
className="ms-[10px] !px-[0] !h-[80px] w-[80px] rounded-[4px] mb-[10px] gap-[8px] !text-primary justify-center items-center flex border border-dashed border-newBgLineColor bg-newColColor"
>
<div className="flex flex-col gap-[5px] items-center">
<div>
<svg
className="!text-primary"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
>
<path
d="M19.5 3H7.5C7.10218 3 6.72064 3.15804 6.43934 3.43934C6.15804 3.72064 6 4.10218 6 4.5V6H4.5C4.10218 6 3.72064 6.15804 3.43934 6.43934C3.15804 6.72064 3 7.10218 3 7.5V19.5C3 19.8978 3.15804 20.2794 3.43934 20.5607C3.72064 20.842 4.10218 21 4.5 21H16.5C16.8978 21 17.2794 20.842 17.5607 20.5607C17.842 20.2794 18 19.8978 18 19.5V18H19.5C19.8978 18 20.2794 17.842 20.5607 17.5607C20.842 17.2794 21 16.8978 21 16.5V4.5C21 4.10218 20.842 3.72064 20.5607 3.43934C20.2794 3.15804 19.8978 3 19.5 3ZM7.5 4.5H19.5V11.0044L17.9344 9.43875C17.6531 9.15766 17.2717 8.99976 16.8741 8.99976C16.4764 8.99976 16.095 9.15766 15.8137 9.43875L8.75344 16.5H7.5V4.5ZM16.5 19.5H4.5V7.5H6V16.5C6 16.8978 6.15804 17.2794 6.43934 17.5607C6.72064 17.842 7.10218 18 7.5 18H16.5V19.5ZM19.5 16.5H10.875L16.875 10.5L19.5 13.125V16.5ZM11.25 10.5C11.695 10.5 12.13 10.368 12.5 10.1208C12.87 9.87357 13.1584 9.52217 13.3287 9.11104C13.499 8.6999 13.5436 8.2475 13.4568 7.81105C13.37 7.37459 13.1557 6.97368 12.841 6.65901C12.5263 6.34434 12.1254 6.13005 11.689 6.04323C11.2525 5.95642 10.8001 6.00097 10.389 6.17127C9.97783 6.34157 9.62643 6.62996 9.37919 6.99997C9.13196 7.36998 9 7.80499 9 8.25C9 8.84674 9.23705 9.41903 9.65901 9.84099C10.081 10.2629 10.6533 10.5 11.25 10.5ZM11.25 7.5C11.3983 7.5 11.5433 7.54399 11.6667 7.6264C11.79 7.70881 11.8861 7.82594 11.9429 7.96299C11.9997 8.10003 12.0145 8.25083 11.9856 8.39632C11.9566 8.5418 11.8852 8.67544 11.7803 8.78033C11.6754 8.88522 11.5418 8.95665 11.3963 8.98559C11.2508 9.01453 11.1 8.99968 10.963 8.94291C10.8259 8.88614 10.7088 8.79001 10.6264 8.66668C10.544 8.54334 10.5 8.39834 10.5 8.25C10.5 8.05109 10.579 7.86032 10.7197 7.71967C10.8603 7.57902 11.0511 7.5 11.25 7.5Z"
fill="currentColor"
/>
</svg>
</div>
<div className="text-[12px] font-[500] !text-current">
{t('insert_media', 'Insert Media')}
</div>
</div>
</Button>
<div className="b1 flex flex-col gap-[8px] rounded-bl-[8px] select-none w-full">
<div className="flex gap-[10px] px-[12px]">
{!!currentMedia && (
<ReactSortable
list={currentMedia}
@ -684,10 +689,27 @@ export const MultiMediaComponent: FC<{
>
{currentMedia.map((media, index) => (
<Fragment key={media.id}>
<div className="cursor-pointer rounded-[4px] w-[80px] h-[80px] border-2 border-tableBorder relative flex transition-all">
<div className="dragging text-sm absolute pe-[1px] z-[10] pb-[3px] -start-[4px] -top-[4px] bg-blue-700 cursor-move rounded-full w-[15px] h-[15px] text-white flex justify-center items-center">
::
</div>
<div className="cursor-pointer rounded-[5px] w-[40px] h-[40px] border-2 border-tableBorder relative flex transition-all">
<svg
className="z-[20] dragging absolute pe-[1px] pb-[3px] -start-[4px] -top-[4px] cursor-move"
xmlns="http://www.w3.org/2000/svg"
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
>
<ellipse
cx="8.23242"
cy="7.5"
rx="6"
ry="5.5"
fill="white"
/>
<path
d="M7.5 0C11.6421 0 15 3.35786 15 7.5C14.9998 11.642 11.642 15 7.5 15C3.35799 15 0.000197912 11.642 0 7.5C0 3.35786 3.35786 0 7.5 0ZM5.55566 8.38867C4.97286 8.38867 4.50026 8.86159 4.5 9.44434C4.5 10.0273 4.9727 10.5 5.55566 10.5C6.13858 10.4999 6.61133 10.0273 6.61133 9.44434C6.61107 8.86162 6.13842 8.38873 5.55566 8.38867ZM9.44434 8.38867C8.86158 8.38873 8.38893 8.86162 8.38867 9.44434C8.38867 10.0273 8.86142 10.4999 9.44434 10.5C10.0273 10.5 10.5 10.0273 10.5 9.44434C10.4997 8.86159 10.0271 8.38867 9.44434 8.38867ZM5.55566 9.38867C5.58614 9.38873 5.61107 9.41391 5.61133 9.44434C5.61133 9.47498 5.5863 9.49994 5.55566 9.5C5.52498 9.5 5.5 9.47502 5.5 9.44434C5.50026 9.41387 5.52514 9.38867 5.55566 9.38867ZM9.44434 9.38867C9.47486 9.38867 9.49974 9.41387 9.5 9.44434C9.5 9.47502 9.47502 9.5 9.44434 9.5C9.4137 9.49994 9.38867 9.47498 9.38867 9.44434C9.38893 9.41391 9.41386 9.38873 9.44434 9.38867ZM5.55566 4.5C4.97282 4.5 4.5002 4.97287 4.5 5.55566C4.50006 6.13858 4.97273 6.61133 5.55566 6.61133C6.13855 6.61127 6.61127 6.13855 6.61133 5.55566C6.61113 4.9729 6.13846 4.50006 5.55566 4.5ZM9.44434 4.5C8.86154 4.50006 8.38887 4.9729 8.38867 5.55566C8.38873 6.13855 8.86145 6.61127 9.44434 6.61133C10.0273 6.61133 10.4999 6.13858 10.5 5.55566C10.4998 4.97287 10.0272 4.5 9.44434 4.5ZM5.55566 5.5C5.58617 5.50006 5.61113 5.52519 5.61133 5.55566C5.61127 5.58626 5.58626 5.61127 5.55566 5.61133C5.52502 5.61133 5.50006 5.5863 5.5 5.55566C5.5002 5.52515 5.5251 5.5 5.55566 5.5ZM9.44434 5.5C9.4749 5.5 9.4998 5.52515 9.5 5.55566C9.49994 5.5863 9.47498 5.61133 9.44434 5.61133C9.41374 5.61127 9.38873 5.58626 9.38867 5.55566C9.38887 5.52519 9.41383 5.50006 9.44434 5.5Z"
fill="#618DFF"
/>
</svg>
<div className="w-full h-full relative group">
<div
@ -699,7 +721,6 @@ export const MultiMediaComponent: FC<{
media={media as any}
onClose={close}
onSelect={(value: any) => {
console.log(value);
onChange({
target: {
name: 'upload',
@ -719,7 +740,7 @@ export const MultiMediaComponent: FC<{
),
});
}}
className="absolute top-[50%] left-[50%] -translate-x-[50%] -translate-y-[50%] bg-black/80 rounded-[10px] opacity-0 group-hover:opacity-100 transition-opacity z-[100]"
className="absolute top-[50%] left-[50%] -translate-x-[50%] -translate-y-[50%] bg-black/80 rounded-[10px] opacity-0 group-hover:opacity-100 transition-opacity z-[9]"
>
<svg
width="40"
@ -744,12 +765,21 @@ export const MultiMediaComponent: FC<{
/>
)}
</div>
<div
<svg
onClick={clearMedia(index)}
className="rounded-full w-[15px] h-[15px] bg-red-800 text-white flex justify-center items-center absolute -end-[4px] -top-[4px]"
className="absolute -end-[4px] -top-[4px] z-[20] rounded-full bg-white"
xmlns="http://www.w3.org/2000/svg"
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
>
x
</div>
<path
d="M7.5 0C3.3675 0 0 3.3675 0 7.5C0 11.6325 3.3675 15 7.5 15C11.6325 15 15 11.6325 15 7.5C15 3.3675 11.6325 0 7.5 0ZM10.02 9.225C10.2375 9.4425 10.2375 9.8025 10.02 10.02C9.9075 10.1325 9.765 10.185 9.6225 10.185C9.48 10.185 9.3375 10.1325 9.225 10.02L7.5 8.295L5.775 10.02C5.6625 10.1325 5.52 10.185 5.3775 10.185C5.235 10.185 5.0925 10.1325 4.98 10.02C4.7625 9.8025 4.7625 9.4425 4.98 9.225L6.705 7.5L4.98 5.775C4.7625 5.5575 4.7625 5.1975 4.98 4.98C5.1975 4.7625 5.5575 4.7625 5.775 4.98L7.5 6.705L9.225 4.98C9.4425 4.7625 9.8025 4.7625 10.02 4.98C10.2375 5.1975 10.2375 5.5575 10.02 5.775L8.295 7.5L10.02 9.225Z"
fill="#FF3535"
/>
</svg>
</div>
</Fragment>
))}
@ -757,32 +787,76 @@ export const MultiMediaComponent: FC<{
)}
</div>
{!dummy && (
<div className="flex gap-[10px] bg-newBgLineColor w-full b1">
<div className="flex py-[10px] b2">
<Button
<div className="flex gap-[8px] px-[12px] border-t border-newColColor w-full b1 text-textColor">
<div className="flex py-[10px] b2 items-center gap-[4px]">
<div
onClick={showModal}
className="cursor-pointer h-[30px] rounded-[6px] justify-center items-center flex bg-newColColor px-[8px]"
>
<div className="flex gap-[8px] items-center">
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<g clip-path="url(#clip0_2352_53043)">
<path
d="M8.33333 1.99967H5.2C4.0799 1.99967 3.51984 1.99967 3.09202 2.21766C2.71569 2.40941 2.40973 2.71537 2.21799 3.09169C2 3.51952 2 4.07957 2 5.19967V10.7997C2 11.9198 2 12.4798 2.21799 12.9077C2.40973 13.284 2.71569 13.5899 3.09202 13.7817C3.51984 13.9997 4.07989 13.9997 5.2 13.9997H11.3333C11.9533 13.9997 12.2633 13.9997 12.5176 13.9315C13.2078 13.7466 13.7469 13.2075 13.9319 12.5173C14 12.263 14 11.953 14 11.333M12.6667 5.33301V1.33301M10.6667 3.33301H14.6667M7 5.66634C7 6.40272 6.40305 6.99967 5.66667 6.99967C4.93029 6.99967 4.33333 6.40272 4.33333 5.66634C4.33333 4.92996 4.93029 4.33301 5.66667 4.33301C6.40305 4.33301 7 4.92996 7 5.66634ZM9.99336 7.94511L4.3541 13.0717C4.03691 13.3601 3.87831 13.5042 3.86429 13.6291C3.85213 13.7374 3.89364 13.8448 3.97546 13.9167C4.06985 13.9997 4.28419 13.9997 4.71286 13.9997H10.9707C11.9301 13.9997 12.4098 13.9997 12.7866 13.8385C13.2596 13.6361 13.6365 13.2593 13.8388 12.7863C14 12.4095 14 11.9298 14 10.9703C14 10.6475 14 10.4861 13.9647 10.3358C13.9204 10.1469 13.8353 9.96991 13.7155 9.81727C13.6202 9.69581 13.4941 9.59497 13.242 9.39331L11.3772 7.90145C11.1249 7.69961 10.9988 7.5987 10.8599 7.56308C10.7374 7.53169 10.6086 7.53575 10.4884 7.5748C10.352 7.6191 10.2324 7.72777 9.99336 7.94511Z"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_2352_53043">
<rect width="16" height="16" fill="currentColor" />
</clipPath>
</defs>
</svg>
</div>
<div className="text-[10px] font-[600] maxMedia:hidden block">
{t('insert_media', 'Insert Media')}
</div>
</div>
</div>
<div
onClick={designMedia}
className="ms-[10px] rounded-[4px] gap-[8px] !text-primary justify-center items-center w-[127px] flex border border-dashed border-newBgLineColor bg-newColColor"
className="cursor-pointer h-[30px] rounded-[6px] justify-center items-center flex bg-newColColor px-[8px]"
>
<div className="flex gap-[5px] items-center">
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M19.5 3H7.5C7.10218 3 6.72064 3.15804 6.43934 3.43934C6.15804 3.72064 6 4.10218 6 4.5V6H4.5C4.10218 6 3.72064 6.15804 3.43934 6.43934C3.15804 6.72064 3 7.10218 3 7.5V19.5C3 19.8978 3.15804 20.2794 3.43934 20.5607C3.72064 20.842 4.10218 21 4.5 21H16.5C16.8978 21 17.2794 20.842 17.5607 20.5607C17.842 20.2794 18 19.8978 18 19.5V18H19.5C19.8978 18 20.2794 17.842 20.5607 17.5607C20.842 17.2794 21 16.8978 21 16.5V4.5C21 4.10218 20.842 3.72064 20.5607 3.43934C20.2794 3.15804 19.8978 3 19.5 3ZM7.5 4.5H19.5V11.0044L17.9344 9.43875C17.6531 9.15766 17.2717 8.99976 16.8741 8.99976C16.4764 8.99976 16.095 9.15766 15.8137 9.43875L8.75344 16.5H7.5V4.5ZM16.5 19.5H4.5V7.5H6V16.5C6 16.8978 6.15804 17.2794 6.43934 17.5607C6.72064 17.842 7.10218 18 7.5 18H16.5V19.5ZM19.5 16.5H10.875L16.875 10.5L19.5 13.125V16.5ZM11.25 10.5C11.695 10.5 12.13 10.368 12.5 10.1208C12.87 9.87357 13.1584 9.52217 13.3287 9.11104C13.499 8.6999 13.5436 8.2475 13.4568 7.81105C13.37 7.37459 13.1557 6.97368 12.841 6.65901C12.5263 6.34434 12.1254 6.13005 11.689 6.04323C11.2525 5.95642 10.8001 6.00097 10.389 6.17127C9.97783 6.34157 9.62643 6.62996 9.37919 6.99997C9.13196 7.36998 9 7.80499 9 8.25C9 8.84674 9.23705 9.41903 9.65901 9.84099C10.081 10.2629 10.6533 10.5 11.25 10.5ZM11.25 7.5C11.3983 7.5 11.5433 7.54399 11.6667 7.6264C11.79 7.70881 11.8861 7.82594 11.9429 7.96299C11.9997 8.10003 12.0145 8.25083 11.9856 8.39632C11.9566 8.5418 11.8852 8.67544 11.7803 8.78033C11.6754 8.88522 11.5418 8.95665 11.3963 8.98559C11.2508 9.01453 11.1 8.99968 10.963 8.94291C10.8259 8.88614 10.7088 8.79001 10.6264 8.66668C10.544 8.54334 10.5 8.39834 10.5 8.25C10.5 8.05109 10.579 7.86032 10.7197 7.71967C10.8603 7.57902 11.0511 7.5 11.25 7.5Z"
fill="currentColor"
/>
<g clip-path="url(#clip0_2352_53048)">
<path
d="M7.79167 1.99984H5.2C4.07989 1.99984 3.51984 1.99984 3.09202 2.21782C2.71569 2.40957 2.40973 2.71553 2.21799 3.09186C2 3.51968 2 4.07973 2 5.19984V10.7998C2 11.9199 2 12.48 2.21799 12.9078C2.40973 13.2841 2.71569 13.5901 3.09202 13.7818C3.51984 13.9998 4.07989 13.9998 5.2 13.9998H11.3333C11.9533 13.9998 12.2633 13.9998 12.5176 13.9317C13.2078 13.7468 13.7469 13.2077 13.9319 12.5175C14 12.2631 14 11.9532 14 11.3332M7 5.6665C7 6.40288 6.40305 6.99984 5.66667 6.99984C4.93029 6.99984 4.33333 6.40288 4.33333 5.6665C4.33333 4.93012 4.93029 4.33317 5.66667 4.33317C6.40305 4.33317 7 4.93012 7 5.6665ZM9.99336 7.94527L4.3541 13.0719C4.03691 13.3602 3.87831 13.5044 3.86429 13.6293C3.85213 13.7376 3.89364 13.8449 3.97546 13.9169C4.06985 13.9998 4.28419 13.9998 4.71286 13.9998H10.9707C11.9301 13.9998 12.4098 13.9998 12.7866 13.8387C13.2596 13.6363 13.6365 13.2595 13.8388 12.7864C14 12.4097 14 11.9299 14 10.9705C14 10.6477 14 10.4863 13.9647 10.3359C13.9204 10.147 13.8353 9.97007 13.7155 9.81743C13.6202 9.69597 13.4941 9.59514 13.242 9.39348L11.3772 7.90161C11.1249 7.69978 10.9988 7.59886 10.8599 7.56324C10.7374 7.53185 10.6086 7.53592 10.4884 7.57496C10.352 7.61926 10.2324 7.72794 9.99336 7.94527ZM15.0951 6.49981L13.0275 5.90908C12.9285 5.88079 12.879 5.86664 12.8328 5.84544C12.7918 5.82662 12.7528 5.80368 12.7164 5.77698C12.6755 5.74692 12.6391 5.71051 12.5663 5.6377L10.2617 3.33317C9.80143 2.87292 9.80144 2.1267 10.2617 1.66646C10.7219 1.20623 11.4681 1.20623 11.9284 1.66647L14.2329 3.97103C14.3058 4.04384 14.3422 4.08025 14.3722 4.12121C14.3989 4.15757 14.4219 4.19655 14.4407 4.23755C14.4619 4.28373 14.476 4.33323 14.5043 4.43224L15.0951 6.49981Z"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_2352_53048">
<rect width="16" height="16" fill="currentColor" />
</clipPath>
</defs>
</svg>
</div>
<div className="text-[12px] font-[500] !text-current">
<div className="text-[10px] font-[600] iconBreak:hidden block">
{t('design_media', 'Design Media')}
</div>
</div>
</Button>
</div>
<ThirdPartyMedia allData={allData} onChange={changeMedia} />
@ -793,6 +867,32 @@ export const MultiMediaComponent: FC<{
</>
)}
</div>
<div className="text-newColColor h-full flex items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="2"
height="17"
viewBox="0 0 2 17"
fill="none"
>
<path
d="M0.75 0.75V16"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
/>
</svg>
</div>
{!!toolBar && (
<div className="flex py-[10px] b2 items-center gap-[4px]">
{toolBar}
</div>
)}
{information && (
<div className="flex-1 justify-end flex py-[10px] b2 items-center gap-[4px]">
{information}
</div>
)}
</div>
)}
</div>

View File

@ -116,7 +116,8 @@ export function useUppyUploader(props: {
uppy2.log(error.message, 'error');
uppy2.info(error.message, 'error', 5000);
toast.show(
`File type "${fileType}" is not allowed. Allowed types: ${allowedFileTypes}`
`File type "${fileType}" is not allowed. Allowed types: ${allowedFileTypes}`,
'warning'
);
uppy2.removeFile(file.id);
return reject(error);
@ -197,6 +198,7 @@ export function useUppyUploader(props: {
});
});
uppy2.on('error', (result) => {
uppy2.clear();
setLocked(false);
});
uppy2.on('complete', async (result) => {

View File

@ -24,27 +24,43 @@ export const AComponent: FC<{
// update link
try {
editor?.chain()?.focus()?.extendMarkRange('link')?.setLink({ href: url })?.run();
} catch (e) {
}
editor
?.chain()
?.focus()
?.extendMarkRange('link')
?.setLink({ href: url })
?.run();
} catch (e) {}
editor?.commands?.focus();
};
return (
<div
data-tooltip-id="tooltip"
data-tooltip-content="Link"
onClick={mark}
className="select-none cursor-pointer w-[40px] p-[5px] text-center"
className="select-none cursor-pointer rounded-[6px] w-[30px] h-[30px] bg-newColColor flex justify-center items-center"
>
<svg
width="20"
height="20"
viewBox="0 0 26 26"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M17.7079 8.29252C17.8008 8.38539 17.8746 8.49568 17.9249 8.61708C17.9752 8.73847 18.0011 8.8686 18.0011 9.00002C18.0011 9.13143 17.9752 9.26156 17.9249 9.38296C17.8746 9.50436 17.8008 9.61465 17.7079 9.70752L9.70786 17.7075C9.61495 17.8004 9.50465 17.8741 9.38325 17.9244C9.26186 17.9747 9.13175 18.0006 9.00036 18.0006C8.86896 18.0006 8.73885 17.9747 8.61746 17.9244C8.49607 17.8741 8.38577 17.8004 8.29286 17.7075C8.19995 17.6146 8.12625 17.5043 8.07596 17.3829C8.02568 17.2615 7.9998 17.1314 7.9998 17C7.9998 16.8686 8.02568 16.7385 8.07596 16.6171C8.12625 16.4957 8.19995 16.3854 8.29286 16.2925L16.2929 8.29252C16.3857 8.19954 16.496 8.12578 16.6174 8.07546C16.7388 8.02513 16.8689 7.99923 17.0004 7.99923C17.1318 7.99923 17.2619 8.02513 17.3833 8.07546C17.5047 8.12578 17.615 8.19954 17.7079 8.29252ZM23.9504 2.05002C23.3003 1.39993 22.5286 0.884251 21.6793 0.532423C20.83 0.180596 19.9197 -0.000488281 19.0004 -0.000488281C18.081 -0.000488281 17.1707 0.180596 16.3214 0.532423C15.4721 0.884251 14.7004 1.39993 14.0504 2.05002L10.2929 5.80627C10.1052 5.99391 9.9998 6.2484 9.9998 6.51377C9.9998 6.77913 10.1052 7.03363 10.2929 7.22127C10.4805 7.40891 10.735 7.51432 11.0004 7.51432C11.2657 7.51432 11.5202 7.40891 11.7079 7.22127L15.4654 3.47127C16.4065 2.55083 17.6726 2.03866 18.989 2.04591C20.3053 2.05316 21.5657 2.57924 22.4966 3.50999C23.4276 4.44074 23.9539 5.70105 23.9613 7.01742C23.9688 8.33379 23.4569 9.6 22.5366 10.5413L18.7779 14.2988C18.5902 14.4862 18.4847 14.7406 18.4846 15.0058C18.4845 15.2711 18.5898 15.5255 18.7772 15.7131C18.9647 15.9008 19.219 16.0063 19.4843 16.0064C19.7495 16.0065 20.004 15.9012 20.1916 15.7138L23.9504 11.95C24.6004 11.3 25.1161 10.5283 25.468 9.67897C25.8198 8.82964 26.0009 7.91933 26.0009 7.00002C26.0009 6.0807 25.8198 5.17039 25.468 4.32107C25.1161 3.47174 24.6004 2.70004 23.9504 2.05002ZM14.2929 18.7775L10.5354 22.535C10.073 23.0078 9.52136 23.3842 8.9125 23.6423C8.30365 23.9004 7.64963 24.0352 6.98832 24.0389C6.32702 24.0425 5.67156 23.9149 5.05989 23.6635C4.44823 23.4121 3.89252 23.0418 3.42494 22.5742C2.95736 22.1065 2.5872 21.5507 2.33589 20.939C2.08458 20.3273 1.95711 19.6718 1.96087 19.0105C1.96463 18.3492 2.09954 17.6952 2.35779 17.0864C2.61603 16.4776 2.99249 15.9261 3.46536 15.4638L7.22161 11.7075C7.40925 11.5199 7.51466 11.2654 7.51466 11C7.51466 10.7347 7.40925 10.4802 7.22161 10.2925C7.03397 10.1049 6.77947 9.99946 6.51411 9.99946C6.24874 9.99946 5.99425 10.1049 5.80661 10.2925L2.05036 14.05C0.737536 15.3628 0 17.1434 0 19C0 20.8566 0.737536 22.6372 2.05036 23.95C3.36318 25.2628 5.14375 26.0004 7.00036 26.0004C8.85697 26.0004 10.6375 25.2628 11.9504 23.95L15.7079 20.1913C15.8953 20.0036 16.0006 19.7492 16.0005 19.4839C16.0004 19.2187 15.8949 18.9644 15.7072 18.7769C15.5196 18.5894 15.2652 18.4842 14.9999 18.4843C14.7347 18.4844 14.4803 18.5899 14.2929 18.7775Z"
fill="currentColor"
/>
<g clip-path="url(#clip0_2452_193804)">
<path
d="M6.6668 8.66599C6.9531 9.04875 7.31837 9.36545 7.73783 9.59462C8.1573 9.82379 8.62114 9.96007 9.0979 9.99422C9.57466 10.0284 10.0532 9.95957 10.501 9.79251C10.9489 9.62546 11.3555 9.36404 11.6935 9.02599L13.6935 7.02599C14.3007 6.39732 14.6366 5.55531 14.629 4.68132C14.6215 3.80733 14.2709 2.97129 13.6529 2.35326C13.0348 1.73524 12.1988 1.38467 11.3248 1.37708C10.4508 1.36948 9.60881 1.70547 8.98013 2.31266L7.83347 3.45266M9.33347 7.33266C9.04716 6.94991 8.68189 6.6332 8.26243 6.40403C7.84297 6.17486 7.37913 6.03858 6.90237 6.00444C6.4256 5.97029 5.94708 6.03908 5.49924 6.20614C5.0514 6.3732 4.64472 6.63461 4.3068 6.97266L2.3068 8.97266C1.69961 9.60133 1.36363 10.4433 1.37122 11.3173C1.37881 12.1913 1.72938 13.0274 2.3474 13.6454C2.96543 14.2634 3.80147 14.614 4.67546 14.6216C5.54945 14.6292 6.39146 14.2932 7.02013 13.686L8.16013 12.546"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_2452_193804">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
</div>
);

View File

@ -128,7 +128,7 @@ export const AddEditModalInnerInner: FC<AddEditModalProps> = (props) => {
internal: state.internal,
setTags: state.setTags,
setEditor: state.setEditor,
setRepeater: state.setRepeater
setRepeater: state.setRepeater,
}))
);
@ -161,8 +161,7 @@ export const AddEditModalInnerInner: FC<AddEditModalProps> = (props) => {
}))
);
setCurrent(existingData.integration);
}
else {
} else {
setEditor('normal');
}
@ -212,5 +211,12 @@ export const AddEditModalInnerInner: FC<AddEditModalProps> = (props) => {
return null;
}
return <ManageModal {...props} />;
return (
<>
<style>
{`#support-discord {display: none !important;}`}
</style>
<ManageModal {...props} />
</>
);
};

View File

@ -13,22 +13,25 @@ export const AddPostButton: FC<{
const t = useT();
return (
<div>
<Button
<div className="flex">
<div
onClick={onClick}
className="!h-[24px] rounded-[3px] flex gap-[4px] text-[12px] font-[500]"
className="select-none cursor-pointer h-[34px] rounded-[6px] flex bg-[#D82D7E] gap-[8px] justify-center items-center pl-[16px] pr-[20px] text-[13px] font-[600] mt-[12px]"
>
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 14 14"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M7 1.3125C5.87512 1.3125 4.7755 1.64607 3.8402 2.27102C2.90489 2.89597 2.17591 3.78423 1.74544 4.82349C1.31496 5.86274 1.20233 7.00631 1.42179 8.10958C1.64124 9.21284 2.18292 10.2263 2.97833 11.0217C3.77374 11.8171 4.78716 12.3588 5.89043 12.5782C6.99369 12.7977 8.13726 12.685 9.17651 12.2546C10.2158 11.8241 11.104 11.0951 11.729 10.1598C12.3539 9.2245 12.6875 8.12488 12.6875 7C12.6859 5.49207 12.0862 4.04636 11.0199 2.98009C9.95365 1.91382 8.50793 1.31409 7 1.3125ZM7 11.8125C6.04818 11.8125 5.11773 11.5303 4.32632 11.0014C3.53491 10.4726 2.91808 9.72103 2.55383 8.84166C2.18959 7.96229 2.09428 6.99466 2.27997 6.06113C2.46566 5.12759 2.92401 4.27009 3.59705 3.59705C4.27009 2.92401 5.1276 2.46566 6.06113 2.27997C6.99466 2.09428 7.9623 2.18958 8.84167 2.55383C9.72104 2.91808 10.4726 3.53491 11.0015 4.32632C11.5303 5.11773 11.8125 6.04818 11.8125 7C11.8111 8.27591 11.3036 9.49915 10.4014 10.4014C9.49915 11.3036 8.27591 11.8111 7 11.8125ZM9.625 7C9.625 7.11603 9.57891 7.22731 9.49686 7.30936C9.41481 7.39141 9.30353 7.4375 9.1875 7.4375H7.4375V9.1875C7.4375 9.30353 7.39141 9.41481 7.30936 9.49686C7.22731 9.57891 7.11603 9.625 7 9.625C6.88397 9.625 6.77269 9.57891 6.69064 9.49686C6.6086 9.41481 6.5625 9.30353 6.5625 9.1875V7.4375H4.8125C4.69647 7.4375 4.58519 7.39141 4.50314 7.30936C4.4211 7.22731 4.375 7.11603 4.375 7C4.375 6.88397 4.4211 6.77269 4.50314 6.69064C4.58519 6.60859 4.69647 6.5625 4.8125 6.5625H6.5625V4.8125C6.5625 4.69647 6.6086 4.58519 6.69064 4.50314C6.77269 4.42109 6.88397 4.375 7 4.375C7.11603 4.375 7.22731 4.42109 7.30936 4.50314C7.39141 4.58519 7.4375 4.69647 7.4375 4.8125V6.5625H9.1875C9.30353 6.5625 9.41481 6.60859 9.49686 6.69064C9.57891 6.77269 9.625 6.88397 9.625 7Z"
fill="white"
d="M8.00065 3.33301V12.6663M3.33398 7.99967H12.6673"
stroke="white"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
@ -41,7 +44,7 @@ export const AddPostButton: FC<{
: ['add_comment', 'Add comment'])
)}
</div>
</Button>
</div>
</div>
);
};

View File

@ -81,32 +81,25 @@ export const BoldText: FC<{
};
return (
<div
data-tooltip-id="tooltip"
data-tooltip-content="Bold Text"
onClick={mark}
className="select-none cursor-pointer w-[40px] p-[5px] text-center"
className="select-none cursor-pointer rounded-[6px] w-[30px] h-[30px] bg-newColColor flex justify-center items-center"
>
<svg
width="25"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<g clipPath="url(#clip0_31_12616)">
<path
d="M14.7686 12.24C15.4192 12.3787 15.9419 12.704 16.3366 13.216C16.7312 13.7173 16.9286 14.2933 16.9286 14.944C16.9286 15.8827 16.5979 16.6293 15.9366 17.184C15.2859 17.728 14.3739 18 13.2006 18H7.96856V6.768H13.0246C14.1659 6.768 15.0566 7.02933 15.6966 7.552C16.3472 8.07467 16.6726 8.784 16.6726 9.68C16.6726 10.3413 16.4966 10.8907 16.1446 11.328C15.8032 11.7653 15.3446 12.0693 14.7686 12.24ZM10.7046 11.312H12.4966C12.9446 11.312 13.2859 11.216 13.5206 11.024C13.7659 10.8213 13.8886 10.528 13.8886 10.144C13.8886 9.76 13.7659 9.46667 13.5206 9.264C13.2859 9.06133 12.9446 8.96 12.4966 8.96H10.7046V11.312ZM12.7206 15.792C13.1792 15.792 13.5312 15.6907 13.7766 15.488C14.0326 15.2747 14.1606 14.9707 14.1606 14.576C14.1606 14.1813 14.0272 13.872 13.7606 13.648C13.5046 13.424 13.1472 13.312 12.6886 13.312H10.7046V15.792H12.7206Z"
fill="currentColor"
/>
</g>
<defs>
<clipPath id="clip0_31_12616">
<rect
width="24"
height="24"
fill="white"
transform="translate(0.25)"
/>
</clipPath>
</defs>
<path
d="M4 8.00033H9.33333C10.8061 8.00033 12 6.80642 12 5.33366C12 3.8609 10.8061 2.66699 9.33333 2.66699H4V8.00033ZM4 8.00033H10C11.4728 8.00033 12.6667 9.19423 12.6667 10.667C12.6667 12.1398 11.4728 13.3337 10 13.3337H4V8.00033Z"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
);

View File

@ -11,19 +11,24 @@ export const Bullets: FC<{
};
return (
<div
data-tooltip-id="tooltip"
data-tooltip-content="Bullets"
onClick={bullet}
className="select-none cursor-pointer w-[40px] p-[5px] text-center"
className="select-none cursor-pointer rounded-[6px] w-[30px] h-[30px] bg-newColColor flex justify-center items-center"
>
<svg
width="20"
height="14"
viewBox="0 0 26 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M6.5 2C6.5 1.60218 6.65804 1.22064 6.93934 0.93934C7.22064 0.658035 7.60218 0.5 8 0.5H24C24.3978 0.5 24.7794 0.658035 25.0607 0.93934C25.342 1.22064 25.5 1.60218 25.5 2C25.5 2.39782 25.342 2.77936 25.0607 3.06066C24.7794 3.34196 24.3978 3.5 24 3.5H8C7.60218 3.5 7.22064 3.34196 6.93934 3.06066C6.65804 2.77936 6.5 2.39782 6.5 2ZM24 8.5H8C7.60218 8.5 7.22064 8.65804 6.93934 8.93934C6.65804 9.22064 6.5 9.60218 6.5 10C6.5 10.3978 6.65804 10.7794 6.93934 11.0607C7.22064 11.342 7.60218 11.5 8 11.5H24C24.3978 11.5 24.7794 11.342 25.0607 11.0607C25.342 10.7794 25.5 10.3978 25.5 10C25.5 9.60218 25.342 9.22064 25.0607 8.93934C24.7794 8.65804 24.3978 8.5 24 8.5ZM24 16.5H8C7.60218 16.5 7.22064 16.658 6.93934 16.9393C6.65804 17.2206 6.5 17.6022 6.5 18C6.5 18.3978 6.65804 18.7794 6.93934 19.0607C7.22064 19.342 7.60218 19.5 8 19.5H24C24.3978 19.5 24.7794 19.342 25.0607 19.0607C25.342 18.7794 25.5 18.3978 25.5 18C25.5 17.6022 25.342 17.2206 25.0607 16.9393C24.7794 16.658 24.3978 16.5 24 16.5ZM2.5 8C2.10444 8 1.71776 8.1173 1.38886 8.33706C1.05996 8.55682 0.803617 8.86918 0.652242 9.23463C0.500867 9.60009 0.46126 10.0022 0.53843 10.3902C0.615601 10.7781 0.806082 11.1345 1.08579 11.4142C1.36549 11.6939 1.72186 11.8844 2.10982 11.9616C2.49778 12.0387 2.89992 11.9991 3.26537 11.8478C3.63082 11.6964 3.94318 11.44 4.16294 11.1111C4.3827 10.7822 4.5 10.3956 4.5 10C4.5 9.46957 4.28929 8.96086 3.91421 8.58579C3.53914 8.21071 3.03043 8 2.5 8ZM2.5 0C2.10444 0 1.71776 0.117298 1.38886 0.337061C1.05996 0.556824 0.803617 0.869181 0.652242 1.23463C0.500867 1.60009 0.46126 2.00222 0.53843 2.39018C0.615601 2.77814 0.806082 3.13451 1.08579 3.41421C1.36549 3.69392 1.72186 3.8844 2.10982 3.96157C2.49778 4.03874 2.89992 3.99913 3.26537 3.84776C3.63082 3.69638 3.94318 3.44004 4.16294 3.11114C4.3827 2.78224 4.5 2.39556 4.5 2C4.5 1.46957 4.28929 0.960859 3.91421 0.585786C3.53914 0.210714 3.03043 0 2.5 0ZM2.5 16C2.10444 16 1.71776 16.1173 1.38886 16.3371C1.05996 16.5568 0.803617 16.8692 0.652242 17.2346C0.500867 17.6001 0.46126 18.0022 0.53843 18.3902C0.615601 18.7781 0.806082 19.1345 1.08579 19.4142C1.36549 19.6939 1.72186 19.8844 2.10982 19.9616C2.49778 20.0387 2.89992 19.9991 3.26537 19.8478C3.63082 19.6964 3.94318 19.44 4.16294 19.1111C4.3827 18.7822 4.5 18.3956 4.5 18C4.5 17.4696 4.28929 16.9609 3.91421 16.5858C3.53914 16.2107 3.03043 16 2.5 16Z"
fill="currentColor"
d="M14 8.00065L6 8.00065M14 4.00065L6 4.00065M14 12.0007L6 12.0007M3.33333 8.00065C3.33333 8.36884 3.03486 8.66732 2.66667 8.66732C2.29848 8.66732 2 8.36884 2 8.00065C2 7.63246 2.29848 7.33398 2.66667 7.33398C3.03486 7.33398 3.33333 7.63246 3.33333 8.00065ZM3.33333 4.00065C3.33333 4.36884 3.03486 4.66732 2.66667 4.66732C2.29848 4.66732 2 4.36884 2 4.00065C2 3.63246 2.29848 3.33398 2.66667 3.33398C3.03486 3.33398 3.33333 3.63246 3.33333 4.00065ZM3.33333 12.0007C3.33333 12.3688 3.03486 12.6673 2.66667 12.6673C2.29848 12.6673 2 12.3688 2 12.0007C2 11.6325 2.29848 11.334 2.66667 11.334C3.03486 11.334 3.33333 11.6325 3.33333 12.0007Z"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>

View File

@ -58,7 +58,8 @@ import Mention from '@tiptap/extension-mention';
import { suggestion } from '@gitroom/frontend/components/new-launch/mention.component';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import { AComponent } from '@gitroom/frontend/components/new-launch/a.component';
import { capitalize } from 'lodash';
import { Placeholder } from '@tiptap/extensions';
import { InformationComponent } from '@gitroom/frontend/components/launches/information.component';
const InterceptBoldShortcut = Extension.create({
name: 'preventBoldWithUnderline',
@ -91,7 +92,7 @@ const InterceptUnderlineShortcut = Extension.create({
export const EditorWrapper: FC<{
totalPosts: number;
value: string;
}> = (props) => {
}> = () => {
const {
setGlobalValueText,
setInternalValueText,
@ -278,6 +279,12 @@ export const EditorWrapper: FC<{
const addValue = useCallback(
(index: number) => () => {
setTimeout(() => {
// scroll the the bottom
document.querySelector('#social-content').scrollTo({
top: document.querySelector('#social-content').scrollHeight,
});
}, 20);
if (internal) {
return addInternalValue(index, current, [
{
@ -326,30 +333,116 @@ export const EditorWrapper: FC<{
}
return (
<div className="relative flex flex-col gap-[20px]">
<div
className={clsx(
'relative flex-col gap-[20px] flex-1',
items.length === 1 && 'flex',
!canEdit && !isCreateSet && 'bg-newSettings rounded-[12px]'
)}
>
{isCreateSet && current !== 'global' && (
<>
<div className="text-center absolute w-full h-full left-0 top-0 items-center justify-center flex z-[101] flex-col gap-[16px]">
<div>
<div className="w-[54px] h-[54px] rounded-full absolute z-[101] flex justify-center items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
>
<path
d="M22.6673 13.3333V10.6667C22.6673 6.98477 19.6825 4 16.0007 4C12.3188 4 9.33398 6.98477 9.33398 10.6667V13.3333M16.0007 19.3333V22M11.734 28H20.2673C22.5075 28 23.6276 28 24.4833 27.564C25.2359 27.1805 25.8479 26.5686 26.2313 25.816C26.6673 24.9603 26.6673 23.8402 26.6673 21.6V19.7333C26.6673 17.4931 26.6673 16.373 26.2313 15.5174C25.8479 14.7647 25.2359 14.1528 24.4833 13.7693C23.6276 13.3333 22.5075 13.3333 20.2673 13.3333H11.734C9.49377 13.3333 8.37367 13.3333 7.51802 13.7693C6.76537 14.1528 6.15345 14.7647 5.76996 15.5174C5.33398 16.373 5.33398 17.4931 5.33398 19.7333V21.6C5.33398 23.8402 5.33398 24.9603 5.76996 25.816C6.15345 26.5686 6.76537 27.1805 7.51802 27.564C8.37367 28 9.49377 28 11.734 28Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="w-[54px] h-[54px] rounded-full bg-newSettings opacity-80" />
</div>
<div className="text-[14px] font-[600] text-white">
You can't edit networks when creating a set
</div>
</div>
<div className="absolute w-full h-full left-0 top-0 bg-newBackdrop opacity-60 z-[100] rounded-[12px]" />
</>
)}
{!canEdit && !isCreateSet && (
<>
<div
onClick={() => {
setLoaded(false);
addRemoveInternal(current);
}}
className="text-center absolute w-full h-full left-0 top-0 items-center justify-center flex z-[101] flex-col gap-[16px]"
>
<div>
<div className="w-[54px] h-[54px] rounded-full absolute z-[101] flex justify-center items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
>
<path
d="M22.6673 13.3333V10.6667C22.6673 6.98477 19.6825 4 16.0007 4C12.3188 4 9.33398 6.98477 9.33398 10.6667V13.3333M16.0007 19.3333V22M11.734 28H20.2673C22.5075 28 23.6276 28 24.4833 27.564C25.2359 27.1805 25.8479 26.5686 26.2313 25.816C26.6673 24.9603 26.6673 23.8402 26.6673 21.6V19.7333C26.6673 17.4931 26.6673 16.373 26.2313 15.5174C25.8479 14.7647 25.2359 14.1528 24.4833 13.7693C23.6276 13.3333 22.5075 13.3333 20.2673 13.3333H11.734C9.49377 13.3333 8.37367 13.3333 7.51802 13.7693C6.76537 14.1528 6.15345 14.7647 5.76996 15.5174C5.33398 16.373 5.33398 17.4931 5.33398 19.7333V21.6C5.33398 23.8402 5.33398 24.9603 5.76996 25.816C6.15345 26.5686 6.76537 27.1805 7.51802 27.564C8.37367 28 9.49377 28 11.734 28Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="w-[54px] h-[54px] rounded-full bg-newSettings opacity-80" />
</div>
<div className="text-[14px] font-[600] text-white">
Click this button to exit global editing
<br />
and customize the post for this channel
</div>
<div>
<div className="text-white rounded-[8px] h-[44px] px-[20px] bg-[#D82D7E] cursor-pointer flex justify-center items-center">
Edit content
</div>
</div>
</div>
<div className="absolute w-full h-full left-0 top-0 bg-newBackdrop opacity-60 z-[100] rounded-[12px]" />
</>
)}
{items.map((g, index) => (
<div key={g.id} className="relative flex flex-col gap-[20px]">
{!canEdit && !isCreateSet && (
<div
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]"
>
{index === 0 && (
<div className="absolute left-[50%] top-[50%] bg-red-400 -translate-x-[50%] z-[101] -translate-y-[50%] border-dashed border p-[10px] border-black">
Edit
<div
key={g.id}
className={clsx(
'relative flex flex-col gap-[20px] flex-1 bg-newSettings',
index === 0 && 'rounded-t-[12px]',
index === items.length - 1 && 'rounded-b-[12px]',
!canEdit && !isCreateSet && 'blur-s'
)}
>
<div className="flex gap-[5px] flex-1 w-full">
<div className="flex-1 flex w-full">
{index > 0 && (
<div className="flex justify-center pl-[12px] text-newSep">
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="87"
viewBox="0 0 18 87"
fill="none"
>
<path
d="M0.75 0.75V79.75C0.75 83.0637 3.43629 85.75 6.75 85.75H16.75"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
/>
</svg>
</div>
)}
</div>
)}
<div className="flex gap-[5px]">
<div className="flex-1">
<Editor
editorType={editor}
allValues={items}
@ -370,61 +463,80 @@ export const EditorWrapper: FC<{
chars={chars}
childButton={
<>
{canEdit ? (
<AddPostButton
num={index}
onClick={addValue(index)}
postComment={postComment}
/>
) : (
<div className="h-[25px]" />
)}
{canEdit && items.length - 1 === index ? (
<div className="flex items-center">
<div className="flex-1">
<AddPostButton
num={index}
onClick={addValue(index)}
postComment={postComment}
/>
</div>
{!!internal && !existingData?.integration && (
<div
className="mt-[12px] flex gap-[20px] items-center cursor-pointer select-none"
onClick={goBackToGlobal}
>
<div className="flex gap-[6px] items-center">
<div className="w-[8px] h-[8px] rounded-full bg-[#FC69FF]" />
<div className="text-[14px] font-[600]">
Editing a Specific Network
</div>
</div>
<div className="flex gap-[6px] items-center">
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M1.33398 6.66667C1.33398 6.66667 2.67064 4.84548 3.75654 3.75883C4.84244 2.67218 6.34305 2 8.00065 2C11.3144 2 14.0007 4.68629 14.0007 8C14.0007 11.3137 11.3144 14 8.00065 14C5.26526 14 2.95739 12.1695 2.23516 9.66667M1.33398 6.66667V2.66667M1.33398 6.66667H5.33398"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="text-[13px] font-[600]">
Back to global
</div>
</div>
</div>
)}
</div>
) : null}
</>
}
/>
</div>
<div className="flex flex-col items-center gap-[10px]">
<div className="flex flex-col items-center gap-[10px] pe-[12px]">
<UpDownArrow
isUp={index !== 0}
isDown={index !== items.length - 1}
onChange={changeOrder(index)}
/>
{index === 0 &&
current !== 'global' &&
canEdit &&
!existingData.integration && (
<svg
onClick={goBackToGlobal}
className="cursor-pointer"
data-tooltip-id="tooltip"
data-tooltip-content="Go back to global mode"
width="20"
height="20"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16 3C13.4288 3 10.9154 3.76244 8.77759 5.1909C6.63975 6.61935 4.97351 8.64968 3.98957 11.0251C3.00563 13.4006 2.74819 16.0144 3.2498 18.5362C3.75141 21.0579 4.98953 23.3743 6.80762 25.1924C8.6257 27.0105 10.9421 28.2486 13.4638 28.7502C15.9856 29.2518 18.5995 28.9944 20.9749 28.0104C23.3503 27.0265 25.3807 25.3603 26.8091 23.2224C28.2376 21.0846 29 18.5712 29 16C28.9964 12.5533 27.6256 9.24882 25.1884 6.81163C22.7512 4.37445 19.4467 3.00364 16 3ZM12.7038 21H19.2963C18.625 23.2925 17.5 25.3587 16 26.9862C14.5 25.3587 13.375 23.2925 12.7038 21ZM12.25 19C11.9183 17.0138 11.9183 14.9862 12.25 13H19.75C20.0817 14.9862 20.0817 17.0138 19.75 19H12.25ZM5.00001 16C4.99914 14.9855 5.13923 13.9759 5.41626 13H10.2238C9.92542 14.9889 9.92542 17.0111 10.2238 19H5.41626C5.13923 18.0241 4.99914 17.0145 5.00001 16ZM19.2963 11H12.7038C13.375 8.7075 14.5 6.64125 16 5.01375C17.5 6.64125 18.625 8.7075 19.2963 11ZM21.7763 13H26.5838C27.1388 14.9615 27.1388 17.0385 26.5838 19H21.7763C22.0746 17.0111 22.0746 14.9889 21.7763 13ZM25.7963 11H21.3675C20.8572 8.99189 20.0001 7.0883 18.835 5.375C20.3236 5.77503 21.7119 6.48215 22.9108 7.45091C24.1097 8.41967 25.0926 9.62861 25.7963 11ZM13.165 5.375C11.9999 7.0883 11.1428 8.99189 10.6325 11H6.20376C6.90741 9.62861 7.89029 8.41967 9.08918 7.45091C10.2881 6.48215 11.6764 5.77503 13.165 5.375ZM6.20376 21H10.6325C11.1428 23.0081 11.9999 24.9117 13.165 26.625C11.6764 26.225 10.2881 25.5178 9.08918 24.5491C7.89029 23.5803 6.90741 22.3714 6.20376 21ZM18.835 26.625C20.0001 24.9117 20.8572 23.0081 21.3675 21H25.7963C25.0926 22.3714 24.1097 23.5803 22.9108 24.5491C21.7119 25.5178 20.3236 26.225 18.835 26.625Z"
fill="#ef4444"
/>
</svg>
)}
{items.length > 1 && (
<svg
onClick={deletePost(index)}
className="cursor-pointer"
xmlns="http://www.w3.org/2000/svg"
data-tooltip-id="tooltip"
data-tooltip-content="Delete Post"
xmlns="http://www.w3.org/2000/svg"
className="cursor-pointer"
width="20"
height="20"
viewBox="0 0 14 14"
fill="currentColor"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M11.8125 2.625H9.625V2.1875C9.625 1.8394 9.48672 1.50556 9.24058 1.25942C8.99444 1.01328 8.6606 0.875 8.3125 0.875H5.6875C5.3394 0.875 5.00556 1.01328 4.75942 1.25942C4.51328 1.50556 4.375 1.8394 4.375 2.1875V2.625H2.1875C2.07147 2.625 1.96019 2.67109 1.87814 2.75314C1.79609 2.83519 1.75 2.94647 1.75 3.0625C1.75 3.17853 1.79609 3.28981 1.87814 3.37186C1.96019 3.45391 2.07147 3.5 2.1875 3.5H2.625V11.375C2.625 11.6071 2.71719 11.8296 2.88128 11.9937C3.04538 12.1578 3.26794 12.25 3.5 12.25H10.5C10.7321 12.25 10.9546 12.1578 11.1187 11.9937C11.2828 11.8296 11.375 11.6071 11.375 11.375V3.5H11.8125C11.9285 3.5 12.0398 3.45391 12.1219 3.37186C12.2039 3.28981 12.25 3.17853 12.25 3.0625C12.25 2.94647 12.2039 2.83519 12.1219 2.75314C12.0398 2.67109 11.9285 2.625 11.8125 2.625ZM5.25 2.1875C5.25 2.07147 5.29609 1.96019 5.37814 1.87814C5.46019 1.79609 5.57147 1.75 5.6875 1.75H8.3125C8.42853 1.75 8.53981 1.79609 8.62186 1.87814C8.70391 1.96019 8.75 2.07147 8.75 2.1875V2.625H5.25V2.1875ZM10.5 11.375H3.5V3.5H10.5V11.375ZM6.125 5.6875V9.1875C6.125 9.30353 6.07891 9.41481 5.99686 9.49686C5.91481 9.57891 5.80353 9.625 5.6875 9.625C5.57147 9.625 5.46019 9.57891 5.37814 9.49686C5.29609 9.41481 5.25 9.30353 5.25 9.1875V5.6875C5.25 5.57147 5.29609 5.46019 5.37814 5.37814C5.46019 5.29609 5.57147 5.25 5.6875 5.25C5.80353 5.25 5.91481 5.29609 5.99686 5.37814C6.07891 5.46019 6.125 5.57147 6.125 5.6875ZM8.75 5.6875V9.1875C8.75 9.30353 8.70391 9.41481 8.62186 9.49686C8.53981 9.57891 8.42853 9.625 8.3125 9.625C8.19647 9.625 8.08519 9.57891 8.00314 9.49686C7.92109 9.41481 7.875 9.30353 7.875 9.1875V5.6875C7.875 5.57147 7.92109 5.46019 8.00314 5.37814C8.08519 5.29609 8.19647 5.25 8.3125 5.25C8.42853 5.25 8.53981 5.29609 8.62186 5.37814C8.70391 5.46019 8.75 5.57147 8.75 5.6875Z"
fill="#ef4444"
d="M7.5 2.5L12.5 2.5M2.5 5L17.5 5M15.8333 5L15.2489 13.7661C15.1612 15.0813 15.1174 15.7389 14.8333 16.2375C14.5833 16.6765 14.206 17.0294 13.7514 17.2497C13.235 17.5 12.5759 17.5 11.2578 17.5H8.74221C7.42409 17.5 6.76503 17.5 6.24861 17.2497C5.79396 17.0294 5.41674 16.6765 5.16665 16.2375C4.88259 15.7389 4.83875 15.0813 4.75107 13.7661L4.16667 5M8.33333 8.75V12.9167M11.6667 8.75L11.6667 12.9167"
stroke="#FF3F3F"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)}
@ -528,64 +640,47 @@ export const Editor: FC<{
[props.value, id]
);
const [loadedEditor, setLoadedEditor] = useState(editorType);
const [showEditor, setShowEditor] = useState(true);
useEffect(() => {
if (editorType === loadedEditor) {
return;
}
setLoadedEditor(editorType);
setShowEditor(false);
}, [editorType]);
useEffect(() => {
if (showEditor) {
return;
}
setTimeout(() => {
setShowEditor(true);
}, 20);
}, [showEditor]);
if (!showEditor) {
return null;
}
return (
<div className="flex flex-col gap-[20px]">
<div className="relative bg-bigStrip" id={id}>
<div className="flex gap-[5px] bg-newBgLineColor border-b border-t border-customColor3 justify-center items-center p-[5px]">
<SignatureBox editor={editorRef?.current?.editor} />
<UText
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
<BoldText
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
{(editorType === 'markdown' || editorType === 'html') &&
identifier !== 'telegram' && (
<>
<AComponent
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
<Bullets
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
<HeadingComponent
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
</>
)}
<div
className="select-none cursor-pointer w-[40px] p-[5px] text-center"
onClick={() => setEmojiPickerOpen(!emojiPickerOpen)}
>
{'\uD83D\uDE00'}
</div>
<div className="relative">
<div className="absolute z-[200] top-[35px] -start-[50px]">
<EmojiPicker
theme={(localStorage.getItem('mode') as Theme) || Theme.DARK}
onEmojiClick={(e) => {
addText(e.emoji);
setEmojiPickerOpen(false);
}}
open={emojiPickerOpen}
/>
</div>
</div>
</div>
<div className="relative cursor-text">
{validateChars &&
props.value.length === 0 &&
pictures?.length === 0 && (
<div className="px-3 text-sm bg-red-600 !text-white mb-[4px]">
Your post should have at least one character or one image.
</div>
)}
<div {...getRootProps()}>
<div className="flex flex-col gap-[20px] flex-1">
<div
className={clsx(
'relative flex-1 px-[12px] pt-[12px] pb-[12px] flex flex-col',
num > 0 && '!rounded-bs-[0]'
)}
id={id}
>
<div className="relative cursor-text flex flex-1 flex-col">
{/*{validateChars &&*/}
{/* props.value.length === 0 &&*/}
{/* pictures?.length === 0 && (*/}
{/* <div className="px-3 text-sm bg-red-600 !text-white mb-[4px]">*/}
{/* Your post should have at least one character or one image.*/}
{/* </div>*/}
{/* )}*/}
<div {...getRootProps()} className="flex flex-1 flex-col">
<div
className={clsx(
'absolute left-0 top-0 w-full h-full bg-black/70 z-[300] transition-all items-center justify-center flex text-white text-sm',
@ -594,7 +689,7 @@ export const Editor: FC<{
>
Drop your files here to upload
</div>
<div className="px-[10px] pt-[10px]">
<div className="px-[10px] pt-[10px] bg-newBgColorInner rounded-t-[6px] relative z-[99]">
<OnlyEditor
value={props.value}
editorType={editorType}
@ -603,38 +698,40 @@ export const Editor: FC<{
ref={editorRef}
/>
</div>
<div
className="w-full h-[46px] overflow-hidden absolute left-0"
className="bg-newBgColorInner flex-1"
onClick={() => {
if (editorRef?.current?.editor?.isFocused) {
return;
}
editorRef?.current?.editor?.commands?.focus('end');
}}
>
<Dashboard
height={46}
uppy={uppy}
id={`prog-${num}`}
showProgressDetails={true}
hideUploadButton={true}
hideRetryButton={true}
hidePauseResumeButton={true}
hideCancelButton={true}
hideProgressAfterFinish={true}
/>
/>
<div className="w-full pointer-events-none">
<div className="w-full h-[46px] overflow-hidden absolute left-0 bg-newBgColorInner uppyChange">
<Dashboard
height={46}
uppy={uppy}
id={`prog-${num}`}
showProgressDetails={true}
hideUploadButton={true}
hideRetryButton={true}
hidePauseResumeButton={true}
hideCancelButton={true}
hideProgressAfterFinish={true}
/>
</div>
</div>
<div className="w-full h-[46px] pointer-events-none" />
<div
className="flex bg-newBgLineColor"
className="w-full h-[46px] bg-newBgColorInner cursor-text"
onClick={() => {
if (editorRef?.current?.editor?.isFocused) {
return;
}
editorRef?.current?.editor?.commands?.focus('end');
}}
>
/>
<div className="flex bg-newBgColorInner rounded-b-[6px] cursor-default">
{setImages && (
<MultiMediaComponent
allData={allValues}
@ -644,6 +741,112 @@ export const Editor: FC<{
value={props.pictures}
dummy={dummy}
name="image"
information={
<InformationComponent
isPicture={pictures?.length > 0}
chars={chars}
totalChars={valueWithoutHtml.length}
totalAllowedChars={props.totalChars}
/>
}
toolBar={
<div className="flex gap-[5px]">
<SignatureBox editor={editorRef?.current?.editor} />
<UText
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
<BoldText
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
{(editorType === 'markdown' || editorType === 'html') &&
identifier !== 'telegram' && (
<>
<AComponent
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
<Bullets
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
<HeadingComponent
editor={editorRef?.current?.editor}
currentValue={props.value!}
/>
</>
)}
<div
data-tooltip-id="tooltip"
data-tooltip-content="Insert Emoji"
className="select-none cursor-pointer rounded-[6px] w-[30px] h-[30px] bg-newColColor flex justify-center items-center"
onClick={() => setEmojiPickerOpen(!emojiPickerOpen)}
>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.97917 14.6663C11.6611 14.6663 14.6458 11.6816 14.6458 7.99967C14.6458 4.31778 11.6611 1.33301 7.97917 1.33301C4.29727 1.33301 1.3125 4.31778 1.3125 7.99967C1.3125 11.6816 4.29727 14.6663 7.97917 14.6663Z"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M4.80664 10C5.50664 11.0067 6.67997 11.6667 7.99997 11.6667C9.31997 11.6667 10.4866 11.0067 11.1933 10"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M4.66602 6.16699C5.33268 6.83366 6.41935 6.83366 7.09268 6.16699"
stroke="currentColor"
strokeWidth="1.2"
strokeMiterlimit="10"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M8.90625 6.16699C9.57292 6.83366 10.6596 6.83366 11.3329 6.16699"
stroke="currentColor"
strokeWidth="1.2"
strokeMiterlimit="10"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="relative">
<div
className={clsx(
'absolute z-[500] -start-[50px]',
num === 0 && allValues?.length > 1
? 'top-[35px]'
: 'bottom-[35px]'
)}
>
<EmojiPicker
height={400}
theme={
(localStorage.getItem('mode') as Theme) ||
Theme.DARK
}
onEmojiClick={(e) => {
addText(e.emoji);
setEmojiPickerOpen(false);
}}
open={emojiPickerOpen}
/>
</div>
</div>
</div>
}
onChange={(value) => {
setImages(value.target.value);
}}
@ -652,52 +855,52 @@ export const Editor: FC<{
/>
)}
</div>
<div>{childButton}</div>
</div>
</div>
</div>
<div className="flex">
<div className="flex-1">{childButton}</div>
<div className="bottom-10px end-[25px]">
{(props?.totalChars || 0) > 0 ? (
<div
className={clsx(
'text-end text-sm mt-1',
valueWithoutHtml.length > props.totalChars && '!text-red-500'
)}
>
{valueWithoutHtml.length}/{props.totalChars}
</div>
) : (
<div
className={clsx(
'text-end text-sm mt-1 grid grid-cols-[max-content_max-content] gap-x-[5px]'
)}
>
{selectedIntegration?.map((p) => (
<Fragment key={p.integration.id}>
<div
className={
valueWithoutHtml.length > chars?.[p.integration.id] &&
'!text-red-500'
}
>
{p.integration.name} ({capitalize(p.integration.identifier)}
):
</div>
<div
className={
valueWithoutHtml.length > chars?.[p.integration.id] &&
'!text-red-500'
}
>
{valueWithoutHtml.length}/{chars?.[p.integration.id]}
</div>
</Fragment>
))}
</div>
)}
</div>
</div>
{/*<div className="flex">*/}
{/* <div className="bottom-10px end-[25px]">*/}
{/* {(props?.totalChars || 0) > 0 ? (*/}
{/* <div*/}
{/* className={clsx(*/}
{/* 'text-end text-sm mt-1',*/}
{/* valueWithoutHtml.length > props.totalChars && '!text-red-500'*/}
{/* )}*/}
{/* >*/}
{/* {valueWithoutHtml.length}/{props.totalChars}*/}
{/* </div>*/}
{/* ) : (*/}
{/* <div*/}
{/* className={clsx(*/}
{/* 'text-end text-sm mt-1 grid grid-cols-[max-content_max-content] gap-x-[5px]'*/}
{/* )}*/}
{/* >*/}
{/* {selectedIntegration?.map((p) => (*/}
{/* <Fragment key={p.integration.id}>*/}
{/* <div*/}
{/* className={*/}
{/* valueWithoutHtml.length > chars?.[p.integration.id] &&*/}
{/* '!text-red-500'*/}
{/* }*/}
{/* >*/}
{/* {p.integration.name} ({capitalize(p.integration.identifier)}*/}
{/* ):*/}
{/* </div>*/}
{/* <div*/}
{/* className={*/}
{/* valueWithoutHtml.length > chars?.[p.integration.id] &&*/}
{/* '!text-red-500'*/}
{/* }*/}
{/* >*/}
{/* {valueWithoutHtml.length}/{chars?.[p.integration.id]}*/}
{/* </div>*/}
{/* </Fragment>*/}
{/* ))}*/}
{/* </div>*/}
{/* )}*/}
{/* </div>*/}
{/*</div>*/}
</div>
);
};
@ -712,6 +915,7 @@ export const OnlyEditor = forwardRef<
}
>(({ editorType, value, onChange, paste }, ref) => {
const fetch = useFetch();
const { internal } = useLaunchStore(
useShallow((state) => ({
internal: state.internal.find((p) => p.integration.id === state.current),
@ -759,6 +963,10 @@ export const OnlyEditor = forwardRef<
InterceptUnderlineShortcut,
BulletList,
ListItem,
Placeholder.configure({
placeholder: 'Write something …',
emptyEditorClass: 'is-editor-empty',
}),
...(editorType === 'html' || editorType === 'markdown'
? [
Link.configure({

View File

@ -13,20 +13,27 @@ export const HeadingComponent: FC<{
};
return (
<div className="select-none cursor-pointer w-[40px] p-[5px] text-center relative group">
<div className="select-none cursor-pointer rounded-[6px] w-[30px] h-[30px] bg-newColColor flex justify-center items-center group relative">
<svg
width="20"
height="16"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M22 0H2C1.46957 0 0.960859 0.210714 0.585786 0.585786C0.210714 0.960859 0 1.46957 0 2V22C0 22.5304 0.210714 23.0391 0.585786 23.4142C0.960859 23.7893 1.46957 24 2 24H22C22.5304 24 23.0391 23.7893 23.4142 23.4142C23.7893 23.0391 24 22.5304 24 22V2C24 1.46957 23.7893 0.960859 23.4142 0.585786C23.0391 0.210714 22.5304 0 22 0ZM19 18C19 18.2652 18.8946 18.5196 18.7071 18.7071C18.5196 18.8946 18.2652 19 18 19C17.7348 19 17.4804 18.8946 17.2929 18.7071C17.1054 18.5196 17 18.2652 17 18V13H7V18C7 18.2652 6.89464 18.5196 6.70711 18.7071C6.51957 18.8946 6.26522 19 6 19C5.73478 19 5.48043 18.8946 5.29289 18.7071C5.10536 18.5196 5 18.2652 5 18V6C5 5.73478 5.10536 5.48043 5.29289 5.29289C5.48043 5.10536 5.73478 5 6 5C6.26522 5 6.51957 5.10536 6.70711 5.29289C6.89464 5.48043 7 5.73478 7 6V11H17V6C17 5.73478 17.1054 5.48043 17.2929 5.29289C17.4804 5.10536 17.7348 5 18 5C18.2652 5 18.5196 5.10536 18.7071 5.29289C18.8946 5.48043 19 5.73478 19 6V18Z"
fill="currentColor"
d="M3.9974 2.66602V13.3327M11.9974 2.66602V13.3327M5.33073 2.66602H2.66406M11.9974 7.99935L3.9974 7.99935M5.33073 13.3327H2.66406M13.3307 13.3327H10.6641M13.3307 2.66602H10.6641"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
<div className="flex p-[10px] gap-[5px] -left-[50%] opacity-0 pointer-events-none group-hover:pointer-events-auto group-hover:opacity-100 bg-customColor55 border border-customColor3 z-[100] absolute transition-all">
<div
data-tooltip-id="tooltip"
data-tooltip-content="Title"
className="flex p-[10px] gap-[5px] -left-[50%] rounded-[6px] bottom-[100%] opacity-0 pointer-events-none group-hover:pointer-events-auto group-hover:opacity-100 bg-newColColor border border-newColColor z-[100] absolute transition-all"
>
<div onClick={setHeading(1)}>
<svg
width="20"

View File

@ -1,6 +1,6 @@
'use client';
import React, { FC, useCallback, useRef, useState } from 'react';
import React, { FC, useCallback, useMemo, 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';
@ -43,6 +43,577 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
const [loading, setLoading] = useState(false);
const toaster = useToaster();
const modal = useModals();
const [showSettings, setShowSettings] = useState(false);
const { addEditSets, mutate, customClose, dummy } = props;
const {
selectedIntegrations,
hide,
date,
setDate,
repeater,
setRepeater,
tags,
setTags,
integrations,
setSelectedIntegrations,
locked,
current,
activateExitButton,
} = useLaunchStore(
useShallow((state) => ({
hide: state.hide,
date: state.date,
setDate: state.setDate,
current: state.current,
repeater: state.repeater,
setRepeater: state.setRepeater,
tags: state.tags,
setTags: state.setTags,
selectedIntegrations: state.selectedIntegrations,
integrations: state.integrations,
setSelectedIntegrations: state.setSelectedIntegrations,
locked: state.locked,
activateExitButton: state.activateExitButton,
}))
);
const currentIntegrationText = useMemo(() => {
if (current === 'global') {
return '';
}
const currentIntegration = integrations.find((p) => p.id === current)!;
return `${currentIntegration.name} (${capitalize(
currentIntegration.identifier.split('-').shift()
)})`;
}, [current]);
const changeCustomer = useCallback(
(customer: string) => {
const neededIntegrations = integrations.filter(
(p) => p?.customer?.id === customer
);
setSelectedIntegrations(
neededIntegrations.map((p) => ({
settings: {},
selectedIntegrations: p,
}))
);
},
[integrations]
);
const askClose = useCallback(async () => {
if (!activateExitButton || dummy) {
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();
}
}, [activateExitButton, dummy]);
const deletePost = useCallback(async () => {
setLoading(true);
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 schedule = useCallback(
(type: 'draft' | 'now' | 'schedule') => async () => {
setLoading(true);
const checkAllValid = await ref.current.checkAllValid();
if (type !== 'draft') {
const notEnoughChars = checkAllValid.filter((p: any) => {
return p.values.some((a: any) => {
return (
countCharacters(
stripHtmlValidation('normal', a.content, true),
p?.integration?.identifier || ''
) === 0 && a.media?.length === 0
);
});
});
for (const item of notEnoughChars) {
toaster.show(
'' +
item.integration.name +
' Your post should have at least one character or one image.',
'warning'
);
setLoading(false);
item.preview();
return;
}
for (const item of checkAllValid) {
if (item.valid === false) {
toaster.show('Please fix your settings', 'warning');
item.fix();
setLoading(false);
setShowSettings(true);
return;
}
if (item.errors !== true) {
toaster.show(
`${capitalize(item.integration.identifier.split('-')[0])} (${
item.integration.name
}): ${item.errors}`,
'warning'
);
item.preview();
setLoading(false);
setShowSettings(true);
return;
}
}
const sliceNeeded = checkAllValid.filter((p: any) => {
return p.values.some((a: any) => {
const strip = stripHtmlValidation('normal', a.content, true);
const weightedLength = countCharacters(
strip,
p?.integration?.identifier || ''
);
const totalCharacters =
weightedLength > strip.length ? weightedLength : strip.length;
return totalCharacters > (p.maximumCharacters || 1000000);
});
});
for (const item of sliceNeeded) {
toaster.show(
`${item?.integration?.name} (${item?.integration?.identifier}) post is too long, please fix it`,
'warning'
);
item.preview();
setLoading(false);
return;
}
}
const shortLinkUrl = dummy
? { ask: false }
: 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,
...(repeater ? { inter: repeater } : {}),
tags,
shortLink,
date: date.utc().format('YYYY-MM-DDTHH:mm:ss'),
posts: checkAllValid.map((post: any) => ({
integration: {
id: post.integration.id,
},
group,
settings: { ...(post.settings || {}) },
value: post.values.map((value: any) => ({
...(value.id ? { id: value.id } : {}),
content: value.content,
image:
(value?.media || []).map(
({ id, path, alt, thumbnail, thumbnailTimestamp }: any) => ({
id,
path,
alt,
thumbnail,
thumbnailTimestamp,
})
) || [],
})),
})),
};
if (dummy) {
modal.openModal({
title: '',
children: <DummyCodeComponent code={data} />,
classNames: {
modal: 'w-[100%] bg-transparent text-textColor',
},
size: '100%',
withCloseButton: false,
closeOnEscape: true,
closeOnClickOutside: true,
});
setLoading(false);
}
if (!dummy) {
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, dummy]
);
return (
<div className="w-full h-full flex-1 p-[40px] flex relative">
<div className="flex flex-1 bg-newBgColorInner rounded-[20px] flex-col">
<div className="flex-1 flex">
<div className="flex flex-col flex-1 border-r border-newBorder">
<div className="bg-newBgColor h-[65px] rounded-tl-[20px] flex items-center px-[20px] text-[20px] font-[600]">
Create Post
</div>
<div className="flex-1 flex flex-col gap-[16px]">
<div className="flex-1 relative">
<div
id="social-content"
className="gap-[32px] flex flex-col pr-[8px] pt-[20px] pl-[20px] absolute top-0 left-0 w-full h-full overflow-x-hidden overflow-y-scroll scrollbar scrollbar-thumb-newColColor scrollbar-track-newBgColorInner"
>
<div className="flex w-full">
<div className="flex flex-1">
<PicksSocialsComponent toolTip={true} />
</div>
<div>
{!dummy && (
<SelectCustomer
onChange={changeCustomer}
integrations={integrations}
/>
)}
</div>
</div>
<div className="flex flex-1 gap-[6px] flex-col">
<div>{!existingData.integration && <SelectCurrent />}</div>
<div className="flex-1 flex">
{!hide && <EditorWrapper totalPosts={1} value="" />}
</div>
<div
id="social-empty"
className={clsx(
'pb-[16px]',
current !== 'global' && 'hidden'
)}
/>
</div>
</div>
</div>
<div
id="wrapper-settings"
className={clsx(
'pb-[20px] px-[20px] select-none',
current === 'global' && 'hidden'
)}
>
<div className="bg-newSettings flex flex-col rounded-[12px] gap-[12px]">
<div
onClick={() => setShowSettings(!showSettings)}
className={clsx(
'bg-[#612BD3] rounded-[12px] flex items-center gap-[8px] cursor-pointer p-[12px]',
showSettings ? '!rounded-b-none' : ''
)}
>
<div className="flex">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M7.82888 16.1429L8.31591 17.2383C8.4607 17.5644 8.69698 17.8414 8.9961 18.0358C9.29522 18.2303 9.64434 18.3337 10.0011 18.3337C10.3579 18.3337 10.707 18.2303 11.0061 18.0358C11.3052 17.8414 11.5415 17.5644 11.6863 17.2383L12.1733 16.1429C12.3467 15.7542 12.6383 15.4302 13.0067 15.217C13.3773 15.0032 13.8061 14.9121 14.2317 14.9568L15.4233 15.0837C15.778 15.1212 16.136 15.055 16.4539 14.8931C16.7717 14.7312 17.0358 14.4806 17.2141 14.1716C17.3925 13.8628 17.4776 13.5089 17.4588 13.1527C17.4401 12.7966 17.3184 12.4535 17.1085 12.1651L16.403 11.1957C16.1517 10.8479 16.0175 10.4293 16.0196 10.0003C16.0195 9.57248 16.155 9.15562 16.4067 8.80959L17.1122 7.84014C17.3221 7.55179 17.4438 7.20872 17.4625 6.85255C17.4813 6.49639 17.3962 6.14244 17.2178 5.83366C17.0395 5.52469 16.7754 5.27407 16.4576 5.11218C16.1397 4.9503 15.7817 4.8841 15.427 4.92162L14.2354 5.04847C13.8098 5.09317 13.381 5.00209 13.0104 4.78829C12.6413 4.57387 12.3496 4.24812 12.177 3.85773L11.6863 2.76236C11.5415 2.4363 11.3052 2.15925 11.0061 1.96482C10.707 1.77039 10.3579 1.66693 10.0011 1.66699C9.64434 1.66693 9.29522 1.77039 8.9961 1.96482C8.69698 2.15925 8.4607 2.4363 8.31591 2.76236L7.82888 3.85773C7.65632 4.24812 7.3646 4.57387 6.99554 4.78829C6.62489 5.00209 6.1961 5.09317 5.77054 5.04847L4.57517 4.92162C4.22045 4.8841 3.86246 4.9503 3.5446 5.11218C3.22675 5.27407 2.96269 5.52469 2.78443 5.83366C2.60595 6.14244 2.52092 6.49639 2.53965 6.85255C2.55839 7.20872 2.68009 7.55179 2.88999 7.84014L3.59554 8.80959C3.84716 9.15562 3.98266 9.57248 3.98258 10.0003C3.98266 10.4282 3.84716 10.845 3.59554 11.1911L2.88999 12.1605C2.68009 12.4489 2.55839 12.7919 2.53965 13.1481C2.52092 13.5043 2.60595 13.8582 2.78443 14.167C2.96286 14.4758 3.22696 14.7263 3.54476 14.8882C3.86257 15.05 4.22047 15.1163 4.57517 15.079L5.76684 14.9522C6.1924 14.9075 6.62119 14.9986 6.99184 15.2124C7.36228 15.4262 7.65535 15.752 7.82888 16.1429Z"
stroke="white"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M9.99961 12.5003C11.3803 12.5003 12.4996 11.381 12.4996 10.0003C12.4996 8.61961 11.3803 7.50033 9.99961 7.50033C8.6189 7.50033 7.49961 8.61961 7.49961 10.0003C7.49961 11.381 8.6189 12.5003 9.99961 12.5003Z"
stroke="white"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div className="flex-1 text-[14px] font-[600] text-white">
{currentIntegrationText} Settings
</div>
<div>
<svg
className={clsx(
showSettings && 'rotate-180',
'transition-transform'
)}
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M5 7.5L10 12.5L15 7.5"
stroke="white"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
</div>
<div
id="social-settings"
className={clsx(
!showSettings && 'hidden',
'px-[12px] pb-[12px] text-[14px] text-textColor font-[500] max-h-[400px] overflow-x-hidden overflow-y-auto scrollbar scrollbar-thumb-newColColor scrollbar-track-newBgColorInner'
)}
/>
<style>
{`#social-settings [data-id="${current}"] {display: block !important;}`}
</style>
</div>
</div>
</div>
</div>
<div className="w-[580px] flex flex-col">
<div className="bg-newBgColor h-[65px] rounded-tr-[20px] flex items-center px-[20px] text-[20px] font-[600]">
<div className="flex-1">Post Preview</div>
<div className="cursor-pointer">
<svg
onClick={askClose}
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M16 4L4 16M4 4L16 16"
stroke="#A3A3A3"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
</div>
<div className="flex-1 relative">
<div className="absolute top-0 p-[20px] left-0 w-full h-full overflow-x-hidden overflow-y-scroll scrollbar scrollbar-thumb-newColColor scrollbar-track-newBgColorInner">
<ShowAllProviders ref={ref} />
</div>
</div>
</div>
</div>
<div className="select-none h-[84px] py-[20px] border-t border-newBorder flex items-center">
<div className="flex-1 flex pl-[20px] gap-[8px]">
{!dummy && (
<TagsComponent
name="tags"
label={t('tags', 'Tags')}
initial={tags}
onChange={(e) => {
setTags(e.target.value);
}}
/>
)}
{!dummy && (
<RepeatComponent repeat={repeater} onChange={setRepeater} />
)}
</div>
<div className="pr-[20px] flex items-center justify-end gap-[8px]">
{existingData?.integration && (
<button onClick={deletePost} className="cursor-pointer flex text-[#FF3F3F] gap-[8px] items-center text-[15px] font-[600]">
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M7.5 2.5H12.5M2.5 5H17.5M15.8333 5L15.2489 13.7661C15.1612 15.0813 15.1174 15.7389 14.8333 16.2375C14.5833 16.6765 14.206 17.0294 13.7514 17.2497C13.235 17.5 12.5759 17.5 11.2578 17.5H8.74221C7.42409 17.5 6.76503 17.5 6.24861 17.2497C5.79396 17.0294 5.41674 16.6765 5.16665 16.2375C4.88259 15.7389 4.83875 15.0813 4.75107 13.7661L4.16667 5M8.33333 8.75V12.9167M11.6667 8.75V12.9167"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
<div>Delete Post</div>
</button>
)}
<DatePicker onChange={setDate} date={date} />
{!addEditSets && (
<button
disabled={
selectedIntegrations.length === 0 || loading || locked
}
onClick={schedule('draft')}
className="cursor-pointer disabled:cursor-not-allowed px-[20px] h-[44px] bg-btnSimple justify-center items-center flex rounded-[8px] text-[15px] font-[600]"
>
Save as Draft
</button>
)}
{addEditSets && (
<button
className="text-white text-[15px] font-[600] min-w-[180px] btnSub disabled:cursor-not-allowed disabled:opacity-80 outline-none gap-[8px] flex justify-center items-center h-[44px] rounded-[8px] bg-[#612BD3] pl-[20px] pr-[16px]"
disabled={
selectedIntegrations.length === 0 || loading || locked
}
onClick={schedule('draft')}
>
Save Set
</button>
)}
{!addEditSets && (
<div className="group cursor-pointer relative">
<button
disabled={
selectedIntegrations.length === 0 || loading || locked
}
onClick={schedule('schedule')}
className="text-white min-w-[180px] btnSub disabled:cursor-not-allowed disabled:opacity-80 outline-none gap-[8px] flex justify-center items-center h-[44px] rounded-[8px] bg-[#612BD3] pl-[20px] pr-[16px]"
>
<div className="text-[15px] font-[600]">
{selectedIntegrations.length === 0
? 'Check the circles above'
: dummy
? 'Create output'
: !existingData?.integration
? t('add_to_calendar', 'Add to calendar')
: existingData?.posts?.[0]?.state === 'DRAFT'
? t('schedule', 'Schedule')
: t('update', 'Update')}
</div>
<div className="flex justify-center items-center h-[20px] w-[20px] pt-[4px] arrow-change">
<svg
className="group-hover:rotate-180 transition-transform"
xmlns="http://www.w3.org/2000/svg"
width="6"
height="4"
viewBox="0 0 6 4"
fill="none"
>
<path
d="M0.456301 9.69291e-07L5.5437 7.97823e-08C5.94941 8.84616e-09 6.15259 0.567978 5.86571 0.90016L3.32201 3.84556C3.14417 4.05148 2.85583 4.05148 2.67799 3.84556L0.134293 0.900162C-0.152585 0.56798 0.0505934 1.04023e-06 0.456301 9.69291e-07Z"
fill="white"
/>
</svg>
</div>
</button>
<button
onClick={schedule('now')}
disabled={
selectedIntegrations.length === 0 || loading || locked
}
className="disabled:cursor-not-allowed disabled:opacity-80 hidden group-hover:flex absolute bottom-[100%] -left-[12px] p-[12px] w-[206px] bg-newBgColorInner"
>
<div className="text-white rounded-[8px] bg-[#D82D7E] h-[44px] w-full flex justify-center items-center post-now">
Post Now
</div>
</button>
</div>
)}
</div>
</div>
</div>
<CopilotPopup
hitEscapeToClose={false}
clickOutsideToClose={true}
instructions={`
You are an assistant that help the user to schedule their social media posts,
Here are the things you can do:
- Add a new comment / post to the list of posts
- Delete a comment / post from the list of posts
- Add content to the comment / post
- Activate or deactivate the comment / post
Post content can be added using the addPostContentFor{num} function.
After using the addPostFor{num} it will create a new addPostContentFor{num+ 1} function.
`}
labels={{
title: 'Your Assistant',
initial: 'Hi! I can help you to refine your social media posts.',
}}
/>
</div>
);
};
export const ManageModalA: FC<AddEditModalProps> = (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();
const { addEditSets, mutate, customClose, dummy } = props;
@ -490,25 +1061,6 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
<ShowAllProviders ref={ref} />
</div>
</div>
<CopilotPopup
hitEscapeToClose={false}
clickOutsideToClose={true}
instructions={`
You are an assistant that help the user to schedule their social media posts,
Here are the things you can do:
- Add a new comment / post to the list of posts
- Delete a comment / post from the list of posts
- Add content to the comment / post
- Activate or deactivate the comment / post
Post content can be added using the addPostContentFor{num} function.
After using the addPostFor{num} it will create a new addPostContentFor{num+ 1} function.
`}
labels={{
title: 'Your Assistant',
initial: 'Hi! 👋 How can I assist you today?',
}}
/>
</div>
</>
);

View File

@ -6,6 +6,7 @@ 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';
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
export const PicksSocialsComponent: FC<{ toolTip?: boolean }> = ({
toolTip,
@ -26,13 +27,13 @@ export const PicksSocialsComponent: FC<{ toolTip?: boolean }> = ({
}))
);
return (
<div className={clsx('flex', locked && 'opacity-50 pointer-events-none')}>
<div className="flex">
<div className="innerComponent">
<div className="grid grid-cols-13 gap-[10px]">
{integrations
.filter((f) => {
<div className="flex flex-1">
<div className="innerComponent flex-1 flex">
<div className="flex flex-wrap gap-[12px] flex-1">
{integrations.filter((f) => {
if (exising.integration) {
return f.id === exising.integration;
}
@ -55,34 +56,41 @@ export const PicksSocialsComponent: FC<{ toolTip?: boolean }> = ({
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',
'cursor-pointer border-[1.5px] relative rounded-full flex justify-center items-center bg-fifth filter transition-all duration-500',
selectedIntegrations.findIndex(
(p) => p.integration.id === integration.id
) === -1
? 'opacity-40'
: ''
? 'grayscale border-transparent'
: 'border-[#622FF6]'
)}
>
<Image
src={integration.picture || '/no-picture.jpg'}
className="rounded-full"
className={clsx(
'rounded-full transition-all min-w-[42px] border-[1.5px] min-h-[42px]',
selectedIntegrations.findIndex(
(p) => p.integration.id === integration.id
) === -1
? 'border-transparent'
: 'border-[#000]'
)}
alt={integration.identifier}
width={32}
height={32}
width={42}
height={42}
/>
{integration.identifier === 'youtube' ? (
<img
src="/icons/platforms/youtube.svg"
className="absolute z-10 -bottom-[5px] -end-[5px]"
width={20}
className="absolute z-10 -bottom-[5px] -end-[5px] min-w-[16px]"
width={16}
/>
) : (
<Image
src={`/icons/platforms/${integration.identifier}.png`}
className="rounded-full absolute z-10 -bottom-[5px] -end-[5px] border border-fifth"
className="rounded-[4px] absolute z-10 bottom-0 -end-[5px] min-w-[16px] min-h-[16px]"
alt={integration.identifier}
width={20}
height={20}
width={16}
height={16}
/>
)}
</div>

View File

@ -22,6 +22,7 @@ import useSWR from 'swr';
import { InternalChannels } from '@gitroom/frontend/components/launches/internal.channels';
import { capitalize } from 'lodash';
import clsx from 'clsx';
import { createPortal } from 'react-dom';
class Empty {
@IsOptional()
@ -255,40 +256,6 @@ export const withProvider = function <T extends object>(params: {
>
<FormProvider {...form}>
<div className={current ? '' : 'hidden'}>
<div className="flex gap-[4px] mb-[20px] p-[4px] border border-newTableBorder rounded-[8px]">
<div className="flex-1 flex">
<div
onClick={() => setTab(0)}
className={clsx(
'cursor-pointer rounded-[4px] flex-1 overflow-hidden whitespace-nowrap text-center pt-[6px] pb-[5px]',
tab !== 0 && !!SettingsComponent
? ''
: 'text-textItemFocused bg-boxFocused'
)}
>
{t('preview', 'Preview')}
</div>
</div>
{current &&
(!!SettingsComponent || !!data?.internalPlugs?.length) && (
<div className="flex-1 flex">
<div
onClick={() => setTab(1)}
className={clsx(
'cursor-pointer rounded-[4px] flex-1 overflow-hidden whitespace-nowrap text-center pt-[6px] pb-[5px]',
tab !== 1 ? '' : 'text-textItemFocused bg-boxFocused'
)}
>
{t('settings', 'Settings')} (
{capitalize(
selectedIntegration.integration.identifier.split('-')[0]
)}
)
</div>
</div>
)}
</div>
{current &&
(tab === 0 ||
(!SettingsComponent && !data?.internalPlugs?.length)) &&
@ -331,14 +298,22 @@ export const withProvider = function <T extends object>(params: {
}
/>
))}
{(SettingsComponent || !!data?.internalPlugs?.length) && (
<div className={tab === 1 ? '' : 'hidden'}>
<SettingsComponent />
{!!data?.internalPlugs?.length && !dummy && (
<InternalChannels plugs={data?.internalPlugs} />
)}
</div>
)}
{(SettingsComponent || !!data?.internalPlugs?.length) &&
createPortal(
<div data-id={props.id} className="hidden">
<SettingsComponent />
{!!data?.internalPlugs?.length && !dummy && (
<InternalChannels plugs={data?.internalPlugs} />
)}
</div>,
document.querySelector('#social-settings') || document.createElement('div')
)}
{current &&
!SettingsComponent &&
createPortal(
<style>{`#wrapper-settings {display: none !important;} #social-empty {display: block !important;}`}</style>,
document.querySelector('#social-settings')!
)}
</div>
</FormProvider>
</IntegrationContext.Provider>

View File

@ -192,13 +192,6 @@ export const ShowAllProviders = forwardRef((props, ref) => {
})),
}}
>
<div className="flex gap-[4px] mb-[20px]">
<div className="flex-1 flex p-[4px] border border-newTableBorder rounded-[8px]">
<div className="rounded-[4px] flex-1 overflow-hidden whitespace-nowrap text-center pt-[6px] pb-[5px] text-textItemFocused bg-boxFocused">
{t('preview', 'Preview')}
</div>
</div>
</div>
{global?.[0]?.content?.length === 0 ? (
<div>
{t(

View File

@ -1,12 +1,6 @@
'use client';
import {
FC,
RefObject,
useEffect,
useRef,
useState,
} 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';
@ -72,11 +66,11 @@ export const SelectCurrent: FC = () => {
return (
<>
<div className="left-0 absolute w-full z-[100] px-[24px]">
<div className="select-none left-0 absolute w-full z-[100] px-[20px]">
<div
ref={contentRef}
className={clsx(
'flex gap-[3px] w-full overflow-x-auto scrollbar scrollbar-thumb-tableBorder scrollbar-track-secondary',
'flex gap-[6px] w-full overflow-x-auto scrollbar scrollbar-thumb-tableBorder scrollbar-track-secondary',
locked && 'opacity-50 pointer-events-none'
)}
>
@ -85,19 +79,27 @@ export const SelectCurrent: FC = () => {
setHide(true);
setCurrent('global');
}}
className="cursor-pointer flex gap-[8px] items-center bg-newBgLineColor p-[10px] rounded-tl-[4px] rounded-tr-[4px]"
className={clsx(
'cursor-pointer flex gap-[8px] rounded-[8px] w-[40px] h-[40px] justify-center items-center bg-newBgLineColor',
current !== 'global'
? 'text-[#A3A3A3]'
: 'border border-[#FC69FF] text-[#FC69FF]'
)}
>
<div className={clsx(current !== 'global' ? 'opacity-40' : '')}>
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 32 32"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16 3C13.4288 3 10.9154 3.76244 8.77759 5.1909C6.63975 6.61935 4.97351 8.64968 3.98957 11.0251C3.00563 13.4006 2.74819 16.0144 3.2498 18.5362C3.75141 21.0579 4.98953 23.3743 6.80762 25.1924C8.6257 27.0105 10.9421 28.2486 13.4638 28.7502C15.9856 29.2518 18.5995 28.9944 20.9749 28.0104C23.3503 27.0265 25.3807 25.3603 26.8091 23.2224C28.2376 21.0846 29 18.5712 29 16C28.9964 12.5533 27.6256 9.24882 25.1884 6.81163C22.7512 4.37445 19.4467 3.00364 16 3ZM12.7038 21H19.2963C18.625 23.2925 17.5 25.3587 16 26.9862C14.5 25.3587 13.375 23.2925 12.7038 21ZM12.25 19C11.9183 17.0138 11.9183 14.9862 12.25 13H19.75C20.0817 14.9862 20.0817 17.0138 19.75 19H12.25ZM5.00001 16C4.99914 14.9855 5.13923 13.9759 5.41626 13H10.2238C9.92542 14.9889 9.92542 17.0111 10.2238 19H5.41626C5.13923 18.0241 4.99914 17.0145 5.00001 16ZM19.2963 11H12.7038C13.375 8.7075 14.5 6.64125 16 5.01375C17.5 6.64125 18.625 8.7075 19.2963 11ZM21.7763 13H26.5838C27.1388 14.9615 27.1388 17.0385 26.5838 19H21.7763C22.0746 17.0111 22.0746 14.9889 21.7763 13ZM25.7963 11H21.3675C20.8572 8.99189 20.0001 7.0883 18.835 5.375C20.3236 5.77503 21.7119 6.48215 22.9108 7.45091C24.1097 8.41967 25.0926 9.62861 25.7963 11ZM13.165 5.375C11.9999 7.0883 11.1428 8.99189 10.6325 11H6.20376C6.90741 9.62861 7.89029 8.41967 9.08918 7.45091C10.2881 6.48215 11.6764 5.77503 13.165 5.375ZM6.20376 21H10.6325C11.1428 23.0081 11.9999 24.9117 13.165 26.625C11.6764 26.225 10.2881 25.5178 9.08918 24.5491C7.89029 23.5803 6.90741 22.3714 6.20376 21ZM18.835 26.625C20.0001 24.9117 20.8572 23.0081 21.3675 21H25.7963C25.0926 22.3714 24.1097 23.5803 22.9108 24.5491C21.7119 25.5178 20.3236 26.225 18.835 26.625Z"
fill="currentColor"
d="M2.56267 6.23601L6.13604 8.78837C6.32197 8.92118 6.41494 8.98759 6.51225 9.00289C6.59786 9.01635 6.68554 9.00278 6.76309 8.96407C6.85121 8.92008 6.91976 8.82868 7.05686 8.64588L7.81194 7.63909C7.85071 7.5874 7.8701 7.56155 7.89288 7.53925C7.91311 7.51945 7.93531 7.50177 7.95913 7.48647C7.98595 7.46924 8.01547 7.45612 8.07452 7.42988L11.2983 5.99707C11.432 5.93767 11.4988 5.90798 11.5492 5.8616C11.5938 5.82057 11.6288 5.77033 11.652 5.71436C11.6782 5.65108 11.6831 5.57812 11.6928 5.4322L11.9288 1.8915M11.2493 11.2503L13.4294 12.1846C13.6823 12.293 13.8088 12.3472 13.8757 12.4372C13.9345 12.5162 13.9634 12.6135 13.9573 12.7117C13.9504 12.8237 13.8741 12.9382 13.7214 13.1672L12.6973 14.7035C12.6249 14.812 12.5887 14.8663 12.5409 14.9056C12.4986 14.9403 12.4498 14.9664 12.3974 14.9824C12.3382 15.0003 12.273 15.0003 12.1426 15.0003H10.4799C10.3071 15.0003 10.2207 15.0003 10.1472 14.9714C10.0822 14.9459 10.0248 14.9045 9.98003 14.851C9.92936 14.7904 9.90204 14.7084 9.8474 14.5445L9.25334 12.7623C9.22111 12.6656 9.205 12.6173 9.20076 12.5681C9.19699 12.5246 9.20011 12.4807 9.21 12.4381C9.22114 12.3901 9.24393 12.3445 9.28951 12.2533L9.74077 11.3508C9.83246 11.1674 9.8783 11.0758 9.94891 11.0188C10.0111 10.9687 10.0865 10.9375 10.166 10.9289C10.2561 10.9193 10.3534 10.9517 10.5479 11.0165L11.2493 11.2503ZM18.3327 10.0003C18.3327 14.6027 14.6017 18.3337 9.99935 18.3337C5.39698 18.3337 1.66602 14.6027 1.66602 10.0003C1.66602 5.39795 5.39698 1.66699 9.99935 1.66699C14.6017 1.66699 18.3327 5.39795 18.3327 10.0003Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
@ -109,34 +111,39 @@ export const SelectCurrent: FC = () => {
setCurrent(integration.id);
}}
key={integration.id}
className="cursor-pointer flex gap-[8px] items-center bg-newBgLineColor p-[10px] rounded-tl-[4px] rounded-tr-[4px]"
className={clsx(
'border cursor-pointer relative flex gap-[8px] w-[40px] h-[40px] rounded-[8px] items-center bg-newBgLineColor justify-center',
current === integration.id
? 'border-[#FC69FF] text-[#FC69FF]'
: 'border-transparent'
)}
>
<IsGlobal id={integration.id} />
<div
className={clsx(
'relative w-[20px] h-[20px] rounded-full flex justify-center items-center bg-fifth filter transition-all duration-500',
current !== integration.id ? 'opacity-40' : ''
'relative w-full h-full rounded-full flex justify-center items-center filter transition-all duration-500'
)}
>
<Image
src={integration.picture || '/no-picture.jpg'}
className="rounded-full"
className="rounded-full min-w-[26px]"
alt={integration.identifier}
width={20}
height={20}
width={26}
height={26}
/>
{integration.identifier === 'youtube' ? (
<img
src="/icons/platforms/youtube.svg"
className="absolute z-10 -bottom-[5px] -end-[5px]"
width={20}
className="absolute z-10 bottom-[2px] end-[2px] min-w-[12px]"
width={12}
/>
) : (
<Image
src={`/icons/platforms/${integration.identifier}.png`}
className="rounded-full absolute z-10 -bottom-[5px] -end-[5px] border border-fifth"
className="min-w-[12px] min-h-[12px] rounded-[3px] absolute z-10 bottom-[6px] end-[6px]"
alt={integration.identifier}
width={15}
height={15}
width={12}
height={12}
/>
)}
</div>
@ -148,3 +155,24 @@ export const SelectCurrent: FC = () => {
</>
);
};
export const IsGlobal: FC<{ id: string }> = ({ id }) => {
const { isInternal } =
useLaunchStore(
useShallow((state) => ({
isInternal: !!state.internal.find(p => p.integration.id === id),
}))
);
if (!isInternal) {
return null;
}
return (
<div
data-tooltip-id="tooltip"
data-tooltip-content="No longer in global mode"
className="w-[8px] h-[8px] bg-[#FC69FF] -top-[1px] -end-[3px] absolute rounded-full"
/>
);
};

View File

@ -81,36 +81,25 @@ export const UText: FC<{
};
return (
<div
data-tooltip-id="tooltip"
data-tooltip-content="Underline"
onClick={mark}
className="select-none cursor-pointer w-[40px] p-[5px] text-center"
className="select-none cursor-pointer rounded-[6px] w-[30px] h-[30px] bg-newColColor flex justify-center items-center"
>
<svg
width="25"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<g clipPath="url(#clip0_31_12620)">
<path
d="M10.4119 6.47V12.77C10.4119 13.4 10.5669 13.885 10.8769 14.225C11.1869 14.565 11.6419 14.735 12.2419 14.735C12.8419 14.735 13.3019 14.565 13.6219 14.225C13.9419 13.885 14.1019 13.4 14.1019 12.77V6.47H16.6669V12.755C16.6669 13.695 16.4669 14.49 16.0669 15.14C15.6669 15.79 15.1269 16.28 14.4469 16.61C13.7769 16.94 13.0269 17.105 12.1969 17.105C11.3669 17.105 10.6219 16.945 9.96191 16.625C9.31191 16.295 8.79691 15.805 8.41691 15.155C8.03691 14.495 7.84691 13.695 7.84691 12.755V6.47H10.4119Z"
fill="currentColor"
/>
<path
d="M6.96191 18.5H17.5369V19.25H6.96191V18.5Z"
fill="currentColor"
/>
</g>
<defs>
<clipPath id="clip0_31_12620">
<rect
width="24"
height="24"
fill="white"
transform="translate(0.25)"
/>
</clipPath>
</defs>
<path
d="M11.9993 2.66699V7.33366C11.9993 9.5428 10.2085 11.3337 7.99935 11.3337C5.79021 11.3337 3.99935 9.5428 3.99935 7.33366V2.66699M2.66602 14.0003H13.3327"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
);

View File

@ -35,7 +35,6 @@ import { TopMenu } from '@gitroom/frontend/components/layout/top.menu';
import { LanguageComponent } from '@gitroom/frontend/components/layout/language.component';
import { ChromeExtensionComponent } from '@gitroom/frontend/components/layout/chrome.extension.component';
import NotificationComponent from '@gitroom/frontend/components/notifications/notification.component';
import { BillingAfter } from '@gitroom/frontend/components/new-layout/billing.after';
import { OrganizationSelector } from '@gitroom/frontend/components/layout/organization.selector';
import { PreConditionComponent } from '@gitroom/frontend/components/layout/pre-condition.component';
import { AttachToFeedbackIcon } from '@gitroom/frontend/components/new-layout/sentry.feedback.component';

View File

@ -94,10 +94,13 @@ export const Sets: FC = () => {
(params?: { id?: string; name?: string; content?: string }) => () => {
modal.openModal({
closeOnClickOutside: false,
removeLayout: true,
closeOnEscape: false,
withCloseButton: false,
removeLayout: true,
askClose: true,
fullScreen: true,
classNames: {
modal: 'w-[100%] max-w-[1400px] text-textColor',
},
id: 'add-edit-modal',
children: (
<AddEditModal

View File

@ -13,6 +13,7 @@ export const SignatureBox: FC<{
const addSignature = useCallback(() => {
modals.openModal({
title: 'Add Signature',
withCloseButton: true,
children: (close) => (
<SignatureModal appendSignature={appendValue} close={close} />
),
@ -23,18 +24,36 @@ export const SignatureBox: FC<{
<>
<div
onClick={addSignature}
className="select-none cursor-pointer w-[40px] p-[5px] text-center"
data-tooltip-id="tooltip"
data-tooltip-content="Add Signature"
className="select-none cursor-pointer rounded-[6px] w-[30px] h-[30px] bg-newColColor flex justify-center items-center"
>
<svg
width="25"
viewBox="0 0 30 28"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M28.0007 18.5H7.79447C8.06947 17.9475 8.34572 17.3825 8.61822 16.8087C8.64822 16.7475 8.67697 16.6837 8.70572 16.6262C10.4007 16.4262 12.3032 15.2187 14.3957 13.0137C15.062 14.5212 16.1545 16.1225 17.852 16.4437C18.5082 16.5687 19.5382 16.5425 20.7145 15.7175C21.1274 15.4227 21.5079 15.085 21.8495 14.71C22.8907 15.6625 24.7345 16.5 28.0007 16.5C28.3985 16.5 28.7801 16.3419 29.0614 16.0606C29.3427 15.7793 29.5007 15.3978 29.5007 15C29.5007 14.6021 29.3427 14.2206 29.0614 13.9393C28.7801 13.658 28.3985 13.5 28.0007 13.5C23.9182 13.5 23.5245 12.0487 23.5007 11.925C23.4832 11.5853 23.3508 11.2617 23.1252 11.0072C22.8996 10.7527 22.5942 10.5824 22.2591 10.5243C21.924 10.4661 21.5791 10.5236 21.2809 10.6873C20.9828 10.8509 20.7491 11.1111 20.6182 11.425C19.447 13.1662 18.6682 13.55 18.4107 13.5C17.797 13.3837 16.8545 11.5375 16.4707 9.70122C16.4097 9.40441 16.2602 9.13304 16.0419 8.92284C15.8237 8.71265 15.5468 8.5735 15.2479 8.5237C14.949 8.47391 14.6421 8.51581 14.3674 8.64389C14.0928 8.77197 13.8634 8.98022 13.7095 9.24122C12.4595 10.7887 11.3895 11.8575 10.4995 12.5537C13.1632 5.90497 12.6432 3.48872 11.9332 2.23247C11.3082 1.12372 10.1832 0.509973 8.76322 0.503723H8.72322C6.47322 0.519973 4.66947 2.58622 3.88197 6.03747C3.45072 7.92872 3.38197 10.0225 3.69947 11.78C4.02947 13.6162 4.74072 14.9887 5.77572 15.8075C5.32947 16.73 4.87572 17.6362 4.43197 18.5H2.00072C1.6029 18.5 1.22137 18.658 0.940062 18.9393C0.658758 19.2206 0.500722 19.6021 0.500722 20C0.500722 20.3978 0.658758 20.7793 0.940062 21.0606C1.22137 21.3419 1.6029 21.5 2.00072 21.5H2.83572C1.62572 23.7087 0.730722 25.2 0.710722 25.2262C0.60917 25.395 0.541869 25.5822 0.512665 25.7771C0.483461 25.9719 0.492925 26.1706 0.540517 26.3618C0.588109 26.5529 0.672896 26.7329 0.790035 26.8913C0.907175 27.0497 1.05437 27.1835 1.22322 27.285C1.45751 27.4272 1.72666 27.5016 2.00072 27.5C2.25956 27.5002 2.51405 27.4334 2.73944 27.3061C2.96483 27.1789 3.15346 26.9955 3.28697 26.7737C3.36447 26.6425 4.65322 24.5 6.25072 21.5H28.0007C28.3985 21.5 28.7801 21.3419 29.0614 21.0606C29.3427 20.7793 29.5007 20.3978 29.5007 20C29.5007 19.6021 29.3427 19.2206 29.0614 18.9393C28.7801 18.658 28.3985 18.5 28.0007 18.5ZM23.5007 12C23.5007 11.9775 23.5007 11.955 23.5007 11.9325C23.5026 11.9549 23.5026 11.9775 23.5007 12ZM6.80572 6.70122C7.22197 4.87497 8.05572 3.49997 8.75072 3.49997C9.20947 3.49997 9.28197 3.62497 9.32572 3.70497C9.50447 4.02247 10.1445 5.84122 7.14822 12.805C6.9073 12.3137 6.73968 11.7898 6.65072 11.25C6.40827 9.73793 6.46091 8.19325 6.80572 6.70122Z"
fill="currentColor"
/>
<g clipPath="url(#clip0_2352_53073)">
<path
d="M1.61528 13.4634C4.98807 11.1708 6.12853 2.72516 2.42576 2.54001C-0.271332 2.40515 1.52719 6.99029 4.04454 11.4405C4.43518 12.1311 5.08312 12.0221 5.35096 11.8873C6.23825 11.4405 6.49355 9.29898 6.95238 8.8935C7.41122 8.48802 7.98909 8.45521 8.49293 9.16322C9.12361 10.0494 9.65463 9.91856 10.0456 9.70264C10.6103 9.39078 11.3197 8.22463 12.1949 9.16322C12.7765 9.78692 12.5068 10.4612 14.9173 10.1915"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
/>
<path
d="M7.16602 12.917H13.8327"
stroke="currentColor"
strokeWidth="1.2"
strokeLinecap="round"
/>
</g>
<defs>
<clipPath id="clip0_2352_53073">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
</div>
</>
@ -45,11 +64,5 @@ export const SignatureModal: FC<{
appendSignature: (sign: string) => void;
}> = (props) => {
const { appendSignature } = props;
return (
<div className="bg-black/40 fixed start-0 top-0 w-full h-full z-[500]">
<div className="relative w-[900px] mx-auto flex gap-[20px] flex-col flex-1 rounded-[4px] pt-0">
<SignaturesComponent appendSignature={appendSignature} />
</div>
</div>
);
return <SignaturesComponent appendSignature={appendSignature} />;
};

View File

@ -182,9 +182,9 @@ export const ThirdPartyMedia: FC<{
return (
<>
<div className="relative group">
<Button
<div
className={clsx(
'relative ms-[10px] !px-[10px] rounded-[4px] gap-[8px] !text-primary justify-center items-center flex border border-dashed border-newBgLineColor bg-newColColor'
'cursor-pointer h-[30px] rounded-[6px] justify-center items-center flex bg-newColColor px-[8px]'
)}
onClick={() => {
modals.openModal({
@ -204,8 +204,8 @@ export const ThirdPartyMedia: FC<{
<div className={clsx('flex gap-[5px] items-center')}>
<div>
<svg
width="24"
height="24"
width="16"
height="16"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
@ -216,11 +216,11 @@ export const ThirdPartyMedia: FC<{
/>
</svg>
</div>
<div className="text-[12px] font-[500] !text-current">
<div className="text-[10px] font-[600] iconBreak:hidden block">
{t('integrations', 'Integrations')}
</div>
</div>
</Button>
</div>
</div>
</>
);

View File

@ -74,6 +74,9 @@ module.exports = {
modalCustom: 'var(--color-modalCustom)',
newBgColor: 'var(--new-bgColor)',
newBackdrop: 'var(--new-back-drop)',
newSep: 'var(--new-sep)',
newBorder: 'var(--new-border)',
newBgColorInner: 'var(--new-bgColorInner)',
newBgLineColor: 'var(--new-bgLineColor)',
textItemFocused: 'var(--new-textItemFocused)',
@ -91,6 +94,7 @@ module.exports = {
newTableText: 'var(--new-table-text)',
newTableTextFocused: 'var(--new-table-text-focused)',
newColColor: 'var(--new-col-color)',
newSettings: 'var(--new-settings)',
menuDots: 'var(--new-menu-dots)',
menuDotsHover: 'var(--new-menu-hover)',
bigStrip: 'var(--new-big-strips)',
@ -223,6 +227,12 @@ module.exports = {
},
}),
screens: {
iconBreak: {
raw: '(max-width: 1560px)',
},
maxMedia: {
raw: '(max-width: 1400px)',
},
custom: {
raw: '(max-height: 800px)',
},

View File

@ -78,10 +78,7 @@ export class MediaRepository {
},
},
};
const pages =
pageNum === 0
? Math.ceil((await this._media.model.media.count(query)) / 28)
: 0;
const pages = Math.ceil((await this._media.model.media.count(query)) / 18);
const results = await this._media.model.media.findMany({
where: {
organizationId: org,
@ -98,8 +95,8 @@ export class MediaRepository {
alt: true,
thumbnailTimestamp: true,
},
skip: pageNum * 28,
take: 28,
skip: pageNum * 18,
take: 18,
});
return {