mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 21:06:42 +07:00
sorting image attaches on comment form
This commit is contained in:
parent
3e1583f0af
commit
72ef4be7a6
6 changed files with 136 additions and 22 deletions
|
@ -12,12 +12,17 @@ const SortableImageGrid = SortableContainer(
|
|||
items,
|
||||
locked,
|
||||
onDrop,
|
||||
size = 200,
|
||||
}: {
|
||||
items: IFile[];
|
||||
locked: IUploadStatus[];
|
||||
onDrop: (file_id: IFile['id']) => void;
|
||||
size?: number;
|
||||
}) => (
|
||||
<div className={styles.grid}>
|
||||
<div
|
||||
className={styles.grid}
|
||||
style={{ gridTemplateColumns: `repeat(auto-fill, minmax(${size}px, 1fr))` }}
|
||||
>
|
||||
{items
|
||||
.filter(file => file && file.id)
|
||||
.map((file, index) => (
|
||||
|
|
|
@ -8,9 +8,6 @@ $stamp_color: $content_bg;
|
|||
|
||||
.grid_test {
|
||||
display: grid;
|
||||
// grid-template-columns: repeat(auto-fit, minmax($cell, 1fr));
|
||||
// grid-template-rows: 50vh $cell;
|
||||
// grid-auto-rows: $cell;
|
||||
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
grid-template-rows: 50vh $cell;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, { FC, useCallback, KeyboardEventHandler, useEffect } from 'react';
|
||||
import React, { FC, useCallback, KeyboardEventHandler, useEffect, useMemo } from 'react';
|
||||
import { Textarea } from '~/components/input/Textarea';
|
||||
import { CommentWrapper } from '~/components/containers/CommentWrapper';
|
||||
import * as styles from './styles.scss';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
import { Button } from '~/components/input/Button';
|
||||
import assocPath from 'ramda/es/assocPath';
|
||||
import { InputHandler, IFileWithUUID } from '~/redux/types';
|
||||
import { InputHandler, IFileWithUUID, IFile } from '~/redux/types';
|
||||
import { connect } from 'react-redux';
|
||||
import * as NODE_ACTIONS from '~/redux/node/actions';
|
||||
import { selectNode } from '~/redux/node/selectors';
|
||||
|
@ -21,6 +21,9 @@ import { selectUser } from '~/redux/auth/selectors';
|
|||
import { getURL } from '~/utils/dom';
|
||||
import { ButtonGroup } from '~/components/input/ButtonGroup';
|
||||
import { AudioPlayer } from '~/components/media/AudioPlayer';
|
||||
import { SortableImageGrid } from '~/components/editors/SortableImageGrid';
|
||||
import { moveArrItem } from '~/utils/fn';
|
||||
import { SortEnd } from 'react-sortable-hoc';
|
||||
|
||||
const mapStateToProps = (state: IState) => ({
|
||||
node: selectNode(state),
|
||||
|
@ -121,6 +124,41 @@ const CommentFormUnconnected: FC<IProps> = ({
|
|||
|
||||
const comment = comment_data[id];
|
||||
|
||||
const images = useMemo(() => comment.files.filter(file => file.type === UPLOAD_TYPES.IMAGE), [
|
||||
comment.files,
|
||||
]);
|
||||
|
||||
const audios = useMemo(() => comment.files.filter(file => file.type === UPLOAD_TYPES.AUDIO), [
|
||||
comment.files,
|
||||
]);
|
||||
|
||||
const onFileDrop = useCallback(
|
||||
(file_id: IFile['id']) => {
|
||||
nodeSetCommentData(
|
||||
id,
|
||||
assocPath(['files'], comment.files.filter(file => file.id != file_id), comment_data[id])
|
||||
);
|
||||
},
|
||||
[comment_data, id, nodeSetCommentData]
|
||||
);
|
||||
|
||||
const onImageMove = useCallback(
|
||||
({ oldIndex, newIndex }: SortEnd) => {
|
||||
nodeSetCommentData(
|
||||
id,
|
||||
assocPath(
|
||||
['files'],
|
||||
[
|
||||
...audios,
|
||||
...(moveArrItem(oldIndex, newIndex, images.filter(file => !!file)) as IFile[]),
|
||||
],
|
||||
comment_data[id]
|
||||
)
|
||||
);
|
||||
},
|
||||
[images, audios]
|
||||
);
|
||||
|
||||
return (
|
||||
<CommentWrapper user={user}>
|
||||
<form onSubmit={onSubmit} className={styles.wrap}>
|
||||
|
@ -134,22 +172,25 @@ const CommentFormUnconnected: FC<IProps> = ({
|
|||
/>
|
||||
</div>
|
||||
|
||||
{comment.temp_ids.map(
|
||||
temp_id =>
|
||||
statuses[temp_id] &&
|
||||
statuses[temp_id].is_uploading && (
|
||||
<div key={statuses[temp_id].temp_id}>{statuses[temp_id].progress}</div>
|
||||
)
|
||||
{(!!images.length || !!audios.length) && (
|
||||
<div className={styles.attaches}>
|
||||
<SortableImageGrid
|
||||
onDrop={onFileDrop}
|
||||
onSortEnd={onImageMove}
|
||||
axis="xy"
|
||||
items={images}
|
||||
locked={[]}
|
||||
pressDelay={window.innerWidth < 768 ? 200 : 0}
|
||||
helperClass={styles.helper}
|
||||
size={120}
|
||||
/>
|
||||
|
||||
{audios.map(file => (
|
||||
<AudioPlayer file={file} key={file.id} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{comment.files.map(file => {
|
||||
if (file.type === UPLOAD_TYPES.AUDIO) {
|
||||
return <AudioPlayer file={file} />;
|
||||
}
|
||||
|
||||
return <div>file.name</div>;
|
||||
})}
|
||||
|
||||
<Group horizontal className={styles.buttons}>
|
||||
<ButtonGroup>
|
||||
<Button iconLeft="image" size="small" grey iconOnly>
|
||||
|
|
|
@ -8,11 +8,15 @@
|
|||
}
|
||||
|
||||
.input {
|
||||
@include outer_shadow();
|
||||
|
||||
flex: 1;
|
||||
padding: ($gap / 2) ($gap / 2 + 1px);
|
||||
}
|
||||
|
||||
.buttons {
|
||||
@include outer_shadow();
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background: transparentize(black, 0.8);
|
||||
|
@ -28,3 +32,10 @@
|
|||
grid-row-gap: $gap / 2;
|
||||
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
||||
}
|
||||
|
||||
.attaches {
|
||||
@include outer_shadow();
|
||||
|
||||
padding: $gap;
|
||||
// background: darken($comment_bg, 2%);
|
||||
}
|
||||
|
|
|
@ -87,7 +87,63 @@ export const NODE_INLINES: INodeComponents = {
|
|||
export const EMPTY_COMMENT: IComment = {
|
||||
id: null,
|
||||
text: '',
|
||||
files: [],
|
||||
// files: [],
|
||||
// temp_ids: [],
|
||||
// is_private: false,
|
||||
// user: null,
|
||||
|
||||
// id: null,
|
||||
// text: '',
|
||||
files: [
|
||||
{
|
||||
name: 'screenshot_2019-09-29_21-13-38_502253296-1572589001092.png',
|
||||
path: 'uploads/2019/10/image/',
|
||||
full_path:
|
||||
'public/uploads/2019/10/image/screenshot_2019-09-29_21-13-38_502253296-1572589001092.png',
|
||||
url:
|
||||
'REMOTE_CURRENT://uploads/2019/10/image/screenshot_2019-09-29_21-13-38_502253296-1572589001092.png',
|
||||
size: 994331,
|
||||
type: 'image',
|
||||
mime: 'image/png',
|
||||
metadata: {
|
||||
width: 1919,
|
||||
height: 1079,
|
||||
},
|
||||
id: 8709,
|
||||
},
|
||||
{
|
||||
name: 'screenshot_2019-09-29_19-05-41_148603009-1572589001080.png',
|
||||
path: 'uploads/2019/10/image/',
|
||||
full_path:
|
||||
'public/uploads/2019/10/image/screenshot_2019-09-29_19-05-41_148603009-1572589001080.png',
|
||||
url:
|
||||
'REMOTE_CURRENT://uploads/2019/10/image/screenshot_2019-09-29_19-05-41_148603009-1572589001080.png',
|
||||
size: 2145,
|
||||
type: 'image',
|
||||
mime: 'image/png',
|
||||
metadata: {
|
||||
width: 445,
|
||||
height: 446,
|
||||
},
|
||||
id: 8708,
|
||||
},
|
||||
{
|
||||
name: 'screenshot_2019-09-29_21-13-26_924738012-1572589001110.png',
|
||||
path: 'uploads/2019/10/image/',
|
||||
full_path:
|
||||
'public/uploads/2019/10/image/screenshot_2019-09-29_21-13-26_924738012-1572589001110.png',
|
||||
url:
|
||||
'REMOTE_CURRENT://uploads/2019/10/image/screenshot_2019-09-29_21-13-26_924738012-1572589001110.png',
|
||||
size: 881224,
|
||||
type: 'image',
|
||||
mime: 'image/png',
|
||||
metadata: {
|
||||
width: 1919,
|
||||
height: 1079,
|
||||
},
|
||||
id: 8710,
|
||||
},
|
||||
],
|
||||
temp_ids: [],
|
||||
is_private: false,
|
||||
user: null,
|
||||
|
|
|
@ -30,7 +30,11 @@ const INITIAL_STATE: INodeState = {
|
|||
files: [],
|
||||
},
|
||||
current: { ...EMPTY_NODE },
|
||||
comment_data: { 0: { ...EMPTY_COMMENT } },
|
||||
comment_data: {
|
||||
0: {
|
||||
...EMPTY_COMMENT,
|
||||
},
|
||||
},
|
||||
comments: [],
|
||||
related: null,
|
||||
current_cover_image: null,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue