Let the owner manage categories, and give the menus a shelf
Categories were baked into config/<site>.site.json, so adding one meant a rebuild and a redeploy. They are now data: data/sections.json, seeded from the config the first time, and managed in the admin (add, rename, reorder, remove). A category's web address is fixed when it is created because that is what a QR code points at, and a category cannot be removed while it still holds menus. The landing and the top bar were the ugliest parts. The landing was a column of hairlines with tiny meta — a broadsheet, and the paper that makes this app worth looking at was nowhere on it. It is now a shelf: each category is a row whose right edge is a sliver of that menu's first page, bleeding off the screen, with the shelf edge in brass and the name in heavy tight Archivo. The bar was a row of teal pills that would not survive more categories: it now names the menu you are reading and opens a sheet listing the rest, each with its own paper sliver, and the current one is the only teal thing on screen. The sheet is a link to the landing page, so navigating still works without the script. Also fixes the category manager's own layout, which I shipped unstyled, and the markup contract the route tests described.
This commit is contained in:
1 parent
7bf67cc299
commit
c31b73d553
25 files changed
+1225
-190
No files matched your search
+32
-2
@@ -89,9 +89,11 @@ describe('the landing page', () => {
|
||||
assert.equal(response.statusCode, 200);
|
||||
assert.match(response.body, /Hops n Grains/);
|
||||
assert.match(response.body, /Handcrafted Microbrewery/);
|
||||
assert.match(response.body, /<span class="row__label">Bar<\/span>/);
|
||||
assert.match(response.body, /class="shelf" href="\/bar\/"/);
|
||||
assert.match(response.body, /<span class="shelf__name">Bar<\/span>/);
|
||||
assert.match(response.body, /2 pages/);
|
||||
assert.doesNotMatch(response.body, /row__label">Wine/);
|
||||
assert.match(response.body, /class="shelf__peek"/, 'the shelf shows a sliver of the menu paper');
|
||||
assert.doesNotMatch(response.body, /shelf__name">Wine/);
|
||||
});
|
||||
|
||||
it('escapes a label that tries to inject markup', async () => {
|
||||
@@ -128,6 +130,9 @@ describe('a Section page', () => {
|
||||
assert.doesNotMatch(body, /Older menus/);
|
||||
assert.doesNotMatch(body, /This is an older menu/);
|
||||
assert.match(body, /src="\/assets\/app\.js"/);
|
||||
assert.match(body, /class="switcher"/, 'the bar names the menu and opens the switcher');
|
||||
assert.match(body, /<span class="switcher__label">Bar<\/span>/);
|
||||
assert.match(body, /id="menu-sheet"/, 'the sheet exists for the script to open');
|
||||
});
|
||||
|
||||
it('serves both the trailing-slash and bare URLs', async () => {
|
||||
@@ -142,6 +147,31 @@ describe('a Section page', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('the menu switcher', () => {
|
||||
it('lists every Section that has a menu, in category order, marking the one being read', async () => {
|
||||
await seedPublishedBar();
|
||||
const store = app.menu.store;
|
||||
const food = await store.create('food', { label: 'Food Menu' });
|
||||
await store.addPage(food.id, { data: pngBytes('food'), originalName: 'f.jpg' });
|
||||
await store.publish(food.id);
|
||||
|
||||
const page = await app.inject({ method: 'GET', url: '/bar/' });
|
||||
const listed = [...page.body.matchAll(/class="sheet__item[^"]*"\s+href="\/([a-z-]+)\//g)].map(
|
||||
(match) => match[1],
|
||||
);
|
||||
assert.deepEqual(listed, ['food', 'bar']);
|
||||
assert.equal((page.body.match(/sheet__item is-current/g) ?? []).length, 1);
|
||||
assert.match(page.body, />Showing</);
|
||||
});
|
||||
|
||||
it('leaves a category with no menu out until it has one', async () => {
|
||||
await seedPublishedBar();
|
||||
const page = await app.inject({ method: 'GET', url: '/bar/' });
|
||||
assert.doesNotMatch(page.body, /sheet__name">Wine/);
|
||||
assert.equal((await app.inject({ method: 'GET', url: '/wine/' })).statusCode, 404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('an archived Menu Set', () => {
|
||||
it('is reachable at its date URL, marked as older, and does not list itself', async () => {
|
||||
const store = app.menu.store;
|
||||
|
||||
Reference in new issue
Block a user