Compare commits
5 Commits
6b8c922d5b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d2f25ef04 | |||
| 9462a74437 | |||
| 1683c0d467 | |||
| 615292ac24 | |||
| 6bcb41820c |
55
src/Cache.ts
Normal file
55
src/Cache.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { InMemoryCache } from "@apollo/client"
|
||||||
|
import ObjID from "./types/ObjID"
|
||||||
|
|
||||||
|
const cache = new InMemoryCache({
|
||||||
|
typePolicies:{
|
||||||
|
File:{
|
||||||
|
fields:{
|
||||||
|
id:{
|
||||||
|
merge(_,incomming){
|
||||||
|
// HACK: i use the merge function to change the id from a string to ObjID object.
|
||||||
|
// afaik apollo does not yet support custom scalar types.
|
||||||
|
if (!incomming){
|
||||||
|
return incomming
|
||||||
|
}else if (incomming instanceof ObjID){
|
||||||
|
return incomming
|
||||||
|
}else{
|
||||||
|
return ObjID.fromString(incomming as string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Directory:{
|
||||||
|
fields:{
|
||||||
|
id:{
|
||||||
|
merge(_,incomming){
|
||||||
|
if (!incomming){
|
||||||
|
return incomming
|
||||||
|
}else if (incomming instanceof ObjID){
|
||||||
|
return incomming
|
||||||
|
}else{
|
||||||
|
return ObjID.fromString(incomming as string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Query: {
|
||||||
|
fields: {
|
||||||
|
files: {
|
||||||
|
merge(existing, incoming){
|
||||||
|
return incoming
|
||||||
|
}
|
||||||
|
},
|
||||||
|
directorys:{
|
||||||
|
merge(existing, incoming){
|
||||||
|
return incoming
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default cache
|
||||||
@@ -5,7 +5,7 @@ import { RouteComponentProps } from "react-router-dom"
|
|||||||
import downloadFile from "../functions/downloadFile"
|
import downloadFile from "../functions/downloadFile"
|
||||||
import genDownloadLink from "../functions/genDownloadLink"
|
import genDownloadLink from "../functions/genDownloadLink"
|
||||||
import uploadFile from "../functions/uploadFile"
|
import uploadFile from "../functions/uploadFile"
|
||||||
import { useCopyMutation, useCreateDirMutation, useDeleteDirMutation, useDeleteFileMutation, useMoveMutation, useOpenDirQuery } from "../generated/graphql"
|
import { useCopyMutation, useCreateDirMutation, useDeleteDirMutation, useDeleteFileMutation, useMoveDirMutation, useMoveMutation, useOpenDirQuery } from "../generated/graphql"
|
||||||
import Breadcrum from "./Breadcrum"
|
import Breadcrum from "./Breadcrum"
|
||||||
import CreateDirButton from "./CreateDirButton"
|
import CreateDirButton from "./CreateDirButton"
|
||||||
import GlobalDragAndDrop from "./GlobalDragAndDrop"
|
import GlobalDragAndDrop from "./GlobalDragAndDrop"
|
||||||
@@ -16,6 +16,7 @@ import { ReactComponent as Spinner } from "./../assets/spinner.svg"
|
|||||||
import FileBrowserList from "./FileBrowserList"
|
import FileBrowserList from "./FileBrowserList"
|
||||||
import MoreMenu from "./MoreMenu"
|
import MoreMenu from "./MoreMenu"
|
||||||
import ObjID from "../types/ObjID"
|
import ObjID from "../types/ObjID"
|
||||||
|
import cache from "../Cache"
|
||||||
|
|
||||||
const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
||||||
const path = ObjID.fromURI(props.location.pathname)
|
const path = ObjID.fromURI(props.location.pathname)
|
||||||
@@ -32,6 +33,7 @@ const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
|||||||
const [moveMutation] = useMoveMutation()
|
const [moveMutation] = useMoveMutation()
|
||||||
const [createDirMutation] = useCreateDirMutation()
|
const [createDirMutation] = useCreateDirMutation()
|
||||||
const [deleteDirMutation] = useDeleteDirMutation()
|
const [deleteDirMutation] = useDeleteDirMutation()
|
||||||
|
const [moveDirMutation] = useMoveDirMutation()
|
||||||
|
|
||||||
const { show: showFileContext } = useContextMenu({
|
const { show: showFileContext } = useContextMenu({
|
||||||
id: CONTEXT_MENU_FILE,
|
id: CONTEXT_MENU_FILE,
|
||||||
@@ -66,6 +68,7 @@ const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
|||||||
break
|
break
|
||||||
case Action.FileCopy:
|
case Action.FileCopy:
|
||||||
case Action.FileMove:
|
case Action.FileMove:
|
||||||
|
case Action.DirMove:
|
||||||
setSrcID(id)
|
setSrcID(id)
|
||||||
setPasteAction(action)
|
setPasteAction(action)
|
||||||
break
|
break
|
||||||
@@ -80,6 +83,18 @@ const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
|||||||
refetchDir()
|
refetchDir()
|
||||||
setSrcID(null)
|
setSrcID(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pasteAction === Action.DirMove && srcID){
|
||||||
|
await moveDirMutation({variables:{src:srcID,dest:path}})
|
||||||
|
refetchDir()
|
||||||
|
|
||||||
|
cache.evict({
|
||||||
|
id: `Directory:${srcID.toString()}` // TODO: check for a better way to generate cache ids
|
||||||
|
})
|
||||||
|
|
||||||
|
setSrcID(null)
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
case Action.DirDelete:
|
case Action.DirDelete:
|
||||||
await deleteDirMutation({variables:{path:id}})
|
await deleteDirMutation({variables:{path:id}})
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ export enum Action {
|
|||||||
FileMove,
|
FileMove,
|
||||||
FileDownload,
|
FileDownload,
|
||||||
FileRename,
|
FileRename,
|
||||||
DirDelete
|
DirDelete,
|
||||||
|
DirMove,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -40,7 +41,7 @@ const FileBrowserContextMenu: React.FC<Props> = (props) => {
|
|||||||
</Menu>
|
</Menu>
|
||||||
<Menu id={CONTEXT_MENU_DIR} animation={false} className="dark:bg-gray-400">
|
<Menu id={CONTEXT_MENU_DIR} animation={false} className="dark:bg-gray-400">
|
||||||
<Item onClick={onClick} data={Action.DirDelete} >Delete</Item>
|
<Item onClick={onClick} data={Action.DirDelete} >Delete</Item>
|
||||||
<Item onClick={onClick} >Item 2</Item>
|
<Item onClick={onClick} data={Action.DirMove} >Move</Item>
|
||||||
<Separator />
|
<Separator />
|
||||||
<Item onClick={onClick} data={Action.FilePaste} disabled={!props.pasteActive}>Paste</Item>
|
<Item onClick={onClick} data={Action.FilePaste} disabled={!props.pasteActive}>Paste</Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ export type RootMutation = {
|
|||||||
delete?: Maybe<Scalars["String"]>;
|
delete?: Maybe<Scalars["String"]>;
|
||||||
deleteDir: Scalars["String"];
|
deleteDir: Scalars["String"];
|
||||||
login: LoginResut;
|
login: LoginResut;
|
||||||
move?: Maybe<File>;
|
move: File;
|
||||||
|
moveDir: Array<Maybe<File>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -98,6 +99,12 @@ export type RootMutationMoveArgs = {
|
|||||||
dest: Scalars["objID"];
|
dest: Scalars["objID"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type RootMutationMoveDirArgs = {
|
||||||
|
src: Scalars["objID"];
|
||||||
|
dest: Scalars["objID"];
|
||||||
|
};
|
||||||
|
|
||||||
export type RootQuery = {
|
export type RootQuery = {
|
||||||
__typename?: "RootQuery";
|
__typename?: "RootQuery";
|
||||||
/** True if the user is authorized */
|
/** True if the user is authorized */
|
||||||
@@ -223,10 +230,24 @@ export type MoveMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type MoveMutation = (
|
export type MoveMutation = (
|
||||||
{ __typename?: "RootMutation" }
|
{ __typename?: "RootMutation" }
|
||||||
& { move?: Maybe<(
|
& { move: (
|
||||||
{ __typename?: "File" }
|
{ __typename?: "File" }
|
||||||
& Pick<File, "id">
|
& Pick<File, "id">
|
||||||
)> }
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
|
export type MoveDirMutationVariables = Exact<{
|
||||||
|
src: Scalars["objID"];
|
||||||
|
dest: Scalars["objID"];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type MoveDirMutation = (
|
||||||
|
{ __typename?: "RootMutation" }
|
||||||
|
& { moveDir: Array<Maybe<(
|
||||||
|
{ __typename?: "File" }
|
||||||
|
& Pick<File, "id">
|
||||||
|
)>> }
|
||||||
);
|
);
|
||||||
|
|
||||||
export type OpenDirQueryVariables = Exact<{
|
export type OpenDirQueryVariables = Exact<{
|
||||||
@@ -547,6 +568,40 @@ export function useMoveMutation(baseOptions?: Apollo.MutationHookOptions<MoveMut
|
|||||||
export type MoveMutationHookResult = ReturnType<typeof useMoveMutation>;
|
export type MoveMutationHookResult = ReturnType<typeof useMoveMutation>;
|
||||||
export type MoveMutationResult = Apollo.MutationResult<MoveMutation>;
|
export type MoveMutationResult = Apollo.MutationResult<MoveMutation>;
|
||||||
export type MoveMutationOptions = Apollo.BaseMutationOptions<MoveMutation, MoveMutationVariables>;
|
export type MoveMutationOptions = Apollo.BaseMutationOptions<MoveMutation, MoveMutationVariables>;
|
||||||
|
export const MoveDirDocument = gql`
|
||||||
|
mutation moveDir($src: objID!, $dest: objID!) {
|
||||||
|
moveDir(src: $src, dest: $dest) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
export type MoveDirMutationFn = Apollo.MutationFunction<MoveDirMutation, MoveDirMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useMoveDirMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useMoveDirMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useMoveDirMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [moveDirMutation, { data, loading, error }] = useMoveDirMutation({
|
||||||
|
* variables: {
|
||||||
|
* src: // value for 'src'
|
||||||
|
* dest: // value for 'dest'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useMoveDirMutation(baseOptions?: Apollo.MutationHookOptions<MoveDirMutation, MoveDirMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<MoveDirMutation, MoveDirMutationVariables>(MoveDirDocument, options)
|
||||||
|
}
|
||||||
|
export type MoveDirMutationHookResult = ReturnType<typeof useMoveDirMutation>;
|
||||||
|
export type MoveDirMutationResult = Apollo.MutationResult<MoveDirMutation>;
|
||||||
|
export type MoveDirMutationOptions = Apollo.BaseMutationOptions<MoveDirMutation, MoveDirMutationVariables>;
|
||||||
export const OpenDirDocument = gql`
|
export const OpenDirDocument = gql`
|
||||||
query openDir($path: objID!) {
|
query openDir($path: objID!) {
|
||||||
files(path: $path) {
|
files(path: $path) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
5
src/graphql/moveDir.graphql
Normal file
5
src/graphql/moveDir.graphql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
mutation moveDir($src: objID!, $dest: objID!) {
|
||||||
|
moveDir(src: $src,dest: $dest){
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,62 +2,13 @@ import React from "react"
|
|||||||
import ReactDOM from "react-dom"
|
import ReactDOM from "react-dom"
|
||||||
import "./index.scss"
|
import "./index.scss"
|
||||||
import App from "./App"
|
import App from "./App"
|
||||||
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client"
|
import { ApolloClient, ApolloProvider } from "@apollo/client"
|
||||||
import "react-contexify/dist/ReactContexify.css"
|
import "react-contexify/dist/ReactContexify.css"
|
||||||
import ObjID from "./types/ObjID"
|
import cache from "./Cache"
|
||||||
|
|
||||||
const client = new ApolloClient({
|
const client = new ApolloClient({
|
||||||
uri: "/api/graphql",
|
uri: "/api/graphql",
|
||||||
cache: new InMemoryCache({
|
cache: cache,
|
||||||
typePolicies:{
|
|
||||||
File:{
|
|
||||||
fields:{
|
|
||||||
id:{
|
|
||||||
merge(_,incomming){
|
|
||||||
// HACK: i use the merge function to change the id from a string to ObjID object.
|
|
||||||
// afaik apollo does not yet support custom scalar types.
|
|
||||||
if (!incomming){
|
|
||||||
return incomming
|
|
||||||
}else if (incomming instanceof ObjID){
|
|
||||||
return incomming
|
|
||||||
}else{
|
|
||||||
return ObjID.fromString(incomming as string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Directory:{
|
|
||||||
fields:{
|
|
||||||
id:{
|
|
||||||
merge(_,incomming){
|
|
||||||
if (!incomming){
|
|
||||||
return incomming
|
|
||||||
}else if (incomming instanceof ObjID){
|
|
||||||
return incomming
|
|
||||||
}else{
|
|
||||||
return ObjID.fromString(incomming as string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Query: {
|
|
||||||
fields: {
|
|
||||||
files: {
|
|
||||||
merge(existing, incoming){
|
|
||||||
return incoming
|
|
||||||
}
|
|
||||||
},
|
|
||||||
directorys:{
|
|
||||||
merge(existing, incoming){
|
|
||||||
return incoming
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Disable drag and drop behaviour on document
|
// Disable drag and drop behaviour on document
|
||||||
|
|||||||
@@ -53,6 +53,30 @@ class ObjID {
|
|||||||
return new ObjID(this.bucket,parts.join("/"))
|
return new ObjID(this.bucket,parts.join("/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the parent of the object. If Obj is a file then the containing directory
|
||||||
|
* if Obj is a directory it returns the parent
|
||||||
|
* @returns parent ObjID or null if already at root
|
||||||
|
*/
|
||||||
|
public parent(): ObjID | null {
|
||||||
|
if (this.key == "/") {
|
||||||
|
// Already at root. We dont have a parent
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isDirectory()) {
|
||||||
|
const parts = this.key.split("/")
|
||||||
|
const parent = new ObjID(this.bucket, parts.slice(0,-2).join("/") + "/")
|
||||||
|
parent.normalize()
|
||||||
|
return parent
|
||||||
|
} else {
|
||||||
|
const parts = this.key.split("/")
|
||||||
|
const parent = new ObjID(this.bucket, parts.slice(0,-1).join("/") + "/")
|
||||||
|
parent.normalize()
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static fromString(from: string): ObjID{
|
public static fromString(from: string): ObjID{
|
||||||
const match = stringRegex.exec(from)
|
const match = stringRegex.exec(from)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user