feat: sort images in a post
This commit is contained in:
parent
2b1020c528
commit
67eb6430e0
|
|
@ -3,6 +3,7 @@
|
|||
import {
|
||||
ClipboardEvent,
|
||||
FC,
|
||||
Fragment,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
|
|
@ -19,7 +20,6 @@ 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 { LoadingComponent } from '@gitroom/frontend/components/layout/loading';
|
||||
import { MultipartFileUploader } from '@gitroom/frontend/components/media/new.uploader';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useUser } from '@gitroom/frontend/components/layout/user.context';
|
||||
|
|
@ -29,6 +29,7 @@ import { DropFiles } from '@gitroom/frontend/components/layout/drop.files';
|
|||
import { deleteDialog } from '@gitroom/react/helpers/delete.dialog';
|
||||
import { useT } from '@gitroom/react/translation/get.transation.service.client';
|
||||
import { ThirdPartyMedia } from '@gitroom/frontend/components/third-parties/third-party.media';
|
||||
import { ReactSortable } from 'react-sortablejs';
|
||||
const Polonto = dynamic(
|
||||
() => import('@gitroom/frontend/components/launches/polonto')
|
||||
);
|
||||
|
|
@ -204,18 +205,21 @@ export const MediaBox: FC<{
|
|||
}, [selectedMedia]);
|
||||
const { data, mutate } = useSWR(`get-media-${page}`, loadMedia);
|
||||
|
||||
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
|
||||
);
|
||||
addNewMedia(onlyNewMedia)();
|
||||
}, [mutate, addNewMedia, mediaList, selectedMedia]);
|
||||
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
|
||||
);
|
||||
addNewMedia(onlyNewMedia)();
|
||||
},
|
||||
[mutate, addNewMedia, mediaList, selectedMedia]
|
||||
);
|
||||
|
||||
const dragAndDrop = useCallback(
|
||||
async (event: ClipboardEvent<HTMLDivElement> | File[]) => {
|
||||
|
|
@ -480,7 +484,8 @@ export const MultiMediaComponent: FC<{
|
|||
};
|
||||
}) => void;
|
||||
}> = (props) => {
|
||||
const { onOpen, onClose, name, error, text, onChange, value, allData } = props;
|
||||
const { onOpen, onClose, name, error, text, onChange, value, allData } =
|
||||
props;
|
||||
const user = useUser();
|
||||
useEffect(() => {
|
||||
if (value) {
|
||||
|
|
@ -614,32 +619,50 @@ export const MultiMediaComponent: FC<{
|
|||
)}
|
||||
</div>
|
||||
|
||||
{!!currentMedia &&
|
||||
currentMedia.map((media, index) => (
|
||||
<>
|
||||
<div className="cursor-pointer w-[40px] h-[40px] border-2 border-tableBorder relative flex">
|
||||
<div
|
||||
className="w-full h-full"
|
||||
onClick={() => window.open(mediaDirectory.set(media?.path))}
|
||||
>
|
||||
{media?.path?.indexOf('mp4') > -1 ? (
|
||||
<VideoFrame url={mediaDirectory.set(media?.path)} />
|
||||
) : (
|
||||
<img
|
||||
className="w-full h-full object-cover"
|
||||
src={mediaDirectory.set(media?.path)}
|
||||
/>
|
||||
)}
|
||||
{!!currentMedia && (
|
||||
<ReactSortable
|
||||
list={currentMedia}
|
||||
setList={(value) =>
|
||||
onChange({ target: { name: 'upload', value } })
|
||||
}
|
||||
className="flex gap-[10px] sortable-container"
|
||||
animation={200}
|
||||
swap={true}
|
||||
handle=".dragging"
|
||||
>
|
||||
{currentMedia.map((media, index) => (
|
||||
<Fragment key={media.id}>
|
||||
<div className="cursor-pointer w-[40px] h-[40px] 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="w-full h-full"
|
||||
onClick={() =>
|
||||
window.open(mediaDirectory.set(media?.path))
|
||||
}
|
||||
>
|
||||
{media?.path?.indexOf('mp4') > -1 ? (
|
||||
<VideoFrame url={mediaDirectory.set(media?.path)} />
|
||||
) : (
|
||||
<img
|
||||
className="w-full h-full object-cover"
|
||||
src={mediaDirectory.set(media?.path)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
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]"
|
||||
>
|
||||
x
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
onClick={clearMedia(index)}
|
||||
className="rounded-full w-[15px] h-[15px] bg-red-800 text-textColor flex justify-center items-center absolute -end-[4px] -top-[4px]"
|
||||
>
|
||||
x
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
</ReactSortable>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-[12px] text-red-400">{error}</div>
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
|
|||
setTags,
|
||||
integrations,
|
||||
setSelectedIntegrations,
|
||||
locked,
|
||||
} = useLaunchStore(
|
||||
useShallow((state) => ({
|
||||
hide: state.hide,
|
||||
|
|
@ -71,6 +72,7 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
|
|||
selectedIntegrations: state.selectedIntegrations,
|
||||
integrations: state.integrations,
|
||||
setSelectedIntegrations: state.setSelectedIntegrations,
|
||||
locked: state.locked,
|
||||
}))
|
||||
);
|
||||
|
||||
|
|
@ -316,7 +318,7 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
|
|||
onClick={deletePost}
|
||||
className="rounded-[4px] border-2 border-red-400 text-red-400"
|
||||
secondary={true}
|
||||
disabled={loading}
|
||||
disabled={loading || locked}
|
||||
>
|
||||
{t('delete_post', 'Delete Post')}
|
||||
</Button>
|
||||
|
|
@ -327,7 +329,7 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
|
|||
onClick={schedule('draft')}
|
||||
className="rounded-[4px] border-2 border-customColor21"
|
||||
secondary={true}
|
||||
disabled={selectedIntegrations.length === 0 || loading}
|
||||
disabled={selectedIntegrations.length === 0 || loading || locked}
|
||||
>
|
||||
{t('save_as_draft', 'Save as draft')}
|
||||
</Button>
|
||||
|
|
@ -336,7 +338,7 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
|
|||
{addEditSets && (
|
||||
<Button
|
||||
className="rounded-[4px] relative group"
|
||||
disabled={selectedIntegrations.length === 0 || loading}
|
||||
disabled={selectedIntegrations.length === 0 || loading || locked}
|
||||
onClick={schedule('draft')}
|
||||
>
|
||||
Save Set
|
||||
|
|
@ -345,7 +347,7 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
|
|||
{!addEditSets && (
|
||||
<Button
|
||||
className="rounded-[4px] relative group"
|
||||
disabled={selectedIntegrations.length === 0 || loading}
|
||||
disabled={selectedIntegrations.length === 0 || loading || locked}
|
||||
>
|
||||
<div className="flex justify-center items-center gap-[5px] h-full">
|
||||
<div
|
||||
|
|
@ -378,7 +380,7 @@ export const ManageModal: FC<AddEditModalProps> = (props) => {
|
|||
onClick={schedule('now')}
|
||||
className={clsx(
|
||||
'hidden group-hover:flex hover:flex flex-col justify-center absolute start-0 top-[100%] w-full h-[40px] bg-customColor22 border border-tableBorder',
|
||||
loading &&
|
||||
(locked || loading) &&
|
||||
'cursor-not-allowed pointer-events-none opacity-50'
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@
|
|||
"react-hook-form": "^7.58.1",
|
||||
"react-i18next": "^15.5.2",
|
||||
"react-loading": "^2.0.3",
|
||||
"react-sortablejs": "^6.1.4",
|
||||
"react-tag-autocomplete": "^7.2.0",
|
||||
"react-tooltip": "^5.26.2",
|
||||
"react-use-cookie": "^1.6.1",
|
||||
|
|
|
|||
|
|
@ -420,6 +420,9 @@ importers:
|
|||
react-loading:
|
||||
specifier: ^2.0.3
|
||||
version: 2.0.3(prop-types@15.8.1)(react@18.3.1)
|
||||
react-sortablejs:
|
||||
specifier: ^6.1.4
|
||||
version: 6.1.4(@types/sortablejs@1.15.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sortablejs@1.15.6)
|
||||
react-tag-autocomplete:
|
||||
specifier: ^7.2.0
|
||||
version: 7.5.0(react@18.3.1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue