proje-react-panel 1.0.17 → 1.1.1

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.
Files changed (119) hide show
  1. package/dist/components/Counter.d.ts +9 -0
  2. package/dist/components/DetailsPage.d.ts +7 -0
  3. package/dist/components/ErrorBoundary.d.ts +16 -0
  4. package/dist/components/ErrorComponent.d.ts +4 -0
  5. package/dist/components/LoadingScreen.d.ts +2 -0
  6. package/dist/components/Login.d.ts +13 -0
  7. package/dist/components/Panel.d.ts +1 -3
  8. package/dist/components/components/Checkbox.d.ts +3 -2
  9. package/dist/components/components/FormField.d.ts +5 -1
  10. package/dist/components/components/InnerForm.d.ts +8 -3
  11. package/dist/components/components/Label.d.ts +3 -2
  12. package/dist/components/components/Uploader.d.ts +8 -0
  13. package/dist/components/components/index.d.ts +1 -1
  14. package/dist/components/components/list/ListPage.d.ts +1 -1
  15. package/dist/components/form/Checkbox.d.ts +7 -0
  16. package/dist/components/form/FormField.d.ts +17 -0
  17. package/dist/components/form/FormPage.d.ts +6 -0
  18. package/dist/components/form/InnerForm.d.ts +10 -0
  19. package/dist/components/form/Label.d.ts +9 -0
  20. package/dist/components/form/Select.d.ts +8 -0
  21. package/dist/components/form/SelectStyles.d.ts +7 -0
  22. package/dist/components/form/Uploader.d.ts +8 -0
  23. package/dist/components/layout/Layout.d.ts +3 -4
  24. package/dist/components/layout/SideBar.d.ts +2 -3
  25. package/dist/components/list/CellField.d.ts +9 -0
  26. package/dist/components/list/Datagrid.d.ts +6 -8
  27. package/dist/components/list/FilterPopup.d.ts +7 -5
  28. package/dist/components/list/ListHeader.d.ts +11 -0
  29. package/dist/components/list/ListPage.d.ts +6 -0
  30. package/dist/components/pages/FormPage.d.ts +8 -2
  31. package/dist/decorators/details/Details.d.ts +11 -0
  32. package/dist/decorators/details/DetailsItem.d.ts +11 -0
  33. package/dist/decorators/details/getDetailsPageMeta.d.ts +8 -0
  34. package/dist/decorators/form/Form.d.ts +16 -5
  35. package/dist/decorators/form/Input.d.ts +14 -9
  36. package/dist/decorators/form/getFormPageMeta.d.ts +10 -0
  37. package/dist/decorators/form/inputs/SelectInput.d.ts +23 -0
  38. package/dist/decorators/list/Cell.d.ts +13 -1
  39. package/dist/decorators/list/List.d.ts +18 -1
  40. package/dist/decorators/list/cells/ImageCell.d.ts +9 -0
  41. package/dist/decorators/list/getListPageMeta.d.ts +8 -0
  42. package/dist/index.cjs.js +1 -1
  43. package/dist/index.d.ts +13 -17
  44. package/dist/index.esm.js +1 -1
  45. package/dist/initPanel.d.ts +1 -1
  46. package/dist/store/store.d.ts +0 -3
  47. package/dist/types/AnyClass.d.ts +2 -1
  48. package/dist/types/getDetailsData.d.ts +1 -0
  49. package/dist/types/initPanelOptions.d.ts +0 -1
  50. package/package.json +1 -1
  51. package/src/assets/icons/svg/check.svg +4 -0
  52. package/src/assets/icons/svg/cross.svg +4 -0
  53. package/src/components/DetailsPage.tsx +55 -0
  54. package/src/components/{components/ErrorComponent.tsx → ErrorComponent.tsx} +1 -1
  55. package/src/components/{pages/Login.tsx → Login.tsx} +2 -2
  56. package/src/components/Panel.tsx +4 -5
  57. package/src/components/form/Checkbox.tsx +21 -0
  58. package/src/components/{components → form}/FormField.tsx +22 -30
  59. package/src/components/form/FormPage.tsx +32 -0
  60. package/src/components/form/InnerForm.tsx +84 -0
  61. package/src/components/form/Label.tsx +21 -0
  62. package/src/components/form/Select.tsx +51 -0
  63. package/src/components/form/SelectStyles.ts +73 -0
  64. package/src/components/form/Uploader.tsx +66 -0
  65. package/src/components/layout/Layout.tsx +29 -32
  66. package/src/components/layout/SideBar.tsx +4 -13
  67. package/src/components/list/CellField.tsx +63 -0
  68. package/src/components/list/Datagrid.tsx +106 -0
  69. package/src/components/{components/list → list}/FilterPopup.tsx +13 -9
  70. package/src/components/list/ListHeader.tsx +47 -0
  71. package/src/components/{components/list → list}/ListPage.tsx +20 -82
  72. package/src/decorators/details/Details.ts +31 -0
  73. package/src/decorators/details/DetailsItem.ts +40 -0
  74. package/src/decorators/details/getDetailsPageMeta.ts +15 -0
  75. package/src/decorators/form/Form.ts +38 -12
  76. package/src/decorators/form/Input.ts +31 -9
  77. package/src/decorators/form/getFormPageMeta.ts +21 -0
  78. package/src/decorators/form/inputs/SelectInput.ts +19 -0
  79. package/src/decorators/list/Cell.ts +41 -1
  80. package/src/decorators/list/List.ts +30 -6
  81. package/src/decorators/list/cells/ImageCell.ts +17 -0
  82. package/src/decorators/list/getListPageMeta.ts +16 -0
  83. package/src/index.ts +33 -24
  84. package/src/initPanel.ts +1 -4
  85. package/src/store/store.ts +0 -5
  86. package/src/styles/components/checkbox.scss +42 -0
  87. package/src/styles/components/uploader.scss +86 -0
  88. package/src/styles/details.scss +62 -0
  89. package/src/styles/form.scss +9 -11
  90. package/src/styles/index.scss +26 -12
  91. package/src/styles/list.scss +3 -1
  92. package/src/types/AnyClass.ts +2 -1
  93. package/src/types/initPanelOptions.ts +1 -3
  94. package/src/components/components/Checkbox.tsx +0 -9
  95. package/src/components/components/ImageUploader.tsx +0 -301
  96. package/src/components/components/InnerForm.tsx +0 -74
  97. package/src/components/components/Label.tsx +0 -15
  98. package/src/components/components/index.ts +0 -8
  99. package/src/components/components/list/Datagrid.tsx +0 -127
  100. package/src/components/pages/ControllerDetails.tsx +0 -37
  101. package/src/components/pages/FormPage.tsx +0 -34
  102. package/src/decorators/Crud.ts +0 -20
  103. package/src/decorators/form/FormOptions.ts +0 -8
  104. package/src/decorators/form/getFormFields.ts +0 -13
  105. package/src/decorators/list/GetCellFields.ts +0 -13
  106. package/src/decorators/list/ImageCell.ts +0 -13
  107. package/src/decorators/list/ListData.ts +0 -7
  108. package/src/decorators/list/getListFields.ts +0 -10
  109. package/src/styles/image-uploader.scss +0 -94
  110. package/src/types/Screen.ts +0 -4
  111. package/src/types/ScreenCreatorData.ts +0 -14
  112. package/src/utils/createScreens.ts +0 -5
  113. package/src/utils/getFields.ts +0 -22
  114. /package/src/components/{components/Counter.tsx → Counter.tsx} +0 -0
  115. /package/src/components/{components/ErrorBoundary.tsx → ErrorBoundary.tsx} +0 -0
  116. /package/src/components/{components/LoadingScreen.tsx → LoadingScreen.tsx} +0 -0
  117. /package/src/components/{components/list → list}/EmptyList.tsx +0 -0
  118. /package/src/components/{components/list → list}/Pagination.tsx +0 -0
  119. /package/src/components/{components/list → list}/index.ts +0 -0
