Compare commits
5 Commits
2aea95c6ab
...
b08a527199
| Author | SHA1 | Date | |
|---|---|---|---|
| b08a527199 | |||
| 53969946d2 | |||
| a24ed03e1f | |||
| c20e894d52 | |||
| abbcaf9166 |
@@ -5,7 +5,7 @@ generates:
|
||||
src/generated/graphql.tsx:
|
||||
hooks:
|
||||
afterOneFileWrite:
|
||||
- yarn run eslint --fix src/generated/graphql.tsx
|
||||
- yarn run eslint --fix --no-ignore src/generated/graphql.tsx
|
||||
plugins:
|
||||
- "typescript"
|
||||
- "typescript-operations"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"spectre.css": "^0.5.9",
|
||||
"typescript": "^4.1.2",
|
||||
"web-vitals": "^1.0.1"
|
||||
},
|
||||
@@ -57,5 +58,6 @@
|
||||
"apollo": "^2.33.4",
|
||||
"eslint": "^7.31.0",
|
||||
"eslint-plugin-react": "^7.24.0"
|
||||
}
|
||||
},
|
||||
"proxy": "http://localhost:8080"
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import FileBrowser from "./components/FileBrowser"
|
||||
|
||||
const App: React.FC = () => {
|
||||
return (
|
||||
<div className="App">
|
||||
<FileBrowser></FileBrowser>
|
||||
<div className="container">
|
||||
<FileBrowser/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
38
src/components/Breadcrum.tsx
Normal file
38
src/components/Breadcrum.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
|
||||
interface Props{
|
||||
path: string
|
||||
onDirClick?: (path: string) => void
|
||||
}
|
||||
|
||||
const Breadcrum: React.FC<Props> = (props) => {
|
||||
const parts = props.path.split("/").filter(e=>e.length > 0)
|
||||
|
||||
return (
|
||||
<ul className="breadcrumb">
|
||||
<li className="breadcrumb-item">
|
||||
<a onClick={()=>{
|
||||
props.onDirClick?.("/")
|
||||
}}>
|
||||
Root
|
||||
</a>
|
||||
</li>
|
||||
{parts.map((e,i,arr)=>(
|
||||
<li key={e} className="breadcrumb-item">
|
||||
<a onClick={()=>{
|
||||
if (i != arr.length - 1){
|
||||
props.onDirClick?.("/"+arr.slice(0,i-1).join("/"))
|
||||
}
|
||||
}}>{e}</a>
|
||||
</li>))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
Breadcrum.propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
onDirClick: PropTypes.func
|
||||
}
|
||||
|
||||
export default Breadcrum
|
||||
@@ -8,9 +8,14 @@ interface Props {
|
||||
|
||||
const DirectoryElement: React.FC<Props> = (props) => {
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<td>
|
||||
📂 {props.dir.name}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
import React from "react"
|
||||
import { useState } from "react"
|
||||
import { useOpenDirQuery } from "../generated/graphql"
|
||||
import Breadcrum from "./Breadcrum"
|
||||
import FileBrowserElement from "./FileBrowserElement"
|
||||
|
||||
function parentDir(path:string): string {
|
||||
if(path.endsWith("/")){
|
||||
path = path.substr(0,path.length - 1)
|
||||
}
|
||||
const paths = path.split("/")
|
||||
paths.pop()
|
||||
return paths.join("/")
|
||||
}
|
||||
|
||||
const FileBrowser: React.FC = () => {
|
||||
const [path,setPath] = useState("/")
|
||||
|
||||
@@ -23,16 +15,18 @@ const FileBrowser: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div onClick={()=>{
|
||||
setPath(parentDir(path))
|
||||
}}>
|
||||
..
|
||||
</div>
|
||||
<Breadcrum path={path} onDirClick={(newPath)=>{
|
||||
setPath(newPath)
|
||||
}}/>
|
||||
<div>
|
||||
{ data?.files.map(v => (<FileBrowserElement
|
||||
key={v?.id}
|
||||
file={v}
|
||||
/>))}
|
||||
<table className="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{ data?.directorys.map(v => (<FileBrowserElement
|
||||
key={v?.id}
|
||||
@@ -41,6 +35,13 @@ const FileBrowser: React.FC = () => {
|
||||
setPath(data.id)
|
||||
}}
|
||||
/>))}
|
||||
|
||||
{ data?.files.map(v => (<FileBrowserElement
|
||||
key={v?.id}
|
||||
file={v}
|
||||
/>))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ interface Props {
|
||||
|
||||
const FileBrowserElement: React.FC<Props> = (props) => {
|
||||
return (
|
||||
<div onClick={()=>{
|
||||
<tr onClick={()=>{
|
||||
if(props.file){
|
||||
props.onClick?.(props.file)
|
||||
}else if(props.dir){
|
||||
@@ -20,7 +20,7 @@ const FileBrowserElement: React.FC<Props> = (props) => {
|
||||
}
|
||||
}}>
|
||||
{(props.file) ? <FileElement file={props.file}/>:(props.dir)?<DirectoryComponent dir={props.dir} />:<></>}
|
||||
</div>
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { File } from "../generated/graphql"
|
||||
import sizeToReadable from "../functions/sizeToReadable"
|
||||
|
||||
interface Props {
|
||||
file: File
|
||||
@@ -8,9 +9,14 @@ interface Props {
|
||||
|
||||
const FileElement: React.FC<Props> = (props) => {
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<td>
|
||||
📄 {props.file.name}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{sizeToReadable(props.file.size)}
|
||||
</td>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
7
src/functions/sizeToReadable.ts
Normal file
7
src/functions/sizeToReadable.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
function sizeToReadable(size: number): string {
|
||||
const i = Math.floor(Math.log(size) / Math.log(1024))
|
||||
return (size / Math.pow(1024, i)).toFixed(1) + " " + ["B", "kB", "MB", "GB", "TB"][i]
|
||||
|
||||
}
|
||||
|
||||
export default sizeToReadable
|
||||
@@ -33,7 +33,7 @@ export type File = {
|
||||
id: Scalars["ID"];
|
||||
name?: Maybe<Scalars["String"]>;
|
||||
parent?: Maybe<Directory>;
|
||||
size?: Maybe<Scalars["Int"]>;
|
||||
size: Scalars["Int"];
|
||||
};
|
||||
|
||||
export type RootQuery = {
|
||||
@@ -67,7 +67,7 @@ export type OpenDirQuery = (
|
||||
{ __typename?: "RootQuery" }
|
||||
& { files: Array<Maybe<(
|
||||
{ __typename?: "File" }
|
||||
& Pick<File, "id" | "name">
|
||||
& Pick<File, "id" | "name" | "size">
|
||||
)>>, directorys: Array<Maybe<(
|
||||
{ __typename?: "Directory" }
|
||||
& Pick<Directory, "id" | "name">
|
||||
@@ -80,6 +80,7 @@ export const OpenDirDocument = gql`
|
||||
files(path: $path) {
|
||||
id
|
||||
name
|
||||
size
|
||||
}
|
||||
directorys(path: $path) {
|
||||
id
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@ query openDir($path: String!) {
|
||||
files(path:$path){
|
||||
id
|
||||
name
|
||||
size
|
||||
}
|
||||
directorys(path: $path){
|
||||
id
|
||||
|
||||
@@ -3,9 +3,10 @@ import ReactDOM from "react-dom"
|
||||
import "./index.scss"
|
||||
import App from "./App"
|
||||
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client"
|
||||
import "spectre.css"
|
||||
|
||||
const client = new ApolloClient({
|
||||
uri: "http://localhost:8080/graphql",
|
||||
uri: "/graphql",
|
||||
cache: new InMemoryCache()
|
||||
})
|
||||
|
||||
|
||||
@@ -12959,6 +12959,11 @@ spdy@^4.0.2:
|
||||
select-hose "^2.0.0"
|
||||
spdy-transport "^3.0.0"
|
||||
|
||||
spectre.css@^0.5.9:
|
||||
version "0.5.9"
|
||||
resolved "https://registry.yarnpkg.com/spectre.css/-/spectre.css-0.5.9.tgz#86c732d093036d9fdc0a2ba570f005e4023ae6ca"
|
||||
integrity sha512-9jUqwZmCnvflrxFGcK+ize43TvjwDjqMwZPVubEtSIHzvinH0TBUESm1LcOJx3Ur7bdPaeOHQIjOqBl1Y5kLFw==
|
||||
|
||||
split-on-first@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz"
|
||||
|
||||
Reference in New Issue
Block a user