1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 12:56:41 +07:00

fixed audio attaches

This commit is contained in:
Fedor Katurov 2020-08-26 18:30:01 +07:00
parent c9d84a4947
commit b11593c45e
7 changed files with 68 additions and 69 deletions

View file

@ -18,7 +18,10 @@ const SortableAudioGrid = SortableContainer(
locked: IUploadStatus[]; locked: IUploadStatus[];
onDrop: (file_id: IFile['id']) => void; onDrop: (file_id: IFile['id']) => void;
onTitleChange: (file_id: IFile['id'], title: IFile['metadata']['title']) => void; onTitleChange: (file_id: IFile['id'], title: IFile['metadata']['title']) => void;
}) => ( }) => {
console.log(locked);
return (
<div className={styles.grid}> <div className={styles.grid}>
{items {items
.filter(file => file && file.id) .filter(file => file && file.id)
@ -34,7 +37,8 @@ const SortableAudioGrid = SortableContainer(
</SortableAudioGridItem> </SortableAudioGridItem>
))} ))}
</div> </div>
) );
}
); );
export { SortableAudioGrid }; export { SortableAudioGrid };

View file

@ -1,10 +1,10 @@
import React, { FC, useCallback, KeyboardEventHandler, useEffect, useMemo, memo } from 'react'; import React, { FC, KeyboardEventHandler, memo, useCallback, useEffect, useMemo } from 'react';
import { Textarea } from '~/components/input/Textarea'; import { Textarea } from '~/components/input/Textarea';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import { Filler } from '~/components/containers/Filler'; import { Filler } from '~/components/containers/Filler';
import { Button } from '~/components/input/Button'; import { Button } from '~/components/input/Button';
import assocPath from 'ramda/es/assocPath'; import assocPath from 'ramda/es/assocPath';
import { InputHandler, IFileWithUUID, IFile } from '~/redux/types'; import { IFile, IFileWithUUID, InputHandler } from '~/redux/types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as NODE_ACTIONS from '~/redux/node/actions'; import * as NODE_ACTIONS from '~/redux/node/actions';
import { selectNode } from '~/redux/node/selectors'; import { selectNode } from '~/redux/node/selectors';
@ -233,6 +233,10 @@ const CommentFormUnconnected: FC<IProps> = memo(
const placeholder = getRandomPhrase('SIMPLE'); const placeholder = getRandomPhrase('SIMPLE');
const hasImageAttaches = images.length > 0 || locked_images.length > 0;
const hasAudioAttaches = audios.length > 0 || locked_audios.length > 0;
const hasAttaches = hasImageAttaches || hasAudioAttaches;
return ( return (
<form onSubmit={onSubmit} className={styles.wrap}> <form onSubmit={onSubmit} className={styles.wrap}>
<div className={styles.input}> <div className={styles.input}>
@ -246,9 +250,9 @@ const CommentFormUnconnected: FC<IProps> = memo(
/> />
</div> </div>
{(!!images.length || !!audios.length) && ( {hasAttaches && (
<div className={styles.attaches}> <div className={styles.attaches}>
{!!images.length && ( {hasImageAttaches && (
<SortableImageGrid <SortableImageGrid
onDrop={onFileDrop} onDrop={onFileDrop}
onSortEnd={onImageMove} onSortEnd={onImageMove}
@ -261,7 +265,7 @@ const CommentFormUnconnected: FC<IProps> = memo(
/> />
)} )}
{(!!audios.length || !!locked_audios.length) && ( {hasAudioAttaches && (
<SortableAudioGrid <SortableAudioGrid
items={audios} items={audios}
onDrop={onFileDrop} onDrop={onFileDrop}

View file

@ -1,7 +1,6 @@
import React, { FC, ChangeEventHandler, KeyboardEventHandler, FocusEventHandler } from 'react'; import React, { ChangeEventHandler, FC, FocusEventHandler, KeyboardEventHandler } from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import { ITag } from '~/redux/types'; import { ITag } from '~/redux/types';
import classNames = require('classnames'); import classNames = require('classnames');
const getTagFeature = (tag: Partial<ITag>) => { const getTagFeature = (tag: Partial<ITag>) => {
@ -14,13 +13,21 @@ interface IProps {
tag: Partial<ITag>; tag: Partial<ITag>;
is_hoverable?: boolean; is_hoverable?: boolean;
is_editing?: boolean;
onInput?: ChangeEventHandler<HTMLInputElement>; onInput?: ChangeEventHandler<HTMLInputElement>;
onKeyUp?: KeyboardEventHandler; onKeyUp?: KeyboardEventHandler;
onBlur?: FocusEventHandler<HTMLInputElement>; onBlur?: FocusEventHandler<HTMLInputElement>;
} }
const Tag: FC<IProps> = ({ tag, is_hoverable, onInput, onKeyUp, onBlur }) => ( const Tag: FC<IProps> = ({ tag, is_hoverable, is_editing, onInput, onKeyUp, onBlur }) => (
<div className={classNames(styles.tag, getTagFeature(tag), { is_hoverable, input: !!onInput })}> <div
className={classNames(styles.tag, getTagFeature(tag), {
is_hoverable,
is_editing,
input: !!onInput,
})}
>
<div className={styles.hole} /> <div className={styles.hole} />
<div className={styles.title}>{tag.title}</div> <div className={styles.title}>{tag.title}</div>

View file

@ -11,7 +11,6 @@
font: $font_14_semibold; font: $font_14_semibold;
align-self: flex-start; align-self: flex-start;
padding: 0 8px 0 0; padding: 0 8px 0 0;
// box-shadow: $shadow_depth_2;
margin: 0 $gap $gap 0; margin: 0 $gap $gap 0;
position: relative; position: relative;
@ -19,6 +18,11 @@
cursor: pointer; cursor: pointer;
} }
&:global(.is_editing) {
cursor: pointer;
background-color: lighten($tag_bg, 10%);
}
&:global(.red) { &:global(.red) {
background: $red_gradient; background: $red_gradient;
} }

View file

@ -77,9 +77,15 @@ export const Tags: FC<IProps> = ({ tags, is_editable, onTagsChange, ...props })
const onSubmit = useCallback(() => { const onSubmit = useCallback(() => {
const title = input && input.trim(); const title = input && input.trim();
const items = title ? [...data, { title }] : data; const items = (title ? [...data, { title }] : data)
.filter(tag => tag.title.length > 0)
.map(tag => ({
...tag,
title: tag.title.toLowerCase(),
}));
if (!items.length) return; if (!items.length) return;
setData(items); setData(items);
setInput(''); setInput('');
onTagsChange(uniq([...tags, ...items]).map(tag => tag.title)); onTagsChange(uniq([...tags, ...items]).map(tag => tag.title));
@ -100,7 +106,7 @@ export const Tags: FC<IProps> = ({ tags, is_editable, onTagsChange, ...props })
))} ))}
{data.map(tag => ( {data.map(tag => (
<Tag key={tag.title} tag={tag} /> <Tag key={tag.title} tag={tag} is_editing />
))} ))}
{is_editable && ( {is_editable && (

View file

@ -240,7 +240,8 @@ function* onCancelCommentEdit({ id }: ReturnType<typeof nodeCancelCommentEdit>)
} }
function* onUpdateTags({ id, tags }: ReturnType<typeof nodeUpdateTags>) { function* onUpdateTags({ id, tags }: ReturnType<typeof nodeUpdateTags>) {
yield delay(1000); yield delay(100);
const { const {
data: { node }, data: { node },
}: IResultWithStatus<{ node: INode }> = yield call(reqWrapper, updateNodeTags, { id, tags }); }: IResultWithStatus<{ node: INode }> = yield call(reqWrapper, updateNodeTags, { id, tags });

View file

@ -1,49 +1,37 @@
import { import { takeEvery, all, spawn, call, put, take, fork, race } from 'redux-saga/effects';
takeEvery, import { postUploadFile } from './api';
all, import { UPLOAD_ACTIONS, FILE_MIMES } from '~/redux/uploads/constants';
spawn,
call,
put,
take,
fork,
race
} from "redux-saga/effects";
import { postUploadFile } from "./api";
import { UPLOAD_ACTIONS, FILE_MIMES } from "~/redux/uploads/constants";
import { import {
uploadUploadFiles, uploadUploadFiles,
uploadSetStatus, uploadSetStatus,
uploadAddStatus, uploadAddStatus,
uploadDropStatus, uploadDropStatus,
uploadAddFile uploadAddFile,
} from "./actions"; } from './actions';
import { reqWrapper } from "../auth/sagas"; import { reqWrapper } from '../auth/sagas';
import { createUploader, uploadGetThumb } from "~/utils/uploader"; import { createUploader, uploadGetThumb } from '~/utils/uploader';
import { HTTP_RESPONSES } from "~/utils/api"; import { HTTP_RESPONSES } from '~/utils/api';
import { IFileWithUUID, IFile, IUploadProgressHandler } from "../types"; import { IFileWithUUID, IFile, IUploadProgressHandler } from '../types';
function* uploadCall({ function* uploadCall({
file, file,
temp_id, temp_id,
target, target,
type, type,
onProgress onProgress,
}: IFileWithUUID & { onProgress: IUploadProgressHandler }) { }: IFileWithUUID & { onProgress: IUploadProgressHandler }) {
return yield call(reqWrapper, postUploadFile, { return yield call(reqWrapper, postUploadFile, {
file, file,
temp_id, temp_id,
type, type,
target, target,
onProgress onProgress,
}); });
} }
function* onUploadProgress(chan) { function* onUploadProgress(chan) {
while (true) { while (true) {
const { const { progress, temp_id }: { progress: number; temp_id: string } = yield take(chan);
progress,
temp_id
}: { progress: number; temp_id: string } = yield take(chan);
yield put(uploadSetStatus(temp_id, { progress })); yield put(uploadSetStatus(temp_id, { progress }));
} }
@ -59,10 +47,10 @@ function* uploadCancelWorker(id) {
} }
function* uploadWorker({ file, temp_id, target, type }: IFileWithUUID) { function* uploadWorker({ file, temp_id, target, type }: IFileWithUUID) {
const [promise, chan] = createUploader< const [promise, chan] = createUploader<Partial<IFileWithUUID>, Partial<IFileWithUUID>>(
Partial<IFileWithUUID>, uploadCall,
Partial<IFileWithUUID> { temp_id, target, type }
>(uploadCall, { temp_id, target, type }); );
yield fork(onUploadProgress, chan); yield fork(onUploadProgress, chan);
@ -70,23 +58,16 @@ function* uploadWorker({ file, temp_id, target, type }: IFileWithUUID) {
temp_id, temp_id,
file, file,
target, target,
type type,
}); });
} }
function* uploadFile({ function* uploadFile({ file, temp_id, type, target, onSuccess, onFail }: IFileWithUUID) {
file, if (!file.type || !FILE_MIMES[type] || !FILE_MIMES[type].includes(file.type)) {
temp_id,
type,
target,
onSuccess,
onFail
}: IFileWithUUID) {
if (!file.type || !file.type || !FILE_MIMES[type].includes(file.type)) {
return { return {
error: "File_Not_Image", error: 'File_Not_Image',
status: HTTP_RESPONSES.BAD_REQUEST, status: HTTP_RESPONSES.BAD_REQUEST,
data: {} data: {},
}; };
} }
@ -99,10 +80,9 @@ function* uploadFile({
{ {
preview, preview,
is_uploading: true, is_uploading: true,
// type: file.type,
temp_id, temp_id,
type, type,
name: file.name name: file.name,
} }
) )
); );
@ -112,13 +92,9 @@ function* uploadFile({
file, file,
temp_id, temp_id,
target, target,
type type,
}), }),
cancel: call(uploadCancelWorker, temp_id) cancel: call(uploadCancelWorker, temp_id),
// subject_cancel: call(uploadSubjectCancelWorker, subject)
// add here CANCEL_UPLOADS worker, that will watch for subject
// cancel_editing: take(UPLOAD_ACTIONS.CANCEL_EDITING),
// save_inventory: take(INVENTORY_ACTIONS.SAVE_INVENTORY),
}); });
if (cancel || cancel_editing) { if (cancel || cancel_editing) {
@ -126,10 +102,7 @@ function* uploadFile({
return yield put(uploadDropStatus(temp_id)); return yield put(uploadDropStatus(temp_id));
} }
const { const { data, error }: { data: IFile & { detail: string }; error: string } = result;
data,
error
}: { data: IFile & { detail: string }; error: string } = result;
if (error) { if (error) {
if (onFail) onFail(); if (onFail) onFail();
@ -138,7 +111,7 @@ function* uploadFile({
uploadSetStatus(temp_id, { uploadSetStatus(temp_id, {
is_uploading: false, is_uploading: false,
error: data.detail || error, error: data.detail || error,
type type,
}) })
); );
} }
@ -152,7 +125,7 @@ function* uploadFile({
type, type,
thumbnail_url: data.full_path, thumbnail_url: data.full_path,
progress: 1, progress: 1,
name: file.name name: file.name,
}) })
); );