@@ -1,301 +0,0 @@
1
- import React, { useEffect } from "react";
2
- import { useFormContext } from "react-hook-form";
3
- import { bytesToSize } from "../../utils/format";
4
-
5
- interface ThumbnailImageProps {
6
- name: string;
7
- src: string;
8
- size: number;
9
- style?: React.CSSProperties;
10
- }
11
-
12
- interface MultipleImageUploaderProps {
13
- value?: Array<{ file: File; image: string; remove?: boolean }>;
14
- onError?: (error: string | null) => void;
15
- onClear?: () => void;
16
- reset?: any;
17
- onFilesChange?: (files: File[]) => void;
18
- }
19
-
20
- interface FileWithPreview {
21
- file: File;
22
- image: string;
23
- }
24
-
25
- const uploadState = Object.freeze({
26
- BEFORE: "before",
27
- HOVER: "hover",
28
- AFTER: "after",
29
- } as const);
30
-
31
- type UploadStateType = (typeof uploadState)[keyof typeof uploadState];
32
-
33
- function ThumbnailImage(props: ThumbnailImageProps) {
34
- return (
35
- <div>
36
- <img {...props} style={{ width: 100 }} />
37
- <p>
38
- {props.name} <span style={{ whiteSpace: "none" }}>({bytesToSize(props.size)})</span>
39
- </p>
40
- </div>
41
- );
42
- }
43
-
44
- export function ImageUploader() {
45
- const {
46
- register,
47
- formState: { errors },
48
- watch,
49
- setValue,
50
- clearErrors,
51
- setError,
52
- } = useFormContext();
53
- const up = watch("uploader");
54
-
55
- useEffect(() => {
56
- register("uploader", { required: true });
57
- }, [register]);
58
-
59
- return (
60
- <div>
61
- <span className="form-error" style={{ bottom: 2, top: "unset" }}>
62
- {errors.uploader?.type === "required" && "At least 1 image is required!"}
63
- {errors.uploader?.type === "custom" && errors.uploader.message?.toString()}
64
- </span>
65
- <MultipleImageUploader
66
- reset={up}
67
- onError={(data: string | null) => {
68
- if (!data) {
69
- setValue("uploader", { files: [] });
70
- clearErrors("uploader");
71
- } else {
72
- setError("uploader", {
73
- type: "custom",
74
- message: data,
75
- });
76
- }
77
- }}
78
- onClear={() => {
79
- setValue("uploader", { files: [] });
80
- clearErrors("uploader");
81
- }}
82
- onFilesChange={(files) => {
83
- setValue("uploader", { files });
84
- }}
85
- />
86
- </div>
87
- );
88
- }
89
-
90
- export function MultipleImageUploader(props: MultipleImageUploaderProps) {
91
- const [currentUploadState, setUploadState] = React.useState<UploadStateType>(uploadState.BEFORE);
92
- const [images, setImages] = React.useState<Array<{ file: File; image: string; remove?: boolean }>>(
93
- props.value || []
94
- );
95
- const [files, setFiles] = React.useState<FileWithPreview[]>([]);
96
- const [counter, setCounter] = React.useState(0);
97
- console.log("files", files);
98
- const dropzoneElement = React.useRef<HTMLDivElement>(null);
99
- const imageInputRef = React.useRef<HTMLInputElement>(null);
100
-
101
- React.useEffect(() => {
102
- const element = dropzoneElement.current;
103
- if (!element) return;
104
-
105
- const handleDragEnter = (e: DragEvent) => {
106
- e.preventDefault();
107
- e.stopPropagation();
108
- dragEnter();
109
- };
110
-
111
- const handleDragLeave = (e: DragEvent) => {
112
- e.preventDefault();
113
- e.stopPropagation();
114
- dragLeave();
115
- };
116
-
117
- const handleDragOver = (e: DragEvent) => {
118
- e.preventDefault();
119
- e.stopPropagation();
120
- };
121
-
122
- const handleDrop = (e: DragEvent) => {
123
- e.preventDefault();
124
- e.stopPropagation();
125
- setCounter(0);
126
- const droppedFiles = e.dataTransfer?.files;
127
- if (!droppedFiles) return;
128
-
129
- setFiles([]);
130
- setUploadState(uploadState.AFTER);
131
-
132
- const newFiles: File[] = [];
133
- for (let i = 0; i < droppedFiles.length; i++) {
134
- const reader = new FileReader();
135
- reader.onload = (event) => {
136
- if (!event.target) return;
137
- const check = onFileChange([
138
- ...files,
139
- { file: droppedFiles[i], image: event.target.result as string },
140
- ]);
141
- if (check) {
142
- newFiles.push(droppedFiles[i]);
143
- if (imageInputRef.current) {
144
- imageInputRef.current.files = droppedFiles;
145
- }
146
- setFiles([]);
147
- }
148
- // Notify parent of file changes
149
- if (props.onFilesChange) {
150
- props.onFilesChange(newFiles);
151
- }
152
- };
153
- reader.readAsDataURL(droppedFiles[i]);
154
- }
155
- if (imageInputRef.current) {
156
- imageInputRef.current.files = droppedFiles;
157
- }
158
- };
159
-
160
- element.addEventListener("dragenter", handleDragEnter, false);
161
- element.addEventListener("dragleave", handleDragLeave, false);
162
- element.addEventListener("dragover", handleDragOver, false);
163
- element.addEventListener("drop", handleDrop, false);
164
-
165
- return () => {
166
- element.removeEventListener("dragenter", handleDragEnter);
167
- element.removeEventListener("dragleave", handleDragLeave);
168
- element.removeEventListener("dragover", handleDragOver);
169
- element.removeEventListener("drop", handleDrop);
170
- };
171
- }, [files]);
172
-
173
- const dragEnter = () => {
174
- setCounter((prev) => prev + 1);
175
- setUploadState(uploadState.HOVER);
176
- };
177
-
178
- const dragLeave = () => {
179
- setCounter((prev) => {
180
- if (prev - 1 === 0) {
181
- setUploadState(uploadState.BEFORE);
182
- return 0;
183
- }
184
- return prev - 1;
185
- });
186
- };
187
-
188
- const clickRemoveImage = (i: number) => {
189
- const sources = [...images];
190
- sources[i].remove = !sources[i].remove;
191
- setImages(sources);
192
- };
193
-
194
- const clickRemoveFile = () => {
195
- setFiles([]);
196
- if (imageInputRef.current) {
197
- imageInputRef.current.value = "";
198
- }
199
- props.onClear?.();
200
- };
201
-
202
- const checkValid = (filesInner: FileWithPreview[]): string | null => {
203
- if (!filesInner) return null;
204
- if (filesInner.length >= 10) return "you can't send more than 10 images";
205
- for (let i = 0; i < filesInner.length; i++) {
206
- const file = filesInner[i].file;
207
- const split = file.name.split(".");
208
- if (!["png", "jpg", "jpeg"].includes(split[split.length - 1])) {
209
- return `Extension of the file can only be "png", "jpg" or "jpeg" `;
210
- }
211
- if (file) {
212
- if (file.size > 1048576) {
213
- return `Size of "${file.name}" can't be bigger than 1mb`;
214
- }
215
- }
216
- }
217
- return null;
218
- };
219
-
220
- const onFileChange = (filesInner: FileWithPreview[]): string | null => {
221
- const check = checkValid(filesInner);
222
- if (!check) {
223
- setFiles(filesInner);
224
- }
225
- props.onError?.(check);
226
- return check;
227
- };
228
-
229
- const renderImages = () => {
230
- const imageElements = [];
231
- if (files) {
232
- console.log("---->", files);
233
- for (let i = 0; i < files.length; i++) {
234
- let imageClassName = "image";
235
- imageElements.push(
236
- <div key={i} className="image-container">
237
- <div className={imageClassName}>
238
- <ThumbnailImage name={files[i].file.name} src={files[i].image} size={files[i].file.size} />
239
- </div>
240
- </div>
241
- );
242
- }
243
- }
244
- return imageElements;
245
- };
246
-
247
- return (
248
- <div ref={dropzoneElement} className={"multi-image form-element dropzone " + currentUploadState}>
249
- <input ref={imageInputRef} type="file" style={{ display: "none" }} className="target" name={"file"} />
250
- <div className="container">
251
- <button className="trash" onClick={clickRemoveFile} type="button">
252
- Delete All
253
- </button>
254
- {renderImages()}
255
- <div>
256
- <button
257
- type={"button"}
258
- onClick={() => {
259
- const fileInput = document.getElementById("file__") as HTMLInputElement;
260
- if (fileInput) {
261
- fileInput.click();
262
- }
263
- }}
264
- className="plus">
265
- <span>
266
- + Add Image
267
- <p>Drag image here or Select Image</p>
268
- </span>
269
- </button>
270
- </div>
271
- <input
272
- hidden
273
- id={"file__"}
274
- multiple
275
- type={"file"}
276
- onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
277
- const selectedFiles = event.target.files;
278
- if (!selectedFiles) return;
279
-
280
- setFiles([]);
281
- setUploadState(uploadState.AFTER);
282
- for (let i = 0; i < selectedFiles.length; i++) {
283
- const reader = new FileReader();
284
- reader.onload = (eventInner) => {
285
- if (!eventInner.target) return;
286
- onFileChange([
287
- ...files,
288
- { file: selectedFiles[i], image: eventInner.target.result as string },
289
- ]);
290
- };
291
- reader.readAsDataURL(selectedFiles[i]);
292
- }
293
- if (imageInputRef.current) {
294
- imageInputRef.current.files = selectedFiles;
295
- }
296
- }}
297
- />
298
- </div>
299
- </div>
300
- );
301
- }
@@ -1,74 +0,0 @@
1
- import React, { useEffect, useState } from 'react';
2
- import { FormProvider, useForm } from 'react-hook-form';
3
- import { InputOptions } from '../../decorators/form/Input';
4
- import { FormField } from './FormField';
5
- import { FormOptions } from '../../decorators/form/FormOptions';
6
- import { AnyClass } from '../../types/AnyClass';
7
- import { OnSubmitFN, GetDetailsDataFN } from '../pages/FormPage';
8
- import { useParams, useNavigate } from 'react-router';
9
-
10
- interface InnerFormProps<T extends AnyClass> {
11
- formOptions: FormOptions;
12
- onSubmit: OnSubmitFN<T>;
13
- getDetailsData?: GetDetailsDataFN<T>;
14
- redirectBackOnSuccess?: boolean;
15
- }
16
-
17
- export function InnerForm<T extends AnyClass>({
18
- formOptions,
19
- onSubmit,
20
- getDetailsData,
21
- redirectBackOnSuccess,
22
- }: InnerFormProps<T>) {
23
- const params = useParams();
24
- const form = useForm<T>({
25
- resolver: formOptions.resolver,
26
- });
27
- const navigate = useNavigate();
28
- const inputs = formOptions.inputs;
29
- useEffect(() => {
30
- if (getDetailsData) {
31
- getDetailsData(params as Record<string, string>).then(data => {
32
- form.reset({ ...data });
33
- });
34
- }
35
- }, [params, form.reset]);
36
-
37
- return (
38
- <div className="form-wrapper">
39
- <FormProvider {...form}>
40
- <form
41
- onSubmit={form.handleSubmit(
42
- async dataForm => {
43
- await onSubmit(dataForm);
44
- if (redirectBackOnSuccess) {
45
- navigate(-1);
46
- }
47
- },
48
- (errors, event) => {
49
- console.log('error creating creation', errors, event);
50
- }
51
- )}
52
- >
53
- <div>
54
- {inputs?.map((input: InputOptions) => (
55
- <FormField
56
- key={input.name || ''}
57
- input={input}
58
- register={form.register}
59
- error={
60
- input.name
61
- ? { message: (form.formState.errors[input.name as keyof T] as any)?.message }
62
- : undefined
63
- }
64
- />
65
- ))}
66
- <button type="submit" className="submit-button">
67
- Submit
68
- </button>
69
- </div>
70
- </form>
71
- </FormProvider>
72
- </div>
73
- );
74
- }
@@ -1,15 +0,0 @@
1
- import React from 'react';
2
-
3
- interface LabelProps {
4
- htmlFor: string;
5
- label?: string;
6
- fieldName: string;
7
- }
8
-
9
- export function Label({ htmlFor, label, fieldName }: LabelProps) {
10
- return (
11
- <label htmlFor={htmlFor}>
12
- {label ?? fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}
13
- </label>
14
- );
15
- }
@@ -1,8 +0,0 @@
1
- export { InnerForm } from './InnerForm';
2
- export { FormField } from './FormField';
3
- export { LoadingScreen } from './LoadingScreen';
4
- export { Counter } from './Counter';
5
- export { ImageUploader } from './ImageUploader';
6
- export { ErrorComponent } from './ErrorComponent';
7
- export { Label } from './Label';
8
- export { ErrorBoundary } from './ErrorBoundary';
@@ -1,127 +0,0 @@
1
- import React from 'react';
2
- import { CellOptions } from '../../../decorators/list/Cell';
3
- import { Link } from 'react-router';
4
- import { useAppStore } from '../../../store/store';
5
- import { ImageCellOptions } from '../../../decorators/list/ImageCell';
6
- import { ListData } from '../../../decorators/list/ListData';
7
- import { EmptyList } from './EmptyList';
8
- import SearchIcon from '../../../assets/icons/svg/search.svg';
9
- import PencilIcon from '../../../assets/icons/svg/pencil.svg';
10
- import TrashIcon from '../../../assets/icons/svg/trash.svg';
11
-
12
- interface DatagridProps<T> {
13
- data: T[];
14
- listData: ListData<T>;
15
- onRemoveItem?: (item: T) => Promise<void>;
16
- }
17
-
18
- export function Datagrid<T>({ data, listData, onRemoveItem }: DatagridProps<T>) {
19
- const cells = listData.cells;
20
- const listGeneralCells =
21
- typeof listData.list?.cells === 'function'
22
- ? listData.list?.cells?.(data[0])
23
- : listData.list?.cells;
24
-
25
- return (
26
- <div className="datagrid">
27
- {!data || data.length === 0 ? (
28
- <EmptyList />
29
- ) : (
30
- <table className="datagrid-table">
31
- <thead>
32
- <tr>
33
- {cells.map(cellOptions => (
34
- <th key={cellOptions.name}>{cellOptions.title ?? cellOptions.name}</th>
35
- ))}
36
- {listGeneralCells?.details && <th>Details</th>}
37
- {listGeneralCells?.edit && <th>Edit</th>}
38
- {listGeneralCells?.delete && <th>Delete</th>}
39
- </tr>
40
- </thead>
41
- <tbody>
42
- {data.map((item, index) => (
43
- <tr key={index}>
44
- {cells.map(cellOptions => {
45
- // @ts-ignore
46
- const value = item[cellOptions.name];
47
- let render = value ?? '-'; // Default value if the field is undefined or null
48
-
49
- switch (cellOptions.type) {
50
- case 'date':
51
- if (value) {
52
- const date = new Date(value);
53
- render = `${date.getDate().toString().padStart(2, '0')}/${(
54
- date.getMonth() + 1
55
- )
56
- .toString()
57
- .padStart(
58
- 2,
59
- '0'
60
- )}/${date.getFullYear()} ${date.getHours().toString().padStart(2, '0')}:${date
61
- .getMinutes()
62
- .toString()
63
- .padStart(2, '0')}`;
64
- }
65
- break;
66
-
67
- case 'image': {
68
- const imageCellOptions = cellOptions as ImageCellOptions;
69
- render = (
70
- <img
71
- width={100}
72
- height={100}
73
- src={imageCellOptions.baseUrl + value}
74
- style={{ objectFit: 'contain' }}
75
- />
76
- );
77
- break;
78
- }
79
- case 'string':
80
- default:
81
- render = value ? value.toString() : (cellOptions?.placeHolder ?? '-'); // Handles string type or default fallback
82
- break;
83
- }
84
- /*
85
- if (cellOptions.linkTo) {
86
- render = <Link to={cellOptions.linkTo(item)}>{formattedValue}</Link>;
87
- }
88
- */
89
- return <td key={cellOptions.name}>{render}</td>;
90
- })}
91
- {listGeneralCells?.details && (
92
- <td>
93
- <Link to={listGeneralCells.details.path} className="util-cell-link">
94
- <SearchIcon className="icon icon-search" />
95
- <span className="util-cell-label">{listGeneralCells.details.label}</span>
96
- </Link>
97
- </td>
98
- )}
99
- {listGeneralCells?.edit && (
100
- <td>
101
- <Link to={listGeneralCells.edit.path} className="util-cell-link">
102
- <PencilIcon className="icon icon-pencil" />
103
- <span className="util-cell-label">{listGeneralCells.edit.label}</span>
104
- </Link>
105
- </td>
106
- )}
107
- {listGeneralCells?.delete && (
108
- <td>
109
- <a
110
- onClick={() => {
111
- onRemoveItem?.(item);
112
- }}
113
- className="util-cell-link"
114
- >
115
- <TrashIcon className="icon icon-trash" />
116
- <span className="util-cell-label">{listGeneralCells.delete.label}</span>
117
- </a>
118
- </td>
119
- )}
120
- </tr>
121
- ))}
122
- </tbody>
123
- </table>
124
- )}
125
- </div>
126
- );
127
- }
@@ -1,37 +0,0 @@
1
- import { useParams } from 'react-router';
2
- import React, { useEffect, useState } from 'react';
3
- import { Screen } from '../../types/Screen';
4
- import { ErrorComponent } from '../components/ErrorComponent';
5
-
6
- export function ControllerDetails({ screen }: { screen: Screen }) {
7
- const { id } = useParams();
8
- const [data, setData] = useState<any>(null);
9
- const [error, setError] = useState(null);
10
-
11
- useEffect(() => {
12
- if (screen.controller && id) {
13
- /*
14
- CrudApi.details({ ...fetchSettings, token }, screen.controller, id)
15
- .then(res => {
16
- setData(res);
17
- })
18
- .catch((e: any) => {
19
- setError(e);
20
- console.error(e);
21
- });
22
- */
23
- }
24
- }, [id, screen]);
25
-
26
- if (error) {
27
- return <ErrorComponent error={error} />;
28
- }
29
-
30
- return (
31
- <p
32
- dangerouslySetInnerHTML={{
33
- __html: JSON.stringify(data, null, ' ' + '<br/>'),
34
- }}
35
- />
36
- );
37
- }
@@ -1,34 +0,0 @@
1
- import React, { useMemo } from 'react';
2
- import { InnerForm } from '../components';
3
- import { AnyClass } from '../../types/AnyClass';
4
- import { getFormFields } from '../../decorators/form/getFormFields';
5
-
6
- export type GetDetailsDataFN<T> = (param: Record<string, string>) => Promise<T>;
7
- export type OnSubmitFN<T> = (data: T) => Promise<T>;
8
-
9
- export interface FormPageProps<T extends AnyClass> {
10
- model: T;
11
- getDetailsData?: GetDetailsDataFN<T>;
12
- redirect?: string;
13
- onSubmit: OnSubmitFN<T>;
14
- redirectBackOnSuccess?: boolean;
15
- }
16
-
17
- export function FormPage<T extends AnyClass>({
18
- model,
19
- getDetailsData,
20
- onSubmit,
21
- redirect,
22
- redirectBackOnSuccess = true,
23
- ...rest
24
- }: FormPageProps<T>) {
25
- const formOptions = useMemo(() => getFormFields(model), [model]);
26
- return (
27
- <InnerForm
28
- getDetailsData={getDetailsData}
29
- onSubmit={onSubmit}
30
- formOptions={formOptions}
31
- redirectBackOnSuccess={redirectBackOnSuccess}
32
- />
33
- );
34
- }
@@ -1,20 +0,0 @@
1
- import 'reflect-metadata';
2
-
3
- const CRUD_KEY = 'Crud'; // Changed from Symbol to string
4
-
5
- export interface CrudOptions {
6
- controller: string;
7
- }
8
-
9
- export function Crud(options?: CrudOptions): ClassDecorator {
10
- return (target: Function) => {
11
- if (options) {
12
- Reflect.defineMetadata(CRUD_KEY, options, target);
13
- }
14
- };
15
- }
16
-
17
-
18
- export function getClassCrudData(entityClass: any): CrudOptions | undefined {
19
- return Reflect.getMetadata(CRUD_KEY, entityClass);
20
- }
@@ -1,8 +0,0 @@
1
- import { FormConfiguration } from "./Form";
2
- import { InputOptions } from "./Input";
3
-
4
- export interface FormOptions {
5
- resolver: any; //TODO: type
6
- form?: FormConfiguration;
7
- inputs?: InputOptions[];
8
- }
@@ -1,13 +0,0 @@
1
- import { AnyClass } from "../../types/AnyClass";
2
- import { FormOptions } from "./FormOptions";
3
- import { getInputFields } from "./Input";
4
- import { getFormConfiguration } from "./Form";
5
- import { classValidatorResolver } from "@hookform/resolvers/class-validator";
6
-
7
- export function getFormFields<T extends AnyClass>(entityClass: T): FormOptions {
8
- return {
9
- resolver: classValidatorResolver(entityClass as any),
10
- form: getFormConfiguration(entityClass),
11
- inputs: getInputFields<T>(entityClass),
12
- };
13
- }
@@ -1,13 +0,0 @@
1
- import { CELL_KEY, CellOptions } from "./Cell";
2
-
3
- export function getCellFields(entityClass: any): CellOptions[] {
4
- const prototype = entityClass.prototype;
5
- const cellFields: string[] = Reflect.getMetadata(CELL_KEY, prototype) || [];
6
- return cellFields.map((field) => {
7
- const fields = Reflect.getMetadata(`${CELL_KEY.toString()}:${field}:options`, prototype) || {};
8
- return {
9
- ...fields,
10
- name: fields?.name ?? field,
11
- };
12
- });
13
- }
@@ -1,13 +0,0 @@
1
- import "reflect-metadata";
2
- import { Cell, CellOptions } from "./Cell";
3
-
4
- export interface ImageCellOptions extends CellOptions {
5
- baseUrl: string;
6
- }
7
-
8
- export function ImageCell(options?: ImageCellOptions): PropertyDecorator {
9
- return Cell({
10
- ...options,
11
- type: "image",
12
- });
13
- }
@@ -1,7 +0,0 @@
1
- import { ListOptions } from './List';
2
- import { CellOptions } from './Cell';
3
-
4
- export interface ListData<T> {
5
- list?: ListOptions<T>;
6
- cells: CellOptions[];
7
- }
@@ -1,10 +0,0 @@
1
- import { getClassListData } from './List';
2
- import { getCellFields } from './GetCellFields';
3
- import { ListData } from './ListData';
4
-
5
- export function getListFields<T>(entityClass: T): ListData<T> {
6
- return {
7
- list: getClassListData(entityClass),
8
- cells: getCellFields(entityClass),
9
- };
10
- }