mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 04:46:40 +07:00
Merge branch 'master' into 15-use-cra-or-nextjs
# Conflicts: # src/components/node/CommentForm/index.tsx # src/utils/node.ts
This commit is contained in:
commit
332d09e3bd
46 changed files with 936 additions and 487 deletions
|
@ -1,36 +0,0 @@
|
|||
import {
|
||||
useCallback, useEffect, useRef, useState
|
||||
} from 'react';
|
||||
|
||||
export const useCloseOnEscape = (onRequestClose: () => void, ignore_inputs = false) => {
|
||||
const onEscape = useCallback(
|
||||
(event) => {
|
||||
if (event.key !== 'Escape') return;
|
||||
if (
|
||||
ignore_inputs
|
||||
&& (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA')
|
||||
) return;
|
||||
|
||||
onRequestClose();
|
||||
},
|
||||
[ignore_inputs, onRequestClose],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keyup', onEscape);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('keyup', onEscape);
|
||||
};
|
||||
}, [onEscape]);
|
||||
};
|
||||
|
||||
export const useDelayedReady = (setReady: (val: boolean) => void, delay: number = 500) => {
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setReady(true), delay);
|
||||
|
||||
return () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
};
|
||||
}, [delay, setReady]);
|
||||
};
|
56
src/utils/hooks/index.ts
Normal file
56
src/utils/hooks/index.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
export const useCloseOnEscape = (onRequestClose: () => void, ignore_inputs = false) => {
|
||||
const onEscape = useCallback(
|
||||
event => {
|
||||
if (event.key !== 'Escape') return;
|
||||
if (
|
||||
ignore_inputs &&
|
||||
(event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA')
|
||||
)
|
||||
return;
|
||||
|
||||
onRequestClose();
|
||||
},
|
||||
[ignore_inputs, onRequestClose]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keyup', onEscape);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('keyup', onEscape);
|
||||
};
|
||||
}, [onEscape]);
|
||||
};
|
||||
|
||||
export const useDelayedReady = (setReady: (val: boolean) => void, delay: number = 500) => {
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setReady(true), delay);
|
||||
|
||||
return () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
};
|
||||
}, [delay, setReady]);
|
||||
};
|
||||
|
||||
/**
|
||||
* useDropZone returns onDrop handler to upload files
|
||||
* @param onUpload -- upload callback
|
||||
* @param allowedTypes -- list of allowed types
|
||||
*/
|
||||
export const useDropZone = (onUpload: (file: File[]) => void, allowedTypes?: string[]) => {
|
||||
return useCallback(
|
||||
event => {
|
||||
event.preventDefault();
|
||||
const files: File[] = Array.from((event.dataTransfer?.files as File[]) || []).filter(
|
||||
(file: File) => file?.type && (!allowedTypes || allowedTypes.includes(file.type))
|
||||
);
|
||||
|
||||
if (!files || !files.length) return;
|
||||
|
||||
onUpload(files);
|
||||
},
|
||||
[onUpload]
|
||||
);
|
||||
};
|
23
src/utils/hooks/keys.ts
Normal file
23
src/utils/hooks/keys.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
export const useArrows = (onNext: () => void, onPrev: () => void, locked) => {
|
||||
const onKeyDown = useCallback(
|
||||
event => {
|
||||
if ((event.target.tagName && ['TEXTAREA', 'INPUT'].includes(event.target.tagName)) || locked)
|
||||
return;
|
||||
|
||||
switch (event.key) {
|
||||
case 'ArrowLeft':
|
||||
return onPrev();
|
||||
case 'ArrowRight':
|
||||
return onNext();
|
||||
}
|
||||
},
|
||||
[onNext, onPrev, locked]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
return () => window.removeEventListener('keydown', onKeyDown);
|
||||
}, [onKeyDown]);
|
||||
};
|
|
@ -1,8 +1,10 @@
|
|||
import { USER_ROLES } from '~/redux/auth/constants';
|
||||
import { ICommentGroup, INode } from '~/redux/types';
|
||||
import { ICommentGroup, IFile, INode } from '~/redux/types';
|
||||
import { IUser } from '~/redux/auth/types';
|
||||
import { path } from 'ramda';
|
||||
import { NODE_TYPES } from '~/redux/node/constants';
|
||||
import { useMemo } from 'react';
|
||||
import { UPLOAD_TYPES } from '~/redux/uploads/constants';
|
||||
|
||||
export const canEditNode = (node: Partial<INode>, user: Partial<IUser>): boolean =>
|
||||
path(['role'], user) === USER_ROLES.ADMIN ||
|
||||
|
@ -19,3 +21,11 @@ export const canStarNode = (node: Partial<INode>, user: Partial<IUser>): boolean
|
|||
node.type === NODE_TYPES.IMAGE &&
|
||||
path(['role'], user) &&
|
||||
path(['role'], user) === USER_ROLES.ADMIN;
|
||||
|
||||
export const useNodeImages = (node: INode): IFile[] => {
|
||||
return useMemo(
|
||||
() =>
|
||||
(node && node.files && node.files.filter(({ type }) => type === UPLOAD_TYPES.IMAGE)) || [],
|
||||
[node.files]
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue