Petstore: Orders
The Orders page, served at /console/orders, is the petstore's workflow table. Orders move through
PLACED, APPROVED and DELIVERED; each row offers only the transitions that are legal for its status, and
creating an order is a two-step dialog. It shows what row actions, dialogs, confirmations and a ribbon dialog button look
like when they are wired to real state changes.
What this page shows
- Server mode with BeanQuery, like the Pets page, plus two URL-state directives,
dayandwindow. The query endpoint accepts?day=yyyy-mm-dd, or?start=and?end=for a date window (both ends inclusive, either may be omitted), and applies them before the column filters. A missing or malformed value is ignored. The Store page's trend chart links here with?state=day({day}). - Row actions with
visibleWhen. Approve appears only onPLACEDrows and Deliver only onAPPROVEDrows. Each posts to/console/orders/{id}/approveor/console/orders/{id}/deliver; an illegal transition is a 409. - A dialog from an action. Cancel opens a form (
GET /console/orders/{id}/cancel-form, with a reason and a notify checkbox) and submits aDELETEto/console/orders/{id}. The reason is recorded in the audit trail. - A typed confirmation. Delete uses
confirmRenderer: 'typed', so the user must type to confirm. The row action'stoneisdanger. - A two-step wizard. The ribbon's "+ New order" button opens a
ModalDef: step one picks an available pet and an optional ship date; its child action "Review order" stacks a second dialog, carrying the first step's inputs as drafts, and Confirm posts to/console/orders. Only pets that are for sale are offered.
Template
The template is orders.ftlh. The excerpt keeps the URL state and two of the row actions.
<@card type="datatables" id="orders" title="Orders">
{
rowType: 'Order',
dataMode: 'server',
dataUrl: '/console/orders/query',
urlState: { day: {}, window: {} },
rowActions: [
{ id: 'approve', label: 'Approve', endpoint: '/console/orders/{id}/approve', method: 'POST', onSuccess: 'redraw',
visibleWhen: [ { field: 'status', op: 'eq', value: 'PLACED' } ] },
{ id: 'cancel', label: 'Cancel', form: '/console/orders/{id}/cancel-form', present: 'dialog',
endpoint: '/console/orders/{id}', method: 'DELETE', onSuccess: 'redraw' }
]
}
</@card>
The ribbon also carries a "+ New order" dialog item whose form is /console/orders/new-form; see the wizard above.
Builder twin
OrdersPageBuilders.orders builds the same table. Request /console/orders?builder to render it.
TableSpec.create("orders").rowType("Order").dataMode(DataMode.SERVER).dataUrl("/console/orders/query")
.urlState("day", "window")
.rowActions(
RowAction.create("approve").label("Approve").endpoint("/console/orders/{id}/approve").method(Method.POST)
.onSuccess(OnSuccess.REDRAW).visibleWhen(VisibilityRule.when("status").eq("PLACED")),
RowAction.create("delete").label("Delete").endpoint("/console/orders/{id}").method(Method.DELETE)
.confirm("Delete order '{id}'?").tone(Tone.DANGER).confirmRenderer("typed").onSuccess(OnSuccess.REDRAW));
The wizard is not part of the template or the builder: both pages point the ribbon button at the same two form
endpoints on OrdersRest, which return ModalDef beans (newForm and reviewForm).
Source and tests
Source: juneau-petstore/juneau-petstore-core, classes OrdersRest (in the orders package) and
OrdersPageBuilders (in the pages package), and the template orders.ftlh.
Tests: OrdersRest_Test (query, day and window, transitions and their 409s, cancel, the wizard steps and order
placement), PetstorePages_ContractTest and PetstoreTwins_Test.
See also
- Twin pattern: see 19.17. Template and Builder Twins.
- Petstore: Pets: the other server-mode table.
- Petstore: Pet Detail: the Orders tab and order selection for one pet.
- Rich Table Views: Actions: row actions,
visibleWhenand action results. - Rich Table Views: Security: confirmation mechanisms such as typed confirm.
- Declarative Widgets:
ModalDefandFormDef. - Data Table View Settings: URL state.