datastake-daf 0.6.711 → 0.6.712
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.
- package/dist/components/index.js +347 -8
- package/dist/hooks/index.js +19 -4673
- package/dist/pages/index.js +0 -15
- package/dist/services/index.js +0 -15
- package/dist/style/datastake/datastake.css +2 -2
- package/dist/utils/index.js +0 -4
- package/package.json +1 -1
- package/src/@daf/core/components/Screens/Admin/AdminScreens/Accounts.jsx +109 -0
- package/src/@daf/core/components/Screens/Admin/AdminScreens/AccountsView.jsx +73 -0
- package/src/@daf/core/components/Screens/Admin/AdminScreens/Dashboard.jsx +77 -0
- package/src/@daf/core/components/Screens/Admin/AdminScreens/README.md +216 -0
- package/src/@daf/core/components/Screens/Admin/AdminScreens/Users.jsx +117 -0
- package/src/@daf/core/components/Screens/Admin/AdminScreens/index.js +11 -0
- package/src/@daf/core/components/Screens/Admin/adminRoutes.js +104 -0
- package/src/@daf/services/DashboardService.js +0 -15
- package/src/helpers/StringHelper.js +0 -6
- package/src/index.js +19 -1
- package/src/styles/datastake/datastake.css +2 -2
- package/src/utils.js +1 -1
- package/build/favicon.ico +0 -0
- package/build/logo192.png +0 -0
- package/build/logo512.png +0 -0
- package/build/manifest.json +0 -25
- package/build/robots.txt +0 -3
package/dist/pages/index.js
CHANGED
|
@@ -6322,21 +6322,6 @@ class DashboardService extends BaseService {
|
|
|
6322
6322
|
isApp: true
|
|
6323
6323
|
});
|
|
6324
6324
|
}
|
|
6325
|
-
getUserGrowth(activeFilter) {
|
|
6326
|
-
return this.apiGet({
|
|
6327
|
-
url: `/accounts/dashboard/user-growth`,
|
|
6328
|
-
isUserManager: true,
|
|
6329
|
-
params: {
|
|
6330
|
-
activeFilter
|
|
6331
|
-
}
|
|
6332
|
-
});
|
|
6333
|
-
}
|
|
6334
|
-
getAdminDashboard() {
|
|
6335
|
-
return this.apiGet({
|
|
6336
|
-
url: `/accounts/dashboard`,
|
|
6337
|
-
isUserManager: true
|
|
6338
|
-
});
|
|
6339
|
-
}
|
|
6340
6325
|
}
|
|
6341
6326
|
var DashboardService$1 = createLazyService(DashboardService);
|
|
6342
6327
|
|
package/dist/services/index.js
CHANGED
|
@@ -1200,21 +1200,6 @@ class DashboardService extends BaseService {
|
|
|
1200
1200
|
isApp: true
|
|
1201
1201
|
});
|
|
1202
1202
|
}
|
|
1203
|
-
getUserGrowth(activeFilter) {
|
|
1204
|
-
return this.apiGet({
|
|
1205
|
-
url: `/accounts/dashboard/user-growth`,
|
|
1206
|
-
isUserManager: true,
|
|
1207
|
-
params: {
|
|
1208
|
-
activeFilter
|
|
1209
|
-
}
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
|
-
getAdminDashboard() {
|
|
1213
|
-
return this.apiGet({
|
|
1214
|
-
url: `/accounts/dashboard`,
|
|
1215
|
-
isUserManager: true
|
|
1216
|
-
});
|
|
1217
|
-
}
|
|
1218
1203
|
}
|
|
1219
1204
|
var DashboardService$1 = createLazyService(DashboardService);
|
|
1220
1205
|
|
|
@@ -1542,13 +1542,13 @@ ul.ant-menu.ant-menu-dark.ant-menu-root.ant-menu-vertical::-webkit-scrollbar-thu
|
|
|
1542
1542
|
}
|
|
1543
1543
|
|
|
1544
1544
|
.components-layout:not(.nested) .sidenav-sider:not(.custom) .sidenav-cont .menus-cont.not-collapsed .sidemenu-cont .ant-menu.ant-menu-root.ant-menu-inline.ant-menu-dark
|
|
1545
|
-
.ant-menu-item:not(.ant-menu-item-selected)
|
|
1545
|
+
.ant-menu-item:not(.ant-menu-item-selected) svg path
|
|
1546
1546
|
{
|
|
1547
1547
|
stroke: #ffffff !important;
|
|
1548
1548
|
}
|
|
1549
1549
|
|
|
1550
1550
|
.components-layout:not(.nested) .sidenav-sider:not(.custom) .sidenav-cont .menus-cont.not-collapsed .sidemenu-cont .ant-menu.ant-menu-root.ant-menu-inline.ant-menu-dark
|
|
1551
|
-
.ant-menu-item:not(.ant-menu-item-selected)
|
|
1551
|
+
.ant-menu-item:not(.ant-menu-item-selected) .ant-menu-title-content {
|
|
1552
1552
|
color: #ffffff !important;
|
|
1553
1553
|
}
|
|
1554
1554
|
|
package/dist/utils/index.js
CHANGED
|
@@ -5127,9 +5127,6 @@ const cleanJSON = json => {
|
|
|
5127
5127
|
}
|
|
5128
5128
|
return json;
|
|
5129
5129
|
};
|
|
5130
|
-
function formatToKebabCase(str) {
|
|
5131
|
-
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
5132
|
-
}
|
|
5133
5130
|
|
|
5134
5131
|
function _checkValue$1(wantedValue, match, fieldValue) {
|
|
5135
5132
|
match = match ? match.trim() : null;
|
|
@@ -14158,7 +14155,6 @@ exports.filterSelectOptions = filterSelectOptions;
|
|
|
14158
14155
|
exports.filterString = filterString;
|
|
14159
14156
|
exports.findOptions = findOptions;
|
|
14160
14157
|
exports.formatErrors = formatErrors;
|
|
14161
|
-
exports.formatToKebabCase = formatToKebabCase;
|
|
14162
14158
|
exports.getDefaultActiveFilters = getDefaultActiveFilters;
|
|
14163
14159
|
exports.getDivergenceOrEqual = getDivergenceOrEqual;
|
|
14164
14160
|
exports.getImageUploadViewValue = getImageUploadViewValue;
|
package/package.json
CHANGED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useCallback, useMemo, useState } from "react";
|
|
2
|
+
import { message } from "antd";
|
|
3
|
+
import AccountTable from "../AdminTables/AccountTable/index.jsx";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Admin Accounts Screen Wrapper
|
|
7
|
+
* This is a ready-to-use route component that can be configured per application
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} config - Application configuration
|
|
10
|
+
* @param {string} config.appName - Application name
|
|
11
|
+
* @param {string} config.module - Module identifier (APP constant)
|
|
12
|
+
* @param {Function} config.goTo - Navigation function
|
|
13
|
+
* @param {Function} config.t - Translation function
|
|
14
|
+
* @param {Object} config.location - Router location object
|
|
15
|
+
* @param {boolean} config.isMobile - Is mobile viewport
|
|
16
|
+
* @param {Array} config.accountTypes - Account types configuration
|
|
17
|
+
* @param {Function} config.getRedirectLink - Function to get redirect links
|
|
18
|
+
* @param {Object} config.AdminService - Admin service with methods
|
|
19
|
+
* @param {Object} config.options - Options object with countries, etc.
|
|
20
|
+
* @param {Function} config.useQuery - Hook to get query parameters
|
|
21
|
+
* @param {Component} config.NewAccountModal - Custom NewAccount modal component (optional)
|
|
22
|
+
*/
|
|
23
|
+
export default function AdminAccountsScreen({ config }) {
|
|
24
|
+
const {
|
|
25
|
+
appName = "app",
|
|
26
|
+
module,
|
|
27
|
+
goTo,
|
|
28
|
+
t,
|
|
29
|
+
location,
|
|
30
|
+
isMobile,
|
|
31
|
+
accountTypes,
|
|
32
|
+
getRedirectLink,
|
|
33
|
+
AdminService,
|
|
34
|
+
options,
|
|
35
|
+
useQuery,
|
|
36
|
+
NewAccountModal,
|
|
37
|
+
} = config;
|
|
38
|
+
|
|
39
|
+
const query = useQuery ? useQuery() : { get: () => null };
|
|
40
|
+
const [addAccountVisible, setAddAccountVisible] = useState(!!query.get("create"));
|
|
41
|
+
|
|
42
|
+
const onResendInvitation = useCallback(() => {
|
|
43
|
+
// TODO: implement in calling app if needed
|
|
44
|
+
message.success(t("Invitation email resent"));
|
|
45
|
+
}, [t]);
|
|
46
|
+
|
|
47
|
+
const onCopyInvitation = useCallback(() => {
|
|
48
|
+
message.success(t("Invitation link copied"));
|
|
49
|
+
}, [t]);
|
|
50
|
+
|
|
51
|
+
const actionButtons = useMemo(
|
|
52
|
+
() => [
|
|
53
|
+
{
|
|
54
|
+
type: "primary",
|
|
55
|
+
onClick: () => setAddAccountVisible(true),
|
|
56
|
+
tooltip: t("Add"),
|
|
57
|
+
icon: "Add",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
[t]
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
function handleGetData(params) {
|
|
64
|
+
return AdminService.getAccounts(params);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function handleCancelVerification(token) {
|
|
68
|
+
return AdminService.cancelInvitation(token);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<>
|
|
73
|
+
<AccountTable
|
|
74
|
+
t={t}
|
|
75
|
+
goTo={goTo}
|
|
76
|
+
location={location}
|
|
77
|
+
getRedirectLink={getRedirectLink}
|
|
78
|
+
isMobile={isMobile}
|
|
79
|
+
module={module}
|
|
80
|
+
headerTitle="accounts"
|
|
81
|
+
actionButton={actionButtons}
|
|
82
|
+
getData={handleGetData}
|
|
83
|
+
config={{
|
|
84
|
+
accountTypes,
|
|
85
|
+
options: {
|
|
86
|
+
countries: options?.countries,
|
|
87
|
+
},
|
|
88
|
+
onTableClick: {
|
|
89
|
+
onCanelVerification: handleCancelVerification,
|
|
90
|
+
onCopyInvitation,
|
|
91
|
+
onResendInvitation,
|
|
92
|
+
setAddAccountVisible,
|
|
93
|
+
},
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
{NewAccountModal && (
|
|
98
|
+
<NewAccountModal
|
|
99
|
+
fetchData={() => {
|
|
100
|
+
// Refresh table data - handled by AccountTable internally
|
|
101
|
+
}}
|
|
102
|
+
addAccountVisible={addAccountVisible}
|
|
103
|
+
onClose={() => setAddAccountVisible(false)}
|
|
104
|
+
/>
|
|
105
|
+
)}
|
|
106
|
+
</>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import AdminView from "../AdminViews/index.jsx";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Admin Accounts View/Edit Screen Wrapper
|
|
6
|
+
* This is a ready-to-use route component for viewing/editing accounts
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} config - Application configuration
|
|
9
|
+
* @param {string} config.module - Module identifier (APP constant)
|
|
10
|
+
* @param {Function} config.goTo - Navigation function
|
|
11
|
+
* @param {Function} config.t - Translation function
|
|
12
|
+
* @param {Object} config.location - Router location object
|
|
13
|
+
* @param {Function} config.getRedirectLink - Function to get redirect links
|
|
14
|
+
* @param {Function} config.renderBreadCrumbs - Function to render breadcrumbs
|
|
15
|
+
* @param {string} config.id - Account ID from route params
|
|
16
|
+
* @param {string} config.mode - "view" or "edit"
|
|
17
|
+
* @param {string} config.group - Current group/section being viewed
|
|
18
|
+
* @param {Array} config.userRoles - User roles configuration
|
|
19
|
+
* @param {Object} config.options - Options object with countries, etc.
|
|
20
|
+
* @param {Array} config.accountTypes - Account types configuration
|
|
21
|
+
* @param {Array} config.accountStatuses - Account statuses configuration
|
|
22
|
+
* @param {Function} config.getAccountData - Function to fetch account data
|
|
23
|
+
* @param {Function} config.updateAccount - Function to update account
|
|
24
|
+
* @param {Function} config.handleError - Error handling function
|
|
25
|
+
* @param {Function} config.toggleAccountStatus - Function to toggle account status
|
|
26
|
+
* @param {Function} config.transferAdmin - Function to transfer admin rights
|
|
27
|
+
*/
|
|
28
|
+
export default function AdminAccountsViewScreen({ config }) {
|
|
29
|
+
const {
|
|
30
|
+
module,
|
|
31
|
+
goTo,
|
|
32
|
+
t,
|
|
33
|
+
location,
|
|
34
|
+
getRedirectLink,
|
|
35
|
+
renderBreadCrumbs,
|
|
36
|
+
id,
|
|
37
|
+
mode,
|
|
38
|
+
group,
|
|
39
|
+
userRoles,
|
|
40
|
+
options,
|
|
41
|
+
accountTypes,
|
|
42
|
+
accountStatuses,
|
|
43
|
+
getAccountData,
|
|
44
|
+
updateAccount,
|
|
45
|
+
handleError,
|
|
46
|
+
toggleAccountStatus,
|
|
47
|
+
transferAdmin,
|
|
48
|
+
} = config;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<AdminView
|
|
52
|
+
t={t}
|
|
53
|
+
goTo={goTo}
|
|
54
|
+
getRedirectLink={getRedirectLink}
|
|
55
|
+
location={location}
|
|
56
|
+
renderBreadCrumbs={renderBreadCrumbs}
|
|
57
|
+
id={id}
|
|
58
|
+
mode={mode}
|
|
59
|
+
group={group}
|
|
60
|
+
module={module}
|
|
61
|
+
userRoles={userRoles}
|
|
62
|
+
options={options}
|
|
63
|
+
accountTypes={accountTypes}
|
|
64
|
+
accountStatuses={accountStatuses}
|
|
65
|
+
getAccountData={getAccountData}
|
|
66
|
+
updateAccount={updateAccount}
|
|
67
|
+
handleError={handleError}
|
|
68
|
+
toggleAccountStatus={toggleAccountStatus}
|
|
69
|
+
transferAdmin={transferAdmin}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import AdminDashboard from "../AdminDashboard/index.jsx";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Admin Dashboard Screen Wrapper
|
|
6
|
+
* This is a ready-to-use route component that can be configured per application
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} config - Application configuration
|
|
9
|
+
* @param {string} config.appName - Application name for translations (e.g., "wazi", "tazama")
|
|
10
|
+
* @param {Function} config.goTo - Navigation function (useNavigate)
|
|
11
|
+
* @param {Function} config.t - Translation function (useTranslation)
|
|
12
|
+
* @param {Function} config.getRedirectLink - Function to get redirect links
|
|
13
|
+
* @param {Function} config.getActionWidgetsConfig - Function that returns action widgets config
|
|
14
|
+
* @param {Function} config.getKeyIndicatorsConfig - Function that returns key indicators config
|
|
15
|
+
* @param {Function} config.useWidgetFetch - Hook to fetch dashboard data
|
|
16
|
+
*/
|
|
17
|
+
export default function AdminDashboardScreen({ config }) {
|
|
18
|
+
const {
|
|
19
|
+
appName = "app",
|
|
20
|
+
goTo,
|
|
21
|
+
t,
|
|
22
|
+
getRedirectLink,
|
|
23
|
+
getActionWidgetsConfig,
|
|
24
|
+
getKeyIndicatorsConfig,
|
|
25
|
+
useWidgetFetch,
|
|
26
|
+
} = config;
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
data,
|
|
30
|
+
loading,
|
|
31
|
+
userGrowthData,
|
|
32
|
+
fetchUserGrowth,
|
|
33
|
+
userGrowthDataLoading,
|
|
34
|
+
} = useWidgetFetch();
|
|
35
|
+
|
|
36
|
+
const actionsWidgetsConfig = useMemo(
|
|
37
|
+
() => getActionWidgetsConfig({ getRedirectLink }),
|
|
38
|
+
[getRedirectLink]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const keyIndicatorsConfig = useMemo(
|
|
42
|
+
() =>
|
|
43
|
+
getKeyIndicatorsConfig({
|
|
44
|
+
getRedirectLink,
|
|
45
|
+
keyIndicatorsData: data?.keyInformation,
|
|
46
|
+
}),
|
|
47
|
+
[data?.keyInformation, getRedirectLink]
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Dummy data for top contributors if not provided
|
|
51
|
+
const TOTAL_DUMMY = [
|
|
52
|
+
{ label: "Contributor 1", Score: 0 },
|
|
53
|
+
{ label: "Contributor 2", Score: 0 },
|
|
54
|
+
{ label: "Contributor 3", Score: 0 },
|
|
55
|
+
{ label: "Contributor 4", Score: 0 },
|
|
56
|
+
{ label: "Contributor 5", Score: 0 },
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<AdminDashboard
|
|
61
|
+
t={t}
|
|
62
|
+
loading={loading}
|
|
63
|
+
goTo={goTo}
|
|
64
|
+
actionWidgetConfig={actionsWidgetsConfig}
|
|
65
|
+
loadingUserGrowth={userGrowthDataLoading}
|
|
66
|
+
fetchUserGrowth={fetchUserGrowth}
|
|
67
|
+
data={{
|
|
68
|
+
keyIndicatorsData: keyIndicatorsConfig,
|
|
69
|
+
userActivityData: data?.userActivity,
|
|
70
|
+
topContributorsData: data?.topContributors || TOTAL_DUMMY,
|
|
71
|
+
userGrowthData: userGrowthData,
|
|
72
|
+
}}
|
|
73
|
+
adminTranslationIdentifier={appName}
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Admin Screens - Reusable Admin Panel Components
|
|
2
|
+
|
|
3
|
+
This module provides ready-to-use admin panel screens that can be easily configured for any application.
|
|
4
|
+
|
|
5
|
+
## 🎯 Purpose
|
|
6
|
+
|
|
7
|
+
The admin panel is mostly static across applications - it only needs configuration changes (app name, services, etc.). These components allow you to:
|
|
8
|
+
|
|
9
|
+
1. **Export admin routes from DAF** instead of duplicating code per application
|
|
10
|
+
2. **Configure via props** instead of rewriting components
|
|
11
|
+
3. **Maintain consistency** across all applications using DAF
|
|
12
|
+
|
|
13
|
+
## 📦 Available Components
|
|
14
|
+
|
|
15
|
+
### 1. `AdminDashboardScreen`
|
|
16
|
+
The main admin dashboard with key indicators, action widgets, and statistics.
|
|
17
|
+
|
|
18
|
+
**Configuration:**
|
|
19
|
+
```javascript
|
|
20
|
+
{
|
|
21
|
+
appName: "wazi", // App name for translations
|
|
22
|
+
goTo: useNavigate(), // Navigation function
|
|
23
|
+
t: useTranslation(), // Translation function
|
|
24
|
+
getRedirectLink: (path) => path, // Redirect link generator
|
|
25
|
+
getActionWidgetsConfig: (opts) => [], // Action widgets config
|
|
26
|
+
getKeyIndicatorsConfig: (opts) => [], // Key indicators config
|
|
27
|
+
useWidgetFetch: () => {} // Hook to fetch dashboard data
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. `AdminUsersScreen`
|
|
32
|
+
User management table with impersonation, password reset, etc.
|
|
33
|
+
|
|
34
|
+
**Configuration:**
|
|
35
|
+
```javascript
|
|
36
|
+
{
|
|
37
|
+
appName: "wazi",
|
|
38
|
+
module: APP, // App identifier
|
|
39
|
+
goTo: useNavigate(),
|
|
40
|
+
t: useTranslation(),
|
|
41
|
+
location: useLocation(),
|
|
42
|
+
isMobile: false,
|
|
43
|
+
userRoles: [], // User roles config
|
|
44
|
+
accountTypes: [], // Account types config
|
|
45
|
+
getRedirectLink: (path) => path,
|
|
46
|
+
AdminService: {}, // Admin service methods
|
|
47
|
+
AuthenticationService: {}, // Auth service methods
|
|
48
|
+
handleError: (err) => {}, // Error handler
|
|
49
|
+
getAppRedirect: ({token}) => "" // App redirect for impersonation
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. `AdminAccountsScreen`
|
|
54
|
+
Accounts management table with invitation management.
|
|
55
|
+
|
|
56
|
+
**Configuration:**
|
|
57
|
+
```javascript
|
|
58
|
+
{
|
|
59
|
+
appName: "wazi",
|
|
60
|
+
module: APP,
|
|
61
|
+
goTo: useNavigate(),
|
|
62
|
+
t: useTranslation(),
|
|
63
|
+
location: useLocation(),
|
|
64
|
+
isMobile: false,
|
|
65
|
+
accountTypes: [],
|
|
66
|
+
getRedirectLink: (path) => path,
|
|
67
|
+
AdminService: {},
|
|
68
|
+
options: { countries: [] }, // Options with countries, etc.
|
|
69
|
+
useQuery: () => {}, // Query params hook
|
|
70
|
+
NewAccountModal: Component // Optional custom modal
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 4. `AdminAccountsViewScreen`
|
|
75
|
+
View/Edit individual accounts with user management.
|
|
76
|
+
|
|
77
|
+
**Configuration:**
|
|
78
|
+
```javascript
|
|
79
|
+
{
|
|
80
|
+
module: APP,
|
|
81
|
+
goTo: useNavigate(),
|
|
82
|
+
t: useTranslation(),
|
|
83
|
+
location: useLocation(),
|
|
84
|
+
getRedirectLink: (path) => path,
|
|
85
|
+
renderBreadCrumbs: (opts) => [], // Breadcrumbs renderer
|
|
86
|
+
id: "account-id", // From route params
|
|
87
|
+
mode: "view|edit", // From route params
|
|
88
|
+
group: "general", // From route params
|
|
89
|
+
userRoles: [],
|
|
90
|
+
options: { countries: [] },
|
|
91
|
+
accountTypes: [],
|
|
92
|
+
accountStatuses: [],
|
|
93
|
+
getAccountData: (opts) => {}, // Fetch account data
|
|
94
|
+
updateAccount: (opts) => {}, // Update account
|
|
95
|
+
handleError: (err) => {},
|
|
96
|
+
toggleAccountStatus: (opts) => {}, // Toggle account status
|
|
97
|
+
transferAdmin: (opts) => {} // Transfer admin rights
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 🚀 Usage in Applications
|
|
102
|
+
|
|
103
|
+
### Step 1: Create Configuration Hooks
|
|
104
|
+
|
|
105
|
+
Create a file `privateRoutes/adminConfig.js` in your application:
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
import { useNavigate, useLocation, useParams } from "react-router-dom";
|
|
109
|
+
import { useTranslation } from "react-i18next";
|
|
110
|
+
// ... import your services and hooks
|
|
111
|
+
|
|
112
|
+
export function useAdminDashboardConfig() {
|
|
113
|
+
const goTo = useNavigate();
|
|
114
|
+
const { t } = useTranslation();
|
|
115
|
+
// ... gather all needed config
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
appName: "your-app",
|
|
119
|
+
goTo,
|
|
120
|
+
t,
|
|
121
|
+
// ... all other config
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Create similar hooks for other screens
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Step 2: Create Wrapper Components
|
|
129
|
+
|
|
130
|
+
In your `privateRoutes/index.js`:
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
import {
|
|
134
|
+
AdminDashboardScreen,
|
|
135
|
+
AdminUsersScreen,
|
|
136
|
+
AdminAccountsScreen,
|
|
137
|
+
AdminAccountsViewScreen,
|
|
138
|
+
} from "datastake-daf/dist/components";
|
|
139
|
+
import {
|
|
140
|
+
useAdminDashboardConfig,
|
|
141
|
+
useAdminUsersConfig,
|
|
142
|
+
useAdminAccountsConfig,
|
|
143
|
+
useAdminAccountsViewConfig,
|
|
144
|
+
} from "./adminConfig";
|
|
145
|
+
|
|
146
|
+
function DashboardWrapper() {
|
|
147
|
+
const config = useAdminDashboardConfig();
|
|
148
|
+
return <AdminDashboardScreen config={config} />;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Create similar wrappers for other screens
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Step 3: Define Routes
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
const routes = [
|
|
158
|
+
{
|
|
159
|
+
path: "",
|
|
160
|
+
key: "APP_YOUR_APP_DASHBOARD",
|
|
161
|
+
component: <DashboardWrapper />,
|
|
162
|
+
visible: () => true,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
path: "accounts",
|
|
166
|
+
key: "APP_YOUR_APP_ACCOUNTS",
|
|
167
|
+
component: <AccountsWrapper />,
|
|
168
|
+
visible: (user) => userIsAdmin(user),
|
|
169
|
+
},
|
|
170
|
+
// ... more routes
|
|
171
|
+
];
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## ✅ Benefits
|
|
175
|
+
|
|
176
|
+
1. **No Code Duplication**: Write admin logic once in DAF, use everywhere
|
|
177
|
+
2. **Easy Maintenance**: Fix bugs once, applies to all apps
|
|
178
|
+
3. **Consistent UX**: Same admin experience across all applications
|
|
179
|
+
4. **Configurable**: Each app can customize behavior via config
|
|
180
|
+
5. **Type Safe**: Well-documented configuration interfaces
|
|
181
|
+
|
|
182
|
+
## 🔄 Migration from Old Pattern
|
|
183
|
+
|
|
184
|
+
**Before** (duplicated code per app):
|
|
185
|
+
```
|
|
186
|
+
wazi-frontend/src/screens/Admin/
|
|
187
|
+
├── Dashboard/index.js ❌ Duplicated
|
|
188
|
+
├── Users/index.js ❌ Duplicated
|
|
189
|
+
└── Accounts/index.js ❌ Duplicated
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**After** (configuration only):
|
|
193
|
+
```
|
|
194
|
+
wazi-frontend/src/privateRoutes/
|
|
195
|
+
├── index.js ✅ Route definitions
|
|
196
|
+
└── adminConfig.js ✅ Configuration hooks
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## 📚 Example: Complete Setup
|
|
200
|
+
|
|
201
|
+
See `/wazi-frontend/src/privateRoutes/` for a complete working example of how to configure and use these admin screens.
|
|
202
|
+
|
|
203
|
+
## 🔧 Customization
|
|
204
|
+
|
|
205
|
+
If you need custom behavior:
|
|
206
|
+
|
|
207
|
+
1. **Small changes**: Use configuration options
|
|
208
|
+
2. **Moderate changes**: Create a custom wrapper component
|
|
209
|
+
3. **Large changes**: Extend the base admin components
|
|
210
|
+
|
|
211
|
+
## 📝 Notes
|
|
212
|
+
|
|
213
|
+
- All screens expect React Router hooks (useNavigate, useLocation, useParams)
|
|
214
|
+
- Translation keys follow the pattern: `{appName}::key` and `admin::key`
|
|
215
|
+
- Services should follow the AdminService interface from DAF
|
|
216
|
+
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React, { useCallback } from "react";
|
|
2
|
+
import { message, Modal } from "antd";
|
|
3
|
+
import UserTable from "../AdminTables/UserTable/index.jsx";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Admin Users Screen Wrapper
|
|
7
|
+
* This is a ready-to-use route component that can be configured per application
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} config - Application configuration
|
|
10
|
+
* @param {string} config.appName - Application name
|
|
11
|
+
* @param {string} config.module - Module identifier (APP constant)
|
|
12
|
+
* @param {Function} config.goTo - Navigation function
|
|
13
|
+
* @param {Function} config.t - Translation function
|
|
14
|
+
* @param {Object} config.location - Router location object
|
|
15
|
+
* @param {boolean} config.isMobile - Is mobile viewport
|
|
16
|
+
* @param {Array} config.userRoles - User roles configuration
|
|
17
|
+
* @param {Array} config.accountTypes - Account types configuration
|
|
18
|
+
* @param {Function} config.getRedirectLink - Function to get redirect links
|
|
19
|
+
* @param {Object} config.AdminService - Admin service with methods
|
|
20
|
+
* @param {Object} config.AuthenticationService - Authentication service
|
|
21
|
+
* @param {Function} config.handleError - Error handling function
|
|
22
|
+
* @param {Function} config.getAppRedirect - Get app redirect URL for impersonation
|
|
23
|
+
*/
|
|
24
|
+
export default function AdminUsersScreen({ config }) {
|
|
25
|
+
const {
|
|
26
|
+
appName = "app",
|
|
27
|
+
module,
|
|
28
|
+
goTo,
|
|
29
|
+
t,
|
|
30
|
+
location,
|
|
31
|
+
isMobile,
|
|
32
|
+
userRoles,
|
|
33
|
+
accountTypes,
|
|
34
|
+
getRedirectLink,
|
|
35
|
+
AdminService,
|
|
36
|
+
AuthenticationService,
|
|
37
|
+
handleError,
|
|
38
|
+
getAppRedirect,
|
|
39
|
+
} = config;
|
|
40
|
+
|
|
41
|
+
const onImpersonate = useCallback(
|
|
42
|
+
async (id) => {
|
|
43
|
+
try {
|
|
44
|
+
const { data } = await AdminService.impersonate({ id });
|
|
45
|
+
localStorage.setItem("previous", true);
|
|
46
|
+
localStorage.setItem("previous_app", module);
|
|
47
|
+
window.location = getAppRedirect({ token: data.token });
|
|
48
|
+
} catch (err) {
|
|
49
|
+
handleError(err);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
[AdminService, module, getAppRedirect, handleError]
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const onResendVerification = useCallback(() => {
|
|
56
|
+
// TODO: implement in calling app if needed
|
|
57
|
+
message.success(t("Verification email resent"));
|
|
58
|
+
}, [t]);
|
|
59
|
+
|
|
60
|
+
const onCopyVerification = useCallback(() => {
|
|
61
|
+
// TODO: implement in calling app if needed
|
|
62
|
+
message.success(t("Verification link copied"));
|
|
63
|
+
}, [t]);
|
|
64
|
+
|
|
65
|
+
const onResetPassword = useCallback(
|
|
66
|
+
async (email) => {
|
|
67
|
+
Modal.confirm({
|
|
68
|
+
title: t("Send password reset link?"),
|
|
69
|
+
content: t("Are you sure you want to send password reset link to this user?"),
|
|
70
|
+
okText: t("Yes"),
|
|
71
|
+
cancelText: t("No"),
|
|
72
|
+
onOk: async () => {
|
|
73
|
+
try {
|
|
74
|
+
await AuthenticationService.resetPasswordRequest({ email });
|
|
75
|
+
message.success(t("Password reset link sent to user"));
|
|
76
|
+
} catch (err) {
|
|
77
|
+
handleError(err);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
[AuthenticationService, t, handleError]
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
function getUsers(params) {
|
|
86
|
+
return AdminService.getUsers(params);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getAccounts(params) {
|
|
90
|
+
return AdminService.getAccounts(params);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<UserTable
|
|
95
|
+
t={t}
|
|
96
|
+
goTo={goTo}
|
|
97
|
+
getRedirectLink={getRedirectLink}
|
|
98
|
+
location={location}
|
|
99
|
+
module={module}
|
|
100
|
+
headerTitle="users"
|
|
101
|
+
getData={getUsers}
|
|
102
|
+
getAccounts={getAccounts}
|
|
103
|
+
isMobile={isMobile}
|
|
104
|
+
config={{
|
|
105
|
+
userRoles,
|
|
106
|
+
accountTypes,
|
|
107
|
+
tableOnClick: {
|
|
108
|
+
onResendVerification,
|
|
109
|
+
onCopyVerification,
|
|
110
|
+
onImpersonate,
|
|
111
|
+
onResetPassword,
|
|
112
|
+
},
|
|
113
|
+
}}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Screens - Ready-to-use route components
|
|
3
|
+
* These components wrap the base admin components and provide
|
|
4
|
+
* a consistent interface that can be configured per application
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { default as AdminDashboardScreen } from "./Dashboard.jsx";
|
|
8
|
+
export { default as AdminUsersScreen } from "./Users.jsx";
|
|
9
|
+
export { default as AdminAccountsScreen } from "./Accounts.jsx";
|
|
10
|
+
export { default as AdminAccountsViewScreen } from "./AccountsView.jsx";
|
|
11
|
+
|