awing-library 2.1.2-beta → 2.1.3

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 (151) hide show
  1. package/README.md +14 -45
  2. package/lib/ACM-AXN/Campaign/Container.js +5 -6
  3. package/lib/ACM-AXN/Campaign/Container.test.js +1 -1
  4. package/lib/ACM-AXN/Campaign/CreateOrEdit/Recoils.d.ts +3 -1
  5. package/lib/ACM-AXN/Campaign/CreateOrEdit/Recoils.js +22 -21
  6. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabInfomation.d.ts +1 -1
  7. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabInfomation.js +79 -24
  8. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/AdDetail.test.js +1 -1
  9. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/AdList.js +50 -6
  10. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/AdRow.d.ts +5 -0
  11. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/AdRow.js +6 -18
  12. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/AddOrEditRule/AddOrEditRule.js +7 -12
  13. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/AddOrEditRule/RuleForm/RetargetMacAddress/container.d.ts +1 -0
  14. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/AddOrEditRule/RuleForm/RetargetMacAddress/container.js +4 -12
  15. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/Advanced.js +16 -1
  16. package/lib/ACM-AXN/Campaign/CreateOrEdit/TabSubCampaign/SubCampaignList.test.js +1 -1
  17. package/lib/ACM-AXN/Campaign/CreateOrEdit/index.js +19 -3
  18. package/lib/ACM-AXN/Campaign/Types.d.ts +10 -0
  19. package/lib/ACM-AXN/Campaign/Utils.d.ts +8 -0
  20. package/lib/ACM-AXN/Campaign/Utils.js +22 -18
  21. package/lib/ACM-AXN/Campaign/index.js +1 -1
  22. package/lib/ACM-AXN/CampaignSchedule/Components/ControlPanel/Filter.d.ts +2 -2
  23. package/lib/ACM-AXN/CampaignSchedule/Components/ControlPanel/Filter.js +44 -42
  24. package/lib/ACM-AXN/CampaignSchedule/Components/ControlPanel/GroupPanel.d.ts +1 -1
  25. package/lib/ACM-AXN/CampaignSchedule/Components/ControlPanel/GroupPanel.js +38 -30
  26. package/lib/ACM-AXN/CampaignSchedule/Components/ControlPanel/index.d.ts +2 -2
  27. package/lib/ACM-AXN/CampaignSchedule/Components/ControlPanel/index.js +2 -2
  28. package/lib/ACM-AXN/CampaignSchedule/Components/EnhancedPagination/index.d.ts +1 -1
  29. package/lib/ACM-AXN/CampaignSchedule/Components/EnhancedPagination/index.js +4 -2
  30. package/lib/ACM-AXN/CampaignSchedule/Components/RowAdvance/component.js +33 -3
  31. package/lib/ACM-AXN/CampaignSchedule/Components/RowAdvance/container.d.ts +1 -1
  32. package/lib/ACM-AXN/CampaignSchedule/Components/RowAdvance/container.js +80 -35
  33. package/lib/ACM-AXN/CampaignSchedule/Components/TableHeaderDragable.d.ts +1 -1
  34. package/lib/ACM-AXN/CampaignSchedule/Components/TableHeaderDragable.js +38 -20
  35. package/lib/ACM-AXN/CampaignSchedule/DataConfigAXN.d.ts +4 -0
  36. package/lib/ACM-AXN/CampaignSchedule/DataConfigAXN.js +58 -0
  37. package/lib/ACM-AXN/CampaignSchedule/Enum.d.ts +14 -2
  38. package/lib/ACM-AXN/CampaignSchedule/Enum.js +12 -0
  39. package/lib/ACM-AXN/CampaignSchedule/component.js +6 -5
  40. package/lib/ACM-AXN/CampaignSchedule/container.d.ts +1 -1
  41. package/lib/ACM-AXN/CampaignSchedule/container.js +100 -99
  42. package/lib/ACM-AXN/CampaignSchedule/interface.d.ts +16 -3
  43. package/lib/ACM-AXN/Directory/Constant.d.ts +2 -0
  44. package/lib/ACM-AXN/Directory/Constant.js +2 -0
  45. package/lib/ACM-AXN/Directory/MenuDirectory/MenuDirectory.test.d.ts +1 -0
  46. package/lib/ACM-AXN/Directory/MenuDirectory/MenuDirectory.test.js +90 -0
  47. package/lib/ACM-AXN/Directory/MenuDirectory/index.d.ts +1 -0
  48. package/lib/ACM-AXN/Directory/MenuDirectory/index.js +109 -0
  49. package/lib/ACM-AXN/Directory/SystemDirectory/index.js +6 -5
  50. package/lib/ACM-AXN/Directory/components/Permission/AddAuthen.d.ts +4 -0
  51. package/lib/ACM-AXN/Directory/components/Permission/AddAuthen.js +9 -7
  52. package/lib/ACM-AXN/Directory/components/Permission/CreateOrEditPermission.js +8 -6
  53. package/lib/ACM-AXN/Directory/components/Permission/Management.js +19 -14
  54. package/lib/ACM-AXN/Directory/components/Permission/MenuPermissions/MenuPermissionManagement.d.ts +1 -0
  55. package/lib/ACM-AXN/Directory/components/Permission/MenuPermissions/MenuPermissionManagement.js +185 -0
  56. package/lib/ACM-AXN/Directory/components/Permission/MenuPermissions/MenuPermissionManagement.test.d.ts +1 -0
  57. package/lib/ACM-AXN/Directory/components/Permission/MenuPermissions/MenuPermissionManagement.test.js +86 -0
  58. package/lib/ACM-AXN/Directory/function.d.ts +2 -0
  59. package/lib/ACM-AXN/Directory/function.js +39 -1
  60. package/lib/ACM-AXN/DomainPreview/PreviewButton.d.ts +15 -0
  61. package/lib/ACM-AXN/DomainPreview/PreviewButton.js +165 -0
  62. package/lib/ACM-AXN/DomainPreview/index.d.ts +7 -0
  63. package/lib/ACM-AXN/DomainPreview/index.js +10 -0
  64. package/lib/ACM-AXN/GroupUser/Constants.d.ts +7 -0
  65. package/lib/ACM-AXN/GroupUser/Constants.js +10 -0
  66. package/lib/ACM-AXN/GroupUser/Container.d.ts +2 -0
  67. package/lib/ACM-AXN/GroupUser/Container.js +55 -0
  68. package/lib/ACM-AXN/GroupUser/Container.test.d.ts +1 -0
  69. package/lib/ACM-AXN/GroupUser/Container.test.js +210 -0
  70. package/lib/ACM-AXN/GroupUser/CreateOrEdit.d.ts +3 -0
  71. package/lib/ACM-AXN/GroupUser/CreateOrEdit.js +84 -0
  72. package/lib/ACM-AXN/GroupUser/CreateOrEdit.test.d.ts +1 -0
  73. package/lib/ACM-AXN/GroupUser/CreateOrEdit.test.js +235 -0
  74. package/lib/ACM-AXN/GroupUser/Hooks.d.ts +5 -0
  75. package/lib/ACM-AXN/GroupUser/Hooks.js +13 -0
  76. package/lib/ACM-AXN/GroupUser/Types.d.ts +31 -0
  77. package/lib/ACM-AXN/GroupUser/Types.js +2 -0
  78. package/lib/ACM-AXN/GroupUser/User/SearchUser.d.ts +9 -0
  79. package/lib/ACM-AXN/GroupUser/User/SearchUser.js +63 -0
  80. package/lib/ACM-AXN/GroupUser/User/SearchUser.test.d.ts +1 -0
  81. package/lib/ACM-AXN/GroupUser/User/SearchUser.test.js +140 -0
  82. package/lib/ACM-AXN/GroupUser/User/UserComponent.d.ts +8 -0
  83. package/lib/ACM-AXN/GroupUser/User/UserComponent.js +77 -0
  84. package/lib/ACM-AXN/GroupUser/User/UserComponent.test.d.ts +1 -0
  85. package/lib/ACM-AXN/GroupUser/User/UserComponent.test.js +128 -0
  86. package/lib/ACM-AXN/GroupUser/index.d.ts +4 -0
  87. package/lib/ACM-AXN/GroupUser/index.js +27 -0
  88. package/lib/ACM-AXN/Page/Container.js +99 -61
  89. package/lib/ACM-AXN/Page/CreateOrEdit/DrawerAction.js +22 -5
  90. package/lib/ACM-AXN/Page/CreateOrEdit/Recoil.d.ts +1 -0
  91. package/lib/ACM-AXN/Page/CreateOrEdit/Recoil.js +5 -1
  92. package/lib/ACM-AXN/Page/CreateOrEdit/Tabview/ViewContent.js +1 -1
  93. package/lib/ACM-AXN/Page/CreateOrEdit/Tabview/ViewInfo.js +10 -4
  94. package/lib/ACM-AXN/Page/CreateOrEdit/Utils.d.ts +1 -1
  95. package/lib/ACM-AXN/Page/CreateOrEdit/Utils.js +1 -1
  96. package/lib/ACM-AXN/Page/Types.d.ts +8 -0
  97. package/lib/ACM-AXN/Page/ViewDomain/index.d.ts +9 -0
  98. package/lib/ACM-AXN/Page/ViewDomain/index.js +148 -0
  99. package/lib/ACM-AXN/Permission/Components/Management.test.js +1 -1
  100. package/lib/ACM-AXN/Statistics/ControlPanel.js +142 -85
  101. package/lib/ACM-AXN/Statistics/Enums.d.ts +1 -0
  102. package/lib/ACM-AXN/Statistics/Enums.js +1 -0
  103. package/lib/ACM-AXN/Statistics/container.js +1 -1
  104. package/lib/ACM-AXN/StatisticsAudienceDemographic/container.d.ts +1 -1
  105. package/lib/ACM-AXN/StatisticsAudienceDemographic/container.js +2 -3
  106. package/lib/ACM-AXN/StatisticsAudienceDemographic/interfaces.d.ts +1 -0
  107. package/lib/ACM-AXN/TransactionLog/Constant.d.ts +10 -0
  108. package/lib/ACM-AXN/TransactionLog/Constant.js +13 -0
  109. package/lib/ACM-AXN/TransactionLog/Container.d.ts +7 -0
  110. package/lib/ACM-AXN/TransactionLog/Container.js +189 -0
  111. package/lib/ACM-AXN/TransactionLog/Context.d.ts +8 -0
  112. package/lib/ACM-AXN/TransactionLog/Context.js +10 -0
  113. package/lib/ACM-AXN/TransactionLog/Detail.d.ts +7 -0
  114. package/lib/ACM-AXN/TransactionLog/Detail.js +204 -0
  115. package/lib/ACM-AXN/TransactionLog/Hooks.d.ts +7 -0
  116. package/lib/ACM-AXN/TransactionLog/Hooks.js +17 -0
  117. package/lib/ACM-AXN/TransactionLog/Types.d.ts +273 -0
  118. package/lib/ACM-AXN/TransactionLog/Types.js +413 -0
  119. package/lib/ACM-AXN/TransactionLog/Utils.d.ts +128 -0
  120. package/lib/ACM-AXN/TransactionLog/Utils.js +166 -0
  121. package/lib/ACM-AXN/TransactionLog/index.d.ts +8 -0
  122. package/lib/ACM-AXN/TransactionLog/index.js +36 -0
  123. package/lib/ACM-AXN/User/Add.d.ts +2 -0
  124. package/lib/ACM-AXN/User/Add.js +64 -0
  125. package/lib/ACM-AXN/User/Add.test.d.ts +1 -0
  126. package/lib/ACM-AXN/User/Add.test.js +115 -0
  127. package/lib/ACM-AXN/User/Constants.d.ts +2 -0
  128. package/lib/ACM-AXN/User/Constants.js +5 -0
  129. package/lib/ACM-AXN/User/Container.d.ts +2 -0
  130. package/lib/ACM-AXN/User/Container.js +60 -0
  131. package/lib/ACM-AXN/User/Container.test.d.ts +1 -0
  132. package/lib/ACM-AXN/User/Container.test.js +202 -0
  133. package/lib/ACM-AXN/User/Hook.d.ts +5 -0
  134. package/lib/ACM-AXN/User/Hook.js +13 -0
  135. package/lib/ACM-AXN/User/Types.d.ts +45 -0
  136. package/lib/ACM-AXN/User/Types.js +2 -0
  137. package/lib/ACM-AXN/User/index.d.ts +4 -0
  138. package/lib/ACM-AXN/User/index.js +18 -0
  139. package/lib/AWING/AdvancedSearch/component.js +1 -1
  140. package/lib/AWING/AdvancedSearch/interface.d.ts +1 -0
  141. package/lib/AWING/ButtonDateRangePicker/ButtonDateRangePicker.js +2 -2
  142. package/lib/AWING/ButtonDateRangePicker/interface.d.ts +1 -0
  143. package/lib/AWING/DataForm/DataInput.js +17 -8
  144. package/lib/AWING/DataForm/interface.d.ts +6 -2
  145. package/lib/AWING/DataGrid/index.js +4 -1
  146. package/lib/AWING/DataGrid/interface.d.ts +6 -1
  147. package/lib/AWING/ultis/validation.d.ts +1 -1
  148. package/lib/AWING/ultis/validation.js +3 -3
  149. package/lib/translate/en/translation.json +28 -1
  150. package/lib/translate/vi/translation.json +28 -1
  151. package/package.json +5 -3
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ var jsx_runtime_1 = require("react/jsx-runtime");
54
+ require("@testing-library/jest-dom/extend-expect");
55
+ var react_1 = require("@testing-library/react");
56
+ var Router_1 = require("../../AWING/Router");
57
+ var Container_1 = __importDefault(require("./Container"));
58
+ var initUser = { userId: 'mockUserId' };
59
+ var items = [
60
+ {
61
+ userId: '5667797591087411902',
62
+ name: 'isobar',
63
+ description: '',
64
+ username: 'isobar',
65
+ gender: 1,
66
+ image: null,
67
+ },
68
+ {
69
+ userId: '4703920046752099132',
70
+ name: 'Kantar',
71
+ description: null,
72
+ username: 'kantar',
73
+ gender: 1,
74
+ image: null,
75
+ },
76
+ ];
77
+ var clientMethod = {
78
+ usersPaging: function () {
79
+ return Promise.resolve({
80
+ items: items,
81
+ totalItemCount: items.length,
82
+ });
83
+ },
84
+ usersDelete: function () { return function (_id) { }; },
85
+ };
86
+ // Mock Axios client
87
+ jest.mock('./Hooks', function () { return ({
88
+ __esModule: true,
89
+ default: function () { return ({
90
+ service: {
91
+ usersPaging: jest.fn(function (_param) {
92
+ return Promise.resolve(clientMethod.usersPaging());
93
+ }),
94
+ usersDelete: jest.fn(function (_id) {
95
+ return Promise.resolve(clientMethod.usersDelete());
96
+ }),
97
+ },
98
+ currentUser: initUser,
99
+ }); },
100
+ }); });
101
+ // Mock i18next
102
+ jest.mock('react-i18next', function () { return (__assign(__assign({}, jest.requireActual('react-i18next')), { useTranslation: function () { return ({ t: jest.fn(function (key) { return key; }) }); } })); });
103
+ // Mock PageManagement
104
+ jest.mock('AWING/PageManagement', function () { return ({
105
+ PageManagement: function (props) {
106
+ props.onChangeQueryInput({
107
+ searchString: '',
108
+ pageIndex: 0,
109
+ pageSize: 10,
110
+ });
111
+ return ((0, jsx_runtime_1.jsxs)("div", { children: [props.columns
112
+ .filter(function (item) { return item.valueGetter; })
113
+ .map(function (getter, idx) { return ((0, jsx_runtime_1.jsx)("span", { children: getter.valueGetter(items[0], idx) }, idx)); }), (0, jsx_runtime_1.jsx)("span", { "data-testid": "rowid", children: props.getRowId(items[0]) }), (0, jsx_runtime_1.jsx)("button", { "data-testid": "CreateBtn", onClick: props.onCreateButtonClick, children: "CreateBtn" }), (0, jsx_runtime_1.jsx)("button", { onClick: function () {
114
+ props.onChangeQueryInput({
115
+ pageIndex: 1,
116
+ pageSize: 10,
117
+ });
118
+ }, children: "ChangeInput" }), props.customActions, (0, jsx_runtime_1.jsx)("button", { "data-testid": "onDelete", onClick: function () {
119
+ props.onDelete('onDelete');
120
+ }, children: "Remove Btn" }), (0, jsx_runtime_1.jsx)("p", { children: JSON.stringify(props.rows) }), (0, jsx_runtime_1.jsxs)("span", { children: ["totalItemCount:", props.totalOfRows] })] }));
121
+ },
122
+ }); });
123
+ var renderUi = function () {
124
+ return (0, react_1.render)((0, jsx_runtime_1.jsx)(Router_1.BrowserRouter, { children: (0, jsx_runtime_1.jsx)(Container_1.default, {}) }));
125
+ };
126
+ describe('User Container Component', function () {
127
+ it('renders without crashing', function () {
128
+ renderUi();
129
+ });
130
+ it('render state', function () { return __awaiter(void 0, void 0, void 0, function () {
131
+ return __generator(this, function (_a) {
132
+ switch (_a.label) {
133
+ case 0:
134
+ renderUi();
135
+ expect(react_1.screen.getByTestId('CreateBtn')).toBeInTheDocument();
136
+ return [4 /*yield*/, (0, react_1.waitFor)(function () {
137
+ expect(react_1.screen.getByText(JSON.stringify(items))).toBeInTheDocument();
138
+ })];
139
+ case 1:
140
+ _a.sent();
141
+ return [4 /*yield*/, (0, react_1.waitFor)(function () {
142
+ expect(react_1.screen.getByText("totalItemCount:".concat(items.length))).toBeInTheDocument();
143
+ })];
144
+ case 2:
145
+ _a.sent();
146
+ return [2 /*return*/];
147
+ }
148
+ });
149
+ }); });
150
+ it('get paging', function () {
151
+ var usersPagingSpy = jest.spyOn(clientMethod, 'usersPaging');
152
+ renderUi();
153
+ expect(usersPagingSpy).toBeCalled();
154
+ });
155
+ it('get rowid', function () {
156
+ renderUi();
157
+ expect(react_1.screen.getByText(items[0].userId)).toBeInTheDocument();
158
+ });
159
+ it('row getter', function () {
160
+ renderUi();
161
+ expect(react_1.screen.getByText('Common.Gender.Male')).toBeInTheDocument();
162
+ });
163
+ it('Trigger Create user button', function () {
164
+ var openSpy = jest.spyOn(window, 'open');
165
+ renderUi();
166
+ react_1.fireEvent.click(react_1.screen.getByTestId('CreateBtn'));
167
+ expect(openSpy).toHaveBeenCalledWith("undefined/organization/mockUserId/User", '_blank');
168
+ openSpy.mockRestore();
169
+ });
170
+ it('Trigger Add Existed user button', function () { return __awaiter(void 0, void 0, void 0, function () {
171
+ return __generator(this, function (_a) {
172
+ switch (_a.label) {
173
+ case 0:
174
+ renderUi();
175
+ react_1.fireEvent.click(react_1.screen.getByText('User.AddExistedUser'));
176
+ return [4 /*yield*/, (0, react_1.waitFor)(function () {
177
+ return expect(window.location.href).toContain('http://localhost/AddExistedUser');
178
+ })];
179
+ case 1:
180
+ _a.sent();
181
+ return [2 /*return*/];
182
+ }
183
+ });
184
+ }); });
185
+ it('Delete user', function () { return __awaiter(void 0, void 0, void 0, function () {
186
+ var usersDeleteSpy;
187
+ return __generator(this, function (_a) {
188
+ switch (_a.label) {
189
+ case 0:
190
+ usersDeleteSpy = jest.spyOn(clientMethod, 'usersDelete');
191
+ renderUi();
192
+ react_1.fireEvent.click(react_1.screen.getByTestId('onDelete'));
193
+ return [4 /*yield*/, (0, react_1.waitFor)(function () {
194
+ expect(usersDeleteSpy).toBeCalled();
195
+ })];
196
+ case 1:
197
+ _a.sent();
198
+ return [2 /*return*/];
199
+ }
200
+ });
201
+ }); });
202
+ });
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ import { UserProps } from "./Types";
3
+ export declare const userPropsContext: import("react").Context<UserProps>;
4
+ declare const useUserProps: () => UserProps;
5
+ export default useUserProps;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.userPropsContext = void 0;
4
+ var react_1 = require("react");
5
+ var react_2 = require("react");
6
+ exports.userPropsContext = (0, react_1.createContext)({});
7
+ var useUserProps = function () {
8
+ var props = (0, react_2.useContext)(exports.userPropsContext);
9
+ return (0, react_2.useMemo)(function () {
10
+ return props;
11
+ }, [props]);
12
+ };
13
+ exports.default = useUserProps;
@@ -0,0 +1,45 @@
1
+ export interface IUserViewModel {
2
+ userId?: string;
3
+ name?: string | undefined;
4
+ username?: string | undefined;
5
+ gender?: number;
6
+ status?: boolean;
7
+ description?: string | undefined;
8
+ phone?: string | undefined;
9
+ image?: string | undefined;
10
+ }
11
+ export interface IUser {
12
+ userId?: string;
13
+ name?: string | undefined;
14
+ description?: string | undefined;
15
+ username?: string | undefined;
16
+ gender?: number | undefined;
17
+ image?: string | undefined;
18
+ }
19
+ export interface IUserPagingModel {
20
+ userId?: string;
21
+ name?: string;
22
+ description?: string;
23
+ username?: string;
24
+ gender?: number;
25
+ image?: string;
26
+ }
27
+ export interface IPagedList_1OfUserPagingModel {
28
+ items?: IUserPagingModel[];
29
+ pageCount?: number;
30
+ totalItemCount?: number;
31
+ pageNumber?: number;
32
+ pageSize?: number;
33
+ hasPreviousPage?: boolean;
34
+ hasNextPage?: boolean;
35
+ }
36
+ export interface IUserService {
37
+ usersPaging: (searchString: string | undefined, pageIndex: number | undefined, pageSize: number | undefined) => Promise<IPagedList_1OfUserPagingModel>;
38
+ usersDelete: (id: string) => Promise<void>;
39
+ usersGetIdByUsername: (username: string | undefined) => Promise<string>;
40
+ usersAddExisted: (username: string | undefined) => Promise<void>;
41
+ }
42
+ export interface UserProps {
43
+ service: IUserService;
44
+ currentUser: IUserViewModel;
45
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ import { UserProps } from './Types';
3
+ export declare const UserFeature: React.FC<UserProps>;
4
+ export default UserFeature;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.UserFeature = void 0;
7
+ var jsx_runtime_1 = require("react/jsx-runtime");
8
+ var Router_1 = require("../../AWING/Router");
9
+ var Container_1 = __importDefault(require("./Container"));
10
+ var Hook_1 = require("./Hook");
11
+ var react_i18next_1 = require("react-i18next");
12
+ var react_helmet_async_1 = require("react-helmet-async");
13
+ var i18n_1 = __importDefault(require("../../i18n"));
14
+ var Constants_1 = require("./Constants");
15
+ var Add_1 = __importDefault(require("./Add"));
16
+ var UserFeature = function (props) { return ((0, jsx_runtime_1.jsx)(react_i18next_1.I18nextProvider, { i18n: i18n_1.default, children: (0, jsx_runtime_1.jsx)(react_helmet_async_1.HelmetProvider, { children: (0, jsx_runtime_1.jsxs)(Hook_1.userPropsContext.Provider, { value: props, children: [(0, jsx_runtime_1.jsx)(Container_1.default, {}), (0, jsx_runtime_1.jsx)(Router_1.Routes, { children: (0, jsx_runtime_1.jsx)(Router_1.Route, { path: Constants_1.ADD_EXISTED_USER, element: (0, jsx_runtime_1.jsx)(Add_1.default, {}) }, Constants_1.ADD_EXISTED_USER) })] }) }) })); };
17
+ exports.UserFeature = UserFeature;
18
+ exports.default = exports.UserFeature;
@@ -60,7 +60,7 @@ var AdvancedSearch = function (props) {
60
60
  : undefined, onChange: function (val) {
61
61
  var _a;
62
62
  return onChangeValue(__assign(__assign({}, value), (_a = {}, _a[fieldName] = val, _a)));
63
- }, isOutsideRange: fieldDef.isOutsideRange, isDayBlocked: fieldDef.isDayBlocked, children: fieldDef.label }, fieldName));
63
+ }, isOutsideRange: fieldDef.isOutsideRange, isDayBlocked: fieldDef.isDayBlocked, isShowCalendarInfo: fieldDef.isShowCalendarInfo, children: fieldDef.label }, fieldName));
64
64
  case 'directory':
