the big refactor 2: ObjID
This commit is contained in:
parent
dc4133a705
commit
3e8fbb01bb
@ -10,7 +10,10 @@ generates:
|
|||||||
- "typescript"
|
- "typescript"
|
||||||
- "typescript-operations"
|
- "typescript-operations"
|
||||||
- "typescript-react-apollo"
|
- "typescript-react-apollo"
|
||||||
|
- add:
|
||||||
|
content: "import ObjID from './../types/ObjID'"
|
||||||
config:
|
config:
|
||||||
withHooks: true
|
withHooks: true
|
||||||
scalars:
|
scalars:
|
||||||
DateTime: string
|
DateTime: string
|
||||||
|
objID: ObjID
|
@ -41,6 +41,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@craco/craco": "^6.2.0",
|
"@craco/craco": "^6.2.0",
|
||||||
|
"@graphql-codegen/add": "^3.1.0",
|
||||||
"@graphql-codegen/cli": "1.21.7",
|
"@graphql-codegen/cli": "1.21.7",
|
||||||
"@graphql-codegen/introspection": "1.18.2",
|
"@graphql-codegen/introspection": "1.18.2",
|
||||||
"@graphql-codegen/typescript": "^1.23.0",
|
"@graphql-codegen/typescript": "^1.23.0",
|
||||||
|
@ -1,25 +1,36 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
|
import ObjID from "../types/ObjID"
|
||||||
import { ReactComponent as BreadcrumImage } from "./../assets/breadcrum.svg"
|
import { ReactComponent as BreadcrumImage } from "./../assets/breadcrum.svg"
|
||||||
|
|
||||||
interface Props{
|
interface Props{
|
||||||
path: string
|
path: ObjID
|
||||||
onDirClick?: (path: string) => void
|
onDirClick?: (path: ObjID) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Breadcrum: React.FC<Props> = (props) => {
|
const Breadcrum: React.FC<Props> = (props) => {
|
||||||
const parts = props.path.split("/").filter(e=>e.length > 0)
|
const keyParts = props.path.key.split("/").filter(e=>e.length > 0)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className="flex text-gray-500 dark:text-gray-400 text-lg">
|
<ul className="flex text-gray-500 dark:text-gray-400 text-lg ">
|
||||||
<li className="inline-flex items-center cursor-pointer">
|
<div className="inline-flex items-center cursor-pointer">
|
||||||
<a onClick={()=>{
|
<li>
|
||||||
props.onDirClick?.("/")
|
<a>
|
||||||
}}>
|
{props.path.bucket}
|
||||||
Root
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</div>
|
||||||
|
<div className="inline-flex items-center cursor-pointer">
|
||||||
|
<BreadcrumImage className="h-5 w-auto text-gray-400" />
|
||||||
|
<li>
|
||||||
|
<a onClick={()=>{
|
||||||
|
props.onDirClick?.(new ObjID(props.path.bucket,"/"))
|
||||||
|
}}>
|
||||||
|
root
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
|
||||||
{parts.map((e,i,arr)=>{
|
{keyParts.map((e,i,arr)=>{
|
||||||
const last = i == arr.length - 1
|
const last = i == arr.length - 1
|
||||||
return <div key={e} className="inline-flex items-center cursor-pointer">
|
return <div key={e} className="inline-flex items-center cursor-pointer">
|
||||||
<BreadcrumImage className="h-5 w-auto text-gray-400" />
|
<BreadcrumImage className="h-5 w-auto text-gray-400" />
|
||||||
@ -28,7 +39,7 @@ const Breadcrum: React.FC<Props> = (props) => {
|
|||||||
className={`${last?"text-blue-500":""}`}
|
className={`${last?"text-blue-500":""}`}
|
||||||
onClick={()=>{
|
onClick={()=>{
|
||||||
if (!last){
|
if (!last){
|
||||||
props.onDirClick?.("/"+arr.slice(0,i-1).join("/"))
|
props.onDirClick?.(new ObjID(props.path.bucket,"/"+arr.slice(0,i-1).join("/")))
|
||||||
}
|
}
|
||||||
}}>{e}</a>
|
}}>{e}</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -4,7 +4,6 @@ import { useContextMenu } from "react-contexify"
|
|||||||
import { RouteComponentProps } from "react-router-dom"
|
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 normalizeDirPath from "../functions/normalizeDirPath"
|
|
||||||
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, useMoveMutation, useOpenDirQuery } from "../generated/graphql"
|
||||||
import Breadcrum from "./Breadcrum"
|
import Breadcrum from "./Breadcrum"
|
||||||
@ -15,31 +14,17 @@ import FileOpen from "./FileOpen"
|
|||||||
import FileUploadButton from "./FileUploadButton"
|
import FileUploadButton from "./FileUploadButton"
|
||||||
import { ReactComponent as Spinner } from "./../assets/spinner.svg"
|
import { ReactComponent as Spinner } from "./../assets/spinner.svg"
|
||||||
import FileBrowserList from "./FileBrowserList"
|
import FileBrowserList from "./FileBrowserList"
|
||||||
import pathRename from "../functions/pathRename"
|
|
||||||
import MoreMenu from "./MoreMenu"
|
import MoreMenu from "./MoreMenu"
|
||||||
|
import ObjID from "../types/ObjID"
|
||||||
function uriToPath(pathname:string) {
|
|
||||||
// strip the "/f" from e.g. "/f/dir1/dir2"
|
|
||||||
const path = pathname.substr(2)
|
|
||||||
if (!path.endsWith("/")){
|
|
||||||
return path + "/"
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
function pathToUri(path:string) {
|
|
||||||
return (path.startsWith("/")?"/f":"/f/") + path
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
||||||
const path = uriToPath(props.location.pathname)
|
const path = ObjID.fromURI(props.location.pathname)
|
||||||
|
const [openFileId, setOpenFileId] = useState<ObjID>()
|
||||||
const [openFileId, setOpenFileId] = useState("")
|
|
||||||
const [showFile, setShowFile] = useState(false)
|
const [showFile, setShowFile] = useState(false)
|
||||||
|
|
||||||
const [srcID,setSrcID] = useState("")
|
const [srcID,setSrcID] = useState<ObjID>(path)
|
||||||
const [pasteAction,setPasteAction] = useState<Action>()
|
const [pasteAction,setPasteAction] = useState<Action>()
|
||||||
const [editID,setEditID] = useState("")
|
const [editID,setEditID] = useState<ObjID>(path)
|
||||||
const [editEnable,setEditEnable] = useState(false)
|
const [editEnable,setEditEnable] = useState(false)
|
||||||
|
|
||||||
const [deleteMutation] = useDeleteFileMutation()
|
const [deleteMutation] = useDeleteFileMutation()
|
||||||
@ -58,7 +43,7 @@ const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
|||||||
|
|
||||||
const { data, loading, refetch: refetchDir } = useOpenDirQuery({
|
const { data, loading, refetch: refetchDir } = useOpenDirQuery({
|
||||||
variables:{
|
variables:{
|
||||||
path
|
path: path
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -66,14 +51,14 @@ const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
|||||||
const wait: Promise<boolean>[] = []
|
const wait: Promise<boolean>[] = []
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
const file = files[i]
|
const file = files[i]
|
||||||
wait.push(uploadFile(file, path + file.name))
|
wait.push(uploadFile(file, new ObjID(path.bucket,path.key + file.name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(wait)
|
await Promise.all(wait)
|
||||||
refetchDir()
|
refetchDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onContextSelect(action:Action, id: string) {
|
async function onContextSelect(action:Action, id: ObjID) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case Action.FileDelete:
|
case Action.FileDelete:
|
||||||
await deleteMutation({variables:{id}})
|
await deleteMutation({variables:{id}})
|
||||||
@ -124,13 +109,13 @@ const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<Breadcrum path={path} onDirClick={(newPath)=>{
|
<Breadcrum path={path} onDirClick={(newPath)=>{
|
||||||
props.history.push(pathToUri(newPath))
|
props.history.push(newPath.toURI())
|
||||||
}}/>
|
}}/>
|
||||||
<div className="ml-auto">
|
<div className="ml-auto">
|
||||||
<CreateDirButton
|
<CreateDirButton
|
||||||
onPressed={async (dirName)=>{
|
onPressed={async (dirName)=>{
|
||||||
const fullPath = normalizeDirPath(path + dirName)
|
const dirID = new ObjID(path.bucket,path.key + dirName)
|
||||||
await createDirMutation({variables:{path: fullPath}})
|
await createDirMutation({variables:{path: dirID}})
|
||||||
refetchDir()
|
refetchDir()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -147,11 +132,11 @@ const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<FileBrowserList
|
<FileBrowserList
|
||||||
directorys={data?.directorys || []}
|
directorys={data?.directories || []}
|
||||||
files={data?.files || []}
|
files={data?.files || []}
|
||||||
|
|
||||||
onDirClick={(e,path)=>{
|
onDirClick={(e,path)=>{
|
||||||
props.history.push(pathToUri(path))
|
props.history.push(path.toURI())
|
||||||
}}
|
}}
|
||||||
|
|
||||||
onDirContext={(e,path)=>{
|
onDirContext={(e,path)=>{
|
||||||
@ -179,7 +164,7 @@ const FileBrowser: React.FC<RouteComponentProps> = (props) => {
|
|||||||
// TODO: input check & error handling
|
// TODO: input check & error handling
|
||||||
await moveMutation({variables:{
|
await moveMutation({variables:{
|
||||||
src:id,
|
src:id,
|
||||||
dest: pathRename(id,newName)
|
dest: id.rename(newName)
|
||||||
}})
|
}})
|
||||||
refetchDir()
|
refetchDir()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { Item, ItemParams, Menu, Separator } from "react-contexify"
|
import { Item, ItemParams, Menu, Separator } from "react-contexify"
|
||||||
|
import ObjID from "../types/ObjID"
|
||||||
|
|
||||||
export const CONTEXT_MENU_FILE = "CONTEXT_MENU_FILE"
|
export const CONTEXT_MENU_FILE = "CONTEXT_MENU_FILE"
|
||||||
export const CONTEXT_MENU_DIR = "CONTEXT_MENU_DIR"
|
export const CONTEXT_MENU_DIR = "CONTEXT_MENU_DIR"
|
||||||
@ -16,12 +16,12 @@ export enum Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onSelect?: (action: Action, id: string)=>void
|
onSelect?: (action: Action, id: ObjID)=>void
|
||||||
pasteActive?: boolean
|
pasteActive?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileBrowserContextMenu: React.FC<Props> = (props) => {
|
const FileBrowserContextMenu: React.FC<Props> = (props) => {
|
||||||
function onClick({ props: itemProps, data }: ItemParams<{id:string}, Action>) {
|
function onClick({ props: itemProps, data }: ItemParams<{id:ObjID}, Action>) {
|
||||||
if (itemProps?.id && data != null){
|
if (itemProps?.id && data != null){
|
||||||
props.onSelect?.(data,itemProps.id)
|
props.onSelect?.(data,itemProps.id)
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { Directory, File } from "../generated/graphql"
|
import { Directory, File } from "../generated/graphql"
|
||||||
|
import ObjID from "../types/ObjID"
|
||||||
import FileBrowserElement from "./FileBrowserElement"
|
import FileBrowserElement from "./FileBrowserElement"
|
||||||
|
|
||||||
interface Props{
|
interface Props{
|
||||||
directorys: Directory[]
|
directorys: Directory[]
|
||||||
files: File[]
|
files: File[]
|
||||||
|
|
||||||
onFileContext?: (event: React.MouseEvent, id: string)=>void
|
onFileContext?: (event: React.MouseEvent, id: ObjID)=>void
|
||||||
onDirContext?: (event: React.MouseEvent, path: string)=>void
|
onDirContext?: (event: React.MouseEvent, path: ObjID)=>void
|
||||||
onFileClick?: (event: React.MouseEvent,id: string)=>void
|
onFileClick?: (event: React.MouseEvent,id: ObjID)=>void
|
||||||
onDirClick?: (event: React.MouseEvent,path: string)=>void
|
onDirClick?: (event: React.MouseEvent,path: ObjID)=>void
|
||||||
|
|
||||||
editId: string
|
editId?: ObjID
|
||||||
editEnable: boolean
|
editEnable: boolean
|
||||||
onRenameDone?: (id: string, changed: boolean, newName: string)=>void
|
onRenameDone?: (id: ObjID, changed: boolean, newName: string)=>void
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileBrowserList: React.FC<Props> = (props) => {
|
const FileBrowserList: React.FC<Props> = (props) => {
|
||||||
@ -28,7 +29,7 @@ const FileBrowserList: React.FC<Props> = (props) => {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y dark:divide-gray-900">
|
<tbody className="divide-y dark:divide-gray-900">
|
||||||
{ props.directorys.map(v => (<FileBrowserElement
|
{ props.directorys.map(v => (<FileBrowserElement
|
||||||
key={v.id}
|
key={v.id.toString()}
|
||||||
dir={v}
|
dir={v}
|
||||||
onClick={(e,dir)=>{
|
onClick={(e,dir)=>{
|
||||||
props.onDirClick?.(e,dir.id)
|
props.onDirClick?.(e,dir.id)
|
||||||
@ -51,7 +52,7 @@ const FileBrowserList: React.FC<Props> = (props) => {
|
|||||||
/>))}
|
/>))}
|
||||||
|
|
||||||
{ props.files.map(v => (<FileBrowserElement
|
{ props.files.map(v => (<FileBrowserElement
|
||||||
key={v.id}
|
key={v.id.toString()}
|
||||||
file={v}
|
file={v}
|
||||||
onClick={(e,file)=>{
|
onClick={(e,file)=>{
|
||||||
props.onFileClick?.(e,file.id)
|
props.onFileClick?.(e,file.id)
|
||||||
|
@ -4,9 +4,10 @@ import ImageOpener from "./ImageOpener"
|
|||||||
import TextOpener from "./TextOpener"
|
import TextOpener from "./TextOpener"
|
||||||
import Modal from "./Modal"
|
import Modal from "./Modal"
|
||||||
import AudioOpener from "./AudioOpener"
|
import AudioOpener from "./AudioOpener"
|
||||||
|
import ObjID from "../types/ObjID"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
id: string
|
id?: ObjID
|
||||||
show: boolean
|
show: boolean
|
||||||
onCloseClick?: ()=>void
|
onCloseClick?: ()=>void
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
function genDownloadLink(id:string): string {
|
import ObjID from "../types/ObjID"
|
||||||
return `/api/file?id=${encodeURIComponent(id)}`
|
|
||||||
|
function genDownloadLink(id:ObjID): string {
|
||||||
|
return `/api/file?id=${encodeURIComponent(id.toString())}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export default genDownloadLink
|
export default genDownloadLink
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
function pathRename(id:string, newFilename: string): string {
|
|
||||||
const isDir = id.endsWith("/")
|
|
||||||
const parts = id.split("/")
|
|
||||||
if (!parts.length)
|
|
||||||
throw new Error("Maleformed id")
|
|
||||||
parts[parts.length - (isDir?2:1)] = newFilename
|
|
||||||
|
|
||||||
return parts.join("/")
|
|
||||||
}
|
|
||||||
|
|
||||||
export default pathRename
|
|
@ -1,5 +1,7 @@
|
|||||||
async function uploadFile(file:File,id: string): Promise<boolean> {
|
import ObjID from "../types/ObjID"
|
||||||
const res = await fetch(`/api/file?${new URLSearchParams({id:id}).toString()}`,{
|
|
||||||
|
async function uploadFile(file:File,id: ObjID): Promise<boolean> {
|
||||||
|
const res = await fetch(`/api/file?${new URLSearchParams({id:id.toString()}).toString()}`,{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": file.type
|
"Content-Type": file.type
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import ObjID from "./../types/ObjID"
|
||||||
import { gql } from "@apollo/client"
|
import { gql } from "@apollo/client"
|
||||||
import * as Apollo from "@apollo/client"
|
import * as Apollo from "@apollo/client"
|
||||||
export type Maybe<T> = T | null;
|
export type Maybe<T> = T | null;
|
||||||
@ -14,6 +15,11 @@ export type Scalars = {
|
|||||||
Float: number;
|
Float: number;
|
||||||
/** DateTime is a DateTime in ISO 8601 format */
|
/** DateTime is a DateTime in ISO 8601 format */
|
||||||
DateTime: string;
|
DateTime: string;
|
||||||
|
/**
|
||||||
|
* String representing a bucket, key and version combination.
|
||||||
|
* Looks like this: "bucketName:/name/of/key" or "bucketName@version:/name/of/key"
|
||||||
|
*/
|
||||||
|
objID: ObjID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -22,7 +28,7 @@ export type Directory = {
|
|||||||
__typename?: "Directory";
|
__typename?: "Directory";
|
||||||
directorys?: Maybe<Array<Maybe<Directory>>>;
|
directorys?: Maybe<Array<Maybe<Directory>>>;
|
||||||
files?: Maybe<Array<Maybe<File>>>;
|
files?: Maybe<Array<Maybe<File>>>;
|
||||||
id: Scalars["ID"];
|
id: Scalars["objID"];
|
||||||
name?: Maybe<Scalars["String"]>;
|
name?: Maybe<Scalars["String"]>;
|
||||||
parent?: Maybe<Directory>;
|
parent?: Maybe<Directory>;
|
||||||
};
|
};
|
||||||
@ -33,7 +39,7 @@ export type File = {
|
|||||||
contentType?: Maybe<Scalars["String"]>;
|
contentType?: Maybe<Scalars["String"]>;
|
||||||
etag?: Maybe<Scalars["String"]>;
|
etag?: Maybe<Scalars["String"]>;
|
||||||
/** The uniqe ID of the file. Represents the path and the s3 key. */
|
/** The uniqe ID of the file. Represents the path and the s3 key. */
|
||||||
id: Scalars["ID"];
|
id: Scalars["objID"];
|
||||||
lastModified?: Maybe<Scalars["DateTime"]>;
|
lastModified?: Maybe<Scalars["DateTime"]>;
|
||||||
name?: Maybe<Scalars["String"]>;
|
name?: Maybe<Scalars["String"]>;
|
||||||
parent?: Maybe<Directory>;
|
parent?: Maybe<Directory>;
|
||||||
@ -61,64 +67,65 @@ export type RootMutation = {
|
|||||||
|
|
||||||
|
|
||||||
export type RootMutationCopyArgs = {
|
export type RootMutationCopyArgs = {
|
||||||
src: Scalars["ID"];
|
src: Scalars["objID"];
|
||||||
dest: Scalars["ID"];
|
dest: Scalars["objID"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootMutationCreateDirArgs = {
|
export type RootMutationCreateDirArgs = {
|
||||||
path: Scalars["ID"];
|
path: Scalars["objID"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootMutationDeleteArgs = {
|
export type RootMutationDeleteArgs = {
|
||||||
id: Scalars["ID"];
|
id: Scalars["objID"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootMutationDeleteDirArgs = {
|
export type RootMutationDeleteDirArgs = {
|
||||||
path: Scalars["ID"];
|
path: Scalars["objID"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootMutationLoginArgs = {
|
export type RootMutationLoginArgs = {
|
||||||
password: Scalars["String"];
|
|
||||||
username: Scalars["String"];
|
username: Scalars["String"];
|
||||||
|
password: Scalars["String"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootMutationMoveArgs = {
|
export type RootMutationMoveArgs = {
|
||||||
src: Scalars["ID"];
|
src: Scalars["objID"];
|
||||||
dest: Scalars["ID"];
|
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 */
|
||||||
authorized: Scalars["Boolean"];
|
authorized: Scalars["Boolean"];
|
||||||
directorys: Array<Directory>;
|
directories: Array<Directory>;
|
||||||
file?: Maybe<File>;
|
file?: Maybe<File>;
|
||||||
files: Array<File>;
|
files: Array<File>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootQueryDirectorysArgs = {
|
export type RootQueryDirectoriesArgs = {
|
||||||
path: Scalars["String"];
|
path: Scalars["objID"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootQueryFileArgs = {
|
export type RootQueryFileArgs = {
|
||||||
id: Scalars["ID"];
|
id: Scalars["objID"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type RootQueryFilesArgs = {
|
export type RootQueryFilesArgs = {
|
||||||
path: Scalars["String"];
|
path: Scalars["objID"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type CopyMutationVariables = Exact<{
|
export type CopyMutationVariables = Exact<{
|
||||||
src: Scalars["ID"];
|
src: Scalars["objID"];
|
||||||
dest: Scalars["ID"];
|
dest: Scalars["objID"];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@ -131,7 +138,7 @@ export type CopyMutation = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export type CreateDirMutationVariables = Exact<{
|
export type CreateDirMutationVariables = Exact<{
|
||||||
path: Scalars["ID"];
|
path: Scalars["objID"];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@ -144,7 +151,7 @@ export type CreateDirMutation = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export type DeleteDirMutationVariables = Exact<{
|
export type DeleteDirMutationVariables = Exact<{
|
||||||
path: Scalars["ID"];
|
path: Scalars["objID"];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@ -154,7 +161,7 @@ export type DeleteDirMutation = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export type DeleteFileMutationVariables = Exact<{
|
export type DeleteFileMutationVariables = Exact<{
|
||||||
id: Scalars["ID"];
|
id: Scalars["objID"];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@ -164,7 +171,7 @@ export type DeleteFileMutation = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export type GetFileQueryVariables = Exact<{
|
export type GetFileQueryVariables = Exact<{
|
||||||
id: Scalars["ID"];
|
id: Scalars["objID"];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@ -199,8 +206,8 @@ export type LoginMutation = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export type MoveMutationVariables = Exact<{
|
export type MoveMutationVariables = Exact<{
|
||||||
src: Scalars["ID"];
|
src: Scalars["objID"];
|
||||||
dest: Scalars["ID"];
|
dest: Scalars["objID"];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@ -213,7 +220,7 @@ export type MoveMutation = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export type OpenDirQueryVariables = Exact<{
|
export type OpenDirQueryVariables = Exact<{
|
||||||
path: Scalars["String"];
|
path: Scalars["objID"];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@ -222,7 +229,7 @@ export type OpenDirQuery = (
|
|||||||
& { files: Array<(
|
& { files: Array<(
|
||||||
{ __typename?: "File" }
|
{ __typename?: "File" }
|
||||||
& Pick<File, "id" | "name" | "size" | "lastModified">
|
& Pick<File, "id" | "name" | "size" | "lastModified">
|
||||||
)>, directorys: Array<(
|
)>, directories: Array<(
|
||||||
{ __typename?: "Directory" }
|
{ __typename?: "Directory" }
|
||||||
& Pick<Directory, "id" | "name">
|
& Pick<Directory, "id" | "name">
|
||||||
)> }
|
)> }
|
||||||
@ -230,7 +237,7 @@ export type OpenDirQuery = (
|
|||||||
|
|
||||||
|
|
||||||
export const CopyDocument = gql`
|
export const CopyDocument = gql`
|
||||||
mutation copy($src: ID!, $dest: ID!) {
|
mutation copy($src: objID!, $dest: objID!) {
|
||||||
copy(src: $src, dest: $dest) {
|
copy(src: $src, dest: $dest) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@ -264,7 +271,7 @@ export type CopyMutationHookResult = ReturnType<typeof useCopyMutation>;
|
|||||||
export type CopyMutationResult = Apollo.MutationResult<CopyMutation>;
|
export type CopyMutationResult = Apollo.MutationResult<CopyMutation>;
|
||||||
export type CopyMutationOptions = Apollo.BaseMutationOptions<CopyMutation, CopyMutationVariables>;
|
export type CopyMutationOptions = Apollo.BaseMutationOptions<CopyMutation, CopyMutationVariables>;
|
||||||
export const CreateDirDocument = gql`
|
export const CreateDirDocument = gql`
|
||||||
mutation createDir($path: ID!) {
|
mutation createDir($path: objID!) {
|
||||||
createDir(path: $path) {
|
createDir(path: $path) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@ -297,7 +304,7 @@ export type CreateDirMutationHookResult = ReturnType<typeof useCreateDirMutation
|
|||||||
export type CreateDirMutationResult = Apollo.MutationResult<CreateDirMutation>;
|
export type CreateDirMutationResult = Apollo.MutationResult<CreateDirMutation>;
|
||||||
export type CreateDirMutationOptions = Apollo.BaseMutationOptions<CreateDirMutation, CreateDirMutationVariables>;
|
export type CreateDirMutationOptions = Apollo.BaseMutationOptions<CreateDirMutation, CreateDirMutationVariables>;
|
||||||
export const DeleteDirDocument = gql`
|
export const DeleteDirDocument = gql`
|
||||||
mutation deleteDir($path: ID!) {
|
mutation deleteDir($path: objID!) {
|
||||||
deleteDir(path: $path)
|
deleteDir(path: $path)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -328,7 +335,7 @@ export type DeleteDirMutationHookResult = ReturnType<typeof useDeleteDirMutation
|
|||||||
export type DeleteDirMutationResult = Apollo.MutationResult<DeleteDirMutation>;
|
export type DeleteDirMutationResult = Apollo.MutationResult<DeleteDirMutation>;
|
||||||
export type DeleteDirMutationOptions = Apollo.BaseMutationOptions<DeleteDirMutation, DeleteDirMutationVariables>;
|
export type DeleteDirMutationOptions = Apollo.BaseMutationOptions<DeleteDirMutation, DeleteDirMutationVariables>;
|
||||||
export const DeleteFileDocument = gql`
|
export const DeleteFileDocument = gql`
|
||||||
mutation deleteFile($id: ID!) {
|
mutation deleteFile($id: objID!) {
|
||||||
delete(id: $id)
|
delete(id: $id)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -359,7 +366,7 @@ export type DeleteFileMutationHookResult = ReturnType<typeof useDeleteFileMutati
|
|||||||
export type DeleteFileMutationResult = Apollo.MutationResult<DeleteFileMutation>;
|
export type DeleteFileMutationResult = Apollo.MutationResult<DeleteFileMutation>;
|
||||||
export type DeleteFileMutationOptions = Apollo.BaseMutationOptions<DeleteFileMutation, DeleteFileMutationVariables>;
|
export type DeleteFileMutationOptions = Apollo.BaseMutationOptions<DeleteFileMutation, DeleteFileMutationVariables>;
|
||||||
export const GetFileDocument = gql`
|
export const GetFileDocument = gql`
|
||||||
query getFile($id: ID!) {
|
query getFile($id: objID!) {
|
||||||
file(id: $id) {
|
file(id: $id) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@ -465,7 +472,7 @@ export type LoginMutationHookResult = ReturnType<typeof useLoginMutation>;
|
|||||||
export type LoginMutationResult = Apollo.MutationResult<LoginMutation>;
|
export type LoginMutationResult = Apollo.MutationResult<LoginMutation>;
|
||||||
export type LoginMutationOptions = Apollo.BaseMutationOptions<LoginMutation, LoginMutationVariables>;
|
export type LoginMutationOptions = Apollo.BaseMutationOptions<LoginMutation, LoginMutationVariables>;
|
||||||
export const MoveDocument = gql`
|
export const MoveDocument = gql`
|
||||||
mutation move($src: ID!, $dest: ID!) {
|
mutation move($src: objID!, $dest: objID!) {
|
||||||
move(src: $src, dest: $dest) {
|
move(src: $src, dest: $dest) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@ -499,14 +506,14 @@ 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 OpenDirDocument = gql`
|
export const OpenDirDocument = gql`
|
||||||
query openDir($path: String!) {
|
query openDir($path: objID!) {
|
||||||
files(path: $path) {
|
files(path: $path) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
size
|
size
|
||||||
lastModified
|
lastModified
|
||||||
}
|
}
|
||||||
directorys(path: $path) {
|
directories(path: $path) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
mutation copy($src: ID!, $dest: ID!) {
|
mutation copy($src: objID!, $dest: objID!) {
|
||||||
copy(src: $src,dest: $dest){
|
copy(src: $src,dest: $dest){
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
mutation createDir($path: ID!){
|
mutation createDir($path: objID!){
|
||||||
createDir(path:$path){
|
createDir(path:$path){
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
mutation deleteDir($path: ID!){
|
mutation deleteDir($path: objID!){
|
||||||
deleteDir(path:$path)
|
deleteDir(path:$path)
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
mutation deleteFile($id: ID!) {
|
mutation deleteFile($id: objID!) {
|
||||||
delete(id:$id)
|
delete(id:$id)
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
query getFile($id: ID!){
|
query getFile($id: objID!){
|
||||||
file(id: $id){
|
file(id: $id){
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
mutation move($src: ID!, $dest: ID!) {
|
mutation move($src: objID!, $dest: objID!) {
|
||||||
move(src: $src,dest: $dest){
|
move(src: $src,dest: $dest){
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
query openDir($path: String!) {
|
query openDir($path: objID!) {
|
||||||
files(path:$path){
|
files(path:$path){
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
size
|
size
|
||||||
lastModified
|
lastModified
|
||||||
}
|
}
|
||||||
directorys(path: $path){
|
directories(path: $path){
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,44 @@ import "./index.scss"
|
|||||||
import App from "./App"
|
import App from "./App"
|
||||||
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client"
|
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client"
|
||||||
import "react-contexify/dist/ReactContexify.css"
|
import "react-contexify/dist/ReactContexify.css"
|
||||||
|
import ObjID from "./types/ObjID"
|
||||||
|
|
||||||
const client = new ApolloClient({
|
const client = new ApolloClient({
|
||||||
uri: "/api/graphql",
|
uri: "/api/graphql",
|
||||||
cache: new InMemoryCache({
|
cache: new InMemoryCache({
|
||||||
typePolicies:{
|
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: {
|
Query: {
|
||||||
fields: {
|
fields: {
|
||||||
files: {
|
files: {
|
||||||
|
82
src/types/ObjID.ts
Normal file
82
src/types/ObjID.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
const stringRegex = /(.*?)(@(.*))?:(.*)/
|
||||||
|
|
||||||
|
class ObjID {
|
||||||
|
public bucket: string
|
||||||
|
public key: string
|
||||||
|
public version?: string
|
||||||
|
|
||||||
|
constructor(bucket: string, key: string, version?: string) {
|
||||||
|
this.bucket = bucket
|
||||||
|
if(!key){
|
||||||
|
this.key = "/"
|
||||||
|
}else{
|
||||||
|
this.key = key
|
||||||
|
}
|
||||||
|
if (version){
|
||||||
|
this.version = version
|
||||||
|
}
|
||||||
|
|
||||||
|
this.normalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
public toString(): string {
|
||||||
|
if (this.version) {
|
||||||
|
return `${this.bucket}@${this.version}:${this.key}`
|
||||||
|
}else{
|
||||||
|
return `${this.bucket}:${this.key}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public normalize(): void{
|
||||||
|
if (!this.key.startsWith("/")){
|
||||||
|
this.key = "/" + this.key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public isDirectory(): boolean {
|
||||||
|
return this.key.endsWith("/")
|
||||||
|
}
|
||||||
|
|
||||||
|
public toURI(): string {
|
||||||
|
return `/f/${this.bucket}${this.key}`
|
||||||
|
}
|
||||||
|
|
||||||
|
public toJSON(): string{
|
||||||
|
// HACK: toJSON is required so that apollo can parse the ObjID back to a string
|
||||||
|
// that can be used in gql query
|
||||||
|
return this.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
public rename(name: string): ObjID{
|
||||||
|
const parts = this.key.split("/")
|
||||||
|
parts[parts.length - (this.isDirectory()?2:1)] = name
|
||||||
|
return new ObjID(this.bucket,parts.join("/"))
|
||||||
|
}
|
||||||
|
|
||||||
|
public static fromString(from: string): ObjID{
|
||||||
|
const match = stringRegex.exec(from)
|
||||||
|
|
||||||
|
if (!match){
|
||||||
|
throw new Error("Failed to parse ObjID")
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ObjID(match[1],match[4],match[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
public static fromURI(uri: string): ObjID{
|
||||||
|
let uri2 = uri
|
||||||
|
|
||||||
|
if (!uri2.endsWith("/")){
|
||||||
|
uri2 += "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = uri2.split("/")
|
||||||
|
|
||||||
|
const bucket = parts[2]
|
||||||
|
const key = parts.slice(3).join("/")
|
||||||
|
|
||||||
|
return new ObjID(bucket,key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ObjID
|
27
yarn.lock
27
yarn.lock
@ -1392,6 +1392,14 @@
|
|||||||
minimatch "^3.0.4"
|
minimatch "^3.0.4"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
|
"@graphql-codegen/add@^3.1.0":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@graphql-codegen/add/-/add-3.1.0.tgz#cd02fd6d80a7f62839cb27160b62e48366a237c5"
|
||||||
|
integrity sha512-vRRHpuUFadYXnPrb5RNiIzm3Ao39UxjvrdX760lEfXh2qeG7YddM5QFC+ev2BH3X452R15gv/gf/rXy0+Hqm1A==
|
||||||
|
dependencies:
|
||||||
|
"@graphql-codegen/plugin-helpers" "^2.1.0"
|
||||||
|
tslib "~2.3.0"
|
||||||
|
|
||||||
"@graphql-codegen/cli@1.21.7":
|
"@graphql-codegen/cli@1.21.7":
|
||||||
version "1.21.7"
|
version "1.21.7"
|
||||||
resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.21.7.tgz"
|
resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.21.7.tgz"
|
||||||
@ -1466,6 +1474,18 @@
|
|||||||
lodash "~4.17.0"
|
lodash "~4.17.0"
|
||||||
tslib "~2.3.0"
|
tslib "~2.3.0"
|
||||||
|
|
||||||
|
"@graphql-codegen/plugin-helpers@^2.1.0":
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-2.1.1.tgz#fc13e735763574ef308045bbb95c3e7201ec0027"
|
||||||
|
integrity sha512-7jjN9fekMQkpd7cRTbaBxgqt/hkR3CXeOUSsEyHFDDHKtvCrnev3iyc75IeWXpO9tOwDE8mVPTzEZnu4QukrNA==
|
||||||
|
dependencies:
|
||||||
|
"@graphql-tools/utils" "^8.1.1"
|
||||||
|
change-case-all "1.0.14"
|
||||||
|
common-tags "1.8.0"
|
||||||
|
import-from "4.0.0"
|
||||||
|
lodash "~4.17.0"
|
||||||
|
tslib "~2.3.0"
|
||||||
|
|
||||||
"@graphql-codegen/typescript-operations@1.18.4":
|
"@graphql-codegen/typescript-operations@1.18.4":
|
||||||
version "1.18.4"
|
version "1.18.4"
|
||||||
resolved "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-1.18.4.tgz"
|
resolved "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-1.18.4.tgz"
|
||||||
@ -1720,6 +1740,13 @@
|
|||||||
camel-case "4.1.2"
|
camel-case "4.1.2"
|
||||||
tslib "~2.2.0"
|
tslib "~2.2.0"
|
||||||
|
|
||||||
|
"@graphql-tools/utils@^8.1.1":
|
||||||
|
version "8.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.2.3.tgz#9d7b9e7e116d11d26c2687f4d9cfb2b54568838b"
|
||||||
|
integrity sha512-RR+aiusf2gIfnPmrDIH1uA45QuPiHB54RD+BmWyMcl88tWAjeJtqZeWPqUTq/1EXrNeocJAJQqogHV4Fbbzx3A==
|
||||||
|
dependencies:
|
||||||
|
tslib "~2.3.0"
|
||||||
|
|
||||||
"@graphql-tools/wrap@^7.0.4":
|
"@graphql-tools/wrap@^7.0.4":
|
||||||
version "7.0.8"
|
version "7.0.8"
|
||||||
resolved "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-7.0.8.tgz"
|
resolved "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-7.0.8.tgz"
|
||||||
|
Loading…
Reference in New Issue
Block a user