Petstore: Console Tour
Every petstore console page shares one chrome: the header with the brand and theme toggle, the navigation tree, the
pending-changes badge and the footer. That chrome is defined once, in the shared base.ftlh template, and every
page template wraps itself in it. This page walks the chrome, the navigation tree and the contract test that pins
the pages. For the directives themselves, see Admin-Console Chrome.
The base template
Each page's template calls <@page>, which captures the page's cards and includes base.ftlh. The base template
holds the <@console> directive, so the chrome is declared exactly once.
Source: juneau-petstore-core/src/main/resources/org/apache/juneau/petstore/console/templates/base.ftlh.
<@console brand="Juneau Petstore" title=(pageTitle!"") theme=(petstoreTheme!"open") schemeToggle=true>
<@scripts phase="after-toolkit"><script src="${assetUrl('/console/petstore.js')}"></script></@scripts>
<@navigation>
<@node id="store" label="Store" href="/console/store"/>
<@node id="pets" label="Pets" href="/console/pets">
<@node id="sold" label="Sold" href="/console/pets/sold"/>
<@node id="changes" label="Pending changes" href="/console/pets/changes"/>
</@node>
...
</@navigation>
<@badge id="pending" src="/console/pets/changes/pending" href="/console/pets/changes" ... placement="header"/>
<@main/>
<@footer text="Apache Juneau petstore sample"/>
</@console>
Three things to notice:
- The theme comes from the model (
petstoreTheme), so the Themes page can switch it. A custom theme layers<@token>overrides inside a nameless<@theme>in the same template. petstore.jsis the one petstore-specific script, loaded after the toolkit on every page.- The
<@badge>sits after</@navigation>and is unscoped on purpose; see Pending Changes.
The navigation tree
The tree goes four levels deep, which is the deepest the shell draws:
| Level | Nodes |
|---|---|
| 1 | Store, Pets, Orders, Users, Operations, Developer, About |
| 2 | Pets: Sold, Pending changes (plus a node for the open pet, see below). Operations: Jobs, Audit. Developer: Custom cards, Themes, Rendering flavors, Secure |
| 3 | The open pet's tabs (summary, photo, orders, history). The four rendering flavors (Html, Freemarker, Mustache, React) |
| 4 | An order under a pet's orders tab |
The pet nodes are not in the static tree: the pet detail page builds its own activeNav (for example
pets/p1/summary) and passes it to <@page tab=activeNav>. See Pet Detail.
Pages normally state their node with <@page tab="ops/jobs">. A page that omits it, such as the Sold Pets page,
falls back to the longest node href that prefixes the current URL, on path-segment boundaries. That is why
/console/pets/sold highlights the Sold node without naming it. The fallback is described under the page contract
in Admin-Console Chrome.
The page contract test
PetstorePages_ContractTest is the pattern to copy into your own console. It holds a list of Page records, each a
path plus a set of assertions on the contract the server wrote into the document: the active nav path, the card
order, each card's type, and selected keys of a card's catalog (for example that the Pets table is server-mode with
a persistent selection). Adding a page to the console means adding one row.
new Page("audit", "/console/ops/audit", p -> p.hasActiveNav("ops", "audit").hasCard("audit", "datatables")),
Source: juneau-petstore-core/src/test/java/org/apache/juneau/petstore/console/PetstorePages_ContractTest.java.
Because the assertions are on the JSON contract, not on rendered HTML, the test needs no browser. The browser tests
(PetstoreNav_BrowserTest and friends) cover what only a browser can show, such as the current-page marker at each
nav level.
Tests
PetstorePages_ContractTest, PetstoreConsoleShell_Test, PetstoreNav_BrowserTest.
See also
- Twin pattern: see 19.17. Template and Builder Twins.
- Porting these patterns to your own console: see 19.19. Porting to the Console.
- Admin-Console Chrome: the directives, themes and the page contract.
- Building a Console Page: the end-to-end tutorial.
- juneau-petstore: the tour landing page.