proje-react-panel 1.0.14-test-3 → 1.0.15

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 (149) hide show
  1. package/.cursor/rules.md +122 -0
  2. package/.cursor/settings.json +57 -0
  3. package/.eslintrc.js +5 -0
  4. package/.eslintrc.json +26 -0
  5. package/.prettierrc +10 -0
  6. package/.vscode/launch.json +17 -0
  7. package/.vscode/settings.json +8 -0
  8. package/PTD.md +234 -0
  9. package/README.md +62 -28
  10. package/dist/api/CrudApi.d.ts +12 -0
  11. package/dist/components/Panel.d.ts +2 -2
  12. package/dist/components/components/Checkbox.d.ts +6 -0
  13. package/dist/components/components/Counter.d.ts +9 -0
  14. package/dist/components/components/FormField.d.ts +12 -0
  15. package/dist/components/components/ImageUploader.d.ts +15 -0
  16. package/dist/components/components/InnerForm.d.ts +12 -0
  17. package/dist/components/components/LoadingScreen.d.ts +2 -0
  18. package/dist/components/components/index.d.ts +8 -0
  19. package/dist/components/layout/Layout.d.ts +2 -1
  20. package/dist/components/layout/SideBar.d.ts +4 -3
  21. package/dist/components/layout/index.d.ts +2 -0
  22. package/dist/components/list/Datagrid.d.ts +8 -0
  23. package/dist/components/list/Pagination.d.ts +11 -0
  24. package/dist/components/list/index.d.ts +0 -0
  25. package/dist/{src/screens → components/pages}/ControllerDetails.d.ts +1 -1
  26. package/dist/components/pages/FormPage.d.ts +11 -0
  27. package/dist/components/pages/ListPage.d.ts +17 -0
  28. package/dist/components/pages/Login.d.ts +13 -0
  29. package/dist/decorators/form/Form.d.ts +6 -0
  30. package/dist/decorators/form/FormOptions.d.ts +7 -0
  31. package/dist/decorators/form/Input.d.ts +13 -0
  32. package/dist/decorators/form/getFormFields.d.ts +3 -0
  33. package/dist/decorators/{Cell.d.ts → list/Cell.d.ts} +2 -2
  34. package/dist/decorators/list/GetCellFields.d.ts +2 -0
  35. package/dist/decorators/list/ImageCell.d.ts +6 -0
  36. package/dist/decorators/list/List.d.ts +5 -0
  37. package/dist/decorators/list/ListData.d.ts +6 -0
  38. package/dist/decorators/list/getListFields.d.ts +2 -0
  39. package/dist/index.cjs.js +1 -1
  40. package/dist/index.d.ts +19 -10
  41. package/dist/index.esm.js +1 -1
  42. package/dist/initPanel.d.ts +2 -2
  43. package/dist/store/store.d.ts +1 -5
  44. package/dist/types/AnyClass.d.ts +1 -0
  45. package/dist/types/ScreenCreatorData.d.ts +5 -3
  46. package/dist/types/initPanelOptions.d.ts +0 -6
  47. package/dist/utils/format.d.ts +1 -0
  48. package/dist/utils/getFields.d.ts +2 -1
  49. package/package.json +5 -4
  50. package/src/api/CrudApi.ts +30 -11
  51. package/src/components/Panel.tsx +11 -11
  52. package/src/components/components/Checkbox.tsx +9 -0
  53. package/src/components/components/Counter.tsx +51 -0
  54. package/src/components/components/FormField.tsx +60 -0
  55. package/src/components/components/ImageUploader.tsx +301 -0
  56. package/src/components/components/InnerForm.tsx +75 -0
  57. package/src/components/components/LoadingScreen.tsx +12 -0
  58. package/src/components/components/index.ts +8 -0
  59. package/src/components/layout/Layout.tsx +7 -3
  60. package/src/components/layout/SideBar.tsx +103 -31
  61. package/src/components/layout/index.ts +2 -0
  62. package/src/components/list/Datagrid.tsx +101 -0
  63. package/src/components/list/Pagination.tsx +110 -0
  64. package/src/components/list/index.ts +1 -0
  65. package/src/components/pages/ControllerDetails.tsx +37 -0
  66. package/src/components/pages/FormPage.tsx +32 -0
  67. package/src/components/pages/ListPage.tsx +85 -0
  68. package/src/components/pages/Login.tsx +79 -0
  69. package/src/decorators/form/Form.ts +18 -0
  70. package/src/decorators/form/FormOptions.ts +8 -0
  71. package/src/decorators/form/Input.ts +52 -0
  72. package/src/decorators/form/getFormFields.ts +13 -0
  73. package/src/decorators/{Cell.ts → list/Cell.ts} +2 -14
  74. package/src/decorators/list/GetCellFields.ts +13 -0
  75. package/src/decorators/list/ImageCell.ts +13 -0
  76. package/src/decorators/list/List.ts +17 -0
  77. package/src/decorators/list/ListData.ts +7 -0
  78. package/src/decorators/list/getListFields.ts +10 -0
  79. package/src/index.ts +23 -10
  80. package/src/initPanel.ts +4 -12
  81. package/src/store/store.ts +23 -28
  82. package/src/styles/_scrollbar.scss +19 -0
  83. package/src/styles/counter.scss +42 -0
  84. package/src/styles/image-uploader.scss +94 -0
  85. package/src/styles/index.scss +30 -7
  86. package/src/styles/layout.scss +1 -6
  87. package/src/styles/list.scss +32 -5
  88. package/src/styles/loading-screen.scss +42 -0
  89. package/src/styles/pagination.scss +66 -0
  90. package/src/styles/sidebar.scss +64 -0
  91. package/src/types/AnyClass.ts +1 -0
  92. package/src/types/ScreenCreatorData.ts +5 -3
  93. package/src/types/initPanelOptions.ts +1 -7
  94. package/src/utils/format.ts +7 -0
  95. package/src/utils/getFields.ts +11 -9
  96. package/dist/api/crudApi.d.ts +0 -17
  97. package/dist/components/Form.d.ts +0 -6
  98. package/dist/components/FormField.d.ts +0 -13
  99. package/dist/components/list/List.d.ts +0 -10
  100. package/dist/components/screens/ControllerCreate.d.ts +0 -5
  101. package/dist/components/screens/ControllerDetails.d.ts +0 -5
  102. package/dist/components/screens/ControllerEdit.d.ts +0 -5
  103. package/dist/components/screens/ControllerList.d.ts +0 -5
  104. package/dist/components/screens/Login.d.ts +0 -2
  105. package/dist/decorators/Input.d.ts +0 -13
  106. package/dist/hooks/useScreens.d.ts +0 -2
  107. package/dist/initPanelOptions.d.ts +0 -8
  108. package/dist/screens/ControllerCreate.d.ts +0 -5
  109. package/dist/screens/ControllerDetails.d.ts +0 -5
  110. package/dist/screens/ControllerEdit.d.ts +0 -5
  111. package/dist/screens/ControllerList.d.ts +0 -5
  112. package/dist/screens/Form.d.ts +0 -6
  113. package/dist/src/api/crudApi.d.ts +0 -6
  114. package/dist/src/components/Panel.d.ts +0 -9
  115. package/dist/src/components/layout/Layout.d.ts +0 -11
  116. package/dist/src/components/layout/SideBar.d.ts +0 -10
  117. package/dist/src/components/list/List.d.ts +0 -10
  118. package/dist/src/decorators/Cell.d.ts +0 -10
  119. package/dist/src/decorators/Crud.d.ts +0 -6
  120. package/dist/src/index.d.ts +0 -8
  121. package/dist/src/screens/ControllerCreate.d.ts +0 -5
  122. package/dist/src/screens/ControllerEdit.d.ts +0 -5
  123. package/dist/src/screens/ControllerList.d.ts +0 -5
  124. package/dist/src/screens/Form.d.ts +0 -6
  125. package/dist/src/store/store.d.ts +0 -19
  126. package/dist/src/types/Screen.d.ts +0 -4
  127. package/dist/src/types/ScreenCreatorData.d.ts +0 -8
  128. package/dist/src/utils/createScreens.d.ts +0 -1
  129. package/dist/src/utils/getFields.d.ts +0 -2
  130. package/dist/src/utils/getScreens.d.ts +0 -2
  131. package/dist/utils/crudScreens.d.ts +0 -2
  132. package/dist/utils/getScreens.d.ts +0 -2
  133. package/src/api/AuthApi.ts +0 -14
  134. package/src/components/Form.tsx +0 -80
  135. package/src/components/FormField.tsx +0 -60
  136. package/src/components/list/List.tsx +0 -81
  137. package/src/components/screens/ControllerCreate.tsx +0 -7
  138. package/src/components/screens/ControllerDetails.tsx +0 -40
  139. package/src/components/screens/ControllerEdit.tsx +0 -35
  140. package/src/components/screens/ControllerList.tsx +0 -45
  141. package/src/components/screens/Login.tsx +0 -68
  142. package/src/decorators/Input.ts +0 -50
  143. package/src/hooks/useScreens.tsx +0 -36
  144. /package/dist/components/{ErrorBoundary.d.ts → components/ErrorBoundary.d.ts} +0 -0
  145. /package/dist/components/{ErrorComponent.d.ts → components/ErrorComponent.d.ts} +0 -0
  146. /package/dist/components/{Label.d.ts → components/Label.d.ts} +0 -0
  147. /package/src/components/{ErrorBoundary.tsx → components/ErrorBoundary.tsx} +0 -0
  148. /package/src/components/{ErrorComponent.tsx → components/ErrorComponent.tsx} +0 -0
  149. /package/src/components/{Label.tsx → components/Label.tsx} +0 -0
@@ -0,0 +1,110 @@
1
+ import React from 'react';
2
+
3
+ interface PaginationProps {
4
+ pagination: {
5
+ total: number;
6
+ page: number;
7
+ limit: number;
8
+ };
9
+ onPageChange: (page: number) => void;
10
+ }
11
+
12
+ export function Pagination({ pagination, onPageChange }: PaginationProps) {
13
+ const { total, page, limit } = pagination;
14
+ const totalPages = Math.floor(total / limit);
15
+
16
+ if (totalPages <= 1) return null;
17
+
18
+ const renderPageNumbers = () => {
19
+ const pages = [];
20
+ const range = 2; // Number of pages to show before and after current page
21
+
22
+ // Always show first 2 pages
23
+ for (let i = 1; i <= Math.min(2, totalPages); i++) {
24
+ pages.push(
25
+ <button
26
+ key={i}
27
+ onClick={() => onPageChange(i)}
28
+ className={`pagination-item ${page === i ? 'active' : ''}`}
29
+ disabled={page === i}
30
+ >
31
+ {i}
32
+ </button>
33
+ );
34
+ }
35
+
36
+ // Add ellipsis if needed
37
+ if (page - range > 3) {
38
+ pages.push(
39
+ <span key="ellipsis1" className="pagination-ellipsis">
40
+ ...
41
+ </span>
42
+ );
43
+ }
44
+
45
+ // Show pages around current page
46
+ for (let i = Math.max(3, page - range); i <= Math.min(totalPages - 2, page + range); i++) {
47
+ if (i > 2 && i < totalPages - 1) {
48
+ pages.push(
49
+ <button
50
+ key={i}
51
+ onClick={() => onPageChange(i)}
52
+ className={`pagination-item ${page === i ? 'active' : ''}`}
53
+ disabled={page === i}
54
+ >
55
+ {i}
56
+ </button>
57
+ );
58
+ }
59
+ }
60
+
61
+ // Add ellipsis if needed
62
+ if (page + range < totalPages - 2) {
63
+ pages.push(
64
+ <span key="ellipsis2" className="pagination-ellipsis">
65
+ ...
66
+ </span>
67
+ );
68
+ }
69
+
70
+ // Always show last 2 pages
71
+ for (let i = Math.max(totalPages - 1, 3); i <= totalPages; i++) {
72
+ if (i > 2) {
73
+ pages.push(
74
+ <button
75
+ key={i}
76
+ onClick={() => onPageChange(i)}
77
+ className={`pagination-item ${page === i ? 'active' : ''}`}
78
+ disabled={page === i}
79
+ >
80
+ {i}
81
+ </button>
82
+ );
83
+ }
84
+ }
85
+
86
+ return pages;
87
+ };
88
+
89
+ return (
90
+ <div className="pagination">
91
+ <button
92
+ onClick={() => onPageChange(page - 1)}
93
+ className={`pagination-item ${page === 1 ? 'disabled' : ''}`}
94
+ disabled={page === 1}
95
+ aria-disabled={page === 1}
96
+ >
97
+ Previous
98
+ </button>
99
+ {renderPageNumbers()}
100
+ <button
101
+ onClick={() => onPageChange(page + 1)}
102
+ className={`pagination-item ${page === totalPages ? 'disabled' : ''}`}
103
+ disabled={page === totalPages}
104
+ aria-disabled={page === totalPages}
105
+ >
106
+ Next
107
+ </button>
108
+ </div>
109
+ );
110
+ }
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,37 @@
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
+ }
@@ -0,0 +1,32 @@
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: 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
+ }
15
+
16
+ export function FormPage<T extends AnyClass>({
17
+ model,
18
+ getDetailsData,
19
+ onSubmit,
20
+ redirect,
21
+ ...rest
22
+ }: FormPageProps<T>) {
23
+ const formOptions = useMemo(() => getFormFields(model), [model]);
24
+ return (
25
+ <InnerForm
26
+ getDetailsData={getDetailsData}
27
+ redirect={redirect}
28
+ onSubmit={onSubmit}
29
+ formOptions={formOptions}
30
+ />
31
+ );
32
+ }
@@ -0,0 +1,85 @@
1
+ import React, { useMemo, useCallback } from 'react';
2
+ import { useEffect, useState } from 'react';
3
+ import { Link, useParams } from 'react-router';
4
+ import { Datagrid } from '../list/Datagrid';
5
+ import { ErrorComponent } from '../components/ErrorComponent';
6
+ import { LoadingScreen } from '../components/LoadingScreen';
7
+ import { AnyClass } from '../../types/AnyClass';
8
+ import { getListFields } from '../../decorators/list/getListFields';
9
+ import { Pagination } from '../list/Pagination';
10
+
11
+ export interface PaginationParams {
12
+ page?: number;
13
+ limit?: number;
14
+ }
15
+
16
+ export interface PaginatedResponse<T> {
17
+ data: T[];
18
+ total: number;
19
+ page: number;
20
+ limit: number;
21
+ }
22
+
23
+ export type GetDataForList<T> = ({
24
+ page,
25
+ }: PaginationParams) => PaginatedResponse<T> | Promise<PaginatedResponse<T>>;
26
+
27
+ export function ListPage<T extends AnyClass>({
28
+ model,
29
+ getData,
30
+ }: {
31
+ model: T;
32
+ getData: GetDataForList<T>;
33
+ }) {
34
+ const [loading, setLoading] = useState(true);
35
+ const [pagination, setPagination] = useState({ total: 0, page: 0, limit: 0 });
36
+ const [data, setData] = useState<any>(null);
37
+ const [error, setError] = useState<unknown | null>(null);
38
+ const listData = useMemo(() => getListFields(model), [model]);
39
+ const params = useParams();
40
+
41
+ const fetchData = useCallback(
42
+ async (page: number) => {
43
+ setLoading(true);
44
+ try {
45
+ const result = await getData({ page });
46
+ setData(result.data);
47
+ setPagination({
48
+ total: result.total,
49
+ page: result.page,
50
+ limit: result.limit,
51
+ });
52
+ } catch (e: unknown) {
53
+ setError(e);
54
+ console.error(e);
55
+ } finally {
56
+ setLoading(false);
57
+ }
58
+ },
59
+ [getData]
60
+ );
61
+
62
+ useEffect(() => {
63
+ fetchData(parseInt(params.page as string) || 1);
64
+ }, [fetchData, params.page]);
65
+
66
+ if (loading) return <LoadingScreen />;
67
+ if (error) return <ErrorComponent error={error} />;
68
+
69
+ return (
70
+ <div className="list">
71
+ <div className="list-header">
72
+ <Link to={'create'}>Create</Link>
73
+ </div>
74
+ <Datagrid cells={listData.cells} data={data} />
75
+ <div className="list-footer">
76
+ <Pagination
77
+ pagination={pagination}
78
+ onPageChange={(page: number) => {
79
+ fetchData(page);
80
+ }}
81
+ />
82
+ </div>
83
+ </div>
84
+ );
85
+ }
@@ -0,0 +1,79 @@
1
+ import React from 'react';
2
+ import { useForm } from 'react-hook-form';
3
+ import { FormField } from '../components/FormField';
4
+ import { useNavigate } from 'react-router';
5
+ import { useAppStore } from '../../store/store';
6
+
7
+ interface LoginFormData {
8
+ username: string;
9
+ password: string;
10
+ }
11
+
12
+ export type OnLogin = {
13
+ login: (username: string, password: string) => Promise<LoginResponse>;
14
+ };
15
+
16
+ interface LoginResponse {
17
+ user: any; // Replace with proper user type if available
18
+ token: string;
19
+ }
20
+
21
+ interface LoginProps {
22
+ onLogin: OnLogin;
23
+ }
24
+
25
+ export function Login({ onLogin }: LoginProps) {
26
+ const {
27
+ register,
28
+ handleSubmit,
29
+ formState: { errors },
30
+ } = useForm<LoginFormData>();
31
+ const navigate = useNavigate();
32
+ const onSubmit = async (data: LoginFormData) => {
33
+ onLogin.login(data.username, data.password).then((dataInner: LoginResponse) => {
34
+ const { user, token } = dataInner;
35
+ localStorage.setItem('token', token);
36
+ useAppStore.setState({ user });
37
+ navigate('/');
38
+ });
39
+ };
40
+
41
+ return (
42
+ <div className="login-container">
43
+ <div className="login-panel">
44
+ <div className="login-header">
45
+ <h1>Welcome Back</h1>
46
+ <p>Please sign in to continue</p>
47
+ </div>
48
+ <form onSubmit={handleSubmit(onSubmit)} className="login-form">
49
+ <FormField
50
+ input={{
51
+ name: 'username',
52
+ label: 'Username',
53
+ placeholder: 'Enter your username',
54
+ type: 'input',
55
+ }}
56
+ register={register}
57
+ error={errors.username}
58
+ />
59
+ <FormField
60
+ input={{
61
+ name: 'password',
62
+ label: 'Password',
63
+ inputType: 'password',
64
+ placeholder: 'Enter your password',
65
+ type: 'input',
66
+ }}
67
+ register={register}
68
+ error={errors.password}
69
+ />
70
+ <div className="form-actions">
71
+ <button type="submit" className="submit-button">
72
+ Sign In
73
+ </button>
74
+ </div>
75
+ </form>
76
+ </div>
77
+ </div>
78
+ );
79
+ }
@@ -0,0 +1,18 @@
1
+ import "reflect-metadata";
2
+ import { AnyClass } from "../../types/AnyClass";
3
+
4
+ const FORM_METADATA_KEY = "FormMetadata"; // More descriptive name indicating it's a metadata key
5
+
6
+ export interface FormConfiguration {} // Better describes that this is configuration/options for the form
7
+
8
+ export function FormDecorator(options?: FormConfiguration): ClassDecorator {
9
+ return (target: Function) => {
10
+ if (options) {
11
+ Reflect.defineMetadata(FORM_METADATA_KEY, options, target);
12
+ }
13
+ };
14
+ }
15
+
16
+ export function getFormConfiguration(entityClass: AnyClass): FormConfiguration | undefined {
17
+ return Reflect.getMetadata(FORM_METADATA_KEY, entityClass);
18
+ }
@@ -0,0 +1,8 @@
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
+ }
@@ -0,0 +1,52 @@
1
+ import 'reflect-metadata';
2
+ import { AnyClass } from '../../types/AnyClass';
3
+
4
+ const INPUT_KEY = Symbol('input');
5
+
6
+ const isFieldSensitive = (fieldName: string): boolean => {
7
+ return ['password'].some(term => fieldName.toLowerCase().includes(term));
8
+ };
9
+
10
+ export interface InputOptions {
11
+ name?: string;
12
+ label?: string;
13
+ placeholder?: string;
14
+ inputType?: 'text' | 'email' | 'tel' | 'password' | 'number' | 'date';
15
+ type?: 'input' | 'select' | 'textarea' | 'file-upload' | 'checkbox' | 'hidden';
16
+ selectOptions?: string[]; //TODO: label/value
17
+ cancelPasswordValidationOnEdit?: boolean;
18
+ }
19
+
20
+ export function Input(options?: InputOptions): PropertyDecorator {
21
+ return (target, propertyKey) => {
22
+ const existingInputs: string[] = Reflect.getMetadata(INPUT_KEY, target) || [];
23
+ Reflect.defineMetadata(INPUT_KEY, [...existingInputs, propertyKey.toString()], target);
24
+
25
+ if (options) {
26
+ const keyString = `${INPUT_KEY.toString()}:${propertyKey.toString()}:options`;
27
+ Reflect.defineMetadata(keyString, options, target);
28
+ }
29
+ };
30
+ }
31
+
32
+ export function getInputFields<T extends AnyClass>(entityClass: T): InputOptions[] {
33
+ const prototype = entityClass.prototype;
34
+ const inputFields: string[] = Reflect.getMetadata(INPUT_KEY, prototype) || [];
35
+ return inputFields.map(field => {
36
+ const fields = Reflect.getMetadata(`${INPUT_KEY.toString()}:${field}:options`, prototype) || {};
37
+ const inputType = fields?.inputType ?? (isFieldSensitive(field) ? 'password' : 'text');
38
+ return {
39
+ ...fields,
40
+ editable: fields.editable ?? true,
41
+ sensitive: fields.sensitive,
42
+ name: fields?.name ?? field,
43
+ label: fields?.label ?? field,
44
+ placeholder: fields?.placeholder ?? field,
45
+ inputType: inputType,
46
+ type: fields?.type ?? 'input',
47
+ selectOptions: fields?.selectOptions ?? [],
48
+ cancelPasswordValidationOnEdit:
49
+ fields?.cancelPasswordValidationOnEdit ?? inputType === 'password',
50
+ };
51
+ });
52
+ }
@@ -0,0 +1,13 @@
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,11 +1,11 @@
1
1
  import "reflect-metadata";