65
65
  return ((0, jsx_runtime_1.jsx)(DirectoryTree_1.default, { labelSearch: fieldDef.label, rootDirectoryId: fieldDef.rootId || '', defaultValue: fieldValue, options: options !== null && options !== void 0 ? options : [], onChange: function (val) {
66
66
  var _a;
@@ -7,6 +7,7 @@ export interface AdvancedSearchFieldDefinition extends BaseTextFieldProps {
7
7
  icon?: React.ReactElement;
8
8
  label: string;
9
9
  type: 'select' | 'date-range' | 'autocomplete' | 'directory';
10
+ isShowCalendarInfo?: boolean;
10
11
  options?: MenuOption[];
11
12
  loading?: boolean;
12
13
  width?: number;
@@ -50,7 +50,7 @@ var DateRangePicker_1 = __importDefault(require("../DateRangePicker"));
50
50
  var react_i18next_1 = require("react-i18next");
51
51
  var ButtonDateRangePicker = function (props) {
52
52
  var t = (0, react_i18next_1.useTranslation)().t;
53
- var defaultValue = props.value, onChange = props.onChange, isOutsideRange = props.isOutsideRange, isDayBlocked = props.isDayBlocked, other = __rest(props, ["value", "onChange", "isOutsideRange", "isDayBlocked"]);
53
+ var defaultValue = props.value, onChange = props.onChange, isOutsideRange = props.isOutsideRange, isDayBlocked = props.isDayBlocked, isShowCalendarInfo = props.isShowCalendarInfo, other = __rest(props, ["value", "onChange", "isOutsideRange", "isDayBlocked", "isShowCalendarInfo"]);
54
54
  var _a = react_1.default.useState(false), open = _a[0], setOpen = _a[1];
55
55
  var anchorRef = react_1.default.useRef(null);
56
56
  var handleToggle = function () {
@@ -105,7 +105,7 @@ var ButtonDateRangePicker = function (props) {
105
105
  dateRange.startDate,
106
106
  dateRange.endDate,
107
107
  ]);
108
- }, isOutsideRange: isOutsideRange, isDayBlocked: isDayBlocked }) })] }) }) }) })));
108
+ }, isOutsideRange: isOutsideRange, isDayBlocked: isDayBlocked, isShowCalendarInfo: isShowCalendarInfo }) })] }) }) }) })));
109
109
  } })] }));
