trithuc-mvc-react 3.0.6 → 3.0.8
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.
|
@@ -15,7 +15,6 @@ import { TableRowRender } from "./TableRowRender";
|
|
|
15
15
|
import TableToolbar from "./TableToolbar";
|
|
16
16
|
import { useDataTable } from "./hooks";
|
|
17
17
|
const defaultQueryOptions = {
|
|
18
|
-
keepPreviousData: true, // Giữ dữ liệu cũ trong khi tải dữ liệu mới
|
|
19
18
|
staleTime: 1000 * 60 * 1, // Thời gian dữ liệu có thể sử dụng lại trước khi gọi lại API
|
|
20
19
|
cacheTime: 1000 * 60 * 30, // Thời gian dữ liệu được lưu trong cache trước khi bị xóa
|
|
21
20
|
refetchOnWindowFocus: true, // Tự động lấy lại dữ liệu khi người dùng quay lại tab
|
|
@@ -181,8 +181,8 @@ export const FilterGod = ({ tableName, filters, elementSize = "small", setPage =
|
|
|
181
181
|
);
|
|
182
182
|
}
|
|
183
183
|
return (
|
|
184
|
-
<Grid key={field} md={size?.md} xs={size?.xs} sm={size?.sm}>
|
|
185
|
-
<FilterElement name={field} {...rest} setPage={setPage} />
|
|
184
|
+
<Grid key={field.toString()} md={size?.md} xs={size?.xs} sm={size?.sm}>
|
|
185
|
+
<FilterElement name={field.toString()} {...rest} setPage={setPage} />
|
|
186
186
|
</Grid>
|
|
187
187
|
);
|
|
188
188
|
})}
|
|
@@ -27,7 +27,7 @@ DataManagement.propTypes = {
|
|
|
27
27
|
filters: PropTypes.arrayOf(
|
|
28
28
|
PropTypes.shape({
|
|
29
29
|
field: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]).isRequired,
|
|
30
|
-
label: PropTypes.string,
|
|
30
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), // Hỗ trợ cả chuỗi và mảng chuỗi
|
|
31
31
|
placeHolder: PropTypes.string,
|
|
32
32
|
type: PropTypes.oneOf([
|
|
33
33
|
"text",
|
|
@@ -46,6 +46,7 @@ DataManagement.propTypes = {
|
|
|
46
46
|
onChangeAfter: PropTypes.func
|
|
47
47
|
})
|
|
48
48
|
).isRequired,
|
|
49
|
+
|
|
49
50
|
editorFields: PropTypes.array,
|
|
50
51
|
validationSchema: PropTypes.object,
|
|
51
52
|
disableStatus: PropTypes.bool,
|
package/hooks/usePermission.js
CHANGED
|
@@ -10,10 +10,8 @@ const usePermission = (tableName) => {
|
|
|
10
10
|
throw new Error("usePermission must be used within a PermissionProvider");
|
|
11
11
|
}
|
|
12
12
|
const { permissionMap, setPermission } = context;
|
|
13
|
-
|
|
14
13
|
const permission = permissionMap[tableName];
|
|
15
|
-
|
|
16
|
-
const { canEdit, canDelete, canDeleteMulti, canSave, canCreate, canAction, canView, canImport } = useMemo(() => {
|
|
14
|
+
const { canEdit, canDelete, canDeleteMulti, canSave, canCreate, canAction, canView, canImport, canExportWord } = useMemo(() => {
|
|
17
15
|
if (permission) {
|
|
18
16
|
if (permission.TrangThaiXuLy !== undefined && permission.ObjTrangThai) {
|
|
19
17
|
const status = permission.ObjTrangThai.find((t) => t.StatusId === permission.TrangThaiXuLy) || {};
|
|
@@ -25,7 +23,8 @@ const usePermission = (tableName) => {
|
|
|
25
23
|
canCreate: status.Create ?? false,
|
|
26
24
|
canAction: status.Action ?? false,
|
|
27
25
|
canView: status.View ?? false,
|
|
28
|
-
canImport: status.ImportFile ?? false
|
|
26
|
+
canImport: status.ImportFile ?? false,
|
|
27
|
+
canExportWord: status.ExportWord ?? false
|
|
29
28
|
};
|
|
30
29
|
} else {
|
|
31
30
|
return {
|
|
@@ -36,7 +35,8 @@ const usePermission = (tableName) => {
|
|
|
36
35
|
canCreate: permission.Create ?? false,
|
|
37
36
|
canAction: permission.Action ?? false,
|
|
38
37
|
canView: permission.View ?? false,
|
|
39
|
-
canImport: permission.ImportFile ?? false
|
|
38
|
+
canImport: permission.ImportFile ?? false,
|
|
39
|
+
canExportWord: permission.ExportWord ?? false
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
} else {
|
|
@@ -49,7 +49,8 @@ const usePermission = (tableName) => {
|
|
|
49
49
|
canCreate: false,
|
|
50
50
|
canAction: false,
|
|
51
51
|
canView: false,
|
|
52
|
-
canImport: false
|
|
52
|
+
canImport: false,
|
|
53
|
+
canExportWord: false
|
|
53
54
|
};
|
|
54
55
|
}
|
|
55
56
|
}, [permission]);
|
|
@@ -58,6 +59,18 @@ const usePermission = (tableName) => {
|
|
|
58
59
|
setPermission({ ...permissionMap, [tableName]: permission });
|
|
59
60
|
};
|
|
60
61
|
|
|
61
|
-
return {
|
|
62
|
+
return {
|
|
63
|
+
permission,
|
|
64
|
+
set,
|
|
65
|
+
canEdit,
|
|
66
|
+
canDelete,
|
|
67
|
+
canDeleteMulti,
|
|
68
|
+
canSave,
|
|
69
|
+
canCreate,
|
|
70
|
+
canAction,
|
|
71
|
+
canView,
|
|
72
|
+
canImport,
|
|
73
|
+
canExportWord
|
|
74
|
+
};
|
|
62
75
|
};
|
|
63
76
|
export default usePermission;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trithuc-mvc-react",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.8",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
},
|
|
14
14
|
"description": "",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@emotion/react": "^11.13.
|
|
17
|
-
"@emotion/styled": "^11.13.
|
|
16
|
+
"@emotion/react": "^11.13.5",
|
|
17
|
+
"@emotion/styled": "^11.13.5",
|
|
18
18
|
"@hookform/resolvers": "^3.9.1",
|
|
19
19
|
"@iconify/react": "^5.0.2",
|
|
20
20
|
"axios": "^1.7.7",
|
|
21
|
-
"date-fns": "^
|
|
21
|
+
"date-fns": "^3.6.0",
|
|
22
22
|
"lodash": "^4.17.21",
|
|
23
23
|
"moment": "^2.30.1",
|
|
24
24
|
"prop-types": "^15.8.1",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/react": "^18.3.12",
|
|
29
29
|
"@types/react-dom": "^18.3.1",
|
|
30
|
-
"eslint": "^9.
|
|
30
|
+
"eslint": "^9.15.0",
|
|
31
31
|
"eslint-plugin-react": "^7.37.2",
|
|
32
32
|
"eslint-plugin-react-hooks": "^5.0.0",
|
|
33
33
|
"eslint-plugin-react-refresh": "^0.4.14",
|
|
@@ -35,15 +35,16 @@
|
|
|
35
35
|
"react-dom": "^18.3.1"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@mui/icons-material": "^5.15.12",
|
|
39
38
|
"@mui/lab": "^5.0.0-alpha.142",
|
|
40
39
|
"@mui/material": "^5.15.12",
|
|
41
|
-
"@mui/
|
|
40
|
+
"@mui/system": "^5.15.12",
|
|
41
|
+
"@mui/icons-material": "^5.15.12",
|
|
42
42
|
"@mui/x-tree-view": "^7.22.1",
|
|
43
|
-
"
|
|
43
|
+
"@mui/x-date-pickers": "^6.19.6",
|
|
44
|
+
"material-ui-confirm": "^3.0.16",
|
|
44
45
|
"react": ">=16",
|
|
45
46
|
"react-dom": ">=16",
|
|
46
|
-
"react-hook-form": "^7.
|
|
47
|
+
"react-hook-form": "^7.53.2",
|
|
47
48
|
"react-query": "^3.39.3",
|
|
48
49
|
"react-toastify": "^10.0.6",
|
|
49
50
|
"dayjs": "^1.11.13"
|
package/utils/storage.js
CHANGED
|
@@ -3,9 +3,11 @@ import moment from "moment";
|
|
|
3
3
|
|
|
4
4
|
// Khóa bí mật để mã hóa và giải mã MD5 https://zozo.vn/ws/tools/md5encode
|
|
5
5
|
const secretKey = "b0dc70c6a34c0555ac9c63907617f5a5"; // Bạn nên lưu trữ key này an toàn
|
|
6
|
-
|
|
6
|
+
export const encryptPassword = (data) => {
|
|
7
|
+
return btoa(data); // Mã hóa chuỗi sang Base64
|
|
8
|
+
};
|
|
7
9
|
// Hàm mã hóa dữ liệu
|
|
8
|
-
const encryptData = (data) => {
|
|
10
|
+
export const encryptData = (data) => {
|
|
9
11
|
if (!data) {
|
|
10
12
|
return null;
|
|
11
13
|
}
|
|
@@ -18,7 +20,7 @@ const encryptData = (data) => {
|
|
|
18
20
|
}
|
|
19
21
|
};
|
|
20
22
|
|
|
21
|
-
const decryptData = (ciphertext) => {
|
|
23
|
+
export const decryptData = (ciphertext) => {
|
|
22
24
|
if (!ciphertext) {
|
|
23
25
|
return null;
|
|
24
26
|
}
|
|
@@ -38,7 +40,6 @@ const decryptData = (ciphertext) => {
|
|
|
38
40
|
}
|
|
39
41
|
};
|
|
40
42
|
|
|
41
|
-
|
|
42
43
|
export const storeUserData = (data) => {
|
|
43
44
|
if (!data) return;
|
|
44
45
|
|
|
@@ -52,7 +53,8 @@ export const storeUserData = (data) => {
|
|
|
52
53
|
email: data?.Email,
|
|
53
54
|
FullName: data?.FullName,
|
|
54
55
|
Avatar: data?.Avatar,
|
|
55
|
-
Navigate: data?.Navigate
|
|
56
|
+
Navigate: data?.Navigate,
|
|
57
|
+
PhoneNumber: data?.PhoneNumber
|
|
56
58
|
};
|
|
57
59
|
|
|
58
60
|
// Mã hóa và lưu user object vào localStorage
|
|
@@ -63,21 +65,44 @@ export const storeSetCachedSidebarTops = (data) => {
|
|
|
63
65
|
if (!data) return;
|
|
64
66
|
// Mã hóa và lưu
|
|
65
67
|
const encryptedData = encryptData(data);
|
|
66
|
-
localStorage.setItem("cachedSidebarTops",encryptedData);
|
|
68
|
+
localStorage.setItem("cachedSidebarTops", encryptedData);
|
|
67
69
|
};
|
|
68
70
|
export const storeGetCachedSidebarTops = () => {
|
|
69
71
|
const encryptedData = localStorage.getItem("cachedSidebarTops");
|
|
70
72
|
if (!encryptedData) return null;
|
|
71
|
-
// console.log("encryptedData",encryptedData);
|
|
73
|
+
// console.log("encryptedData",encryptedData);
|
|
72
74
|
// Giải mã dữ liệu khi lấy ra từ localStorage
|
|
73
75
|
return decryptData(encryptedData);
|
|
74
76
|
};
|
|
75
77
|
export const storeSetCurrentInfor = (data) => {
|
|
76
78
|
if (!data) return;
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
79
|
+
|
|
80
|
+
const storedUserInfo = storeGetCurrentInfor();
|
|
81
|
+
const storedThamSo = storedUserInfo?.ThamSoHeThong?.find((item) => item.TenThamSo === "DEFAULT_ROWS_PER_PAGE");
|
|
82
|
+
const newThamSo = data?.ThamSoHeThong?.find((item) => item.TenThamSo === "DEFAULT_ROWS_PER_PAGE");
|
|
83
|
+
|
|
84
|
+
// Kiểm tra và cập nhật nếu thông tin mới từ API
|
|
85
|
+
if (newThamSo) {
|
|
86
|
+
const isUpdated = !storedThamSo || new Date(newThamSo.ModifiedDate) > new Date(storedThamSo?.ModifiedDate);
|
|
87
|
+
if (isUpdated) {
|
|
88
|
+
// Xóa dữ liệu `rowsPerPage` cũ từ localStorage nếu cần
|
|
89
|
+
Object.keys(localStorage).forEach((key) => {
|
|
90
|
+
if (key.endsWith("rowsPerPage")) {
|
|
91
|
+
localStorage.removeItem(key);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Mã hóa dữ liệu và lưu vào localStorage
|
|
98
|
+
try {
|
|
99
|
+
const encryptedData = encryptData(data);
|
|
100
|
+
localStorage.setItem("GetCurrentInfor", encryptedData);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error("Error encrypting or saving data to localStorage:", error);
|
|
103
|
+
}
|
|
80
104
|
};
|
|
105
|
+
|
|
81
106
|
export const storeGetUser = () => {
|
|
82
107
|
const encryptedData = localStorage.getItem("user");
|
|
83
108
|
if (!encryptedData) return null;
|
|
@@ -105,10 +130,10 @@ export const storeGetToken = () => {
|
|
|
105
130
|
|
|
106
131
|
try {
|
|
107
132
|
const decryptedToken = decryptData(encryptedData);
|
|
108
|
-
if (!decryptedToken || typeof decryptedToken !==
|
|
133
|
+
if (!decryptedToken || typeof decryptedToken !== "string") {
|
|
109
134
|
throw new Error("Decrypted token is null or not a valid string.");
|
|
110
135
|
}
|
|
111
|
-
return decryptedToken;
|
|
136
|
+
return decryptedToken; // Không cần JSON.parse nếu đã là chuỗi hợp lệ
|
|
112
137
|
} catch (error) {
|
|
113
138
|
console.log("Error decrypting token:", error);
|
|
114
139
|
return null;
|
|
@@ -122,15 +147,21 @@ export const storeGetCurrentInfor = () => {
|
|
|
122
147
|
// Giải mã dữ liệu khi lấy ra từ localStorage
|
|
123
148
|
return decryptData(encryptedData);
|
|
124
149
|
};
|
|
150
|
+
export const storeGetThamSoHeThongObj = (TenThamSo) => {
|
|
151
|
+
const encryptedData = localStorage.getItem("GetCurrentInfor");
|
|
152
|
+
if (!encryptedData) return "";
|
|
125
153
|
|
|
154
|
+
const getCurrentInfor = decryptData(encryptedData) || {};
|
|
155
|
+
return getCurrentInfor?.ThamSoHeThong?.find((item) => item.TenThamSo === TenThamSo) || "";
|
|
156
|
+
};
|
|
126
157
|
export const storeGetThamSoHeThong = (TenThamSo) => {
|
|
127
158
|
const encryptedData = localStorage.getItem("GetCurrentInfor");
|
|
128
159
|
if (!encryptedData) return "";
|
|
129
160
|
|
|
130
|
-
const getCurrentInfor =decryptData(encryptedData) || {};
|
|
161
|
+
const getCurrentInfor = decryptData(encryptedData) || {};
|
|
131
162
|
return getCurrentInfor?.ThamSoHeThong?.find((item) => item.TenThamSo === TenThamSo)?.GiaTri || "";
|
|
132
163
|
};
|
|
133
|
-
export const storeGetcolor= () => {
|
|
164
|
+
export const storeGetcolor = () => {
|
|
134
165
|
const encryptedData = localStorage.getItem("color");
|
|
135
166
|
if (!encryptedData) return "defaultColor";
|
|
136
167
|
return decryptData(encryptedData);
|
|
@@ -138,7 +169,7 @@ export const storeGetcolor= () => {
|
|
|
138
169
|
export const storeSetcolor = (data) => {
|
|
139
170
|
if (!data) return;
|
|
140
171
|
const encryptedData = encryptData(data);
|
|
141
|
-
localStorage.setItem("color",encryptedData);
|
|
172
|
+
localStorage.setItem("color", encryptedData);
|
|
142
173
|
};
|
|
143
174
|
export const storeGetlanguage = () => {
|
|
144
175
|
const encryptedData = localStorage.getItem("language");
|
|
@@ -148,7 +179,7 @@ export const storeGetlanguage = () => {
|
|
|
148
179
|
export const storeSetlanguage = (data) => {
|
|
149
180
|
if (!data) return;
|
|
150
181
|
const encryptedData = encryptData(data);
|
|
151
|
-
localStorage.setItem("language",encryptedData);
|
|
182
|
+
localStorage.setItem("language", encryptedData);
|
|
152
183
|
};
|
|
153
184
|
export const storeGetlanguageVersion = () => {
|
|
154
185
|
const encryptedData = localStorage.getItem("languageVersion");
|
|
@@ -158,7 +189,7 @@ export const storeGetlanguageVersion = () => {
|
|
|
158
189
|
export const storeSetlanguageVersion = (data) => {
|
|
159
190
|
if (!data) return;
|
|
160
191
|
const encryptedData = encryptData(data);
|
|
161
|
-
localStorage.setItem("languageVersion",encryptedData);
|
|
192
|
+
localStorage.setItem("languageVersion", encryptedData);
|
|
162
193
|
};
|
|
163
194
|
export const storeGetlanguageData = () => {
|
|
164
195
|
const encryptedData = localStorage.getItem("languageData");
|
|
@@ -168,11 +199,14 @@ export const storeGetlanguageData = () => {
|
|
|
168
199
|
export const storeSetlanguageData = (data) => {
|
|
169
200
|
if (!data) return;
|
|
170
201
|
const encryptedData = encryptData(data);
|
|
171
|
-
localStorage.setItem("languageData",encryptedData);
|
|
202
|
+
localStorage.setItem("languageData", encryptedData);
|
|
172
203
|
};
|
|
173
|
-
export const storeGetlanguageSystemKey = (TypeKey,SystemKey,TypeLanguage) => {
|
|
204
|
+
export const storeGetlanguageSystemKey = (TypeKey, SystemKey, TypeLanguage) => {
|
|
174
205
|
const encryptedData = localStorage.getItem("languageData");
|
|
175
206
|
if (!encryptedData) return null;
|
|
176
|
-
const languageData =decryptData(encryptedData) || {};
|
|
177
|
-
return
|
|
178
|
-
|
|
207
|
+
const languageData = decryptData(encryptedData) || {};
|
|
208
|
+
return (
|
|
209
|
+
languageData?.find((item) => item.TypeKey === TypeKey && item.SystemKey === SystemKey && item.TypeLanguage === TypeLanguage)
|
|
210
|
+
?.Description || ""
|
|
211
|
+
);
|
|
212
|
+
};
|