mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-03 20:27:50 +00:00
feat(file-upload): implement selecting and uploading file via button on the editor toolbar (#15036)
Co-authored-by: Chris Collins <chriscollins3456@gmail.com>
This commit is contained in:
parent
afdf18e370
commit
efae5559fb
@ -147,7 +147,7 @@ class FileDragDropExtension extends NodeExtension<FileDragDropOptions> {
|
||||
}
|
||||
}
|
||||
|
||||
private updateNodeWithUrl(view: EditorView, nodeId: string, url: string): void {
|
||||
public updateNodeWithUrl(view: EditorView, nodeId: string, url: string): void {
|
||||
const { nodePos, nodeToUpdate } = this.findNodeById(view.state, nodeId);
|
||||
|
||||
if (!nodePos || !nodeToUpdate) return;
|
||||
|
||||
@ -0,0 +1,119 @@
|
||||
import { Button, Dropdown, Text, Tooltip, colors } from '@components';
|
||||
import { useRemirrorContext } from '@remirror/react';
|
||||
import { FileArrowUp } from 'phosphor-react';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import {
|
||||
FileDragDropExtension,
|
||||
SUPPORTED_FILE_TYPES,
|
||||
createFileNodeAttributes,
|
||||
validateFile,
|
||||
} from '@components/components/Editor/extensions/fileDragDrop';
|
||||
import { CommandButton } from '@components/components/Editor/toolbar/CommandButton';
|
||||
|
||||
const DropdownContainer = styled.div`
|
||||
box-shadow: 0 4px 12px 0 rgba(9, 1, 61, 0.12);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 8px;
|
||||
gap: 8px;
|
||||
border-radius: 12px;
|
||||
width: 192px;
|
||||
background: ${colors.white};
|
||||
`;
|
||||
|
||||
const StyledText = styled(Text)`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const FileInput = styled.input`
|
||||
display: none;
|
||||
`;
|
||||
|
||||
export const FileUploadButton = () => {
|
||||
const { commands } = useRemirrorContext();
|
||||
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const remirrorContext = useRemirrorContext();
|
||||
const fileExtension = remirrorContext.getExtension(FileDragDropExtension);
|
||||
|
||||
const [showDropdown, setShowDropdown] = useState(false);
|
||||
|
||||
const handlebuttonClick = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const input = event.target as HTMLInputElement;
|
||||
const files = input.files ? Array.from(input.files) : [];
|
||||
if (files.length === 0) return;
|
||||
|
||||
const supportedTypes = SUPPORTED_FILE_TYPES;
|
||||
const { onFileUpload } = fileExtension.options;
|
||||
|
||||
try {
|
||||
// Process files concurrently
|
||||
await Promise.all(
|
||||
files.map(async (file) => {
|
||||
const validation = validateFile(file, { allowedTypes: supportedTypes });
|
||||
if (!validation.isValid) {
|
||||
// TODO: Handle validation errors
|
||||
return;
|
||||
}
|
||||
|
||||
// Create placeholder node
|
||||
const attrs = createFileNodeAttributes(file);
|
||||
commands.insertFileNode({ ...attrs, url: '' });
|
||||
|
||||
// Upload file if handler exists
|
||||
if (onFileUpload) {
|
||||
try {
|
||||
const finalUrl = await onFileUpload(file);
|
||||
fileExtension.updateNodeWithUrl(remirrorContext.view, attrs.id, finalUrl);
|
||||
} catch (uploadError) {
|
||||
// TODO: Handle upload errors
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
// Error processing file - skip silently
|
||||
} finally {
|
||||
input.value = '';
|
||||
setShowDropdown(false);
|
||||
}
|
||||
};
|
||||
|
||||
const dropdownContent = () => (
|
||||
<DropdownContainer>
|
||||
<StyledButton size="sm" onClick={handlebuttonClick}>
|
||||
Choose File
|
||||
</StyledButton>
|
||||
<FileInput ref={fileInputRef} type="file" onChange={handleFileChange} />
|
||||
<StyledText color="gray" size="sm" lineHeight="normal">
|
||||
Max size: 2GB
|
||||
</StyledText>
|
||||
</DropdownContainer>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dropdown open={showDropdown} onOpenChange={(open) => setShowDropdown(open)} dropdownRender={dropdownContent}>
|
||||
<Tooltip title="Upload File">
|
||||
<CommandButton
|
||||
icon={<FileArrowUp size={20} color={colors.gray[1800]} />}
|
||||
onClick={() => setShowDropdown(true)}
|
||||
commandName="uploadFile"
|
||||
/>
|
||||
</Tooltip>
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
@ -17,6 +17,7 @@ import styled from 'styled-components';
|
||||
import { AddImageButton } from '@components/components/Editor/toolbar/AddImageButton';
|
||||
import { AddLinkButton } from '@components/components/Editor/toolbar/AddLinkButton';
|
||||
import { CommandButton } from '@components/components/Editor/toolbar/CommandButton';
|
||||
import { FileUploadButton } from '@components/components/Editor/toolbar/FileUploadButton';
|
||||
import { FontSizeSelect } from '@components/components/Editor/toolbar/FontSizeSelect';
|
||||
import { HeadingMenu } from '@components/components/Editor/toolbar/HeadingMenu';
|
||||
|
||||
@ -127,6 +128,7 @@ export const Toolbar = ({ styles }: Props) => {
|
||||
onClick={() => commands.createTable()}
|
||||
disabled={active.table()} /* Disables nested tables */
|
||||
/>
|
||||
<FileUploadButton />
|
||||
</InnerContainer>
|
||||
</Container>
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user