feat: fix dates, attachments
This commit is contained in:
parent
4100fdfeb7
commit
3bd2fbdb56
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 1.4 KiB |
|
|
@ -5,11 +5,14 @@ import 'react-tooltip/dist/react-tooltip.css';
|
|||
|
||||
import LayoutContext from '@gitroom/frontend/components/layout/layout.context';
|
||||
import { ReactNode } from 'react';
|
||||
import { Chakra_Petch } from 'next/font/google';
|
||||
import { Chakra_Petch, Inter } from 'next/font/google';
|
||||
|
||||
const chakra = Chakra_Petch({ weight: '400', subsets: ['latin'] });
|
||||
const inter = Inter({ subsets: ['latin'], display: 'swap' });
|
||||
|
||||
export default async function AppLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html>
|
||||
<html className={inter.className}>
|
||||
<head>
|
||||
<link rel="icon" href="/favicon.png" sizes="any" />
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -37,12 +37,16 @@ import { useSWRConfig } from 'swr';
|
|||
import { useToaster } from '@gitroom/react/toaster/toaster';
|
||||
import { postSelector } from '@gitroom/frontend/components/post-url-selector/post.url.selector';
|
||||
import { UpDownArrow } from '@gitroom/frontend/components/launches/up.down.arrow';
|
||||
import { DatePicker } from '@gitroom/frontend/components/launches/helpers/date.picker';
|
||||
import { arrayMoveImmutable } from 'array-move';
|
||||
|
||||
export const AddEditModal: FC<{
|
||||
date: dayjs.Dayjs;
|
||||
integrations: Integrations[];
|
||||
}> = (props) => {
|
||||
const { date, integrations } = props;
|
||||
const [dateState, setDateState] = useState(date);
|
||||
|
||||
const { mutate } = useSWRConfig();
|
||||
|
||||
// selected integrations to allow edit
|
||||
|
|
@ -115,47 +119,47 @@ export const AddEditModal: FC<{
|
|||
target: { name: string; value?: Array<{ id: string; path: string }> };
|
||||
}) => {
|
||||
return setValue((prev) => {
|
||||
prev[index].image = newValue.target.value;
|
||||
return [...prev];
|
||||
return prev.map((p, i) => {
|
||||
if (i === index) {
|
||||
return { ...p, image: newValue.target.value };
|
||||
}
|
||||
return p;
|
||||
});
|
||||
});
|
||||
},
|
||||
[value]
|
||||
[]
|
||||
);
|
||||
|
||||
// Add another editor
|
||||
const addValue = useCallback(
|
||||
(index: number) => () => {
|
||||
setValue((prev) => {
|
||||
prev.splice(index + 1, 0, { content: '' });
|
||||
return [...prev];
|
||||
return prev.reduce((acc, p, i) => {
|
||||
acc.push(p);
|
||||
if (i === index) {
|
||||
acc.push({ content: '' });
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, [] as Array<{ content: string }>);
|
||||
});
|
||||
},
|
||||
[value]
|
||||
[]
|
||||
);
|
||||
|
||||
const changePosition = useCallback(
|
||||
(index: number) => (type: 'up' | 'down') => {
|
||||
if (type === 'up' && index !== 0) {
|
||||
setValue((prev) => {
|
||||
const temp = prev[index];
|
||||
prev[index] = prev[index - 1];
|
||||
prev[index - 1] = temp;
|
||||
return [...prev];
|
||||
return arrayMoveImmutable(prev, index, index - 1);
|
||||
});
|
||||
} else if (
|
||||
type === 'down' &&
|
||||
value.length !== 0 &&
|
||||
value.length !== index + 1
|
||||
) {
|
||||
} else if (type === 'down') {
|
||||
setValue((prev) => {
|
||||
const temp = prev[index];
|
||||
prev[index] = prev[index + 1];
|
||||
prev[index + 1] = temp;
|
||||
return [...prev];
|
||||
return arrayMoveImmutable(prev, index, index + 1);
|
||||
});
|
||||
}
|
||||
},
|
||||
[value]
|
||||
[]
|
||||
);
|
||||
|
||||
// Delete post
|
||||
|
|
@ -249,7 +253,7 @@ export const AddEditModal: FC<{
|
|||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
type,
|
||||
date: date.utc().format('YYYY-MM-DDTHH:mm:ss'),
|
||||
date: dateState.utc().format('YYYY-MM-DDTHH:mm:ss'),
|
||||
posts: allKeys,
|
||||
}),
|
||||
});
|
||||
|
|
@ -283,26 +287,9 @@ export const AddEditModal: FC<{
|
|||
title={existingData?.group ? 'Edit Post' : 'Create Post'}
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={askClose}
|
||||
className="outline-none absolute right-[20px] top-[20px] 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"
|
||||
>
|
||||
<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 className="absolute h-[57px] right-0 top-0 flex justify-center items-center">
|
||||
<DatePicker onChange={setDateState} date={dateState} />
|
||||
</div>
|
||||
|
||||
{!existingData.integration && (
|
||||
<PickPlatforms
|
||||
|
|
@ -328,7 +315,7 @@ export const AddEditModal: FC<{
|
|||
.getCommands()
|
||||
.filter((f) => f.name !== 'image'),
|
||||
newImage,
|
||||
postSelector(date),
|
||||
postSelector(dateState),
|
||||
]}
|
||||
value={p.content}
|
||||
preview="edit"
|
||||
|
|
@ -421,6 +408,12 @@ export const AddEditModal: FC<{
|
|||
<div className="relative h-[68px] flex flex-col rounded-[4px] border border-[#172034] bg-[#0B101B]">
|
||||
<div className="flex flex-1 gap-[10px] relative">
|
||||
<div className="absolute w-full h-full flex gap-[10px] justify-end items-center right-[16px]">
|
||||
<Button
|
||||
className="bg-transparent text-inputText"
|
||||
onClick={askClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
{!!existingData.integration && (
|
||||
<Button
|
||||
onClick={schedule('delete')}
|
||||
|
|
@ -495,7 +488,7 @@ export const AddEditModal: FC<{
|
|||
<ProvidersOptions
|
||||
integrations={selectedIntegrations}
|
||||
editorValue={value}
|
||||
date={date}
|
||||
date={dateState}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
import { FC, useCallback, useState } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import { Calendar, TimeInput } from '@mantine/dates';
|
||||
import { useClickOutside } from '@mantine/hooks';
|
||||
import { Button } from '@gitroom/react/form/button';
|
||||
|
||||
export const DatePicker: FC<{
|
||||
date: dayjs.Dayjs;
|
||||
onChange: (day: dayjs.Dayjs) => void;
|
||||
}> = (props) => {
|
||||
const { date, onChange } = props;
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const changeShow = useCallback(() => {
|
||||
setOpen((prev) => !prev);
|
||||
}, []);
|
||||
|
||||
const ref = useClickOutside<HTMLDivElement>(() => {
|
||||
setOpen(false);
|
||||
});
|
||||
|
||||
const changeDate = useCallback(
|
||||
(type: 'date' | 'time') => (day: Date) => {
|
||||
console.log(
|
||||
type === 'time'
|
||||
? date.format('YYYY-MM-DD') + ' ' + dayjs(day).format('HH:mm:ss')
|
||||
: dayjs(day).format('YYYY-MM-DD') + ' ' + date.format('HH:mm:ss')
|
||||
);
|
||||
onChange(
|
||||
dayjs(
|
||||
type === 'time'
|
||||
? date.format('YYYY-MM-DD') + ' ' + dayjs(day).format('HH:mm:ss')
|
||||
: dayjs(day).format('YYYY-MM-DD') + ' ' + date.format('HH:mm:ss')
|
||||
)
|
||||
);
|
||||
},
|
||||
[date]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex gap-[8px] items-center relative px-[16px] select-none"
|
||||
onClick={changeShow}
|
||||
ref={ref}
|
||||
>
|
||||
<div className="cursor-pointer">{date.format('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"
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
{open && (
|
||||
<div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="animate-normalFadeDown absolute top-[100%] mt-[16px] right-0 bg-sixth border border-tableBorder text-white rounded-[16px] z-[300] p-[16px] flex flex-col"
|
||||
>
|
||||
<Calendar
|
||||
onChange={changeDate('date')}
|
||||
value={date.toDate()}
|
||||
dayClassName={(date, modifiers) => {
|
||||
if (modifiers.weekend) {
|
||||
return '!text-[#B69DEC]';
|
||||
}
|
||||
|
||||
if (modifiers.outside) {
|
||||
return '!text-gray';
|
||||
}
|
||||
|
||||
if (modifiers.selected) {
|
||||
return '!text-white !bg-seventh !outline-none';
|
||||
}
|
||||
|
||||
return '!text-white';
|
||||
}}
|
||||
classNames={{
|
||||
day: 'hover:bg-seventh',
|
||||
calendarHeaderControl: 'text-white hover:bg-third',
|
||||
calendarHeaderLevel: 'text-white hover:bg-third', // cell: 'child:!text-white'
|
||||
}}
|
||||
/>
|
||||
<TimeInput
|
||||
onChange={changeDate('time')}
|
||||
label="Pick time"
|
||||
classNames={{
|
||||
label: 'text-white py-[12px]',
|
||||
input:
|
||||
'bg-sixth h-[40px] border border-tableBorder text-white rounded-[4px] outline-none',
|
||||
}}
|
||||
placeholder="Pick time"
|
||||
defaultValue={date.toDate()}
|
||||
/>
|
||||
<Button className="mt-[12px]" onClick={changeShow}>
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -27,6 +27,7 @@ import clsx from 'clsx';
|
|||
import { newImage } from '@gitroom/frontend/components/launches/helpers/new.image.component';
|
||||
import { postSelector } from '@gitroom/frontend/components/post-url-selector/post.url.selector';
|
||||
import { UpDownArrow } from '@gitroom/frontend/components/launches/up.down.arrow';
|
||||
import { arrayMoveImmutable } from 'array-move';
|
||||
|
||||
// Simple component to change back to settings on after changing tab
|
||||
export const SetTab: FC<{ changeTab: () => void }> = (props) => {
|
||||
|
|
@ -145,36 +146,32 @@ export const withProvider = (
|
|||
const addValue = useCallback(
|
||||
(index: number) => () => {
|
||||
setInPlaceValue((prev) => {
|
||||
prev.splice(index + 1, 0, { content: '' });
|
||||
return [...prev];
|
||||
return prev.reduce((acc, p, i) => {
|
||||
acc.push(p);
|
||||
if (i === index) {
|
||||
acc.push({ content: '' });
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, [] as Array<{ content: string }>);
|
||||
});
|
||||
},
|
||||
[InPlaceValue]
|
||||
[]
|
||||
);
|
||||
|
||||
const changePosition = useCallback(
|
||||
(index: number) => (type: 'up' | 'down') => {
|
||||
if (type === 'up' && index !== 0) {
|
||||
setInPlaceValue((prev) => {
|
||||
const temp = prev[index];
|
||||
prev[index] = prev[index - 1];
|
||||
prev[index - 1] = temp;
|
||||
return [...prev];
|
||||
return arrayMoveImmutable(prev, index, index - 1);
|
||||
});
|
||||
} else if (
|
||||
type === 'down' &&
|
||||
InPlaceValue.length !== 0 &&
|
||||
InPlaceValue.length !== index + 1
|
||||
) {
|
||||
} else if (type === 'down') {
|
||||
setInPlaceValue((prev) => {
|
||||
const temp = prev[index];
|
||||
prev[index] = prev[index + 1];
|
||||
prev[index + 1] = temp;
|
||||
return [...prev];
|
||||
return arrayMoveImmutable(prev, index, index + 1);
|
||||
});
|
||||
}
|
||||
},
|
||||
[InPlaceValue]
|
||||
[]
|
||||
);
|
||||
|
||||
// Delete post
|
||||
|
|
@ -213,7 +210,7 @@ export const withProvider = (
|
|||
setInPlaceValue(
|
||||
editInPlace
|
||||
? [{ content: '' }]
|
||||
: props.value.map((p) => ({ id: p.id, content: p.content }))
|
||||
: props.value.map((p) => ({ id: p.id, content: p.content, image: p.image}))
|
||||
);
|
||||
}, [props.value, editInPlace]);
|
||||
|
||||
|
|
|
|||
|
|
@ -86,5 +86,11 @@ module.exports = {
|
|||
}),
|
||||
},
|
||||
},
|
||||
plugins: [require('tailwind-scrollbar')],
|
||||
plugins: [
|
||||
require('tailwind-scrollbar'),
|
||||
function ({ addVariant }) {
|
||||
addVariant('child', '& > *');
|
||||
addVariant('child-hover', '& > *:hover');
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -213,28 +213,30 @@ export class PostsService {
|
|||
post
|
||||
);
|
||||
|
||||
if (posts?.length) {
|
||||
await this._workerServiceProducer.delete(
|
||||
'post',
|
||||
previousPost ? previousPost : posts?.[0]?.id
|
||||
);
|
||||
if (
|
||||
(body.type === 'schedule' || body.type === 'now') &&
|
||||
dayjs(body.date).isAfter(dayjs())
|
||||
) {
|
||||
this._workerServiceProducer.emit('post', {
|
||||
if (!posts?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._workerServiceProducer.delete(
|
||||
'post',
|
||||
previousPost ? previousPost : posts?.[0]?.id
|
||||
);
|
||||
if (
|
||||
(body.type === 'schedule' || body.type === 'now') &&
|
||||
dayjs(body.date).isAfter(dayjs())
|
||||
) {
|
||||
this._workerServiceProducer.emit('post', {
|
||||
id: posts[0].id,
|
||||
options: {
|
||||
delay:
|
||||
body.type === 'now'
|
||||
? 0
|
||||
: dayjs(posts[0].publishDate).diff(dayjs(), 'millisecond'),
|
||||
},
|
||||
payload: {
|
||||
id: posts[0].id,
|
||||
options: {
|
||||
delay:
|
||||
body.type === 'now'
|
||||
? 0
|
||||
: dayjs(posts[0].publishDate).diff(dayjs(), 'millisecond'),
|
||||
},
|
||||
payload: {
|
||||
id: posts[0].id,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"@casl/ability": "^6.5.0",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@mantine/core": "^5.10.5",
|
||||
"@mantine/dates": "^5.10.5",
|
||||
"@mantine/hooks": "^5.10.5",
|
||||
"@mantine/modals": "^5.10.5",
|
||||
"@nestjs/cache-manager": "^2.2.1",
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"@uiw/react-md-editor": "^4.0.3",
|
||||
"@virtual-grid/react": "^2.0.2",
|
||||
"array-move": "^4.0.0",
|
||||
"axios": "1.6.7",
|
||||
"bcrypt": "^5.1.1",
|
||||
"bufferutil": "^4.0.8",
|
||||
|
|
@ -148,6 +150,9 @@
|
|||
"url-loader": "^4.1.1",
|
||||
"vite": "^5.0.0",
|
||||
"vitest": "1.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0 <21.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
|
|
@ -4397,6 +4402,20 @@
|
|||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mantine/dates": {
|
||||
"version": "5.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-5.10.5.tgz",
|
||||
"integrity": "sha512-l7lSgDKEV+phTgUAHIkc/22Qgq+WBg0P7JS2WpeZeERX8eyD4BGlsY3ZWqHigYxhBq/Ycd2tHZFmwl2p+694Zw==",
|
||||
"dependencies": {
|
||||
"@mantine/utils": "5.10.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mantine/core": "5.10.5",
|
||||
"@mantine/hooks": "5.10.5",
|
||||
"dayjs": ">=1.0.0",
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mantine/hooks": {
|
||||
"version": "5.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-5.10.5.tgz",
|
||||
|
|
@ -13221,6 +13240,17 @@
|
|||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/array-move": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-move/-/array-move-4.0.0.tgz",
|
||||
"integrity": "sha512-+RY54S8OuVvg94THpneQvFRmqWdAHeqtMzgMW6JNurHxe8rsS07cHQdfGkXnTUXiBcyZ0j3SiDIxxj0RPiqCkQ==",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/array-timsort": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
"@casl/ability": "^6.5.0",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@mantine/core": "^5.10.5",
|
||||
"@mantine/dates": "^5.10.5",
|
||||
"@mantine/hooks": "^5.10.5",
|
||||
"@mantine/modals": "^5.10.5",
|
||||
"@nestjs/cache-manager": "^2.2.1",
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"@uiw/react-md-editor": "^4.0.3",
|
||||
"@virtual-grid/react": "^2.0.2",
|
||||
"array-move": "^4.0.0",
|
||||
"axios": "1.6.7",
|
||||
"bcrypt": "^5.1.1",
|
||||
"bufferutil": "^4.0.8",
|
||||
|
|
|
|||
Loading…
Reference in New Issue