@addsign/moje-agenda-shared-lib 2.0.61 → 2.0.63

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.
@@ -1,209 +1,211 @@
1
- import React, { useState, useEffect, useCallback } from "react";
2
- import { useDropzone } from "react-dropzone";
3
- import { handleErrors, useFederationContext } from "../../main";
4
- import { MdDeleteOutline, MdInsertDriveFile } from "react-icons/md";
5
- import { AxiosError } from "axios";
6
-
7
- export interface FileData {
8
- id: number;
9
- mimeType: string;
10
- size: number;
11
- filename: string;
12
- createdByEmpId: string;
13
- created: string;
14
- }
15
-
16
- interface FileInputProps {
17
- name: string;
18
- label?: string;
19
- initialFile?: FileData;
20
- onFileChanged: (e: any) => void;
21
- required?: boolean;
22
- description?: string;
23
- disabled?: boolean;
24
- errors?: { [key: string]: { message: string } };
25
- attachmentName?: string;
26
- }
27
-
28
- const MAX_FILE_SIZE = 1024 * 1024; // 1MB
29
-
30
- const FileInput: React.FC<FileInputProps> = ({
31
- initialFile,
32
- onFileChanged,
33
- label,
34
- name,
35
- required,
36
- description,
37
- disabled,
38
- errors = {},
39
- attachmentName,
40
- }) => {
41
- const [fileData, setFileData] = useState<FileData | null>(
42
- initialFile || null
43
- );
44
- const [isFocused, setIsFocused] = useState(false);
45
-
46
- const federationContext = useFederationContext();
47
- useEffect(() => {
48
- if (initialFile) {
49
- setFileData(initialFile);
50
- }
51
- }, [initialFile]);
52
-
53
- const onDrop = useCallback(
54
- async (acceptedFiles: File[]) => {
55
- if (acceptedFiles.length > 0) {
56
- const file = acceptedFiles[0];
57
-
58
- if (file.size > MAX_FILE_SIZE) {
59
- // Handle the case when the file size is exceeded
60
- federationContext.emitter.emit("message", {
61
- title: "Velikost souboru byla překročena",
62
- message: `Maximální povolená velikost je ${MAX_FILE_SIZE / (1024 * 1024)} MB.`,
63
- classes: "bg-danger ",
64
- timeout: 0,
65
- type: "error",
66
- });
67
- return;
68
- }
69
-
70
- const formData = new FormData();
71
- formData.append("file", file);
72
-
73
- try {
74
- const response = await federationContext.apiClient.post<FileData>(
75
- "/files/upload",
76
- formData,
77
- {
78
- headers: {
79
- "Content-Type": "multipart/form-data",
80
- },
81
- params: attachmentName ? { attachmentName } : undefined,
82
- }
83
- );
84
- setFileData(response.data);
85
- onFileChanged({
86
- target: { name, value: response.data.id.toString() },
87
- });
88
- setIsFocused(false);
89
- } catch (error) {
90
- handleErrors(error as AxiosError, federationContext.emitter);
91
- console.error("There was an error!", error);
92
- }
93
- }
94
- },
95
- [
96
- federationContext.apiClient,
97
- federationContext.emitter,
98
- onFileChanged,
99
- name,
100
- attachmentName,
101
- ]
102
- );
103
-
104
- const { getRootProps, getInputProps, isDragActive } = useDropzone({
105
- onDrop,
106
- disabled,
107
- multiple: false,
108
- });
109
-
110
- const handleRemove = () => {
111
- setFileData(null);
112
- onFileChanged({ target: { name, value: null } });
113
- };
114
-
115
- return (
116
- <div className="w-full min-h-30 flex-col justify-start items-start gap-1.5 inline-flex sharedLibrary">
117
- <div className="self-stretch flex-col justify-start items-start gap-1.5 flex">
118
- {label && (
119
- <label
120
- className="text-slate-700 text-sm leading-tight font-medium"
121
- htmlFor={name}
122
- >
123
- {label} {required ? "*" : ""}
124
- </label>
125
- )}
126
- <div
127
- className={
128
- `self-stretch px-2 py-2 rounded-lg justify-start items-center gap-2 inline-flex outline-none border` +
129
- ` ${
130
- isFocused && !errors[name]?.message
131
- ? "outline-4 outline-indigo-200 outline-offset-0 border-indigo-300"
132
- : ""
133
- }` +
134
- ` ${
135
- isFocused && errors[name]?.message
136
- ? "outline-4 outline-red-200 outline-offset-0 border-none"
137
- : ""
138
- } ` +
139
- ` ${!isFocused && errors[name]?.message ? "border-red-200" : ""} ` +
140
- ` ${disabled ? "bg-gray-100" : "bg-transparent"}`
141
- }
142
- onFocus={() => setIsFocused(true)}
143
- onBlur={() => setIsFocused(false)}
144
- >
145
- <div className="flex relative grow shrink basis-0 min-h-5 lg:min-h-[32px] justify-start items-stretch gap-2 max-w-full ">
146
- {!fileData ? (
147
- <div
148
- {...getRootProps()}
149
- className={`w-full p-4 border-dashed border-2 rounded-lg text-center ${
150
- isDragActive
151
- ? "border-indigo-300 bg-indigo-50"
152
- : "border-gray-300"
153
- }`}
154
- >
155
- <input {...getInputProps()} id={name} />
156
- <p className="text-gray-500">
157
- {isDragActive
158
- ? "Sem přetáhněte soubor"
159
- : "Klikněte pro nahrání, nebo nahrajte přetažením souboru"}
160
- </p>
161
- </div>
162
- ) : (
163
- <div className="w-full flex items-center justify-between">
164
- <div className=" flex">
165
- <MdInsertDriveFile style={{ fontSize: "2rem" }} />
166
- <a
167
- href={`/api/files/download/${fileData.id}`}
168
- className="pl-2 text-left underline text-primary"
169
- target="_blank"
170
- >
171
- {fileData.filename}
172
- </a>
173
- </div>
174
- {!disabled && (
175
- <div
176
- onClick={handleRemove}
177
- className="text-gray-600 cursor-pointer hover:text-primary hover:bg-gray-200 rounded-full ml-4"
178
- >
179
- <MdDeleteOutline
180
- style={{ fontSize: "1.5rem", margin: "15px" }}
181
- />
182
- </div>
183
- )}
184
- </div>
185
- )}
186
- </div>
187
- </div>
188
- </div>
189
- {description && (
190
- <div
191
- className="HintText self-stretch text-slate-600 text-sm font-normal leading-tight"
192
- id={name + ":description"}
193
- >
194
- {description}
195
- </div>
196
- )}
197
- {errors[name] && (
198
- <div
199
- className="HintText self-stretch text-red-600 text-sm font-normal leading-tight"
200
- id={name + ":error"}
201
- >
202
- {errors[name]?.message}
203
- </div>
204
- )}
205
- </div>
206
- );
207
- };
208
-
209
- export default FileInput;
1
+ import React, { useState, useEffect, useCallback } from "react";
2
+ import { useDropzone } from "react-dropzone";
3
+ import { handleErrors, useFederationContext } from "../../main";
4
+ import { MdDeleteOutline, MdInsertDriveFile } from "react-icons/md";
5
+ import { AxiosError } from "axios";
6
+ import { cn } from "../../utils/utils";
7
+
8
+ export interface FileData {
9
+ id: number;
10
+ mimeType: string;
11
+ size: number;
12
+ filename: string;
13
+ createdByEmpId: string;
14
+ created: string;
15
+ }
16
+
17
+ export interface FileInputProps {
18
+ name: string;
19
+ label?: string;
20
+ initialFile?: FileData;
21
+ onFileChanged: (e: any) => void;
22
+ required?: boolean;
23
+ description?: string;
24
+ disabled?: boolean;
25
+ attachmentName?: string;
26
+ attachmentType?: string;
27
+ hasError?: boolean;
28
+ }
29
+
30
+ const MAX_FILE_SIZE = 1024 * 1024; // 1MB
31
+
32
+ const FileInput: React.FC<FileInputProps> = ({
33
+ initialFile,
34
+ onFileChanged,
35
+ label,
36
+ name,
37
+ required,
38
+ description,
39
+ disabled,
40
+ attachmentName,
41
+ attachmentType,
42
+ hasError,
43
+ }) => {
44
+ const [fileData, setFileData] = useState<FileData | null>(
45
+ initialFile || null
46
+ );
47
+ const [isFocused, setIsFocused] = useState(false);
48
+
49
+ const federationContext = useFederationContext();
50
+ useEffect(() => {
51
+ if (initialFile) {
52
+ setFileData(initialFile);
53
+ }
54
+ }, [initialFile]);
55
+
56
+ const onDrop = useCallback(
57
+ async (acceptedFiles: File[]) => {
58
+ if (acceptedFiles.length > 0) {
59
+ const file = acceptedFiles[0];
60
+
61
+ if (file.size > MAX_FILE_SIZE) {
62
+ // Handle the case when the file size is exceeded
63
+ federationContext.emitter.emit("message", {
64
+ title: "Velikost souboru byla překročena",
65
+ message: `Maximální povolená velikost je ${MAX_FILE_SIZE / (1024 * 1024)} MB.`,
66
+ classes: "bg-danger ",
67
+ timeout: 0,
68
+ type: "error",
69
+ });
70
+ return;
71
+ }
72
+
73
+ const formData = new FormData();
74
+
75
+ // Add the JSON data object
76
+ const dataObject = {
77
+ ...(attachmentName && { attachmentName }),
78
+ ...(attachmentType && { attachmentType }),
79
+ };
80
+
81
+ formData.append(
82
+ "data",
83
+ new Blob([JSON.stringify(dataObject)], { type: "application/json" })
84
+ );
85
+ formData.append("file", file);
86
+
87
+ try {
88
+ const response = await federationContext.apiClient.post<FileData>(
89
+ "/files/upload",
90
+ formData,
91
+ {
92
+ headers: {
93
+ "Content-Type": "multipart/form-data",
94
+ },
95
+ }
96
+ );
97
+ setFileData(response.data);
98
+ onFileChanged({
99
+ target: { name, value: response.data.id.toString() },
100
+ });
101
+ setIsFocused(false);
102
+ } catch (error) {
103
+ handleErrors(error as AxiosError, federationContext.emitter);
104
+ console.error("There was an error!", error);
105
+ }
106
+ }
107
+ },
108
+ [
109
+ federationContext.apiClient,
110
+ federationContext.emitter,
111
+ onFileChanged,
112
+ name,
113
+ attachmentName,
114
+ attachmentType,
115
+ ]
116
+ );
117
+
118
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
119
+ onDrop,
120
+ disabled,
121
+ multiple: false,
122
+ });
123
+
124
+ const handleRemove = () => {
125
+ setFileData(null);
126
+ onFileChanged({ target: { name, value: null } });
127
+ };
128
+
129
+ return (
130
+ <div className="w-full min-h-30 flex-col justify-start items-start gap-1.5 inline-flex sharedLibrary">
131
+ <div className="self-stretch flex-col justify-start items-start gap-1.5 flex">
132
+ {label && (
133
+ <label
134
+ className="text-slate-700 text-sm leading-tight font-medium"
135
+ htmlFor={name}
136
+ >
137
+ {label} {required ? "*" : ""}
138
+ </label>
139
+ )}
140
+ <div
141
+ className={cn(
142
+ `self-stretch px-2 py-2 rounded-lg justify-start items-center gap-2 inline-flex outline-none border`,
143
+ isFocused &&
144
+ !hasError &&
145
+ "outline-4 outline-indigo-200 outline-offset-0 border-indigo-300",
146
+
147
+ hasError &&
148
+ "outline-4 outline-red-200 outline-offset-0 border-none",
149
+ !isFocused && hasError && "border-red-200 ",
150
+ disabled ? "bg-gray-100" : "bg-transparent"
151
+ )}
152
+ onFocus={() => setIsFocused(true)}
153
+ onBlur={() => setIsFocused(false)}
154
+ >
155
+ <div className="flex relative grow shrink basis-0 min-h-5 lg:min-h-[32px] justify-start items-stretch gap-2 max-w-full ">
156
+ {!fileData ? (
157
+ <div
158
+ {...getRootProps()}
159
+ className={`w-full p-4 border-dashed border-2 rounded-lg text-center ${
160
+ isDragActive
161
+ ? "border-indigo-300 bg-indigo-50"
162
+ : "border-gray-300"
163
+ }`}
164
+ >
165
+ <input {...getInputProps()} id={name} />
166
+ <p className="text-gray-500">
167
+ {isDragActive
168
+ ? "Sem přetáhněte soubor"
169
+ : "Klikněte pro nahrání, nebo nahrajte přetažením souboru"}
170
+ </p>
171
+ </div>
172
+ ) : (
173
+ <div className="w-full flex items-center justify-between">
174
+ <div className=" flex">
175
+ <MdInsertDriveFile style={{ fontSize: "2rem" }} />
176
+ <a
177
+ href={`/api/files/download/${fileData.id}`}
178
+ className="pl-2 text-left underline text-primary"
179
+ target="_blank"
180
+ >
181
+ {fileData.filename}
182
+ </a>
183
+ </div>
184
+ {!disabled && (
185
+ <div
186
+ onClick={handleRemove}
187
+ className="text-gray-600 cursor-pointer hover:text-primary hover:bg-gray-200 rounded-full ml-4"
188
+ >
189
+ <MdDeleteOutline
190
+ style={{ fontSize: "1.5rem", margin: "15px" }}
191
+ />
192
+ </div>
193
+ )}
194
+ </div>
195
+ )}
196
+ </div>
197
+ </div>
198
+ </div>
199
+ {description && (
200
+ <div
201
+ className="HintText self-stretch text-slate-600 text-sm font-normal leading-tight"
202
+ id={name + ":description"}
203
+ >
204
+ {description}
205
+ </div>
206
+ )}
207
+ </div>
208
+ );
209
+ };
210
+
211
+ export default FileInput;
@@ -4,6 +4,7 @@ import { MdDeleteOutline, MdInsertDriveFile } from "react-icons/md";
4
4
  import { IAttachment } from "../../types";
