basic file opening
This commit is contained in:
		
							parent
							
								
									b08a527199
								
							
						
					
					
						commit
						67cbf7ab28
					
				
							
								
								
									
										3
									
								
								src/App.module.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/App.module.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
.imageOpener{
 | 
			
		||||
    width: 90%;
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
import React from "react"
 | 
			
		||||
import "./App.scss"
 | 
			
		||||
import FileBrowser from "./components/FileBrowser"
 | 
			
		||||
 | 
			
		||||
const App: React.FC = () => {
 | 
			
		||||
 | 
			
		||||
@ -3,9 +3,12 @@ import { useState } from "react"
 | 
			
		||||
import { useOpenDirQuery } from "../generated/graphql"
 | 
			
		||||
import Breadcrum from "./Breadcrum"
 | 
			
		||||
import FileBrowserElement from "./FileBrowserElement"
 | 
			
		||||
import FileOpen from "./FileOpen"
 | 
			
		||||
 | 
			
		||||
const FileBrowser: React.FC = () => {
 | 
			
		||||
	const [path,setPath] = useState("/")
 | 
			
		||||
	const [openFileId, setOpenFileId] = useState("")
 | 
			
		||||
	const [showFile, setShowFile] = useState(false)
 | 
			
		||||
 | 
			
		||||
	const { data } = useOpenDirQuery({
 | 
			
		||||
		variables:{
 | 
			
		||||
@ -31,18 +34,25 @@ const FileBrowser: React.FC = () => {
 | 
			
		||||
						{ data?.directorys.map(v => (<FileBrowserElement
 | 
			
		||||
							key={v?.id}
 | 
			
		||||
							dir={v}
 | 
			
		||||
							onClick={(data)=>{
 | 
			
		||||
								setPath(data.id)
 | 
			
		||||
							onClick={(dir)=>{
 | 
			
		||||
								setPath(dir.id)
 | 
			
		||||
							}}
 | 
			
		||||
						/>))}
 | 
			
		||||
							
 | 
			
		||||
						{ data?.files.map(v => (<FileBrowserElement 
 | 
			
		||||
							key={v?.id}
 | 
			
		||||
							file={v}
 | 
			
		||||
							onClick={(file)=>{
 | 
			
		||||
								setOpenFileId(file.id)
 | 
			
		||||
								setShowFile(true)
 | 
			
		||||
							}}
 | 
			
		||||
						/>))}
 | 
			
		||||
					</tbody>
 | 
			
		||||
				</table>
 | 
			
		||||
			</div>
 | 
			
		||||
			{<FileOpen id={openFileId} show={showFile} onCloseClick={()=>{
 | 
			
		||||
				setShowFile(false)
 | 
			
		||||
			}} />}
 | 
			
		||||
		</div>
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										69
									
								
								src/components/FileOpen.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/components/FileOpen.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
			
		||||
import React from "react"
 | 
			
		||||
import PropTypes from "prop-types"
 | 
			
		||||
import { useGetFileQuery } from "../generated/graphql"
 | 
			
		||||
import ImageOpener from "./ImageOpener"
 | 
			
		||||
import TextOpener from "./TextOpener"
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
    id: string
 | 
			
		||||
	show: boolean
 | 
			
		||||
	onCloseClick?: ()=>void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const FileOpen: React.FC<Props> = (props) => {
 | 
			
		||||
 | 
			
		||||
	const { data } = useGetFileQuery({
 | 
			
		||||
		variables:{
 | 
			
		||||
			id: props.id
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	let opener = <div>TODO</div>
 | 
			
		||||
	
 | 
			
		||||
	if(data?.file != null){
 | 
			
		||||
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
 | 
			
		||||
		if (data.file.contentType?.startsWith("image/")){
 | 
			
		||||
			opener = <ImageOpener file={data?.file} />
 | 
			
		||||
		}else if (data.file.contentType?.startsWith("text/")){
 | 
			
		||||
			opener = <TextOpener file={data.file} />
 | 
			
		||||
		}else{
 | 
			
		||||
			// Get Opener bases on file extension
 | 
			
		||||
			const ext = data.file.name?.split(".").pop()
 | 
			
		||||
			switch (ext) {
 | 
			
		||||
			case "png":
 | 
			
		||||
			case "jpg":
 | 
			
		||||
			case "jpeg":
 | 
			
		||||
			case "gif":
 | 
			
		||||
				// TODO: more ext
 | 
			
		||||
				opener = <ImageOpener file={data.file} />
 | 
			
		||||
				break
 | 
			
		||||
			case "txt":
 | 
			
		||||
			case "md":
 | 
			
		||||
				opener = <TextOpener file={data.file} />
 | 
			
		||||
				break
 | 
			
		||||
			default:
 | 
			
		||||
				opener = <ImageOpener file={data?.file} />
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<div className={`modal modal-sm ${props.show ? "active":""}`}>
 | 
			
		||||
			<a className="modal-overlay" onClick={()=>{
 | 
			
		||||
				props.onCloseClick?.()
 | 
			
		||||
			}}>❌</a>
 | 
			
		||||
			<div className="modal-container">
 | 
			
		||||
				{opener}
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileOpen.propTypes = {
 | 
			
		||||
	id: PropTypes.string.isRequired,
 | 
			
		||||
	show: PropTypes.bool.isRequired,
 | 
			
		||||
	onCloseClick: PropTypes.func
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default FileOpen
 | 
			
		||||
							
								
								
									
										23
									
								
								src/components/ImageOpener.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/components/ImageOpener.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
import React from "react"
 | 
			
		||||
import PropTypes from "prop-types"
 | 
			
		||||
import { File } from "../generated/graphql"
 | 
			
		||||
import genDownloadLink from "../functions/genDownloadLink"
 | 
			
		||||
import style from "./../App.module.scss"
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
    file: File
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ImageOpener: React.FC<Props> = (props) => {
 | 
			
		||||
	return (
 | 
			
		||||
		<div className={style.imageOpener}>
 | 
			
		||||
			<img className="img-responsive img-fit-cover" src={genDownloadLink(props.file.id)}/>
 | 
			
		||||
		</div>
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ImageOpener.propTypes = {
 | 
			
		||||
	file: PropTypes.any.isRequired
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default ImageOpener
 | 
			
		||||
							
								
								
									
										23
									
								
								src/components/TextOpener.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/components/TextOpener.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
import React from "react"
 | 
			
		||||
import PropTypes from "prop-types"
 | 
			
		||||
import { File } from "../generated/graphql"
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
    file: File
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const TextOpener: React.FC<Props> = (props) => {
 | 
			
		||||
	return (
 | 
			
		||||
		<div>
 | 
			
		||||
			<textarea>
 | 
			
		||||
				{props.file.name}
 | 
			
		||||
			</textarea>
 | 
			
		||||
		</div>
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextOpener.propTypes = {
 | 
			
		||||
	file: PropTypes.any.isRequired,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default TextOpener
 | 
			
		||||
							
								
								
									
										5
									
								
								src/functions/genDownloadLink.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/functions/genDownloadLink.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
function genDownloadLink(id:string): string {
 | 
			
		||||
	return `/api/file?id=${encodeURIComponent(id)}`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default genDownloadLink
 | 
			
		||||
@ -58,6 +58,19 @@ export type RootQueryFilesArgs = {
 | 
			
		||||
  path: Scalars["String"];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type GetFileQueryVariables = Exact<{
 | 
			
		||||
  id: Scalars["ID"];
 | 
			
		||||
}>;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export type GetFileQuery = (
 | 
			
		||||
  { __typename?: "RootQuery" }
 | 
			
		||||
  & { file?: Maybe<(
 | 
			
		||||
    { __typename?: "File" }
 | 
			
		||||
    & Pick<File, "id" | "name" | "size" | "contentType" | "etag">
 | 
			
		||||
  )> }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export type OpenDirQueryVariables = Exact<{
 | 
			
		||||
  path: Scalars["String"];
 | 
			
		||||
}>;
 | 
			
		||||
@ -75,6 +88,45 @@ export type OpenDirQuery = (
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export const GetFileDocument = gql`
 | 
			
		||||
    query getFile($id: ID!) {
 | 
			
		||||
  file(id: $id) {
 | 
			
		||||
    id
 | 
			
		||||
    name
 | 
			
		||||
    size
 | 
			
		||||
    contentType
 | 
			
		||||
    etag
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
    `
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * __useGetFileQuery__
 | 
			
		||||
 *
 | 
			
		||||
 * To run a query within a React component, call `useGetFileQuery` and pass it any options that fit your needs.
 | 
			
		||||
 * When your component renders, `useGetFileQuery` returns an object from Apollo Client that contains loading, error, and data properties
 | 
			
		||||
 * you can use to render your UI.
 | 
			
		||||
 *
 | 
			
		||||
 * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
 | 
			
		||||
 *
 | 
			
		||||
 * @example
 | 
			
		||||
 * const { data, loading, error } = useGetFileQuery({
 | 
			
		||||
 *   variables: {
 | 
			
		||||
 *      id: // value for 'id'
 | 
			
		||||
 *   },
 | 
			
		||||
 * });
 | 
			
		||||
 */
 | 
			
		||||
export function useGetFileQuery(baseOptions: Apollo.QueryHookOptions<GetFileQuery, GetFileQueryVariables>) {
 | 
			
		||||
	const options = {...defaultOptions, ...baseOptions}
 | 
			
		||||
	return Apollo.useQuery<GetFileQuery, GetFileQueryVariables>(GetFileDocument, options)
 | 
			
		||||
}
 | 
			
		||||
export function useGetFileLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetFileQuery, GetFileQueryVariables>) {
 | 
			
		||||
	const options = {...defaultOptions, ...baseOptions}
 | 
			
		||||
	return Apollo.useLazyQuery<GetFileQuery, GetFileQueryVariables>(GetFileDocument, options)
 | 
			
		||||
}
 | 
			
		||||
export type GetFileQueryHookResult = ReturnType<typeof useGetFileQuery>;
 | 
			
		||||
export type GetFileLazyQueryHookResult = ReturnType<typeof useGetFileLazyQuery>;
 | 
			
		||||
export type GetFileQueryResult = Apollo.QueryResult<GetFileQuery, GetFileQueryVariables>;
 | 
			
		||||
export const OpenDirDocument = gql`
 | 
			
		||||
    query openDir($path: String!) {
 | 
			
		||||
  files(path: $path) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/graphql/getFile.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/graphql/getFile.graphql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
query getFile($id: ID!){
 | 
			
		||||
  file(id: $id){
 | 
			
		||||
    id
 | 
			
		||||
    name
 | 
			
		||||
    size
 | 
			
		||||
    contentType
 | 
			
		||||
    etag
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user