Skip to content
Snippets Groups Projects
Unverified Commit 0db12829 authored by JinSSJ3's avatar JinSSJ3 Committed by GitHub
Browse files

Merge pull request #1 from files-ui/10-Fix-UploadLayer-FileMosaic

10 fix upload layer file mosaic
parents c323d7ca b0aab8c2
No related branches found
No related tags found
No related merge requests found
Showing
with 297 additions and 126 deletions
......@@ -2,14 +2,16 @@
## File Item (mosaic)
- on change progress the loader is reredered again and again, I think that the 3 states or layers must be there from the begining
- [SOLVED]on change progress the loader is reredered again and again, I think that the 3 states or layers must be there from the begining
"preparing", "uploading", "result" - on cancel, the 2nd layer will dissapear, it will not be any big deal
- After uploading, progress must be reiitialized to 0
- [SOLVED] FileiTEMmAINlAYER WORKS STRANGE AT THE TIME NEW fILEiTEM IS ADDED
- Fileptions (menu collapsed from click in option icon)
- [SOLVED] FileItemMainLayer WORKS STRANGE AT THE TIME NEW fILEiTEM IS ADDED
## Dropzone
- When no validation, upload removes all files.
- [SOLVED]: action buttons rendered again and again since they were created again every time "value" prop changed
- [SOLVED]: Uploading works in 2 times (first time stops after setting progress = UPLOADING.progrss), but fails to recover from the manager. [UPDATED]: Problem is at `useDropzoneFileListUpdater.ts` file. The problem is that hook for updating when user wants to interrupt preparing, is called at the begining of the upload process, with value of undefined in all files. It is probably the last update on localFiles outside Dropzone component.
- When file is set from preparing to undefined it can be deleted, however, will appear again if onDelete is called. It would be great to add a reconciliation procedure to support different array sizes in updater hook. Or "canceled" upload status could be added and file Item should not show the "X" button when uploading and canceled. After Upload process, all files with "canceled" upload status should be set to "undefined" again. This can be a workaround.
......
......@@ -3,11 +3,11 @@
## UTILS
- custom icons
- menu icon for FileItem
- Outside actions or buttons for Dropzone
- header and footer custom props
- menu icon for FileItem ( FileOptions (menu collapsed from click in option icon) )
- [DONE]: Outside actions or buttons for Dropzone
- [WIP]:header and footer custom props
- FileItem: checkbox support
- FileItem: detect when width of image is greater than height or viceversa in order to decide the orientation
- [DONE] FileItem: ( smart prop ) detect when width of image is greater than height or viceversa in order to decide the orientation
## Upload
......@@ -25,5 +25,6 @@
- Java spring
## dont know if context would be a good idea
- maybe yes for props like custom buttons for file mosaci
- custom file thumbnails
......@@ -9,7 +9,7 @@
## Phrases
- Stop pain with developing a complex widget, don't need to create a file upload component from scratch
- If you need to do it from scratch, there is an example [show some basic code]
- If you need to do it from scratch, there is an example [show some basic code] Bellow main page component
......
......@@ -64,10 +64,10 @@ export default function AdvancedDropzoneDemo() {
onChange={updateFiles}
minHeight="195px"
value={extFiles}
maxFiles={3}
maxFileSize={2998000 * 20}
/* maxFiles={3}
maxFileSize={2998000 * 20} */
label="Drag'n drop files here or click to browse"
accept=".png,image/*, video/*"
// accept=".png,image/*, video/*"
uploadConfig={{
/* autoUpload: true */
method: "POST",
......
......@@ -35,7 +35,7 @@ const DemoFileMosaicImagePreview: React.FC<DemoFileMosaicImagePreviewProps> = (
preview
/>
) : (
<FileInputButton value={value ? [value] : []} onChange={updateFile} />
<FileInputButton value={value ? [value] : []} onChange={updateFile} accept="image/*"/>
)}
<FileMosaic {...sampleFileProps} alwaysActive info />
</>
......
......@@ -13,14 +13,14 @@ const sampleFilesProps = [
size: 28 * 1024 * 1024,
type: "image/png",
name: "valid file created from props.png",
valid: true,
valid: false,
},
{
id: "fileId-3",
size: 28 * 1024 * 1024,
type: "image/jpeg",
name: "non valid file created from props.jpg",
valid: false,
valid: true,
},
];
......
import * as React from "react";
interface DropzoneActionButtonsProps {}
const DropzoneActionButtons: React.FC<DropzoneActionButtonsProps> = (
props: DropzoneActionButtonsProps
) => {
return <div>DropzoneActionButtons</div>;
};
export default DropzoneActionButtons;
......@@ -53,6 +53,7 @@ const DropzoneButtons: React.FC<DropzoneButtonsProps> = (
containerClassName
);
return (
<div className={finalClassName} style={containerStyle}>
{actionButtonsList.map(
......
......@@ -675,7 +675,24 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => {
if (!dropzoneClassName) return <></>;
return (
<React.Fragment>
<DropzoneActionButtons visible={actionButtonsPosition === "top"} />
{actionButtonsPosition === "top" && (
<DropzoneButtons
abortButton={isUploading ? abortButton : undefined}
onAbort={handleAbortUpload}
deleteButton={deleteButton}
onDelete={!isUploading ? handleReset : undefined}
uploadButton={!isUploading && !autoUpload ? uploadButton : undefined}
onUpload={!autoUpload ? () => uploadfiles(localFiles) : undefined}
cleanButton={
validateFilesFlag && !isUploading && !autoClean
? cleanButton
: undefined
}
onClean={handleClean}
style={containerStyle}
className={containerClassName}
/>
)}
<div
style={style}
className={dropzoneClassName}
......@@ -752,7 +769,24 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => {
<DropzoneDisabledLayer open={disabled} />
</div>
<DropzoneActionButtons visible={actionButtonsPosition === "bottom"} />
{actionButtonsPosition === "bottom" && (
<DropzoneButtons
abortButton={isUploading ? abortButton : undefined}
onAbort={handleAbortUpload}
deleteButton={deleteButton}
onDelete={!isUploading ? handleReset : undefined}
uploadButton={!isUploading && !autoUpload ? uploadButton : undefined}
onUpload={!autoUpload ? () => uploadfiles(localFiles) : undefined}
cleanButton={
validateFilesFlag && !isUploading && !autoClean
? cleanButton
: undefined
}
onClean={handleClean}
style={containerStyle}
className={containerClassName}
/>
)}
</React.Fragment>
);
};
......
......@@ -7,14 +7,16 @@ import {
LocalLabels,
UPLOADSTATUS,
} from "../../../../core";
import {
CheckCircle,
Clear,
//CloudDone,
DoDisturb,
//UploadError,
} from "../../../icons";
import { CheckCircle, Clear, DoDisturb } from "../../../icons";
import { DynamicLoader } from "../../../loader";
import {
AbortedStatus,
EmptyStatus,
ErrorStatus,
PreparingStatus,
SuccessStatus,
UploadingStatus,
} from "../../../file-status";
const FileMosaicUploadLayer: React.FC<FileMosaicUploadLayerProps> = (
props: FileMosaicUploadLayerProps
......@@ -48,118 +50,54 @@ const FileMosaicUploadLayer: React.FC<FileMosaicUploadLayerProps> = (
0 - (statusHistory.length - 1) * 132 + "px";
};
React.useEffect(() => {
if (statusHistory.length > 1) {
elevate();
}
if (statusHistory.length > 1) elevate();
// eslint-disable-next-line
}, [statusHistory.length]);
const PreparingStatus = React.useMemo(
() => () =>
(
<React.Fragment>
<InfiniteLoader onClick={onCancel} size={65} />
<span>{FileItemStatusLocalizer.preparing as string}</span>
</React.Fragment>
),
[]
);
const UploadingStatus = React.useMemo(
() => () =>
(
<React.Fragment>
{progress !== undefined ? (
<DynamicLoader
size={70}
x={35}
y={35}
radius={32}
percentage={progress}
width={6}
hidePerncentage={progress === undefined || onAbort !== undefined}
onClick={onAbort}
/>
) : (
<InfiniteLoader onClick={onAbort} size={70} />
)}
<span> {FileItemStatusLocalizer.uploading as string}</span>
</React.Fragment>
),
[progress, onAbort, FileItemStatusLocalizer]
);
const SuccessStatus = () => {
return (
<React.Fragment>
<CheckCircle
color="#4caf50"
size={65}
//style={{ backgroundColor: "rgba(255,255,255,0.8)", borderRadius: "50%", padding: 8 }}
/>
<span> {FileItemStatusLocalizer.success as string}</span>
</React.Fragment>
);
};
const ErrorStatus = () => {
return (
<React.Fragment>
<Clear
color="rgba(255,255,255,0.4)"
style={{
backgroundColor: "rgba(244, 67, 54, 0.8)",
borderRadius: "50%",
}}
size={65}
/>
<span> {FileItemStatusLocalizer.error as string}</span>
</React.Fragment>
);
};
const AbortedStatus = () => {
return (
<React.Fragment>
<DoDisturb color="#f44336" size={65} />
<span> {FileItemStatusLocalizer.aborted as string}</span>
</React.Fragment>
);
};
const Empty = () => {
return (
<React.Fragment>
<div style={{ width: "100%", height: "132px" }}>
{/* <span> VACIOOOOO</span> */}
</div>
</React.Fragment>
);
};
const StatusSelector = (status: UPLOADSTATUS | undefined) => {
switch (status) {
case "preparing":
return <PreparingStatus />;
case "uploading":
return <UploadingStatus />;
case "error":
return <ErrorStatus />;
case "success":
return <SuccessStatus />;
case "aborted":
return <AbortedStatus />;
default:
return <Empty />;
}
};
//default phase
return (
<div className={"elevation-layer-container"} ref={elevationContainerRef}>
<div className="elevation-list" ref={listContainerStoryRef}>
{statusHistory.map((status, index) => {
return (
<div className="elevation-item" key={index + 1}>
{StatusSelector(status)}
</div>
);
switch (status) {
case "preparing":
return (
<div className="elevation-item" key={index + 1}>
<PreparingStatus onCancel={onCancel}/>
</div>
);
case "uploading":
return (
<div className="elevation-item" key={index + 1}>
<UploadingStatus onAbort={onAbort} progress={progress}/>
</div>
);
case "error":
return (
<div className="elevation-item" key={index + 1}>
<ErrorStatus />
</div>
);
case "success":
return (
<div className="elevation-item" key={index + 1}>
<SuccessStatus />
</div>
);
case "aborted":
return (
<div className="elevation-item" key={index + 1}>
<AbortedStatus />
</div>
);
default:
return (
<div className="elevation-item" key={index + 1}>
<EmptyStatus />
</div>
);
}
})}
</div>
</div>
......
import * as React from "react";
import { FileItemLocalizerSelector, LocalLabels } from "../../core";
import { DoDisturb } from "../icons";
import { FileStatusProps } from "./FileStatusProps";
interface AbortedStatusProps extends FileStatusProps {}
const AbortedStatus: React.FC<AbortedStatusProps> = (
props: AbortedStatusProps
) => {
const { localization, size } = props;
const FileItemStatusLocalizer: LocalLabels = FileItemLocalizerSelector(
localization
).status as LocalLabels;
return (
<React.Fragment>
<DoDisturb color="#f44336" size={size || 65} />
<span> {FileItemStatusLocalizer.aborted as string}</span>
</React.Fragment>
);
};
export default AbortedStatus;
import * as React from "react";
interface EmptyStatusProps {
height?: string | number;
}
const EmptyStatus: React.FC<EmptyStatusProps> = (props: EmptyStatusProps) => {
const { height } = props;
const finalHeight: string = !height
? "132px"
: typeof height === "number"
? `${height}px`
: height;
return (
<React.Fragment>
<div style={{ width: "100%", height: finalHeight }}>
{/* <span> EMPTY </span> */}
</div>
</React.Fragment>
);
};
export default EmptyStatus;
import * as React from "react";
import { FileItemLocalizerSelector, LocalLabels } from "../../core";
import { Clear } from "../icons";
import { FileStatusProps } from "./FileStatusProps";
interface ErrorStatusProps extends FileStatusProps {}
const ErrorStatus: React.FC<ErrorStatusProps> = (props: ErrorStatusProps) => {
const { localization, size } = props;
const FileItemStatusLocalizer: LocalLabels = FileItemLocalizerSelector(
localization
).status as LocalLabels;
return (
<React.Fragment>
<Clear
color="rgba(255,255,255,0.4)"
style={{
backgroundColor: "rgba(244, 67, 54, 0.8)",
borderRadius: "50%",
}}
size={size || 65}
/>
<span> {FileItemStatusLocalizer.error as string}</span>
</React.Fragment>
);
};
export default ErrorStatus;
import { Localization } from "../../core";
export type FileStatusProps = {
localization?: Localization;
size?: number;
}
\ No newline at end of file
import * as React from "react";
import { FileItemLocalizerSelector, LocalLabels } from "../../core";
import InfiniteLoader from "../loader/InfiniteLoader/InfiniteLoader";
import { FileStatusProps } from "./FileStatusProps";
export type PreparingStatusProps = {
[P in keyof FileStatusProps]: FileStatusProps[P];
} & {
onCancel?: Function;
};
const PreparingStatus: React.FC<PreparingStatusProps> = (
props: PreparingStatusProps
) => {
const { onCancel, localization, size } = props;
const FileItemStatusLocalizer: LocalLabels = FileItemLocalizerSelector(
localization
).status as LocalLabels;
return (
<React.Fragment>
<InfiniteLoader onClick={onCancel} size={size || 65} />
<span>{FileItemStatusLocalizer.preparing as string}</span>
</React.Fragment>
);
};
export default PreparingStatus;
import * as React from "react";
import { FileItemLocalizerSelector, LocalLabels } from "../../core";
import { CheckCircle } from "../icons";
import { FileStatusProps } from "./FileStatusProps";
interface SuccessStatusProps extends FileStatusProps {}
const SuccessStatus: React.FC<SuccessStatusProps> = (
props: SuccessStatusProps
) => {
const { localization, size } = props;
const FileItemStatusLocalizer: LocalLabels = FileItemLocalizerSelector(
localization
).status as LocalLabels;
return (
<React.Fragment>
<CheckCircle
color="#4caf50"
size={size || 65}
//style={{ backgroundColor: "rgba(255,255,255,0.8)", borderRadius: "50%", padding: 8 }}
/>
<span> {FileItemStatusLocalizer.success as string}</span>
</React.Fragment>
);
};
export default SuccessStatus;
import * as React from "react";
import { FileItemLocalizerSelector, LocalLabels } from "../../core";
import { DynamicLoader } from "../loader";
import InfiniteLoader from "../loader/InfiniteLoader/InfiniteLoader";
import { FileStatusProps } from "./FileStatusProps";
export type UploadingStatusProps = {
[P in keyof FileStatusProps]: FileStatusProps[P];
} & {
onAbort?: Function;
progress?: number;
};
const UploadingStatus: React.FC<UploadingStatusProps> = (
props: UploadingStatusProps
) => {
const { localization, size, onAbort, progress } = props;
const FileItemStatusLocalizer: LocalLabels = FileItemLocalizerSelector(
localization
).status as LocalLabels;
return (
<React.Fragment>
{progress !== undefined ? (
<DynamicLoader
size={70}
x={35}
y={35}
radius={32}
percentage={progress}
width={6}
hidePerncentage={progress === undefined || onAbort !== undefined}
onClick={onAbort}
/>
) : (
<InfiniteLoader onClick={onAbort} size={size || 70} />
)}
<span> {FileItemStatusLocalizer.uploading as string}</span>
</React.Fragment>
);
};
export default UploadingStatus;
export { default as AbortedStatus } from "./AbortedStatus";
export * from "./AbortedStatus";
export { default as EmptyStatus } from "./EmptyStatus";
export * from "./EmptyStatus";
export { default as ErrorStatus } from "./ErrorStatus";
export * from "./ErrorStatus";
export { default as PreparingStatus } from "./PreparingStatus";
export * from "./PreparingStatus";
export { default as SuccessStatus } from "./SuccessStatus";
export * from "./SuccessStatus";
export { default as UploadingStatus } from "./UploadingStatus";
export * from "./UploadingStatus";
export type { FileStatusProps } from "./FileStatusProps";
\ No newline at end of file
......@@ -47,6 +47,7 @@ const MaterialButton: React.FC<MaterialButtonProps> = (
onClick?.(e as React.MouseEvent<HTMLButtonElement, MouseEvent>);
}
if (materialButtonClassName!==undefined || resetStyles)
return React.createElement(href ? "a" : "button", {
className: resetStyles && className ? className : materialButtonClassName,
......
......@@ -12,6 +12,8 @@ const useMaterialButtonClassName = (
idClassName?: number | string,
resetStyles?: boolean
): string | undefined => {
console.log("useMaterialButtonClassName", variant, disabled, color, textColor,
textDecoration, className, idClassName, resetStyles);
const baseClassName: string = "material-button-root material-button";
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment