Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Admin UI dashboard widgets #334

Closed
michaelbromley opened this issue May 8, 2020 · 3 comments
Closed

Admin UI dashboard widgets #334

michaelbromley opened this issue May 8, 2020 · 3 comments

Comments

@michaelbromley
Copy link
Member

Is your feature request related to a problem? Please describe.
Currently the Admin UI dashboard is empty.

Describe the solution you'd like
There should be a well-defined API that allows modules (including user-defined ui extensions) to provide "dashboard widgets" which can be displayed in the dashboard.

Dashboard widgets could include things like:

  • Order totals
  • Recent orders
  • Stock reports
  • Recent reviews
  • etc

The widgets should be configurable by the administrator, i.e. the admin can select which widgets to display and arrange them.

Widgets should be limited by the permissions system, so e.g. only admin with "ReadOrder" permission can see the order list widget.

User widget settings (selection, layout) should be persisted in the back-end somehow. This may be done via a custom field on the Administrator entity.

@samundra
Copy link
Contributor

  • Also something to include, like the ability for users to change the OrderStatus manually from dashboard.

We have one of the payment method as 'cash on delivery'. Once order is checked out with 'cash on delivery' payment method we change that order to 'Arranging Payment' and further order status is supposed to be changed by person who is in charge of handling the logistics. This person would ideally have access to Admin UI dashboard and will be able to perform Order Status changes manually. I tried to have a look around in dashboard and couldn't find any.

@michaelbromley michaelbromley pinned this issue Aug 31, 2020
@michaelbromley michaelbromley modified the milestones: v1.0.0, v0.18.0 Nov 16, 2020
@michaelbromley
Copy link
Member Author

michaelbromley commented Nov 16, 2020

Prior Art

Some screenshots from dashboards of other projects:

Sylius

screenshot

demo sylius com_admin_

  • Sales summary (with chart, time frame options, time frame step forward/backward)
  • Links to frequently-used routes - Products, Orders, Customers, Promotions
  • New customer list
  • New orders list

Saleor

screenshot

demo saleor io_dashboard_

  • Sales summary (just figures, today only)
  • Activity feed (not linked to anything)
  • Orders/Payments/Stock summary with links to relevant sections
  • Top products list

Magento 2

screenshot

demo-m2 bird eu_admin_admin_dashboard_index_key_56d58b912be8adfe0eca157f7c2d855502b4db16ae3a1e87227174e6c79a1768_

  • Scope selector (for multi channel)
  • Sales summary (lifetime sales, average order value, totals. No time-frame select visible. Chart disabled by default)
  • Latest orders list
  • Latest search terms list
  • Summary tabs for best sellers, most-viewed products, new customers, reviews

nopCommerce

screenshot

admin-demo nopcommerce com_admin_

  • "news" (seems like a marketing thing)
  • Common statistics (single figure summaries of certain stats)
  • Orders & new customers line charts (year, month, week time frame selector)
  • Order totals table for this day, week, month, year, all time
  • Incomplete orders list
  • Latest orders list
  • Popular search keywords
  • Best selling products by quantity/revenue

@michaelbromley
Copy link
Member Author

michaelbromley commented Nov 16, 2020

Design goals

  1. Widgets can display arbitrary HTML, including having their own dependencies (e.g. a charting library)
  2. Widgets can access and make use of the Admin UI data layer (Apollo Client + its cache)
  3. There should be standard set of possible dimensions for the "frame" in which a widget appears. Each widget can declare which sizes it supports. These sizes are not in absolute pixel values, but more like some kind of grid, e.g. like the Bootstrap 12 col grid where a widget can be 4, 6, or 12 wide (Clarity already uses the bootstrap grid).
  4. Widgets must specify a permission which the admin must have in order to display
  5. Ideally we support widgets which are not written in Angular. Infrastructure-wise, we can re-use the patterns (and maybe a lot of the code) we already have for non-Angular UI extensions (i.e. the vendure-devkit postMessage comm channel between the Admin UI and an Iframe in which the widget lives)
  6. Widgets should lazy-load. So we only load the code for a widget when displaying the dashboard. And only those widgets which will be displayed, based on user permissions and/or personalized settings.
  7. Eventually we should enable individual admins to customise the display of widgets, by showing/hiding available widgets and arranging them on the dashboard. This is not necessary though for the initial implementation, though the design of any APIs should keep this future need in mind.

Implementation ideas

Conceptually I think we can follow a similar implementation to how we do CustomFieldControls, where we have a central widget registry which we use to register a widget and all the metadata needed like permissions, supported sizes etc. Both built-in widgets and external ones will use this same infrastructure.

For native Angular-based widgets, we can provide a re-usable widget-wrapper component, which provides a common "chrome" or "frame" around the widget (e.g. with a standard drag-drop handle, context menu, resize handling etc). For non-Angular widgets we use a modified version which additionally embeds an iframe and sets up the postMessage cross-frame communication channel.

Rough sketch:

@Component({
  template: `
    <vdr-widget>
       <ul>
           <li *ngFor="let product of topProducts$ | async">{{ product.name }}</li>
       </ul>
    </vdr-widget>
  `,
})
export class TopProductsWidget implements DashboardWidget {
    readonly dashboardWidgetConfig = { 
      title: 'Top-selling products', // todo consider l10n
      supportedSizes: [WidgetSize.Small, WidgetSize.Medium],
      requiredPermissions: [Permission.ReadCatalog, Permission.ReadOrder],
      
    };

    topProducts$: Observable<Product[]>;

    constructor(private dataService: DataService) {}

    // ... implementation omitted
}

@NgModule({
  imports: [SharedModule],
  declarations: [TopProductsWidget ],
  providers: [
    registerDashboardWidget(TopProductsWidget),
  ]
})
export class SharedExtensionModule { }

Note: the sketch above does not fulfill the lazy-loading design goal - this will be loaded by default as soon as the Admin UI bootstraps. So the final design needs to do something clever with creating a lazy-loaded module just for the widget. Perhaps we can entirely hide the Angular module boilerplate part?

Resources on lazy loading components

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants