1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-24 20:36:40 +07:00

added SortableAudioGrid

This commit is contained in:
Fedor Katurov 2022-06-30 15:58:46 +07:00
parent 586ebb7480
commit 47a6e02c21
14 changed files with 175 additions and 131 deletions

View file

@ -1,14 +1,10 @@
import React, { FC, useCallback } from 'react';
import { SortEnd } from 'react-sortable-hoc';
import { SortableAudioGrid } from '~/components/editors/SortableAudioGrid';
import { SortableImageGrid } from '~/components/sortable';
import { SortableAudioGrid, SortableImageGrid } from '~/components/sortable';
import { COMMENT_FILE_TYPES } from '~/constants/uploads';
import { useFileDropZone } from '~/hooks';
import { IFile } from '~/types';
import { useUploaderContext } from '~/utils/context/UploaderContextProvider';
import { moveArrItem } from '~/utils/fn';
import styles from './styles.module.scss';
@ -37,15 +33,8 @@ const CommentFormAttaches: FC = () => {
);
const onAudioMove = useCallback(
({ oldIndex, newIndex }: SortEnd) => {
setFiles([
...filesImages,
...(moveArrItem(
oldIndex,
newIndex,
filesAudios.filter(file => !!file)
) as IFile[]),
]);
(newFiles: IFile[]) => {
setFiles([...filesImages, ...newFiles]);
},
[setFiles, filesImages, filesAudios]
);
@ -88,10 +77,7 @@ const CommentFormAttaches: FC = () => {
onDelete={onFileDelete}
onTitleChange={onAudioTitleChange}
onSortEnd={onAudioMove}
axis="y"
locked={pendingAudios}
pressDelay={50}
helperClass={styles.helper}
/>
)}
</div>

View file

@ -3,7 +3,3 @@
.attaches {
@include outer_shadow();
}
.helper {
z-index: 10000 !important;
}

View file

