@addsign/moje-agenda-shared-lib 2.0.9 → 2.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Button.js +2 -2
- package/dist/components/Button.js.map +1 -1
- package/dist/components/form/FileInputMultiple.js +15 -8
- package/dist/components/form/FileInputMultiple.js.map +1 -1
- package/lib/components/Button.tsx +2 -2
- package/lib/components/form/FileInputMultiple.tsx +21 -8
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import "../tailwind-l0sNRNKZ.js";
|
|
3
3
|
import Spinner from "./Spinner.js";
|
|
4
|
-
const commonStyles = " py-1 px-4 leading-[32px] min-h-[32px] w-fit rounded-lg whitespace-nowrap font-medium disabled:opacity-50 flex items-center gap-2";
|
|
4
|
+
const commonStyles = " py-1 px-4 leading-[32px] min-h-[32px] w-fit rounded-lg whitespace-nowrap font-medium disabled:opacity-50 flex items-center gap-2 ";
|
|
5
5
|
const buttonStyles = {
|
|
6
6
|
primary: "!bg-primary hover:!bg-primary-hover text-primary-text ",
|
|
7
7
|
secondary: "!bg-secondary hover:!bg-secondary-hover text-secondary-text border border-secondary-border ",
|
|
@@ -19,7 +19,7 @@ const Button = ({
|
|
|
19
19
|
className,
|
|
20
20
|
...props
|
|
21
21
|
}) => {
|
|
22
|
-
const classNames = commonStyles + buttonStyles[variant];
|
|
22
|
+
const classNames = commonStyles + " " + buttonStyles[variant];
|
|
23
23
|
return /* @__PURE__ */ jsxs(
|
|
24
24
|
"button",
|
|
25
25
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sources":["../../lib/components/Button.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport \"../css/tailwind.css\";\r\nimport Spinner from \"./Spinner\";\r\n\r\ntype ButtonVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"transparent\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"icon\";\r\n\r\ninterface IButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n variant?: ButtonVariant;\r\n isLoading?: boolean;\r\n}\r\nconst commonStyles =\r\n \" py-1 px-4 leading-[32px] min-h-[32px] w-fit rounded-lg whitespace-nowrap font-medium disabled:opacity-50 flex items-center gap-2\";\r\nconst buttonStyles: { [key in ButtonVariant]: string } = {\r\n primary: \"!bg-primary hover:!bg-primary-hover text-primary-text \",\r\n secondary:\r\n \"!bg-secondary hover:!bg-secondary-hover text-secondary-text border border-secondary-border \",\r\n transparent:\r\n \"!bg-transparent border border-transparent hover:bg-gray-100 hover:border-gray-200 \",\r\n success: \"!bg-success hover:!bg-success-hover text-success-text \",\r\n danger: \"!bg-danger hover:!bg-danger-hover text-danger-text \",\r\n warning:\r\n \"!bg-warning hover:!bg-warning-hover text-warning-text border border-warning-border\",\r\n icon: \" !rounded-full text-center inline-flex items-center \",\r\n};\r\nconst Button: React.FC<IButtonProps> = ({\r\n variant = \"primary\",\r\n isLoading = false,\r\n children,\r\n onClick,\r\n className,\r\n ...props\r\n}) => {\r\n const classNames = commonStyles + buttonStyles[variant];\r\n return (\r\n <button\r\n className={classNames + \" \" + (className || \" sharedLibraryource \")}\r\n onClick={onClick}\r\n {...props}\r\n >\r\n {children}\r\n {isLoading && (\r\n <span className=\"ml-2 inline-flex \">\r\n <Spinner />{\" \"}\r\n </span>\r\n )}\r\n </button>\r\n );\r\n};\r\n\r\nexport default Button;\r\n"],"names":[],"mappings":";;;AAiBA,MAAM,eACJ;AACF,MAAM,eAAmD;AAAA,EACvD,SAAS;AAAA,EACT,WACE;AAAA,EACF,aACE;AAAA,EACF,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SACE;AAAA,EACF,MAAM;AACR;AACA,MAAM,SAAiC,CAAC;AAAA,EACtC,UAAU;AAAA,EACV,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../../lib/components/Button.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport \"../css/tailwind.css\";\r\nimport Spinner from \"./Spinner\";\r\n\r\ntype ButtonVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"transparent\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"icon\";\r\n\r\ninterface IButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n variant?: ButtonVariant;\r\n isLoading?: boolean;\r\n}\r\nconst commonStyles =\r\n \" py-1 px-4 leading-[32px] min-h-[32px] w-fit rounded-lg whitespace-nowrap font-medium disabled:opacity-50 flex items-center gap-2 \";\r\nconst buttonStyles: { [key in ButtonVariant]: string } = {\r\n primary: \"!bg-primary hover:!bg-primary-hover text-primary-text \",\r\n secondary:\r\n \"!bg-secondary hover:!bg-secondary-hover text-secondary-text border border-secondary-border \",\r\n transparent:\r\n \"!bg-transparent border border-transparent hover:bg-gray-100 hover:border-gray-200 \",\r\n success: \"!bg-success hover:!bg-success-hover text-success-text \",\r\n danger: \"!bg-danger hover:!bg-danger-hover text-danger-text \",\r\n warning:\r\n \"!bg-warning hover:!bg-warning-hover text-warning-text border border-warning-border\",\r\n icon: \" !rounded-full text-center inline-flex items-center \",\r\n};\r\nconst Button: React.FC<IButtonProps> = ({\r\n variant = \"primary\",\r\n isLoading = false,\r\n children,\r\n onClick,\r\n className,\r\n ...props\r\n}) => {\r\n const classNames = commonStyles + \" \" + buttonStyles[variant];\r\n return (\r\n <button\r\n className={classNames + \" \" + (className || \" sharedLibraryource \")}\r\n onClick={onClick}\r\n {...props}\r\n >\r\n {children}\r\n {isLoading && (\r\n <span className=\"ml-2 inline-flex \">\r\n <Spinner />{\" \"}\r\n </span>\r\n )}\r\n </button>\r\n );\r\n};\r\n\r\nexport default Button;\r\n"],"names":[],"mappings":";;;AAiBA,MAAM,eACJ;AACF,MAAM,eAAmD;AAAA,EACvD,SAAS;AAAA,EACT,WACE;AAAA,EACF,aACE;AAAA,EACF,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SACE;AAAA,EACF,MAAM;AACR;AACA,MAAM,SAAiC,CAAC;AAAA,EACtC,UAAU;AAAA,EACV,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,aAAa,eAAe,MAAM,aAAa,OAAO;AAE1D,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,aAAa,OAAO,aAAa;AAAA,MAC5C;AAAA,MACC,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA;AAAA,QACA,aACC,qBAAC,QAAK,EAAA,WAAU,qBACd,UAAA;AAAA,UAAA,oBAAC,SAAQ,EAAA;AAAA,UAAG;AAAA,QAAA,GACd;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;"}
|
|
@@ -24,6 +24,7 @@ import "../ui/button.js";
|
|
|
24
24
|
import "../../Calendar-DWT4e7Th.js";
|
|
25
25
|
import "../ui/DateTimePicker.js";
|
|
26
26
|
import "../ui/DatePicker.js";
|
|
27
|
+
const MAX_FILE_SIZE = 1024 * 1024;
|
|
27
28
|
const FileInputMultiple = ({
|
|
28
29
|
initialFiles = [],
|
|
29
30
|
onFilesChanged,
|
|
@@ -43,6 +44,15 @@ const FileInputMultiple = ({
|
|
|
43
44
|
async (acceptedFiles) => {
|
|
44
45
|
const uploadedFiles = await Promise.all(
|
|
45
46
|
acceptedFiles.map(async (file) => {
|
|
47
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
48
|
+
federationContext.emitter.emit("message", {
|
|
49
|
+
title: "Velikost souboru byla překročena",
|
|
50
|
+
message: `Maximální povolená velikost je ${MAX_FILE_SIZE / (1024 * 1024)} MB.`,
|
|
51
|
+
classes: "bg-danger ",
|
|
52
|
+
timeout: 0
|
|
53
|
+
});
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
46
56
|
const formData = new FormData();
|
|
47
57
|
formData.append("file", file);
|
|
48
58
|
try {
|
|
@@ -69,16 +79,13 @@ const FileInputMultiple = ({
|
|
|
69
79
|
const updatedFileDataList = [...fileDataList, ...validFiles];
|
|
70
80
|
setFileDataList(updatedFileDataList);
|
|
71
81
|
onFilesChanged({
|
|
72
|
-
target: {
|
|
82
|
+
target: {
|
|
83
|
+
name,
|
|
84
|
+
value: updatedFileDataList.map((file) => file.id.toString())
|
|
85
|
+
}
|
|
73
86
|
});
|
|
74
87
|
},
|
|
75
|
-
[
|
|
76
|
-
fileDataList,
|
|
77
|
-
federationContext.apiClient,
|
|
78
|
-
onFilesChanged,
|
|
79
|
-
name,
|
|
80
|
-
federationContext.emitter
|
|
81
|
-
]
|
|
88
|
+
[federationContext, fileDataList, onFilesChanged, name]
|
|
82
89
|
);
|
|
83
90
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
|
84
91
|
onDrop,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileInputMultiple.js","sources":["../../../lib/components/form/FileInputMultiple.tsx"],"sourcesContent":["import React, { useState, useCallback } from \"react\";\r\nimport { useDropzone } from \"react-dropzone\";\r\nimport { MdDeleteOutline, MdInsertDriveFile } from \"react-icons/md\";\r\nimport { IAttachment } from \"../../types\";\r\nimport { handleErrors, useFederationContext } from \"../../main\";\r\nimport { AxiosError } from \"axios\";\r\n\r\ninterface FileInputMultipleProps {\r\n name: string;\r\n label?: string;\r\n initialFiles?: IAttachment[];\r\n onFilesChanged: (e: any) => void;\r\n required?: boolean;\r\n description?: string;\r\n disabled?: boolean;\r\n errors?: { [key: string]: { message: string } };\r\n}\r\n\r\ninterface IAttachmentReadOnly extends IAttachment {\r\n readonly?: boolean;\r\n}\r\nconst FileInputMultiple: React.FC<FileInputMultipleProps> = ({\r\n initialFiles = [],\r\n onFilesChanged,\r\n label,\r\n name,\r\n required,\r\n description,\r\n disabled,\r\n errors = {},\r\n}) => {\r\n const [fileDataList, setFileDataList] = useState<IAttachmentReadOnly[]>(\r\n [...initialFiles].map((file) => ({ ...file, readonly: true }))\r\n );\r\n const federationContext = useFederationContext();\r\n\r\n const onDrop = useCallback(\r\n async (acceptedFiles: File[]) => {\r\n const uploadedFiles = await Promise.all(\r\n acceptedFiles.map(async (file) => {\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n\r\n try {\r\n const response =\r\n await federationContext.apiClient.post<IAttachment>(\r\n \"/files/upload\",\r\n formData,\r\n {\r\n headers: {\r\n \"Content-Type\": \"multipart/form-data\",\r\n },\r\n }\r\n );\r\n return response.data;\r\n } catch (error) {\r\n handleErrors(error as AxiosError, federationContext.emitter);\r\n console.error(\"There was an error!\", error);\r\n return null;\r\n }\r\n })\r\n );\r\n\r\n const validFiles = uploadedFiles.filter(\r\n (file) => file !== null\r\n ) as IAttachment[];\r\n const updatedFileDataList = [...fileDataList, ...validFiles];\r\n setFileDataList(updatedFileDataList);\r\n onFilesChanged({\r\n target: { name, value: updatedFileDataList.map((file) => file.id) },\r\n });\r\n },\r\n [\r\n fileDataList,\r\n federationContext.apiClient,\r\n onFilesChanged,\r\n name,\r\n federationContext.emitter,\r\n ]\r\n );\r\n\r\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\r\n onDrop,\r\n disabled,\r\n });\r\n\r\n const handleRemove = (fileId: number) => {\r\n const updatedFileDataList = fileDataList.filter(\r\n (file) => file.id !== fileId\r\n );\r\n setFileDataList(updatedFileDataList);\r\n onFilesChanged({\r\n target: {\r\n name,\r\n value: updatedFileDataList.map((file) => file.id.toString()),\r\n },\r\n });\r\n };\r\n if (disabled === true && fileDataList.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"w-full min-h-30 flex-col justify-start items-start gap-1.5 inline-flex sharedLibrary\">\r\n <div className=\"self-stretch flex-col justify-start items-start gap-1.5 flex\">\r\n {label && (\r\n <label\r\n className=\"text-slate-700 text-sm leading-tight font-medium\"\r\n htmlFor={name}\r\n >\r\n {label} {required ? \"*\" : \"\"}\r\n </label>\r\n )}\r\n <div\r\n className={\r\n `self-stretch px-3 py-2 rounded-lg justify-start items-center gap-2 outline-none border bg-transparent ` +\r\n ` ${errors[name]?.message ? \"border-red-200\" : \"border-gray-300\"} `\r\n }\r\n >\r\n {!disabled && (\r\n <div\r\n {...getRootProps()}\r\n className={`w-full p-4 border-dashed cursor-pointer \r\n border-2 rounded-lg text-center hover:bg-gray-100\r\n ${isDragActive ? \"border-indigo-300 bg-indigo-50\" : \"border-gray-300\"}`}\r\n >\r\n <input {...getInputProps()} id={name} />\r\n <p className=\"text-gray-500\">\r\n {isDragActive\r\n ? \"Sem přetáhněte soubory\"\r\n : \"Klikněte pro nahrání, nebo nahrajte přetažením souborů\"}\r\n </p>\r\n </div>\r\n )}\r\n <div className=\"w-full\">\r\n {fileDataList.map((file) => (\r\n <div\r\n key={file.id}\r\n className=\"w-full flex items-center justify-between py-2 border-b \"\r\n >\r\n <div className=\"flex items-center content-center\">\r\n <MdInsertDriveFile style={{ fontSize: \"2rem\" }} />\r\n <a\r\n href={`/api/files/download/${file.id}`}\r\n className=\"pl-2 text-left underline text-primary\"\r\n target=\"_blank\"\r\n >\r\n {file.filename}\r\n </a>\r\n </div>\r\n {!disabled && file.readonly !== true && (\r\n <div\r\n onClick={() => handleRemove(file.id)}\r\n className=\"text-gray-600 cursor-pointer hover:text-primary hover:bg-gray-200 rounded-full ml-4\"\r\n >\r\n <MdDeleteOutline\r\n style={{ fontSize: \"1.5rem\", margin: \"10px\" }}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n {description && (\r\n <div\r\n className=\"HintText self-stretch text-slate-600 text-sm font-normal leading-tight\"\r\n id={name + \":description\"}\r\n >\r\n {description}\r\n </div>\r\n )}\r\n {errors[name] && (\r\n <div\r\n className=\"HintText self-stretch text-red-600 text-sm font-normal leading-tight\"\r\n id={name + \":error\"}\r\n >\r\n {errors[name]?.message}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default FileInputMultiple;\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FileInputMultiple.js","sources":["../../../lib/components/form/FileInputMultiple.tsx"],"sourcesContent":["import React, { useState, useCallback } from \"react\";\r\nimport { useDropzone } from \"react-dropzone\";\r\nimport { MdDeleteOutline, MdInsertDriveFile } from \"react-icons/md\";\r\nimport { IAttachment } from \"../../types\";\r\nimport { handleErrors, useFederationContext } from \"../../main\";\r\nimport { AxiosError } from \"axios\";\r\n\r\ninterface FileInputMultipleProps {\r\n name: string;\r\n label?: string;\r\n initialFiles?: IAttachment[];\r\n onFilesChanged: (e: any) => void;\r\n required?: boolean;\r\n description?: string;\r\n disabled?: boolean;\r\n errors?: { [key: string]: { message: string } };\r\n}\r\n\r\ninterface IAttachmentReadOnly extends IAttachment {\r\n readonly?: boolean;\r\n}\r\n\r\nconst MAX_FILE_SIZE = 1024 * 1024; // 1MB\r\n\r\nconst FileInputMultiple: React.FC<FileInputMultipleProps> = ({\r\n initialFiles = [],\r\n onFilesChanged,\r\n label,\r\n name,\r\n required,\r\n description,\r\n disabled,\r\n errors = {},\r\n}) => {\r\n const [fileDataList, setFileDataList] = useState<IAttachmentReadOnly[]>(\r\n [...initialFiles].map((file) => ({ ...file, readonly: true }))\r\n );\r\n const federationContext = useFederationContext();\r\n\r\n const onDrop = useCallback(\r\n async (acceptedFiles: File[]) => {\r\n const uploadedFiles = await Promise.all(\r\n acceptedFiles.map(async (file) => {\r\n if (file.size > MAX_FILE_SIZE) {\r\n // Handle the case when the file size is exceeded\r\n\r\n federationContext.emitter.emit(\"message\", {\r\n title: \"Velikost souboru byla překročena\",\r\n message: `Maximální povolená velikost je ${MAX_FILE_SIZE / (1024 * 1024)} MB.`,\r\n classes: \"bg-danger \",\r\n timeout: 0,\r\n });\r\n\r\n return null;\r\n }\r\n\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n\r\n try {\r\n const response =\r\n await federationContext.apiClient.post<IAttachment>(\r\n \"/files/upload\",\r\n formData,\r\n {\r\n headers: {\r\n \"Content-Type\": \"multipart/form-data\",\r\n },\r\n }\r\n );\r\n return response.data;\r\n } catch (error) {\r\n handleErrors(error as AxiosError, federationContext.emitter);\r\n console.error(\"There was an error!\", error);\r\n return null;\r\n }\r\n })\r\n );\r\n\r\n const validFiles = uploadedFiles.filter(\r\n (file) => file !== null\r\n ) as IAttachment[];\r\n const updatedFileDataList = [...fileDataList, ...validFiles];\r\n setFileDataList(updatedFileDataList);\r\n onFilesChanged({\r\n target: {\r\n name,\r\n value: updatedFileDataList.map((file) => file.id.toString()),\r\n },\r\n });\r\n },\r\n [federationContext, fileDataList, onFilesChanged, name]\r\n );\r\n\r\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\r\n onDrop,\r\n disabled,\r\n });\r\n\r\n const handleRemove = (fileId: number) => {\r\n const updatedFileDataList = fileDataList.filter(\r\n (file) => file.id !== fileId\r\n );\r\n setFileDataList(updatedFileDataList);\r\n onFilesChanged({\r\n target: {\r\n name,\r\n value: updatedFileDataList.map((file) => file.id.toString()),\r\n },\r\n });\r\n };\r\n if (disabled === true && fileDataList.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"w-full min-h-30 flex-col justify-start items-start gap-1.5 inline-flex sharedLibrary\">\r\n <div className=\"self-stretch flex-col justify-start items-start gap-1.5 flex\">\r\n {label && (\r\n <label\r\n className=\"text-slate-700 text-sm leading-tight font-medium\"\r\n htmlFor={name}\r\n >\r\n {label} {required ? \"*\" : \"\"}\r\n </label>\r\n )}\r\n <div\r\n className={\r\n `self-stretch px-3 py-2 rounded-lg justify-start items-center gap-2 outline-none border bg-transparent ` +\r\n ` ${errors[name]?.message ? \"border-red-200\" : \"border-gray-300\"} `\r\n }\r\n >\r\n {!disabled && (\r\n <div\r\n {...getRootProps()}\r\n className={`w-full p-4 border-dashed cursor-pointer \r\n border-2 rounded-lg text-center hover:bg-gray-100\r\n ${isDragActive ? \"border-indigo-300 bg-indigo-50\" : \"border-gray-300\"}`}\r\n >\r\n <input {...getInputProps()} id={name} />\r\n <p className=\"text-gray-500\">\r\n {isDragActive\r\n ? \"Sem přetáhněte soubory\"\r\n : \"Klikněte pro nahrání, nebo nahrajte přetažením souborů\"}\r\n </p>\r\n </div>\r\n )}\r\n <div className=\"w-full\">\r\n {fileDataList.map((file) => (\r\n <div\r\n key={file.id}\r\n className=\"w-full flex items-center justify-between py-2 border-b \"\r\n >\r\n <div className=\"flex items-center content-center\">\r\n <MdInsertDriveFile style={{ fontSize: \"2rem\" }} />\r\n <a\r\n href={`/api/files/download/${file.id}`}\r\n className=\"pl-2 text-left underline text-primary\"\r\n target=\"_blank\"\r\n >\r\n {file.filename}\r\n </a>\r\n </div>\r\n {!disabled && file.readonly !== true && (\r\n <div\r\n onClick={() => handleRemove(file.id)}\r\n className=\"text-gray-600 cursor-pointer hover:text-primary hover:bg-gray-200 rounded-full ml-4\"\r\n >\r\n <MdDeleteOutline\r\n style={{ fontSize: \"1.5rem\", margin: \"10px\" }}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n {description && (\r\n <div\r\n className=\"HintText self-stretch text-slate-600 text-sm font-normal leading-tight\"\r\n id={name + \":description\"}\r\n >\r\n {description}\r\n </div>\r\n )}\r\n {errors[name] && (\r\n <div\r\n className=\"HintText self-stretch text-red-600 text-sm font-normal leading-tight\"\r\n id={name + \":error\"}\r\n >\r\n {errors[name]?.message}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default FileInputMultiple;\r\n"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ interface IButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
16
16
|
isLoading?: boolean;
|
|
17
17
|
}
|
|
18
18
|
const commonStyles =
|
|
19
|
-
" py-1 px-4 leading-[32px] min-h-[32px] w-fit rounded-lg whitespace-nowrap font-medium disabled:opacity-50 flex items-center gap-2";
|
|
19
|
+
" py-1 px-4 leading-[32px] min-h-[32px] w-fit rounded-lg whitespace-nowrap font-medium disabled:opacity-50 flex items-center gap-2 ";
|
|
20
20
|
const buttonStyles: { [key in ButtonVariant]: string } = {
|
|
21
21
|
primary: "!bg-primary hover:!bg-primary-hover text-primary-text ",
|
|
22
22
|
secondary:
|
|
@@ -37,7 +37,7 @@ const Button: React.FC<IButtonProps> = ({
|
|
|
37
37
|
className,
|
|
38
38
|
...props
|
|
39
39
|
}) => {
|
|
40
|
-
const classNames = commonStyles + buttonStyles[variant];
|
|
40
|
+
const classNames = commonStyles + " " + buttonStyles[variant];
|
|
41
41
|
return (
|
|
42
42
|
<button
|
|
43
43
|
className={classNames + " " + (className || " sharedLibraryource ")}
|
|
@@ -19,6 +19,9 @@ interface FileInputMultipleProps {
|
|
|
19
19
|
interface IAttachmentReadOnly extends IAttachment {
|
|
20
20
|
readonly?: boolean;
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
const MAX_FILE_SIZE = 1024 * 1024; // 1MB
|
|
24
|
+
|
|
22
25
|
const FileInputMultiple: React.FC<FileInputMultipleProps> = ({
|
|
23
26
|
initialFiles = [],
|
|
24
27
|
onFilesChanged,
|
|
@@ -38,6 +41,19 @@ const FileInputMultiple: React.FC<FileInputMultipleProps> = ({
|
|
|
38
41
|
async (acceptedFiles: File[]) => {
|
|
39
42
|
const uploadedFiles = await Promise.all(
|
|
40
43
|
acceptedFiles.map(async (file) => {
|
|
44
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
45
|
+
// Handle the case when the file size is exceeded
|
|
46
|
+
|
|
47
|
+
federationContext.emitter.emit("message", {
|
|
48
|
+
title: "Velikost souboru byla překročena",
|
|
49
|
+
message: `Maximální povolená velikost je ${MAX_FILE_SIZE / (1024 * 1024)} MB.`,
|
|
50
|
+
classes: "bg-danger ",
|
|
51
|
+
timeout: 0,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
const formData = new FormData();
|
|
42
58
|
formData.append("file", file);
|
|
43
59
|
|
|
@@ -67,16 +83,13 @@ const FileInputMultiple: React.FC<FileInputMultipleProps> = ({
|
|
|
67
83
|
const updatedFileDataList = [...fileDataList, ...validFiles];
|
|
68
84
|
setFileDataList(updatedFileDataList);
|
|
69
85
|
onFilesChanged({
|
|
70
|
-
target: {
|
|
86
|
+
target: {
|
|
87
|
+
name,
|
|
88
|
+
value: updatedFileDataList.map((file) => file.id.toString()),
|
|
89
|
+
},
|
|
71
90
|
});
|
|
72
91
|
},
|
|
73
|
-
[
|
|
74
|
-
fileDataList,
|
|
75
|
-
federationContext.apiClient,
|
|
76
|
-
onFilesChanged,
|
|
77
|
-
name,
|
|
78
|
-
federationContext.emitter,
|
|
79
|
-
]
|
|
92
|
+
[federationContext, fileDataList, onFilesChanged, name]
|
|
80
93
|
);
|
|
81
94
|
|
|
82
95
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|