110
110
  };
111
111
  exports.ButtonDateRangePicker = ButtonDateRangePicker;
@@ -5,4 +5,5 @@ export interface ButtonDateRangePickerProps extends ButtonProps {
5
5
  onChange?(value: any): void;
6
6
  isOutsideRange?(date: Moment): boolean;
7
7
  isDayBlocked?(date: Moment): boolean;
8
+ isShowCalendarInfo?: boolean;
8
9
  }
@@ -43,14 +43,14 @@ var GeoFencing_1 = __importDefault(require("../../ACM-AXN/GeoFencing"));
43
43
  var i18n_1 = __importDefault(require("../../i18n"));
44
44
  var omit = require('lodash/omit');
45
45
  function DataInput(props) {
46
- var _a, _b, _c, _d, _e, _f, _g, _h;
46
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
47
47
  var t = (0, react_i18next_1.useTranslation)(undefined, { i18n: i18n_1.default }).t;
48
48
  var fieldDefinition = props.fieldDefinition, onChange = props.onChange, value = props.value, error = props.error, disableHelperText = props.disableHelperText;
49
49
  var fieldName = fieldDefinition.fieldName, type = fieldDefinition.type, onValidate = fieldDefinition.onValidate, min = fieldDefinition.min, max = fieldDefinition.max, other = __rest(fieldDefinition, ["fieldName", "type", "onValidate", "min", "max"]);
50
- var _j = react_2.default.useState(t('Common.InvalidData')), errorText = _j[0], setErrorText = _j[1];
50
+ var _k = react_2.default.useState(t('Common.InvalidData')), errorText = _k[0], setErrorText = _k[1];
51
51
  var checkValidationValue = function (fieldDefinition, val) {
52
52
  if (!fieldDefinition.required &&
53
- (val === undefined || val === null || val === '' || val === []))
53
+ (val === undefined || val === null || val === '' || (Array.isArray(val) && val.length === 0)))
54
54
  return true;
55
55
  if (fieldDefinition.onValidate)
56
56
  return fieldDefinition.onValidate(val, fieldDefinition === null || fieldDefinition === void 0 ? void 0 : fieldDefinition.length, fieldDefinition === null || fieldDefinition === void 0 ? void 0 : fieldDefinition.pattern);
@@ -63,6 +63,8 @@ function DataInput(props) {
63
63
  else
64
64
  return (0, validation_1.notNullValid)(val);
65
65
  }
66
+ case 'multiple-hierarchical':
67
+ return (0, validation_1.arrayIsNotEmptyValid)(val);
66
68
  case 'month':
67
69
  case 'date':
68
70
  return (0, validation_1.dateValid)(val);
@@ -108,10 +110,10 @@ function DataInput(props) {
108
110
  case 'autocomplete': {
109
111
  return ((0, jsx_runtime_1.jsx)(material_1.Autocomplete, { multiple: fieldDefinition.multiple, options: fieldDefinition.options, getOptionLabel: function (option) { var _a, _b; return (_b = (_a = option.label) !== null && _a !== void 0 ? _a : option.text) !== null && _b !== void 0 ? _b : ''; }, isOptionEqualToValue: function (option, value) {
110
112
  return (option === null || option === void 0 ? void 0 : option.value) === (value === null || value === void 0 ? void 0 : value.value);
111
- }, onChange: function (e, value) {
113
+ }, disableclearable: fieldDefinition.disableClearable, onChange: function (e, value) {
112
114
  var newValue = fieldDefinition.multiple
113
- ? value.map(function (x) { return x.value; })
114
- : value.value;
115
+ ? value.map(function (x) { return x === null || x === void 0 ? void 0 : x.value; })
116
+ : value === null || value === void 0 ? void 0 : value.value;
115
117
  onChange(newValue, checkValidationValue(fieldDefinition, newValue));
116
118
  }, value: fieldDefinition.multiple
117
119
  ? fieldDefinition.options.filter(function (x) {
@@ -155,7 +157,7 @@ function DataInput(props) {
155
157
  }, readOnly: fieldDefinition.readOnly }));
156
158
  }
157
159
  case 'date-range': {
158
- var _k = other, isDayBlocked = _k.isDayBlocked, isOutsideRange = _k.isOutsideRange;
160
+ var _l = other, isDayBlocked = _l.isDayBlocked, isOutsideRange = _l.isOutsideRange;
159
161
  return ((0, jsx_runtime_1.jsx)(AWING_1.DateRangePicker, { noBorder: true, variant: "standard", textFieldProps: __assign({ fullWidth: true, style: { margin: '8px 0px' } }, omit(other, ['isDayBlocked', 'isOutsideRange'])), value: {
160
162
  startDate: (value === null || value === void 0 ? void 0 : value[0]) || null,
161
163
  endDate: (value === null || value === void 0 ? void 0 : value[1]) || null,
@@ -208,6 +210,13 @@ function DataInput(props) {
208
210
  }), { children: (_a = item.label) !== null && _a !== void 0 ? _a : item.text }), "".concat(fieldName.toString(), "-opt-").concat(index)));
209
211
  })] })));