@ -1,15 +1,8 @@
import React, { FC, useCallback } from 'react';
import { SortEnd } from 'react-sortable-hoc';
import { SortableAudioGrid } from '~/components/editors/SortableAudioGrid';
import { useWindowSize } from '~/hooks/dom/useWindowSize';
import { SortableAudioGrid } from '~/components/sortable';
import { UploadStatus } from '~/store/uploader/UploaderStore';
import { IFile } from '~/types';
import { moveArrItem } from '~/utils/fn';
import styles from './styles.module.scss';
interface IProps {
files: IFile[];
@ -18,17 +11,9 @@ interface IProps {
}
const AudioGrid: FC<IProps> = ({ files, setFiles, locked }) => {
const { innerWidth } = useWindowSize();
const onMove = useCallback(
({ oldIndex, newIndex }: SortEnd) => {
setFiles(
moveArrItem(
oldIndex,
newIndex,
files.filter(file => !!file)
) as IFile[]
);
(newFiles: IFile[]) => {
setFiles(newFiles);
},
[setFiles, files]
);
@ -56,11 +41,8 @@ const AudioGrid: FC<IProps> = ({ files, setFiles, locked }) => {
onDelete={onDrop}
onTitleChange={onTitleChange}
onSortEnd={onMove}
axis="xy"
items={files}
locked={locked}
pressDelay={innerWidth < 768 ? 200 : 0}
helperClass={styles.helper}
/>
);
};

View file

@ -1,6 +0,0 @@
@import "src/styles/variables";
.helper {
opacity: 0.5;
z-index: 10 !important;
}

View file

@ -1,50 +0,0 @@
import React from 'react';
import { SortableContainer } from 'react-sortable-hoc';
import { SortableAudioGridItem } from '~/components/editors/SortableAudioGridItem';
import { AudioPlayer } from '~/components/media/AudioPlayer';
import { AudioUpload } from '~/components/upload/AudioUpload';
import { UploadStatus } from '~/store/uploader/UploaderStore';
import { IFile } from '~/types';
import styles from './styles.module.scss';
const SortableAudioGrid = SortableContainer(
({
items,
locked,
onDelete,
onTitleChange,
}: {
items: IFile[];
locked: UploadStatus[];
onDelete: (file_id: IFile['id']) => void;
onTitleChange: (file_id: IFile['id'], title: string) => void;
}) => {
return (
<div className={styles.grid}>
{items
.filter(file => file && file.id)
.map((file, index) => (
<SortableAudioGridItem key={file.id} index={index} collection={0}>
<AudioPlayer
file={file}
onDelete={onDelete}
onTitleChange={onTitleChange}
isEditing
/>
</SortableAudioGridItem>
))}
{locked.map((item, index) => (
<SortableAudioGridItem key={item.id} index={index} collection={1} disabled>
<AudioUpload title={item.name} progress={item.progress} is_uploading />
</SortableAudioGridItem>
))}
</div>
);
}
);
export { SortableAudioGrid };

View file

@ -0,0 +1,57 @@
import React, { FC, useCallback } from 'react';
import { AudioPlayer } from '~/components/media/AudioPlayer';
import { AudioUpload } from '~/components/upload/AudioUpload';
import { UploadStatus } from '~/store/uploader/UploaderStore';
import { IFile } from '~/types';
import { SortableList } from '../SortableList';
type OnSortEnd = (newValue: IFile[]) => void;
interface SortableAudioGridProps {
onSortEnd: OnSortEnd;
items: IFile[];
locked: UploadStatus[];
className?: string;
onDelete: (file_id: IFile['id']) => void;
onTitleChange: (file_id: IFile['id'], title: string) => void;
}
const SortableAudioGrid: FC<SortableAudioGridProps> = ({
items,
locked,
onDelete,
className,
onSortEnd,
onTitleChange,
}) => {
const renderItem = useCallback<FC<{ item: IFile }>>(
({ item }) => (
<AudioPlayer file={item} onDelete={onDelete} isEditing onTitleChange={onTitleChange} />
),
[]
);
const renderLocked = useCallback<FC<{ locked: UploadStatus }>>(
({ locked }) => (
<AudioUpload id={locked.id} is_uploading title={locked.name} progress={locked.progress} />
),
[]
);
return (
<SortableList
items={items}
locked={locked}
getID={it => it.id}
getLockedID={it => it.id}
renderItem={renderItem}
renderLocked={renderLocked}
onSortEnd={onSortEnd}
className={className}
/>
);
};
export { SortableAudioGrid };

View file

@ -1,27 +1,16 @@
import React, { createElement, FC, useCallback, useMemo, useState } from 'react';
import React, { createElement, FC, useMemo } from "react";
import {
closestCenter,
DndContext,
DragOverlay,
DragStartEvent,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import { DragEndEvent } from '@dnd-kit/core/dist/types';
import { rectSortingStrategy, SortableContext } from '@dnd-kit/sortable';
import classNames from 'classnames';
import { closestCenter, DndContext, DragOverlay } from "@dnd-kit/core";
import { rectSortingStrategy, SortableContext } from "@dnd-kit/sortable";
import classNames from "classnames";
import { DragOverlayItem } from '~/components/sortable/DragOverlayItem';
import { useSortableActions } from '~/hooks/sortable';
import { moveArrItem } from '~/utils/fn';
import { DivProps } from '~/utils/types';
import { DragOverlayItem } from "~/components/sortable/DragOverlayItem";
import { useSortableActions } from "~/hooks/sortable";
import { DivProps } from "~/utils/types";
import { SortableImageGridItem } from '../SortableGridItem';
import { SortableItem } from "../SortableItem";
import styles from './styles.module.scss';
import styles from "./styles.module.scss";
interface SortableGridProps<T extends {}, R extends {}> {
items: T[];
@ -70,7 +59,7 @@ const SortableGrid = <T, R>({
<SortableContext items={ids} strategy={rectSortingStrategy}>
<div className={classNames(styles.grid, className)} style={gridStyle}>
{items.map(item => (
<SortableImageGridItem
<SortableItem
key={getID(item)}
id={getID(item)}
className={
@ -78,7 +67,7 @@ const SortableGrid = <T, R>({
}
>
{createElement(renderItem, { item })}
</SortableImageGridItem>
</SortableItem>
))}
{locked.map(item =>

View file

@ -12,7 +12,7 @@ interface SortableImageGridItemProps {
className?: string;
}
const SortableImageGridItem: FC<SortableImageGridItemProps> = ({
const SortableItem: FC<SortableImageGridItemProps> = ({
children,
id,
disabled = false,
@ -41,4 +41,4 @@ const SortableImageGridItem: FC<SortableImageGridItemProps> = ({
);
};
export { SortableImageGridItem };
export { SortableItem };

View file

@ -0,0 +1,76 @@
import React, { createElement, FC } from 'react';
import { closestCenter, DndContext, DragOverlay } from '@dnd-kit/core';
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
import classNames from 'classnames';
import { DragOverlayItem } from '~/components/sortable/DragOverlayItem';
import { SortableItem } from '~/components/sortable/SortableItem';
import { useSortableActions } from '~/hooks/sortable';
import styles from './styles.module.scss';
interface SortableListProps<T extends {}, R extends {}> {
items: T[];
locked: R[];
getID: (item: T) => number | string;
getLockedID: (locked: R) => number | string;
renderItem: FC<{ item: T }>;
renderLocked: FC<{ locked: R }>;
onSortEnd: (newVal: T[]) => void;
className?: string;
}
const SortableList = <T, R>({
items,
locked,
getID,
getLockedID,
className,
renderItem,
renderLocked,
onSortEnd,
}: SortableListProps<T, R>) => {
const { sensors, onDragEnd, onDragStart, draggingItem, ids } = useSortableActions(
items,
getID,
onSortEnd
);
return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={onDragEnd}
onDragStart={onDragStart}
>
<SortableContext items={ids} strategy={verticalListSortingStrategy}>
<div className={classNames(styles.grid, className)}>
{items.map(item => (
<SortableItem
key={getID(item)}
id={getID(item)}
className={
draggingItem && getID(item) === getID(draggingItem) ? styles.dragging : undefined
}
>
{createElement(renderItem, { item })}
</SortableItem>
))}
{locked.map(item =>
createElement(renderLocked, { locked: item, key: getLockedID(item) })
)}
<DragOverlay>
{draggingItem ? (
<DragOverlayItem>{createElement(renderItem, { item: draggingItem })}</DragOverlayItem>
) : null}
</DragOverlay>
</div>
</SortableContext>
</DndContext>
);
};
export { SortableList };

View file

@ -0,0 +1,15 @@
@import "src/styles/variables";
.grid {
box-sizing: border-box;
display: grid;
grid-row-gap: $gap;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-auto-flow: row;
}
.dragging {
opacity: 0.1;
}

View file

@ -1,2 +1,2 @@
export * from './SortableImageGrid';
export * from './SortableGrid';
export * from './SortableAudioGrid';

View file

@ -1,18 +1,17 @@
import React, { FC, useCallback } from 'react';
import React, { FC, useCallback } from "react";
import classNames from 'classnames';
import classNames from "classnames";
import { ArcProgress } from '~/components/input/ArcProgress';
import { Icon } from '~/components/input/Icon';
import { IFile } from '~/types';
import { ArcProgress } from "~/components/input/ArcProgress";
import { Icon } from "~/components/input/Icon";
import styles from './styles.module.scss';
import styles from "./styles.module.scss";
interface IProps {
id?: IFile['id'];
id?: string;
title?: string;
progress?: number;
onDrop?: (file_id: IFile['id']) => void;
onDrop?: (file_id: string) => void;
is_uploading?: boolean;
}