Skip to content

Commit

Permalink
uploader
Browse files Browse the repository at this point in the history
  • Loading branch information
ciur committed Sep 7, 2024
1 parent 65e8556 commit 355132f
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 99 deletions.
130 changes: 56 additions & 74 deletions ui2/src/components/modals/DropFiles.tsx
Original file line number Diff line number Diff line change
@@ -1,103 +1,85 @@
import {useContext, useState} from "react"
import {createRoot} from "react-dom/client"
import {Checkbox, MantineProvider, Text} from "@mantine/core"
import theme from "@/themes"
import GenericModal from "@/components/modals/Generic"
import {Checkbox, Text} from "@mantine/core"
import {Button, Modal, Container, Group, Loader} from "@mantine/core"
import Error from "@/components/modals/Error"
import type {NodeType, FolderType} from "@/types"
import {MODALS} from "@/cconstants"
import {store} from "@/app/store"
import {uploadFile} from "@/slices/uploader"
import {nodeAdded} from "@/slices/dualPanel/dualPanel"
import PanelContext from "@/contexts/PanelContext"
import {useAddNewDocumentNodeMutation} from "@/features/nodes/apiSlice"

type Args = {
opened: boolean
source_files: FileList | File[]
target: FolderType
onOK: (node: NodeType) => void
onCancel: (msg?: string) => void
onSubmit: () => void
onCancel: () => void
}

