Skip to content

Commit 2058b9e

Browse files
authored
Merge pull request #534 from devforth/feature/AdminForth/1364/here-https-adminfo-on-backend-
feat: add adminforth.refreshMenuBadge method
2 parents 5952880 + c9c4f00 commit 2058b9e

File tree

8 files changed

+64
-15
lines changed

8 files changed

+64
-15
lines changed

adminforth/documentation/docs/tutorial/03-Customization/10-menuConfiguration.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,12 @@ Most times you need to refresh the badge from some backend API or hook. To do th
207207
resourceId: 'posts',
208208
//diff-add
209209
itemId: 'postsMenuItem',
210-
badge: async (adminUser: AdminUser) => {
211-
return 10
210+
//diff-add
211+
badge: async (adminUser: AdminUser, adminForth: IAdminForth) => {
212+
//diff-add
213+
const newCount = await adminforth.resource('posts').count(Filters.EQ('verified', false));
214+
//diff-add
215+
return newCount;
212216
},
213217
badgeTooltip: 'Unverified posts', // explain user what this badge means
214218
...
@@ -226,15 +230,13 @@ Most times you need to refresh the badge from some backend API or hook. To do th
226230
table: 'posts',
227231
hooks: {
228232
edit: {
229-
//diff-add
233+
//diff-add
230234
afterSave: async ({ record, adminUser, resource, adminforth }) => {
231-
//diff-add
232-
const newCount = await adminforth.resource('posts').count(Filters.EQ('verified', false));
233-
//diff-add
234-
adminforth.websocket.publish(`/opentopic/update-menu-badge/postsMenuItem`, { badge: newCount });
235-
//diff-add
235+
//diff-add
236+
adminforth.refreshMenuBadge('postsMenuItem', adminUser);
237+
//diff-add
236238
return { ok: true }
237-
//diff-add
239+
//diff-add
238240
}
239241
}
240242
}

adminforth/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@ class AdminForth implements IAdminForth {
128128

129129
websocket: IWebSocketBroker;
130130

131+
async refreshMenuBadge(menuItemId: string, adminUser: AdminUser) {
132+
const menuItem = this.config.menu.find((item) => item.itemId === menuItemId);
133+
if (!menuItem) {
134+
afLogger.error(`Cannot refresh badge for menu item with id "${menuItemId}" because it was not found in config.menu`);
135+
return;
136+
}
137+
if (!menuItem.badge) {
138+
afLogger.error(`Cannot refresh badge for menu item with id "${menuItemId}" because it does not have badge function in config.menu`);
139+
return;
140+
}
141+
const badgeValue = typeof menuItem.badge === 'function' ? await menuItem.badge(adminUser, this) : menuItem.badge;
142+
this.websocket.publish(`/opentopic/update-menu-badge/${menuItemId}`, { badge: badgeValue });
143+
}
144+
131145
operationalResources: {
132146
[resourceId: string]: IOperationalResource,
133147
}

adminforth/modules/restApi.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,11 +504,13 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
504504

505505
const badgeFunctions = [];
506506

507+
const adminforth = this.adminforth;
508+
507509
function processMenuItem(menuItem) {
508510
if (menuItem.badge) {
509511
if (typeof menuItem.badge === 'function') {
510512
badgeFunctions.push(async () => {
511-
badges[menuItem.itemId] = await menuItem.badge(adminUser);
513+
badges[menuItem.itemId] = await menuItem.badge(adminUser, adminforth);
512514
});
513515
} else {
514516
badges[menuItem.itemId] = menuItem.badge;

adminforth/types/Back.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,8 @@ export interface IAdminForth {
456456
* ```
457457
*/
458458
getPluginById<T>(id: string): T;
459+
460+
refreshMenuBadge(menuItemId: string, adminUser: AdminUser): Promise<void>;
459461
}
460462

461463

adminforth/types/Common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ export interface AdminForthConfigMenuItem {
11641164
* Optional callback which will be called before rendering the menu for each item.
11651165
* Result of callback if not null will be used as a small badge near the menu item.
11661166
*/
1167-
badge?: string | number | ((user: AdminUser) => Promise<string> | string | Promise<number> | number),
1167+
badge?: string | number | ((user: AdminUser, adminForth: IAdminForth) => Promise<string | number> | string | number),
11681168

11691169
/**
11701170
* Tooltip shown on hover for badge

dev-demo/api.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { Express } from "express";
2-
import { IAdminForth } from "adminforth";
2+
import { IAdminForth, IAdminUserExpressRequest } from "adminforth";
33

44
export function initApi(app: Express, admin: IAdminForth) {
55
app.get(`${admin.config.baseUrl}/api/hello/`,
6-
(req, res) => {
6+
admin.express.authorize(
7+
async (req:IAdminUserExpressRequest, res: any) => {
8+
admin.refreshMenuBadge('menuTimestamp', req.adminUser);
79
res.json({ message: "Hello from AdminForth API!" });
810
}
9-
);
11+
));
1012
}

dev-demo/custom/AfComponents.vue

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,18 @@
377377
:expandDepth="2"
378378
/>
379379

380+
<Button @click="createJob">
381+
Create Job
382+
</Button>
383+
384+
<Button @click="callHelloWorldApi">
385+
Call API
386+
</Button>
387+
388+
<Button @click="callHelloWorldApi">
389+
Refresh badge
390+
</Button>
391+
380392
</div>
381393

382394

@@ -522,4 +534,13 @@ watch(numberInput, (newVal) => {
522534
watch(textInput, (newVal) => {
523535
console.log('Text input changed:', newVal, typeof newVal);
524536
});
537+
538+
async function callHelloWorldApi() {
539+
try {
540+
const response = await callApi({ path: '/api/hello/', method: 'GET' });
541+
console.log('API response:', response);
542+
} catch (error) {
543+
console.error('API error:', error);
544+
}
545+
}
525546
</script>

dev-demo/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import express from 'express';
2-
import AdminForth, { Filters } from '../adminforth/index.js';
2+
import AdminForth, { AdminUser, Filters, IAdminForth } from '../adminforth/index.js';
33
import usersResource from "./resources/adminuser.js";
44
import { fileURLToPath } from 'url';
55
import path from 'path';
@@ -143,6 +143,12 @@ export const admin = new AdminForth({
143143
icon: 'flowbite:chart-pie-solid',
144144
component: '@@/AfComponents.vue',
145145
path: '/af-components',
146+
itemId: 'menuTimestamp',
147+
badge: async (adminUser: AdminUser, adminForth: IAdminForth) => {
148+
const now = new Date();
149+
return now.getSeconds();
150+
},
151+
badgeTooltip: 'Seconds in current minute',
146152
},
147153
{
148154
type: 'divider'

0 commit comments

Comments
 (0)