210
212
  }
213
+ case 'multiple-hierarchical': {
214
+ return ((0, jsx_runtime_1.jsx)(AWING_1.MultipleHierarchicalChoice, __assign({}, fieldDefinition, { variant: "standard", value: value, onChange: function (value) {
215
+ onChange(value, checkValidationValue(fieldDefinition, value));
216
+ }, error: error, helperText: !disableHelperText && error
217
+ ? (_h = fieldDefinition.helperText) !== null && _h !== void 0 ? _h : t('Common.InvalidData')
218
+ : '' })));
219
+ }
211
220
  case 'geo-fencing': {
212
221
  var configs = fieldDefinition.configs, label = fieldDefinition.label, initValue = fieldDefinition.initValue, value_1 = fieldDefinition.value, limit = fieldDefinition.limit, isOnlyMap = fieldDefinition.isOnlyMap;
213
222
  return ((0, jsx_runtime_1.jsx)("div", { style: { marginTop: '16px' }, children: (0, jsx_runtime_1.jsx)(GeoFencing_1.default, { configs: configs, label: label, initValue: initValue, value: value_1, limit: limit, isOnlyMap: isOnlyMap, onChange: function (newValue) {
@@ -218,7 +227,7 @@ function DataInput(props) {
218
227
  return ((0, jsx_runtime_1.jsx)(material_1.TextField, __assign({ id: fieldName.toString(), name: fieldName.toString(), type: fieldDefinition.type, fullWidth: true, variant: "standard" }, other, { value: value !== null && value !== void 0 ? value : '', onChange: function (event) {
219
228
  return onChange(event.target.value, checkValidationValue(fieldDefinition, event.target.value));
220
229
  }, error: error, helperText: !disableHelperText && error
221
- ? (_h = fieldDefinition.helperText) !== null && _h !== void 0 ? _h : t('Common.InvalidData')
230
+ ? (_j = fieldDefinition.helperText) !== null && _j !== void 0 ? _j : t('Common.InvalidData')
222
231
  : '' })));
223
232
  }
224
233
  }
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { BaseTextFieldProps } from '@mui/material/TextField';
3
- import { DataObject, MenuOption } from '../../AWING';
3
+ import { DataObject, IMultipleHierarchicalChoiceProps, MenuOption } from '../../AWING';
4
4
  import { IMainObj, IListFunctions } from '../../AWING/LogicExpression/interface';
5
5
  import { GeoFencingValue, IConfig } from '../../ACM-AXN/GeoFencing/interface';
6
6
  import { Moment } from 'moment';
@@ -44,6 +44,7 @@ export type AutocompleteFieldDefinition<T extends DataObject> = BaseFieldDefinit
44
44
  type: 'autocomplete';
45
45
  options: Array<MenuOption>;
46
46
  loading?: boolean;
47
+ disableClearable?: boolean;
47
48
  };
48
49
  export interface CheckBoxFieldDefinition<T extends DataObject> extends BaseFieldDefinition<T> {
49
50
  type: 'checkbox';
@@ -122,5 +123,8 @@ export type SelectFieldDefinition<T extends DataObject> = BaseFieldDefinition<T>
122
123
  row?: Partial<T>;
123
124
  onDisabledSelectItem?: (value: any, row?: Partial<T>) => boolean;
124
125
  };
125
- export type FieldDefinition<T extends DataObject> = AsyncAutocompleteFieldDefinition<T> | AutocompleteFieldDefinition<T> | LogicExpressionDefinition<T> | CheckBoxFieldDefinition<T> | DateTimeFieldDefinition<T> | DateRangeFieldDefinition<T> | NumberFieldDefinition<T> | RadioFieldDefinition<T> | SelectFieldDefinition<T> | TextFieldDefinition<T> | GeoFencingDefinition<T>;
126
+ export type MultipleHierarchicalDefinition<T extends DataObject> = BaseFieldDefinition<T> & Omit<IMultipleHierarchicalChoiceProps, 'defaultValue' | 'onChange'> & {
127
+ type: 'multiple-hierarchical';
128
+ };
129
+ export type FieldDefinition<T extends DataObject> = AsyncAutocompleteFieldDefinition<T> | AutocompleteFieldDefinition<T> | LogicExpressionDefinition<T> | CheckBoxFieldDefinition<T> | DateTimeFieldDefinition<T> | DateRangeFieldDefinition<T> | NumberFieldDefinition<T> | RadioFieldDefinition<T> | SelectFieldDefinition<T> | TextFieldDefinition<T> | GeoFencingDefinition<T> | MultipleHierarchicalDefinition<T>;
126
130
  export {};
@@ -254,7 +254,10 @@ var DataGrid = function (props) {
254
254
  opacity: isShouldHide
255
255
  ? 0
256
256
  : 1,
257
- }, sx: actionDef.sx, children: actionDef.icon }) }, "".concat(id, "-").concat(actIdx)));
257
+ }, sx: __assign(__assign({}, actionDef.sx), { borderRadius: '15%' }), children: typeof actionDef.icon ===
258
+ 'function'
259
+ ? actionDef.icon({ id: id, row: row, idx: idx, order: calcOrder(idx) })
260
+ : actionDef.icon }) }, "".concat(id, "-").concat(actIdx)));
258
261
  }) }))] }), id));