2
2
 
3
- const CELL_KEY = Symbol("cell");
3
+ export const CELL_KEY = Symbol("cell");
4
4
 
5
5
  export interface CellOptions {
6
6
  name?: string;
7
7
  title?: string;
8
- type?: "string" | "number" | "date";
8
+ type?: "string" | "date" | "image";
9
9
  placeHolder?: string;
10
10
  }
11
11
 
@@ -20,15 +20,3 @@ export function Cell(options?: CellOptions): PropertyDecorator {
20
20
  }
21
21
  };
22
22
  }
23
-
24
- export function getCellFields(entityClass: any): CellOptions[] {
25
- const prototype = entityClass.prototype;
26
- const cellFields: string[] = Reflect.getMetadata(CELL_KEY, prototype) || [];
27
- return cellFields.map((field) => {
28
- const fields = Reflect.getMetadata(`${CELL_KEY.toString()}:${field}:options`, prototype) || {};
29
- return {
30
- ...fields,
31
- name: fields?.name ?? field,
32
- };
33
- });
34
- }
@@ -0,0 +1,13 @@
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
+ }
@@ -0,0 +1,13 @@
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
+ }
@@ -0,0 +1,17 @@
1
+ import "reflect-metadata";
2
+
3
+ const LIST_KEY = "List";
4
+
5
+ export interface ListOptions {}
6
+
7
+ export function List(options?: ListOptions): ClassDecorator {
8
+ return (target: Function) => {
9
+ if (options) {
10
+ Reflect.defineMetadata(LIST_KEY, options, target);
11
+ }
12
+ };
13
+ }
14
+
15
+ export function getClassListData(entityClass: any): ListOptions | undefined {
16
+ return Reflect.getMetadata(LIST_KEY, entityClass);
17
+ }
@@ -0,0 +1,7 @@
1
+ import { ListOptions } from "./List";
2
+ import { CellOptions } from "./Cell";
3
+
4
+ export interface ListData {
5
+ list?: ListOptions;
6
+ cells: CellOptions[];
7
+ }
@@ -0,0 +1,10 @@
1
+ import { getClassListData } from "./List";
2
+ import { getCellFields } from "./GetCellFields";
3
+ import { ListData } from "./ListData";
4
+
5
+ export function getListFields<T>(entityClass: T): ListData {
6
+ return {
7
+ list: getClassListData(entityClass),
8
+ cells: getCellFields(entityClass),
9
+ };
10
+ }
package/src/index.ts CHANGED
@@ -1,10 +1,23 @@
1
- export { Login } from "./components/screens/Login";
2
- export { type InitPanelOptions } from "./types/initPanelOptions";
3
- export { type ScreenCreatorData } from "./types/ScreenCreatorData";
4
- export { createScreens } from "./utils/createScreens";
5
- export { useScreens } from "./hooks/useScreens";
6
- export { Crud } from "./decorators/Crud";
7
- export { Cell } from "./decorators/Cell";
8
- export { Input } from "./decorators/Input";
9
- export { Layout } from "./components/layout/Layout";
10
- export { Panel } from "./components/Panel";
1
+ export type { OnSubmitFN, GetDetailsDataFN } from './components/pages/FormPage';
2
+ export type { GetDataForList } from './components/pages/ListPage';
3
+ export type { PaginatedResponse, PaginationParams } from './components/pages/ListPage';
4
+ export type { InitPanelOptions } from './types/initPanelOptions';
5
+ export type { ScreenCreatorData } from './types/ScreenCreatorData';
6
+ export type { OnLogin } from './components/pages/Login';
7
+ export type { AnyClass } from './types/AnyClass';
8
+
9
+ export { ListPage } from './components/pages/ListPage';
10
+ export { FormPage } from './components/pages/FormPage';
11
+ export type { FormPageProps } from './components/pages/FormPage';
12
+ export { Login } from './components/pages/Login';
13
+ export { Layout } from './components/layout/Layout';
14
+ export { Panel } from './components/Panel';
15
+ export { Counter } from './components/components/Counter';
16
+
17
+ //TODO: decerator index.ts ayır
18
+ export { List } from './decorators/list/List';
19
+ export { ImageCell } from './decorators/list/ImageCell';
20
+ export { Crud } from './decorators/Crud';
21
+ export { Cell } from './decorators/list/Cell';
22
+ export { Input } from './decorators/form/Input';
23
+ // Export page components
package/src/initPanel.ts CHANGED
@@ -1,14 +1,6 @@
1
- import { createScreens } from "./utils/createScreens";
2
- import { getFields } from "./utils/getFields";
3
- import { ScreenCreatorData } from "./types/ScreenCreatorData";
4
- import { InitPanelOptions } from "./types/initPanelOptions";
5
- import { useAppStore } from "./store/store";
1
+ import { InitPanelOptions } from './types/initPanelOptions';
2
+ import { useAppStore } from './store/store';
6
3
 
