- docs/examples/shop: types.wo model, per-feature view modules
(render() classes), root controller files, layout shell/header/
footer, static assets controller + real style.css, README with
Angular file map + run + DX referendum notes
- buy flow proven by hand: stock check/decrement, 409s, traversal
404, css typed, WAL-durable; builds on the UNPATCHED toolchain
- two language gaps recorded, not fixed (per directive): pub+@table
cannot combine (controllers forced into root module); @view
projection classes absent
- story 37 REDIRECTED per Vue-SFC review: view.html compiled by woc
({{}} auto-escaped, w:if/w:for, typed against view class, no
runtime engine); render()-as-concatenation failed the referendum;
forks revised; shop named the acceptance consumer
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
34 lines
1.4 KiB
Text
34 lines
1.4 KiB
Text
-- layout/app.wo — the app shell (app.html's analog): one full document
|
|
-- wrapping every page with the shared header and footer. Styles are NOT
|
|
-- inlined here — the shop links /assets/style.css, a real stylesheet
|
|
-- served by the static_files controller, so view markup and styling
|
|
-- stay separate files exactly as the template promises.
|
|
use framework/http
|
|
use html
|
|
|
|
pub fn app_shell(title: Text, content: Text) -> Text {
|
|
let d = "<!doctype html><html><head><meta charset=\"utf-8\">";
|
|
d = d .. "<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">";
|
|
d = d .. "<title>${esc(title)}</title>";
|
|
d = d .. "<link rel=\"stylesheet\" href=\"/assets/style.css\">";
|
|
d = d .. "</head><body>";
|
|
d = d .. header();
|
|
d = d .. el("main", "site-main", content);
|
|
d = d .. footer();
|
|
d = d .. "</body></html>";
|
|
return d;
|
|
}
|
|
|
|
-- The one transport helper every controller shares: a 200 HTML Resp.
|
|
pub fn ok_html(body: Text) -> Resp {
|
|
let h: map<Text, Text> = {};
|
|
h["content-type"] = "text/html; charset=utf-8";
|
|
return Resp { status: 200, headers: h, body: body };
|
|
}
|
|
|
|
pub fn html_error(status: Int, title: Text, msg: Text) -> Resp {
|
|
let content = el("h1", "", esc(title)) .. el("p", "", esc(msg)) .. el("p", "", link("/", "", "Back to products"));
|
|
let h: map<Text, Text> = {};
|
|
h["content-type"] = "text/html; charset=utf-8";
|
|
return Resp { status: status, headers: h, body: app_shell("shop — ${title}", content) };
|
|
}
|