Add badge to admin menu item

Updated at 1691742808000

Overview

Typically, for menu items leading to a list of data, you might want to visually display the number of items, as shown below:

Installation

Suppose you need to add the number of items to the following menu items:

  1. Trash can for posts - ezyarticle.posts.trash.
  2. List of posts - ezyarticle.posts.list.
  3. Trash can for pages - ezyarticle.pages.trash.
  4. List of pages - ezyarticle.pages.list.
  5. List of terms - ezyarticle.posts.terms.

You can achieve this as follows:

@EzySingleton
@AllArgsConstructor
public class AdminEzyArticleViewDecorator implements ViewDecorator {

    private final AdminPostService postService;
    private final AdminPageService pageService;
    private final AdminTermService termService;
    private final AdminMenuService menuService;

    @Override
    public void decorate(HttpServletRequest httpServletRequest, View view) {
        Reactive.multiple()
            .register(
                "ezyarticle.posts.trash",
                () -> postService.countByStatus(
                    PostStatus.TRASH
                )
            )
            .register(
                "ezyarticle.posts.list",
                () -> postService.countPostsByStatuses(
                    Arrays.asList(
                        PostStatus.DRAFT,
                        PostStatus.PUBLISHED
                    )
                )
            )
            .register(
                "ezyarticle.pages.trash",
                () -> pageService.countPagesByStatus(
                    PostStatus.TRASH
                )
            )
            .register(
                "ezyarticle.pages.list",
                () -> pageService.countPagesByStatuses(
                    Arrays.asList(
                        PostStatus.DRAFT,
                        PostStatus.PUBLISHED
                    )
                )
            )
            .register(
                "ezyarticle.posts.terms",
                termService::countAll
            )
            .blockingConsume(it -> {
                view.putKeyValuesToVariable(
                    VIEW_VARIABLE_MENUITEM_BADGES,
                    it.valueMap()
                );
                long postTrashCount = it.get("ezyarticle.posts.trash", 0L);
                long pageTrashCount = it.get("ezyarticle.pages.trash", 0L);
                view.putKeyValueToVariable(
                    VIEW_VARIABLE_MENUITEM_BADGES,
                    "ezyarticle.posts.trash",
                    postTrashCount - pageTrashCount
                );
            });

        view.putKeyValueToVariable(
            VIEW_VARIABLE_MENU_BADGES,
            "ezyarticle.menus",
            menuService.countAllMenus()
        );
    }
}

Here, the variable names will have the form: <module name>.<menu name>.[menu item name]

Note: If the module name is a phrase like youngmonkeys-website, it should be converted to underscores. For example, the variable name would be youngmonkeys_website.projects.