7
- export function initPanel({ crud, fetch, screenPaths }: InitPanelOptions) {
8
- const screensCrudOptions: Record<string, ScreenCreatorData> = {};
9
- Object.entries(crud).forEach(([key, value]) => {
10
- screensCrudOptions[key] = getFields(key, value);
11
- });
12
- createScreens(screensCrudOptions);
13
- useAppStore.setState({ fetchSettings: { baseUrl: fetch.baseURL }, screenPaths });
4
+ export function initPanel({ screenPaths }: InitPanelOptions) {
5
+ useAppStore.setState({ screenPaths });
14
6
  }
@@ -1,37 +1,32 @@
1
- import { createJSONStorage, persist } from "zustand/middleware";
2
- import { createWithEqualityFn } from "zustand/traditional";
3
- import { shallow } from "zustand/vanilla/shallow";
4
- import { ScreenCreatorData } from "../types/ScreenCreatorData";
1
+ import { createJSONStorage, persist } from 'zustand/middleware';
2
+ import { createWithEqualityFn } from 'zustand/traditional';
3
+ import { shallow } from 'zustand/vanilla/shallow';
4
+ import { ScreenCreatorData } from '../types/ScreenCreatorData';
5
5
 
6
6
  interface User {
7
- username: string;
7
+ username: string;
8
8
  }
9
9
 
10
10
  interface AppState {
11
- user: User | null;
12
- screens: Record<string, ScreenCreatorData> | null;
13
- fetchSettings: { baseUrl: string } | null;
14
- screenPaths: Record<string, string>;
15
- token: string | null;
11
+ user: User | null;
12
+ screens: Record<string, ScreenCreatorData> | null;
13
+ screenPaths: Record<string, string>;
16
14
  }
17
15
 
18
16
  export const useAppStore = createWithEqualityFn<AppState>()(
19
- persist(
20
- (_) => ({
21
- screens: null,
22
- user: null,
23
- fetchSettings: null,
24
- screenPaths: {},
25
- token: null,
26
- }),
27
- {
28
- name: "app-store-1",
29
- storage: createJSONStorage(() => localStorage),
30
- partialize: (state) => ({
31
- user: state.user,
32
- token: state.token,
33
- }),
34
- }
35
- ),
36
- shallow
17
+ persist(
18
+ _ => ({
19
+ screens: null,
20
+ user: null,
21
+ screenPaths: {},
22
+ }),
23
+ {
24
+ name: 'app-store-1',
25
+ storage: createJSONStorage(() => localStorage),
26
+ partialize: state => ({
27
+ user: state.user,
28
+ }),
29
+ }
30
+ ),
31
+ shallow
37
32
  );