File manager cleanup for mobile devices
This commit is contained in:
parent
6ec2ae9df8
commit
47283700a8
|
@ -155,7 +155,6 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
||||||
</div>
|
</div>
|
||||||
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {disklimit}</p>
|
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {disklimit}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div css={tw`flex-1 flex justify-end sm:hidden`}>
|
<div css={tw`flex-1 flex justify-end sm:hidden`}>
|
||||||
<div css={tw`flex items-end text-right`}>
|
<div css={tw`flex items-end text-right`}>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -19,11 +19,11 @@ const ConfirmationModal = ({ title, children, buttonText, onConfirmed }: Props)
|
||||||
<>
|
<>
|
||||||
<h2 css={tw`text-2xl mb-6`}>{title}</h2>
|
<h2 css={tw`text-2xl mb-6`}>{title}</h2>
|
||||||
<p css={tw`text-sm`}>{children}</p>
|
<p css={tw`text-sm`}>{children}</p>
|
||||||
<div css={tw`flex items-center justify-end mt-8`}>
|
<div css={tw`flex flex-wrap items-center justify-end mt-8`}>
|
||||||
<Button isSecondary onClick={() => dismiss()}>
|
<Button isSecondary onClick={() => dismiss()} css={tw`w-full sm:w-auto`}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button color={'red'} css={tw`ml-4`} onClick={() => onConfirmed()}>
|
<Button color={'red'} css={tw`w-full sm:w-auto mt-4 sm:mt-0 sm:ml-4`} onClick={() => onConfirmed()}>
|
||||||
{buttonText}
|
{buttonText}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
import { faTimes } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import Spinner from '@/components/elements/Spinner';
|
import Spinner from '@/components/elements/Spinner';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
import styled from 'styled-components/macro';
|
import styled, { css } from 'styled-components/macro';
|
||||||
import { breakpoint } from '@/theme';
|
import { breakpoint } from '@/theme';
|
||||||
import Fade from '@/components/elements/Fade';
|
import Fade from '@/components/elements/Fade';
|
||||||
|
|
||||||
|
@ -27,24 +25,26 @@ export const ModalMask = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ModalContainer = styled.div<{ alignTop?: boolean }>`
|
const ModalContainer = styled.div<{ alignTop?: boolean }>`
|
||||||
${breakpoint('xs')`
|
|
||||||
max-width: 95%;
|
max-width: 95%;
|
||||||
`};
|
max-height: calc(100vh - 8rem);
|
||||||
|
${breakpoint('md')`max-width: 75%`};
|
||||||
${breakpoint('md')`
|
${breakpoint('lg')`max-width: 50%`};
|
||||||
max-width: 50%;
|
|
||||||
`};
|
|
||||||
|
|
||||||
${tw`relative flex flex-col w-full m-auto`};
|
${tw`relative flex flex-col w-full m-auto`};
|
||||||
max-height: calc(100vh - 8rem);
|
${props => props.alignTop && css`
|
||||||
// @todo max-w-screen-lg perhaps?
|
margin-top: 20%;
|
||||||
${props => props.alignTop && 'margin-top: 10%'};
|
${breakpoint('md')`margin-top: 10%`};
|
||||||
|
`};
|
||||||
|
|
||||||
& > .close-icon {
|
& > .close-icon {
|
||||||
${tw`absolute right-0 p-2 text-white cursor-pointer opacity-50 transition-all duration-150 ease-linear hover:opacity-100`};
|
${tw`absolute right-0 p-2 text-white cursor-pointer opacity-50 transition-all duration-150 ease-linear hover:opacity-100`};
|
||||||
top: -2rem;
|
top: -2.5rem;
|
||||||
|
|
||||||
&:hover {${tw`transform rotate-90`}}
|
&:hover {${tw`transform rotate-90`}}
|
||||||
|
|
||||||
|
& > svg {
|
||||||
|
${tw`w-6 h-6`};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ const Modal: React.FC<ModalProps> = ({ visible, appear, dismissable, showSpinner
|
||||||
>
|
>
|
||||||
<ModalMask
|
<ModalMask
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
|
onContextMenu={e => e.stopPropagation()}
|
||||||
onMouseDown={e => {
|
onMouseDown={e => {
|
||||||
if (isDismissable && closeOnBackground) {
|
if (isDismissable && closeOnBackground) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -92,7 +93,14 @@ const Modal: React.FC<ModalProps> = ({ visible, appear, dismissable, showSpinner
|
||||||
<ModalContainer alignTop={top}>
|
<ModalContainer alignTop={top}>
|
||||||
{isDismissable &&
|
{isDismissable &&
|
||||||
<div className={'close-icon'} onClick={() => setRender(false)}>
|
<div className={'close-icon'} onClick={() => setRender(false)}>
|
||||||
<FontAwesomeIcon icon={faTimes}/>
|
<svg xmlns={'http://www.w3.org/2000/svg'} fill={'none'} viewBox={'0 0 24 24'} stroke={'currentColor'}>
|
||||||
|
<path
|
||||||
|
strokeLinecap={'round'}
|
||||||
|
strokeLinejoin={'round'}
|
||||||
|
strokeWidth={'2'}
|
||||||
|
d={'M6 18L18 6M6 6l12 12'}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{showSpinnerOverlay &&
|
{showSpinnerOverlay &&
|
||||||
|
|
|
@ -120,7 +120,7 @@ export default () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div css={tw`flex justify-end mt-4`}>
|
<div css={tw`flex justify-end mt-4`}>
|
||||||
<div css={tw`rounded bg-neutral-900 mr-4`}>
|
<div css={tw`flex-1 sm:flex-none rounded bg-neutral-900 mr-4`}>
|
||||||
<Select value={mode} onChange={e => setMode(e.currentTarget.value)}>
|
<Select value={mode} onChange={e => setMode(e.currentTarget.value)}>
|
||||||
{Object.keys(modes).map(key => (
|
{Object.keys(modes).map(key => (
|
||||||
<option key={key} value={key}>{modes[key]}</option>
|
<option key={key} value={key}>{modes[key]}</option>
|
||||||
|
@ -129,13 +129,13 @@ export default () => {
|
||||||
</div>
|
</div>
|
||||||
{action === 'edit' ?
|
{action === 'edit' ?
|
||||||
<Can action={'file.update'}>
|
<Can action={'file.update'}>
|
||||||
<Button onClick={() => save()}>
|
<Button css={tw`flex-1 sm:flex-none`} onClick={() => save()}>
|
||||||
Save Content
|
Save Content
|
||||||
</Button>
|
</Button>
|
||||||
</Can>
|
</Can>
|
||||||
:
|
:
|
||||||
<Can action={'file.create'}>
|
<Can action={'file.create'}>
|
||||||
<Button onClick={() => setModalVisible(true)}>
|
<Button css={tw`flex-1 sm:flex-none`} onClick={() => setModalVisible(true)}>
|
||||||
Create File
|
Create File
|
||||||
</Button>
|
</Button>
|
||||||
</Can>
|
</Can>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import FileObjectRow from '@/components/server/files/FileObjectRow';
|
||||||
import FileManagerBreadcrumbs from '@/components/server/files/FileManagerBreadcrumbs';
|
import FileManagerBreadcrumbs from '@/components/server/files/FileManagerBreadcrumbs';
|
||||||
import { FileObject } from '@/api/server/files/loadDirectory';
|
import { FileObject } from '@/api/server/files/loadDirectory';
|
||||||
import NewDirectoryButton from '@/components/server/files/NewDirectoryButton';
|
import NewDirectoryButton from '@/components/server/files/NewDirectoryButton';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { NavLink, useLocation } from 'react-router-dom';
|
||||||
import Can from '@/components/elements/Can';
|
import Can from '@/components/elements/Can';
|
||||||
import ServerError from '@/components/screens/ServerError';
|
import ServerError from '@/components/screens/ServerError';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
|
@ -81,16 +81,17 @@ export default () => {
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
}
|
}
|
||||||
<Can action={'file.create'}>
|
<Can action={'file.create'}>
|
||||||
<div css={tw`flex justify-end mt-8`}>
|
<div css={tw`flex flex-wrap-reverse justify-end mt-4`}>
|
||||||
<NewDirectoryButton/>
|
<NewDirectoryButton css={tw`w-full flex-none mt-4 sm:mt-0 sm:w-auto sm:mr-4`}/>
|
||||||
<UploadButton/>
|
<UploadButton css={tw`flex-1 mr-4 sm:flex-none sm:mt-0`}/>
|
||||||
<Button
|
<NavLink
|
||||||
// @ts-ignore
|
|
||||||
as={Link}
|
|
||||||
to={`/server/${id}/files/new${window.location.hash}`}
|
to={`/server/${id}/files/new${window.location.hash}`}
|
||||||
|
css={tw`flex-1 sm:flex-none sm:mt-0`}
|
||||||
>
|
>
|
||||||
|
<Button css={tw`w-full`}>
|
||||||
New File
|
New File
|
||||||
</Button>
|
</Button>
|
||||||
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
</Can>
|
</Can>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Button from '@/components/elements/Button';
|
||||||
import { FileObject } from '@/api/server/files/loadDirectory';
|
import { FileObject } from '@/api/server/files/loadDirectory';
|
||||||
import useFlash from '@/plugins/useFlash';
|
import useFlash from '@/plugins/useFlash';
|
||||||
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
|
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
|
||||||
|
import { WithClassname } from '@/components/types';
|
||||||
|
|
||||||
interface Values {
|
interface Values {
|
||||||
directoryName: string;
|
directoryName: string;
|
||||||
|
@ -34,7 +35,7 @@ const generateDirectoryData = (name: string): FileObject => ({
|
||||||
isEditable: () => false,
|
isEditable: () => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default () => {
|
export default ({ className }: WithClassname) => {
|
||||||
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
||||||
const { clearAndAddHttpError } = useFlash();
|
const { clearAndAddHttpError } = useFlash();
|
||||||
const [ visible, setVisible ] = useState(false);
|
const [ visible, setVisible ] = useState(false);
|
||||||
|
@ -95,7 +96,7 @@ export default () => {
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
</Formik>
|
</Formik>
|
||||||
<Button isSecondary css={tw`mr-2`} onClick={() => setVisible(true)}>
|
<Button isSecondary onClick={() => setVisible(true)} className={className}>
|
||||||
Create Directory
|
Create Directory
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -62,11 +62,11 @@ const RenameFileModal = ({ files, useMoveTerminology, ...props }: OwnProps) => {
|
||||||
<Form css={tw`m-0`}>
|
<Form css={tw`m-0`}>
|
||||||
<div
|
<div
|
||||||
css={[
|
css={[
|
||||||
tw`flex`,
|
tw`flex flex-wrap`,
|
||||||
useMoveTerminology ? tw`items-center` : tw`items-end`,
|
useMoveTerminology ? tw`items-center` : tw`items-end`,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<div css={tw`flex-1 mr-6`}>
|
<div css={tw`w-full sm:flex-1 sm:mr-4`}>
|
||||||
<Field
|
<Field
|
||||||
type={'string'}
|
type={'string'}
|
||||||
id={'file_name'}
|
id={'file_name'}
|
||||||
|
@ -79,8 +79,8 @@ const RenameFileModal = ({ files, useMoveTerminology, ...props }: OwnProps) => {
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div css={tw`w-full sm:w-auto mt-4 sm:mt-0`}>
|
||||||
<Button>{useMoveTerminology ? 'Move' : 'Rename'}</Button>
|
<Button css={tw`w-full`}>{useMoveTerminology ? 'Move' : 'Rename'}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{useMoveTerminology &&
|
{useMoveTerminology &&
|
||||||
|
|
|
@ -11,13 +11,14 @@ import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
||||||
import useFlash from '@/plugins/useFlash';
|
import useFlash from '@/plugins/useFlash';
|
||||||
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
|
import useFileManagerSwr from '@/plugins/useFileManagerSwr';
|
||||||
import { ServerContext } from '@/state/server';
|
import { ServerContext } from '@/state/server';
|
||||||
|
import { WithClassname } from '@/components/types';
|
||||||
|
|
||||||
const InnerContainer = styled.div`
|
const InnerContainer = styled.div`
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
${tw`bg-black w-full border-4 border-primary-500 border-dashed rounded p-10 mx-10`}
|
${tw`bg-black w-full border-4 border-primary-500 border-dashed rounded p-10 mx-10`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default () => {
|
export default ({ className }: WithClassname) => {
|
||||||
const fileUploadInput = useRef<HTMLInputElement>(null);
|
const fileUploadInput = useRef<HTMLInputElement>(null);
|
||||||
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
||||||
const [ visible, setVisible ] = useState(false);
|
const [ visible, setVisible ] = useState(false);
|
||||||
|
@ -114,7 +115,7 @@ export default () => {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
css={tw`mr-2`}
|
className={className}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
fileUploadInput.current
|
fileUploadInput.current
|
||||||
? fileUploadInput.current.click()
|
? fileUploadInput.current.click()
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface WithClassname {
|
||||||
|
className?: string;
|
||||||
|
}
|
Loading…
Reference in New Issue