const DropFilesModal = ({source_files, target, onOK, onCancel}: Args) => {
const mode = useContext(PanelContext)
export const DropFilesModal = ({
source_files,
target,
onSubmit,
onCancel,
opened
}: Args) => {
if (!source_files) {
return
}
const [error, setError] = useState("")
const source_titles = [...source_files].map(n => n.name).join(", ")
const target_title = target.title
const [addNewDocummentNode] = useAddNewDocumentNodeMutation()

const handleSubmit = async () => {
const localSubmit = async () => {
for (let i = 0; i < source_files.length; i++) {
store
.dispatch(
uploadFile({
file: source_files[i],
refreshTarget: true,
skipOCR: false,
target
})
)
.then(value => {
// @ts-ignore
const node: NodeType = value.payload.source as NodeType
store.dispatch(nodeAdded({node, mode}))
onOK(node)
})
addNewDocummentNode({
title: source_files[i].name,
ocr: false,
target: target,
ctype: "document"
}).then(() => {
console.log(`Node ${source_files[i].name} was created`)
onSubmit()
})
}

return true
}

const handleCancel = () => {
const localCancel = () => {
// just close the dialog
setError("")
onCancel()
}

return (
<GenericModal
modal_title="Upload documents"
onSubmit={handleSubmit}
onCancel={handleCancel}
>
Are you sure you want to upload
<Text span c="blue">
{` ${source_titles} `}
</Text>
to
<Text span c="green">
{` ${target_title}`}
</Text>
?
<Checkbox mt="md" mb="md" label="Skip OCR" />
{error && <Error message={error} />}
</GenericModal>
<Modal title="Upload Files" opened={opened} onClose={localCancel}>
<Container>
Are you sure you want to upload
<Text span c="blue">
{` ${source_titles} `}
</Text>
to
<Text span c="green">
{` ${target_title}`}
</Text>
?
<Checkbox mt="md" mb="md" label="Skip OCR" />
{error && <Error message={error} />}
<Group gap="lg" justify="space-between">
<Button variant="default" onClick={localSubmit}>
Cancel
</Button>
<Button
leftSection={false && <Loader size={"sm"} />}
onClick={localSubmit}
disabled={false}
color={"red"}
>
Upload
</Button>
</Group>
</Container>
</Modal>
)
}

type DropFileArgs = {
source_files: FileList | File[]
target: FolderType
}

function drop_files({source_files, target}: DropFileArgs) {
let modals = document.getElementById(MODALS)

let promise = new Promise<NodeType>(function (onOK, onCancel) {
if (modals) {
let dom_root = createRoot(modals)
dom_root.render(
<MantineProvider theme={theme}>
<DropFilesModal
source_files={source_files}
target={target}
onOK={onOK}
onCancel={onCancel}
/>
</MantineProvider>
)
}
}) // new Promise...

return promise
}

export default drop_files
43 changes: 43 additions & 0 deletions ui2/src/features/nodes/apiSlice.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import {apiSlice} from "@/features/api/slice"
import type {Paginated, FolderType, NodeType} from "@/types"
import {
uploaderFileItemAdded,
uploaderFileItemFailed,
UpdateFileStatusArg
} from "@/features/ui/uiSlice"

type CreateFolderType = {
title: string
parent_id: string
ctype: "folder"
}

type CreateDocumentNodeType = {
title: string
target: FolderType
ocr: boolean
ctype: "document"
}

type RenameFolderType = {
title: string
id: string
Expand Down Expand Up @@ -64,6 +76,36 @@ export const apiSliceWithNodes = apiSlice.injectEndpoints({
}),
invalidatesTags: ["Node"]
}),
addNewDocumentNode: builder.mutation<NodeType, CreateDocumentNodeType>({
query: docData => ({
url: "/nodes/",
method: "POST",
body: {
parent_id: docData.target.id,
title: docData.title,
ocr: docData.ocr,
ctype: "document"
}
}),
invalidatesTags: ["Node"],
async onQueryStarted(arg, {dispatch, queryFulfilled}) {
let itemData: UpdateFileStatusArg = {
item: {
source: null,
file_name: arg.title,
target: arg.target
},
status: "uploading",
error: null
}
dispatch(uploaderFileItemAdded(itemData))
try {
await queryFulfilled
} catch (err) {
dispatch(uploaderFileItemFailed(itemData))
}
}
}),
renameFolder: builder.mutation<NodeType, RenameFolderType>({
query: folder => ({
url: `/nodes/${folder.id}`,
Expand Down Expand Up @@ -98,6 +140,7 @@ export const {
useGetPaginatedNodesQuery,
useGetFolderQuery,
useAddNewFolderMutation,
useAddNewDocumentNodeMutation,
useRenameFolderMutation,
useUpdateNodeTagsMutation,
useDeleteNodesMutation
Expand Down
9 changes: 4 additions & 5 deletions ui2/src/features/nodes/components/Commander.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import type {NType, NodeType, PanelMode} from "@/types"
import Breadcrumbs from "@/components/Breadcrumbs"
import Pagination from "@/components/Pagination"
import PanelContext from "@/contexts/PanelContext"
import drop_files from "@/components/modals/DropFiles"
import {selectContentHeight} from "@/features/ui/uiSlice"
import classes from "./Commander.module.scss"
import {useGetPaginatedNodesQuery} from "@/features/nodes/apiSlice"
Expand Down Expand Up @@ -106,10 +105,10 @@ export default function Commander() {
const onDrop = (event: React.DragEvent<HTMLDivElement>) => {
setDragOver(false)
event.preventDefault()
drop_files({
source_files: event.dataTransfer.files,
target: currentFolder!
}).then(() => {})
//drop_files({
// source_files: event.dataTransfer.files,
// target: currentFolder!
//}).then(() => {})
}

const nodes = data.items.map((n: NodeType) => (
Expand Down
37 changes: 26 additions & 11 deletions ui2/src/features/nodes/components/UploadButton.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import {useState} from "react"
import {useAppSelector} from "@/app/hooks"
import {FileButton, ActionIcon, Tooltip} from "@mantine/core"
import {useDisclosure} from "@mantine/hooks"
import {IconUpload} from "@tabler/icons-react"
import drop_files from "@/components/modals/DropFiles"
import {useContext} from "react"
import PanelContext from "@/contexts/PanelContext"
import {PanelMode} from "@/types"
import {selectCurrentFolderID} from "@/slices/dualPanel/dualPanel"
import {useGetFolderQuery} from "../apiSlice"

import {DropFilesModal} from "@/components/modals/DropFiles"

const MIME_TYPES = [
"image/png",
"image/jpeg",
Expand All @@ -16,6 +19,8 @@ const MIME_TYPES = [
].join(",")

export default function UploadButton() {
const [opened, {open, close}] = useDisclosure(false)
const [uploadFiles, setUploadFiles] = useState<File[]>()
const mode: PanelMode = useContext(PanelContext)
const folderID = useAppSelector(s => selectCurrentFolderID(s, mode))
const {data: target} = useGetFolderQuery(folderID!)
Expand All @@ -29,18 +34,28 @@ export default function UploadButton() {
console.error("Current folder is undefined")
return
}
drop_files({source_files: files, target}).then(() => {})
setUploadFiles(files)
open()
}

return (
<FileButton onChange={onUpload} accept={MIME_TYPES} multiple>
{props => (
<Tooltip label="Upload" withArrow>
<ActionIcon {...props} size="lg" variant="default">
<IconUpload stroke={1.4} />
</ActionIcon>
</Tooltip>
)}
</FileButton>
<>
<FileButton onChange={onUpload} accept={MIME_TYPES} multiple>
{props => (
<Tooltip label="Upload" withArrow>
<ActionIcon {...props} size="lg" variant="default">
<IconUpload stroke={1.4} />
</ActionIcon>
</Tooltip>
)}
</FileButton>
<DropFilesModal
opened={opened}
source_files={uploadFiles!}
target={target!}
onSubmit={close}
onCancel={close}
/>
</>
)
}
23 changes: 14 additions & 9 deletions ui2/src/features/ui/uiSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type DualArg = {
value: number
}

type UpdateFileStatusArg = {
export interface UpdateFileStatusArg {
item: {
source: NodeType | null
target: FolderType
Expand Down Expand Up @@ -88,10 +88,10 @@ const uiSlice = createSlice({
state.uploader.opened = false
state.uploader.files = []
},
openUploader: state => {
state.uploader.opened = true
},
updateFileItem: (state, action: PayloadAction<UpdateFileStatusArg>) => {
uploaderFileItemAdded: (
state,
action: PayloadAction<UpdateFileStatusArg>
) => {
const file_name = action.payload.item.file_name
const target_id = action.payload.item.target.id
const itemToAdd = {
Expand Down Expand Up @@ -122,6 +122,10 @@ const uiSlice = createSlice({
state.uploader.files = newItems
state.uploader.opened = true
},
uploaderFileItemFailed: (
state,
action: PayloadAction<UpdateFileStatusArg>
) => {},
toggleNavBar(state) {
if (state.navbar.collapsed) {
state.navbar.collapsed = false
Expand Down Expand Up @@ -190,9 +194,9 @@ const uiSlice = createSlice({
}
})
export const {
openUploader,
closeUploader,
updateFileItem,
uploaderFileItemAdded,
uploaderFileItemFailed,
toggleNavBar,
updateOutlet,
updateActionPanel,
Expand All @@ -201,10 +205,11 @@ export const {
} = uiSlice.actions
export default uiSlice.reducer

export const selectOpened = (state: RootState): boolean => state.uploader.opened
export const selectOpened = (state: RootState): boolean =>
state.ui.uploader.opened

export const selectFiles = (state: RootState): Array<FileItemType> =>
state.uploader.files
state.ui.uploader.files

export const selectNavBarCollapsed = (state: RootState) =>
state.ui.navbar.collapsed
Expand Down

0 comments on commit 355132f

Please sign in to comment.