5
5
  import { handleErrors, useFederationContext } from "../../main";
6
6
  import { AxiosError } from "axios";
7
+ import { cn } from "../../utils/utils";
7
8
 
8
9
  interface FileInputMultipleProps {
9
10
  name: string;
@@ -13,9 +14,10 @@ interface FileInputMultipleProps {
13
14
  required?: boolean;
14
15
  description?: string;
15
16
  disabled?: boolean;
16
- errors?: { [key: string]: { message: string } };
17
17
  initialFilesReadOnly?: boolean;
18
18
  attachmentName?: string;
19
+ attachmentType?: string;
20
+ hasError?: boolean;
19
21
  }
20
22
 
21
23
  interface IAttachmentReadOnly extends IAttachment {
@@ -32,9 +34,10 @@ const FileInputMultiple: React.FC<FileInputMultipleProps> = ({
32
34
  required,
33
35
  description,
34
36
  disabled,
35
- errors = {},
36
37
  initialFilesReadOnly = true,
37
38
  attachmentName,
39
+ attachmentType,
40
+ hasError,
38
41
  }) => {
39
42
  const [fileDataList, setFileDataList] = useState<IAttachmentReadOnly[]>(
40
43
  initialFiles
@@ -80,6 +83,17 @@ const FileInputMultiple: React.FC<FileInputMultipleProps> = ({
80
83
  }
81
84
 
82
85
  const formData = new FormData();
86
+
87
+ // Add the JSON data object
88
+ const dataObject = {
89
+ ...(attachmentName && { attachmentName }),
90
+ ...(attachmentType && { attachmentType }),
91
+ };
92
+
93
+ formData.append(
94
+ "data",
95
+ new Blob([JSON.stringify(dataObject)], { type: "application/json" })
96
+ );
83
97
  formData.append("file", file);
84
98
 
85
99
  try {
@@ -91,7 +105,6 @@ const FileInputMultiple: React.FC<FileInputMultipleProps> = ({
91
105
  headers: {
92
106
  "Content-Type": "multipart/form-data",
93
107
  },
94
- params: attachmentName ? { attachmentName } : undefined,
95
108
  }
96
109
  );
97
110
  return response.data;
@@ -151,10 +164,12 @@ const FileInputMultiple: React.FC<FileInputMultipleProps> = ({
151
164
  </label>
152
165
  )}
153
166
  <div
154
- className={
155
- `self-stretch px-3 py-2 rounded-lg justify-start items-center gap-2 outline-none border bg-transparent ` +
156
- ` ${errors[name]?.message ? "border-red-200" : "border-gray-300"} `
157
- }
167
+ className={cn(
168
+ `self-stretch px-3 py-2 rounded-lg justify-start items-center gap-2 outline-none border bg-transparent `,
169
+ hasError &&
170
+ "outline-4 outline-red-200 outline-offset-0 border-none ",
171
+ disabled ? "bg-gray-100" : "bg-transparent"
172
+ )}
158
173
  >
159
174
  {!disabled && (
160
175
  <div
@@ -210,14 +225,6 @@ const FileInputMultiple: React.FC<FileInputMultipleProps> = ({
210
225
  {description}
211
226
  </div>
212
227
  )}
213
- {errors[name] && (
214
- <div
215
- className="HintText self-stretch text-red-600 text-sm font-normal leading-tight"
216
- id={name + ":error"}
217
- >
218
- {errors[name]?.message}
219
- </div>
220
- )}
221
228
  </div>
222
229
  );
223
230
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@addsign/moje-agenda-shared-lib",
3
3
  "private": false,
4
- "version": "2.0.61",
4
+ "version": "2.0.63",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",
7
7
  "types": "dist/main.d.ts",