259
262
  }), spanningRowsPosition == 'bottom' && spanningRows] })] }), !rows.length && (0, jsx_runtime_1.jsx)(NoData_1.default, {})] }), onPageIndexChange && onPageSizeChange && ((0, jsx_runtime_1.jsx)(Pagination_1.default, { rowsPerPageOptions: rowsPerPageOptions, colSpan: 3, count: totalOfRows, rowsPerPage: pageSize, page: pageIndex, SelectProps: {
260
263
  inputProps: { 'aria-label': 'rows per page' },
@@ -49,7 +49,12 @@ export interface RowActionDefinition {
49
49
  /**
50
50
  * Icon của button action
51
51
  */
52
- icon: ReactNode;
52
+ icon: ReactNode | React.FunctionComponent<{
53
+ id: string;
54
+ row: DataObject;
55
+ idx: number;
56
+ order: number;
57
+ }>;
53
58
  /**
54
59
  * Nội dung hiển thị trên tooltip
55
60
  */
@@ -19,7 +19,7 @@ export declare function logicExpressionValid(value: string | null | undefined):
19
19
  * @param str - The text string to be validated.
20
20
  * @param length - The maximum length of the text string. Default is 50.
21
21
  * @param required - validField required.
22
- * @param pattern - The regular expression pattern to match against the text string. Default is /^[a-zA-Z0-9\/\-_()\[\] ]+$/g.
22
+ * @param pattern - The regular expression pattern to match against the text string. Default is /^[a-zA-Z0-9\/\-_.()\[\] ]+$/g.
23
23
  * @param invertRegex - The inverted regular expression pattern to match against the text string. Default is undefined.
24
24
  * @returns An object containing the validation result and a message describing any validation errors.
25
25
  */
@@ -89,14 +89,14 @@ exports.logicExpressionValid = logicExpressionValid;
89
89
  * @param str - The text string to be validated.
90
90
  * @param length - The maximum length of the text string. Default is 50.
91
91
  * @param required - validField required.
92
- * @param pattern - The regular expression pattern to match against the text string. Default is /^[a-zA-Z0-9\/\-_()\[\] ]+$/g.
92
+ * @param pattern - The regular expression pattern to match against the text string. Default is /^[a-zA-Z0-9\/\-_.()\[\] ]+$/g.
93
93
  * @param invertRegex - The inverted regular expression pattern to match against the text string. Default is undefined.
94
94
  * @returns An object containing the validation result and a message describing any validation errors.
95
95
  */
96
96
  var textValidation = function (str, length, required, pattern, invertRegex) {
97
97
  if (length === void 0) { length = 50; }
98
98
  if (required === void 0) { required = true; }
99
- if (pattern === void 0) { pattern = /^[a-zA-Z0-9\/\-_()\[\] ]+$/g; }
99
+ if (pattern === void 0) { pattern = /^[a-zA-Z0-9\/\-_.()\[\] ]+$/g; }
100
100
  var validRes = {
101
101
  valid: true,
102
102
  message: [],
@@ -113,7 +113,7 @@ var textValidation = function (str, length, required, pattern, invertRegex) {
113
113
  .replace(/[\u0300-\u036f]/g, '')
114
114
  .replace(/đ/g, 'd')
115
115
  .trim();
116
- var invertedRegex = invertRegex || new RegExp("[^".concat(pattern.source.replace(/[.*+?^${}|]/g, ''), "]").replace(/\[\[|\]\]/g, ']'), 'g');
116
+ var invertedRegex = invertRegex || new RegExp("[^".concat(pattern.source.replace(/[*+?^${}|]/g, ''), "]").replace(/\[\[|\]\]/g, ']'), 'g');
117
117
  if (textTransform && pattern && !pattern.test(textTransform)) {
118
118
  validRes.valid = false;
119
119
  validRes.message.push("".concat(i18n_1.default.t('Common.InvalidChars'), ": ").concat(Array.from(new Set(textTransform.match(invertedRegex))).join(' ')));
@@ -115,7 +115,17 @@
115
115
  },
116
116
  "User": {
117
117
  "Username": "Username",
118
- "Password": "Password"
118
+ "Password": "Password",
119
+ "Title": "User Management",
120
+ "AddExistedUser": "Add Existed User"
121
+ },
122
+ "UserGroup": {
123
+ "Title": "User Group Management",
124
+ "Create": "Create User Group",
125
+ "Edit": "Edit User Group",
126
+ "TitleUserGroupInfo": "Infomation User Group",
127
+ "TitleUserGroup": "List User In Group",
128
+ "AddUserGroupButton": "Add User To Group"
119
129
  },
120
130
  "PlaceMultiSelect": {
121
131
  "All": "All",
@@ -168,6 +178,7 @@
168
178
  "Time": "Time",
169
179
  "Estimate": "Estimate",
170
180
  "Reality": "Reality",
181
+ "Domain": "Domain",
171
182
  "Campaign": "Campaign",
172
183
  "Rate": "Rate",
173
184
  "Date": "Day",
@@ -626,5 +637,21 @@
626
637
  "Date": "Date",
627
638
  "Place": "Place",
628
639
  "CampaignDefault": "Campaign Root"
640
+ },
641
+ "TransactionLog": {
642
+ "Title": "Transaction Log Management",
643
+ "TransactionType": "Transaction Type",
644
+ "ObjectID": "Object ID",
645
+ "Username": "User",
646
+ "Date": "Date",
647
+ "Status": "Status",
648
+ "SearchPlaceholder": "Search by ID Object",
649
+ "Old": "Old",
650
+ "New": "New",
651
+ "TitleDetail": "Transaction Log Detail"
652
+ },
653
+ "Filter": {
654
+ "AllCampaign": "All Campaign",
655
+ "CampaignDefault": "Campaign Default"
629
656
  }
630
657
  }
@@ -120,7 +120,17 @@
120
120
  },
121
121
  "User": {
122
122
  "Username": "Tài khoản",
123
- "Password": "Mật khẩu"
123
+ "Password": "Mật khẩu",
124
+ "Title": "Quản trị người dùng",
125
+ "AddExistedUser": "Thêm tài khoản đã tồn tại"
126
+ },
127
+ "UserGroup": {
128
+ "Title": "Quản trị nhóm người dùng",
129
+ "Create": "Tạo mới nhóm người dùng",
130
+ "Edit": "Sửa nhóm người dùng",
131
+ "TitleUserGroupInfo": "Thông tin nhóm người dùng",
132
+ "TitleUserGroup": "Danh sách người dùng trong nhóm",
133
+ "AddUserGroupButton": "Thêm người dùng vào nhóm"
124
134
  },
125
135
  "PlaceMultiSelect": {
126
136
  "All": "Tất cả",
@@ -172,6 +182,7 @@
172
182
  "Place": "Địa điểm",
173
183
  "Time": "Thời gian",
174
184
  "Estimate": "Ước tính",
185
+ "Domain": "Domain",
175
186
  "Reality": "Thực tế",
176
187
  "Campaign": "Chiến dịch",
177
188
  "Rate": "Tỉ lệ",
@@ -628,5 +639,21 @@
628
639
  "Date": "Ngày",
629
640
  "Place": "Địa điểm",
630
641
  "CampaignDefault": "Chiến dịch mặc định"
642
+ },
643
+ "TransactionLog": {
644
+ "Title": "Quản trị Log",
645
+ "TransactionType": "Loại giao dịch",
646
+ "ObjectID": "ID của đối tượng",
647
+ "Username": "Tài khoản",
648
+ "Date": "Thời gian",
649
+ "Status": "Trạng thái",
650
+ "SearchPlaceholder": "Nhập ID đối tượng",
651
+ "Old": "Cũ",
652
+ "New": "Mới",
653
+ "TitleDetail": "Chi tiết Log"
654
+ },
655
+ "Filter": {
656
+ "AllCampaign": "Tất cả chiến dịch",
657
+ "CampaignDefault": "Chiến dịch mặc định"
631
658
  }
632
659
  }