From a7a1026a7a39a04401aed81aacf9ba04b9d25e40 Mon Sep 17 00:00:00 2001 From: Jose Manuel Serrano Amaut <a20122128@pucp.pe> Date: Wed, 15 Mar 2023 23:28:47 -0500 Subject: [PATCH] [FEAT]: Add Header and footer config demo components and code --- .../desc-paragraph/DescParagraphProps.ts | 8 +- .../CodeDemoDropzoneFooterConfig.jsx | 89 +++++++++++ .../CodeDemoDropzoneHeaderConfig.jsx | 141 ++++++++++++++++++ .../DemoDropzoneFooterConfig.jsx | 27 ++++ .../DemoDropzoneHeaderConfig.jsx | 42 ++++++ .../DropzoneFooter/DropzoneFooter.tsx | 32 ++-- .../DropzoneHeader/DropzoneHeader.tsx | 3 + .../dropzone/components/dropzone/Dropzone.tsx | 8 +- .../components/dropzone/DropzoneProps.ts | 11 +- .../loader/DynamicLoader/DynamicLoader.tsx | 102 ++++++------- .../loader/InfiniteLoader/InfiniteLoader.tsx | 42 +++--- src/pages/demo/DropzoneDemoPage.jsx | 17 ++- 12 files changed, 424 insertions(+), 98 deletions(-) create mode 100644 src/components/demo-components/dropzone-demo/CodeDemoDropzoneFooterConfig.jsx create mode 100644 src/components/demo-components/dropzone-demo/CodeDemoDropzoneHeaderConfig.jsx create mode 100644 src/components/demo-components/dropzone-demo/DemoDropzoneFooterConfig.jsx create mode 100644 src/components/demo-components/dropzone-demo/DemoDropzoneHeaderConfig.jsx diff --git a/src/components/demo-components/desc-paragraph/DescParagraphProps.ts b/src/components/demo-components/desc-paragraph/DescParagraphProps.ts index 7fddad8..2475dd1 100644 --- a/src/components/demo-components/desc-paragraph/DescParagraphProps.ts +++ b/src/components/demo-components/desc-paragraph/DescParagraphProps.ts @@ -1,6 +1,6 @@ export type DescParagraphProps = { - content?:string; - children?:React.ReactNode; - margin?:string; - darkMode?:boolean; + content?: string; + children?: React.ReactNode; + margin?: string; + darkMode?: boolean; } \ No newline at end of file diff --git a/src/components/demo-components/dropzone-demo/CodeDemoDropzoneFooterConfig.jsx b/src/components/demo-components/dropzone-demo/CodeDemoDropzoneFooterConfig.jsx new file mode 100644 index 0000000..41275fa --- /dev/null +++ b/src/components/demo-components/dropzone-demo/CodeDemoDropzoneFooterConfig.jsx @@ -0,0 +1,89 @@ +import ShowDemoCode from "../../show-demo-code/ShowDemoCode"; +const CodeDemoDropzoneFooterConfig = ({ splittedOnly = false }) => { + return ( + <ShowDemoCode + splittedOnly={splittedOnly} + codeCompleteJS={completeCodeJS} + codeCompleteTS={completeCodeTS} + codeSandboxJS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSandboxTS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSplittedJS={splittedCodeJS} + codeSplittedTS={splittedCodeTS} + /> + ); +}; +export default CodeDemoDropzoneFooterConfig; + +const splittedCodeJS = `<Dropzone + onChange={updateFiles} + value={files} + footerConfig={{ customMessage: "This is a custom message..." }} +> + {files.length > 0 && + files.map((file) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info/> + ))} +</Dropzone>`; +const splittedCodeTS = `<Dropzone + onChange={updateFiles} + value={files} + footerConfig={{ customMessage: "This is a custom message..." }} +> + {files.length > 0 && + files.map((file: ExtFile) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info/> + ))} +</Dropzone>`; +const completeCodeJS = `import * as React from "react"; +import { Dropzone, FileMosaic } from "@files-ui/react"; + +export default function App() { + const [files, setFiles] = React.useState([]); + const updateFiles = (incommingFiles) => { + //do something with the files + setFiles(incommingFiles); + //even your own upload implementation + }; + const removeFile = (id) => { + setFiles(files.filter((x) => x.id !== id)); + }; + return ( + <Dropzone + onChange={updateFiles} + value={files} + footerConfig={{ customMessage: "This is a custom message..." }} + > + {files.length > 0 && + files.map((file) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info /> + ))} + </Dropzone> + ); +};`; + +const completeCodeTS = `import * as React from "react"; +import { Dropzone, FileMosaic, ExtFile } from "@files-ui/react"; + +export default function App() { + const [files, setFiles] = React.useState<ExtFile[]>([]); + const updateFiles = (incommingFiles:ExtFile[]) => { + //do something with the files + setFiles(incommingFiles); + //even your own upload implementation + }; + const removeFile = (id: string | number | undefined) => { + setFiles(files.filter((x: ExtFile) => x.id !== id)); + }; + return ( + <Dropzone + onChange={updateFiles} + value={files} + footerConfig={{ customMessage: "This is a custom message..." }} + > + {files.length > 0 && + files.map((file:ExtFile) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info /> + ))} + </Dropzone> + ); +}`; diff --git a/src/components/demo-components/dropzone-demo/CodeDemoDropzoneHeaderConfig.jsx b/src/components/demo-components/dropzone-demo/CodeDemoDropzoneHeaderConfig.jsx new file mode 100644 index 0000000..a657730 --- /dev/null +++ b/src/components/demo-components/dropzone-demo/CodeDemoDropzoneHeaderConfig.jsx @@ -0,0 +1,141 @@ +import ShowDemoCode from "../../show-demo-code/ShowDemoCode"; +const CodeDemoDropzoneHeaderConfig = ({ splittedOnly = false }) => { + return ( + <ShowDemoCode + splittedOnly={splittedOnly} + codeCompleteJS={completeCodeJS} + codeCompleteTS={completeCodeTS} + codeSandboxJS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSandboxTS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSplittedJS={splittedCodeJS} + codeSplittedTS={splittedCodeTS} + /> + ); +}; +export default CodeDemoDropzoneHeaderConfig; + +const splittedCodeJS = `<Dropzone + onChange={updateFiles} + value={files} + headerConfig={{ + customHeader: ( + <div style={{ display: "flex", justifyContent: "flex-end" }}> + <button + style={{ backgroundColor: "teal", color: "white" }} + onClick={removeAllFiles} + > + delete files + </button> + </div> + ), + }} +> + {files.length > 0 && + files.map((file) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info/> + ))} +</Dropzone>`; +const splittedCodeTS = `<Dropzone + onChange={updateFiles} + value={files} + headerConfig={{ + customHeader: ( + <div style={{ display: "flex", justifyContent: "flex-end" }}> + <button + style={{ backgroundColor: "teal", color: "white" }} + onClick={removeAllFiles} + > + delete files + </button> + </div> + ), + }} +> + {files.length > 0 && + files.map((file: ExtFile) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info/> + ))} +</Dropzone>`; +const completeCodeJS = `import * as React from "react"; +import { Dropzone, FileMosaic } from "@files-ui/react"; + +export default function App() { + const [files, setFiles] = React.useState([]); + const updateFiles = (incommingFiles) => { + //do something with the files + setFiles(incommingFiles); + //even your own upload implementation + }; + const removeFile = (id) => { + setFiles(files.filter((x) => x.id !== id)); + }; + const removeAllFiles = (evt) => { + evt.stopPropagation(); + setFiles([]); + }; + return ( + <Dropzone + onChange={updateFiles} + value={files} + headerConfig={{ + customHeader: ( + <div style={{ display: "flex", justifyContent: "flex-end" }}> + <button + style={{ backgroundColor: "teal", color: "white" }} + onClick={removeAllFiles} + > + delete files + </button> + </div> + ), + }} + > + {files.length > 0 && + files.map((file) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info /> + ))} + </Dropzone> + ); +};`; + +const completeCodeTS = `import * as React from "react"; +import { Dropzone, FileMosaic, ExtFile } from "@files-ui/react"; + +export default function App() { + const [files, setFiles] = React.useState<ExtFile[]>([]); + const updateFiles = (incommingFiles:ExtFile[]) => { + //do something with the files + setFiles(incommingFiles); + //even your own upload implementation + }; + const removeFile = (id: string | number | undefined) => { + setFiles(files.filter((x: ExtFile) => x.id !== id)); + }; + const removeAllFiles = (evt) => { + evt.stopPropagation(); + setFiles([]); + }; + return ( + <Dropzone + onChange={updateFiles} + value={files} + headerConfig={{ + customHeader: ( + <div style={{ display: "flex", justifyContent: "flex-end" }}> + <button + style={{ backgroundColor: "teal", color: "white" }} + onClick={removeAllFiles} + > + delete files + </button> + </div> + ), + }} + > + {files.length > 0 && + files.map((file:ExtFile) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info /> + ))} + </Dropzone> + ); +}`; diff --git a/src/components/demo-components/dropzone-demo/DemoDropzoneFooterConfig.jsx b/src/components/demo-components/dropzone-demo/DemoDropzoneFooterConfig.jsx new file mode 100644 index 0000000..90a0912 --- /dev/null +++ b/src/components/demo-components/dropzone-demo/DemoDropzoneFooterConfig.jsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { Dropzone, FileMosaic } from "../../../files-ui"; + +const DemoDropzoneFooterConfig = (props) => { + const [files, setFiles] = React.useState([]); + const updateFiles = (incommingFiles) => { + //do something with the files + setFiles(incommingFiles); + //even your own upload implementation + }; + const removeFile = (id) => { + setFiles(files.filter((x) => x.id !== id)); + }; + return ( + <Dropzone + onChange={updateFiles} + value={files} + footerConfig={{ customMessage: "This is a custom message..." }} + > + {files.length > 0 && + files.map((file) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info /> + ))} + </Dropzone> + ); +}; +export default DemoDropzoneFooterConfig; diff --git a/src/components/demo-components/dropzone-demo/DemoDropzoneHeaderConfig.jsx b/src/components/demo-components/dropzone-demo/DemoDropzoneHeaderConfig.jsx new file mode 100644 index 0000000..44f44bc --- /dev/null +++ b/src/components/demo-components/dropzone-demo/DemoDropzoneHeaderConfig.jsx @@ -0,0 +1,42 @@ +import * as React from "react"; +import { Dropzone, FileMosaic } from "../../../files-ui"; + +const DemoDropzoneHeaderConfig = (props) => { + const [files, setFiles] = React.useState([]); + const updateFiles = (incommingFiles) => { + //do something with the files + setFiles(incommingFiles); + //even your own upload implementation + }; + const removeFile = (id) => { + setFiles(files.filter((x) => x.id !== id)); + }; + const removeAllFiles = (evt) => { + evt.stopPropagation(); + setFiles([]); + }; + return ( + <Dropzone + onChange={updateFiles} + value={files} + headerConfig={{ + customHeader: ( + <div style={{ display: "flex", justifyContent: "flex-end" }}> + <button + style={{ backgroundColor: "teal", color: "white" }} + onClick={removeAllFiles} + > + delete files + </button> + </div> + ), + }} + > + {files.length > 0 && + files.map((file) => ( + <FileMosaic key={file.id} {...file} onDelete={removeFile} info /> + ))} + </Dropzone> + ); +}; +export default DemoDropzoneHeaderConfig; diff --git a/src/files-ui/components/dropzone/components/DropzoneFooter/DropzoneFooter.tsx b/src/files-ui/components/dropzone/components/DropzoneFooter/DropzoneFooter.tsx index f58a75f..744f067 100644 --- a/src/files-ui/components/dropzone/components/DropzoneFooter/DropzoneFooter.tsx +++ b/src/files-ui/components/dropzone/components/DropzoneFooter/DropzoneFooter.tsx @@ -30,6 +30,7 @@ const DropzoneFooter: React.FC<DropzoneFooterProps> = ( className = "", resetStyles = false, allowedTypesLabel = true, + customMessage = undefined, } = props; const DropzoneFooterLocalizer: LocalLabels = DropzoneLocalizerSelector( @@ -45,9 +46,12 @@ const DropzoneFooter: React.FC<DropzoneFooterProps> = ( } const finalClassName = resetStyles ? className - : addClassName("files-ui-footer files-ui-footer-border-rd-top-bg-color", className); - - const finalStyle = resetStyles + : addClassName( + "files-ui-footer files-ui-footer-border-rd-top-bg-color", + className + ); + + const finalStyle = resetStyles ? style : { ...style, @@ -58,15 +62,19 @@ const DropzoneFooter: React.FC<DropzoneFooterProps> = ( return ( <div className={finalClassName} onClick={handleClick} style={finalStyle}> - <> - {message - ? message - : !accept - ? allowedTypesLabel - ? DropzoneFooterLocalizer.acceptAll - : undefined - : accepCustomMessenger(accept)} - </> + {customMessage ? ( + <>{customMessage}</> + ) : ( + <> + {message + ? message + : !accept + ? allowedTypesLabel + ? DropzoneFooterLocalizer.acceptAll + : undefined + : accepCustomMessenger(accept)} + </> + )} </div> ); }; diff --git a/src/files-ui/components/dropzone/components/DropzoneHeader/DropzoneHeader.tsx b/src/files-ui/components/dropzone/components/DropzoneHeader/DropzoneHeader.tsx index 0405584..d3cb5c4 100644 --- a/src/files-ui/components/dropzone/components/DropzoneHeader/DropzoneHeader.tsx +++ b/src/files-ui/components/dropzone/components/DropzoneHeader/DropzoneHeader.tsx @@ -121,7 +121,10 @@ const DropzoneHeader: React.FC<DropzoneHeaderProps> = ( borderTopLeftRadius: borderRadius, borderTopRightRadius: borderRadius, }; +console.log("headerx resetStyles", resetStyles); +console.log("headerx style", style); +console.log("headerx finalStyle", finalStyle); return ( <div className={finalClassName} onClick={handleClick} style={finalStyle}> {makeHeader().map((HeaderItem, index) => ( diff --git a/src/files-ui/components/dropzone/components/dropzone/Dropzone.tsx b/src/files-ui/components/dropzone/components/dropzone/Dropzone.tsx index 5b0dde5..d1df335 100644 --- a/src/files-ui/components/dropzone/components/dropzone/Dropzone.tsx +++ b/src/files-ui/components/dropzone/components/dropzone/Dropzone.tsx @@ -98,7 +98,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { header, footer, headerConfig = {}, - footerConfg = {}, + footerConfig = {}, //disabled disabled, //open file dialog @@ -150,7 +150,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { noMissingFilesLabel = true, uploadProgressMessage = true, uploadResultMessage = true, - }: FooterConfig = footerConfg; + }: FooterConfig = footerConfig; //console.log("Dropzone props", dropOnLayer); //localizers const DropzoneLocalizer: LocalLabels = @@ -643,7 +643,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { setLocalFiles(localFiles.filter((f) => f.valid)); } }; - +console.log("Dropzone styleHeader",styleHeader); if (!dropzoneClassName) return <></>; return ( <React.Fragment> @@ -748,7 +748,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { accept={accept} message={isUploading ? localMessage : undefined} localization={localization} - {...footerConfg} + {...footerConfig} /> )} </> diff --git a/src/files-ui/components/dropzone/components/dropzone/DropzoneProps.ts b/src/files-ui/components/dropzone/components/dropzone/DropzoneProps.ts index eb77971..2bcd9ff 100644 --- a/src/files-ui/components/dropzone/components/dropzone/DropzoneProps.ts +++ b/src/files-ui/components/dropzone/components/dropzone/DropzoneProps.ts @@ -199,7 +199,7 @@ export interface DropzoneFullProps extends OverridableComponentProps { /** * Configuration related to the dropzone footer */ - footerConfg?: FooterConfig; + footerConfig?: FooterConfig; //DISABLED /** @@ -233,8 +233,8 @@ export type HeaderConfig = { maxFileSize?: boolean; validFilesCount?: boolean; style?: React.CSSProperties; - className?:string; - resetStyles?:boolean; + className?: string; + resetStyles?: boolean; } export type FooterConfig = { @@ -254,12 +254,15 @@ export type FooterConfig = { * */ noMissingFilesLabel?: boolean; + + customMessage?: JSX.Element; + customFooter?: JSX.Element; } export type DropzoneActionButton = { - children?: React.ReactNode; + children?: JSX.Element; label?: string; style?: React.CSSProperties; className?: string; diff --git a/src/files-ui/components/loader/DynamicLoader/DynamicLoader.tsx b/src/files-ui/components/loader/DynamicLoader/DynamicLoader.tsx index 3a3d210..91c3282 100644 --- a/src/files-ui/components/loader/DynamicLoader/DynamicLoader.tsx +++ b/src/files-ui/components/loader/DynamicLoader/DynamicLoader.tsx @@ -75,59 +75,61 @@ const DynamicLoader: React.FC<DynamicLoaderProps> = ( if (percentage !== undefined) return ( <LoaderContainer size={size}> - <svg - className="dui_svg_circle_loader" - xmlns="http://www.w3.org/2000/svg" - xmlnsXlink="http://www.w3.org/1999/xlink" - width={`${finalSize}px`} - height={`${finalSize}px`} - style={finalStyle} - > - <circle - style={{ - transform: "rotate(-90deg)", - transformOrigin: "center", - }} - stroke={color || "#14ff00"} - cx={`${finalX}`} - cy={`${finalY}`} - r={`${finalRadius}`} - strokeWidth={`${width || 8}px`} - //className="circle_loader" - id="circle" - ref={circleRef} - fill="none" - ></circle> + <> + <svg + className="dui_svg_circle_loader" + xmlns="http://www.w3.org/2000/svg" + xmlnsXlink="http://www.w3.org/1999/xlink" + width={`${finalSize}px`} + height={`${finalSize}px`} + style={finalStyle} + > + <circle + style={{ + transform: "rotate(-90deg)", + transformOrigin: "center", + }} + stroke={color || "#14ff00"} + cx={`${finalX}`} + cy={`${finalY}`} + r={`${finalRadius}`} + strokeWidth={`${width || 8}px`} + //className="circle_loader" + id="circle" + ref={circleRef} + fill="none" + ></circle> - {!hidePerncentage && percentage !== undefined && ( - <text - className="dui-text-dynamic-loader" - x={`${finalX}`} - y={`${(finalX * 7) / 6}`} + {!hidePerncentage && percentage !== undefined && ( + <text + className="dui-text-dynamic-loader" + x={`${finalX}`} + y={`${(finalX * 7) / 6}`} + > + {`${percentage.toFixed(0)} %`} + </text> + )} + </svg> + {onClick && ( + <div + style={{ + position: "absolute", + width: "100%", + height: "100%", + display: "flex", + alignItems: "center", + justifyContent: "center", + }} > - {`${percentage.toFixed(0)} %`} - </text> + <Clear + color={"rgba(255,255,255,0.75)"} + size={45} + onClick={onClick} + //colorFill="transparent" + /> + </div> )} - </svg> - {onClick && ( - <div - style={{ - position: "absolute", - width: "100%", - height: "100%", - display: "flex", - alignItems: "center", - justifyContent: "center", - }} - > - <Clear - color={"rgba(255,255,255,0.75)"} - size={45} - onClick={onClick} - //colorFill="transparent" - /> - </div> - )} + </> </LoaderContainer> ); else { diff --git a/src/files-ui/components/loader/InfiniteLoader/InfiniteLoader.tsx b/src/files-ui/components/loader/InfiniteLoader/InfiniteLoader.tsx index 876172f..bafb3ca 100644 --- a/src/files-ui/components/loader/InfiniteLoader/InfiniteLoader.tsx +++ b/src/files-ui/components/loader/InfiniteLoader/InfiniteLoader.tsx @@ -14,26 +14,28 @@ const InfiniteLoader: React.FC<InfiniteLoaderProps> = ( } = props; return ( <LoaderContainer onClick={onClick} size={size}> - <BasePreparingLoader size={size} /> - <div - style={{ - position: "absolute", - width: "100%", - height: "100%", - display: "flex", - alignItems: "center", - justifyContent: "center", - }} - > - {onClick && ( - <Clear - color={"rgba(255,255,255,0.75)"} - size={45} - onClick={onClick} - //colorFill="transparent" - /> - )} - </div> + <> + <BasePreparingLoader size={size} /> + <div + style={{ + position: "absolute", + width: "100%", + height: "100%", + display: "flex", + alignItems: "center", + justifyContent: "center", + }} + > + {onClick && ( + <Clear + color={"rgba(255,255,255,0.75)"} + size={45} + onClick={onClick} + //colorFill="transparent" + /> + )} + </div> + </> </LoaderContainer> ); }; diff --git a/src/pages/demo/DropzoneDemoPage.jsx b/src/pages/demo/DropzoneDemoPage.jsx index e5d4725..0a4395e 100644 --- a/src/pages/demo/DropzoneDemoPage.jsx +++ b/src/pages/demo/DropzoneDemoPage.jsx @@ -20,6 +20,10 @@ import MainParagraph from "../../components/paragraph-main/MainParagraph"; import RightMenu from "../../components/RightMenu/RightMenu"; import TypeHighlight from "../../components/typeHighlight/TypeHighlight"; import AnchorToTab from "../../components/util-components/AnchorToTab"; +import DemoDropzoneFooterConfig from "../../components/demo-components/dropzone-demo/DemoDropzoneFooterConfig"; +import DemoDropzoneHeaderConfig from "../../components/demo-components/dropzone-demo/DemoDropzoneHeaderConfig"; +import CodeDemoDropzoneHeaderConfig from "../../components/demo-components/dropzone-demo/CodeDemoDropzoneHeaderConfig"; +import CodeDemoDropzoneFooterConfig from "../../components/demo-components/dropzone-demo/CodeDemoDropzoneFooterConfig"; const DropzoneDemoPage = (props) => { return ( @@ -332,10 +336,10 @@ const DropzoneDemoPage = (props) => { </DescParagraph> <Paper variant="outlined" style={{ padding: "25px" }}> - <DemoDropzoneActionButtons /> + <DemoDropzoneHeaderConfig /> </Paper> - <CodeDemoDropzoneActionButtons /> + <CodeDemoDropzoneHeaderConfig /> </section> <section id="footer-config"> @@ -376,16 +380,21 @@ const DropzoneDemoPage = (props) => { prop set to <TypeHighlight>false</TypeHighlight> will not display a label when upload starts with no uploadable files. </li> + <li> + Dropzone with the{" "} + <TypeHighlight>footerConfig.customMessage</TypeHighlight> prop + defined will be considered the message to display in the footer. + </li> </ul> By default all of these values are set to{" "} <TypeHighlight>true</TypeHighlight>. </DescParagraph> <Paper variant="outlined" style={{ padding: "25px" }}> - <DemoDropzoneActionButtons /> + <DemoDropzoneFooterConfig /> </Paper> - <CodeDemoDropzoneActionButtons /> + <CodeDemoDropzoneFooterConfig /> </section> <section id="api"> -- GitLab