Move reference plugin to examples/scheduling-plugin; plugins/ ships empty as a drop-in mount point, e2e bind-mounts the example
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
<%#
|
||||
Scheduling · public overview (reference plugin). A page ANYONE may reach — the route and its
|
||||
nav node are marked `public`, so an anonymous visitor is let through and the menu option shows for
|
||||
everyone. The actual shifts data stays behind `scheduling:read`: a reader gets a link straight to
|
||||
it, anyone else a prompt to sign in. Rendered in the native shell via ctx.chrome.
|
||||
Data: chrome, title, breadcrumbs, canRead, shiftsHref
|
||||
%><%
|
||||
const navHtml = include("partials/nav-tree", { nodes: chrome.nav });
|
||||
const cta = canRead
|
||||
? '<a class="btn btn-primary" href="' + shiftsHref + '">View shifts</a>'
|
||||
: '<a class="btn btn-primary" href="/login?return_to=' + encodeURIComponent(shiftsHref) + '">Sign in to view shifts</a>';
|
||||
-%>
|
||||
<%- include("partials/shell", {
|
||||
actions: "",
|
||||
body: '<div class="scheduling-page"><p>Scheduling coordinates shifts across your team. Anyone can read this overview; the shift list itself is available to people with the <code>scheduling:read</code> role.</p>' + cta + '</div>',
|
||||
brand: chrome.brand,
|
||||
breadcrumbs,
|
||||
csrfToken: chrome.csrfToken,
|
||||
nav: navHtml,
|
||||
signInHref: chrome.signInHref,
|
||||
styles: ["/public/scheduling/scheduling.css"],
|
||||
theme: chrome.theme,
|
||||
title,
|
||||
user: chrome.user,
|
||||
}) %>
|
||||
@@ -0,0 +1,22 @@
|
||||
<%#
|
||||
A plugin's own partial (resolved before the core ones). The new-shift form body, reusing the core
|
||||
`partials/field` + `partials/alert`. Config: form { action, csrfToken, submitLabel, cancelHref,
|
||||
fields: field.ejs config[] }, formError?
|
||||
%><%
|
||||
const form = locals.form;
|
||||
-%>
|
||||
<div class="form-page">
|
||||
<% if (locals.formError) { -%>
|
||||
<%- include("partials/alert", { text: locals.formError, tone: "neg" }) %>
|
||||
<% } -%>
|
||||
<form class="form-card" method="post" action="<%= form.action %>">
|
||||
<input type="hidden" name="_csrf" value="<%= form.csrfToken %>">
|
||||
<% form.fields.forEach((field) => { -%>
|
||||
<%- include("partials/field", field) %>
|
||||
<% }) -%>
|
||||
<div class="form-actions">
|
||||
<a class="btn" href="<%= form.cancelHref %>">Cancel</a>
|
||||
<button class="btn btn-primary" type="submit"><%= form.submitLabel %></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,20 @@
|
||||
<%#
|
||||
Scheduling · New shift form (reference plugin). The form POSTs to /scheduling/shifts; the handler
|
||||
CSRF-verifies and forwards the write upstream. Body comes from this plugin's OWN partial
|
||||
(partials/shift-form — resolved plugin-first), which reuses the core field partial.
|
||||
Data: chrome, title, breadcrumbs, form, formError?
|
||||
%><%
|
||||
const navHtml = include("partials/nav-tree", { nodes: chrome.nav });
|
||||
const body = '<div class="scheduling-page">' + include("partials/shift-form", { form, formError: locals.formError }) + '</div>';
|
||||
-%>
|
||||
<%- include("partials/shell", {
|
||||
body,
|
||||
brand: chrome.brand,
|
||||
breadcrumbs,
|
||||
csrfToken: chrome.csrfToken,
|
||||
nav: navHtml,
|
||||
styles: ["/public/scheduling/scheduling.css"],
|
||||
theme: chrome.theme,
|
||||
title,
|
||||
user: chrome.user,
|
||||
}) %>
|
||||
@@ -0,0 +1,27 @@
|
||||
<%#
|
||||
Scheduling · Shifts list (reference plugin). The handler fetched the rows from the upstream
|
||||
service; this view renders them with the core building blocks inside the native app shell
|
||||
(ctx.chrome). `include()` reaches the core partials (shell, nav-tree, filter-bar, data-table,
|
||||
alert) — see docs/plugin-contract.md. Zero-JS: search round-trips the URL.
|
||||
Data: chrome, title, breadcrumbs, filterBar, table, canWrite, newHref, error?
|
||||
%><%
|
||||
const navHtml = include("partials/nav-tree", { nodes: chrome.nav });
|
||||
const filtersHtml = include("partials/filter-bar", filterBar);
|
||||
const tableHtml = include("partials/data-table", table);
|
||||
const alertHtml = locals.error ? include("partials/alert", { text: locals.error, tone: "neg" }) : "";
|
||||
const actions = canWrite
|
||||
? '<a class="btn btn-primary" href="' + newHref + '"><svg class="ico ico-sm" aria-hidden="true"><use href="#i-plus"/></svg>New shift</a>'
|
||||
: "";
|
||||
-%>
|
||||
<%- include("partials/shell", {
|
||||
actions,
|
||||
body: '<div class="scheduling-page">' + alertHtml + filtersHtml + tableHtml + '</div>',
|
||||
brand: chrome.brand,
|
||||
breadcrumbs,
|
||||
csrfToken: chrome.csrfToken,
|
||||
nav: navHtml,
|
||||
styles: ["/public/scheduling/scheduling.css"],
|
||||
theme: chrome.theme,
|
||||
title,
|
||||
user: chrome.user,
|
||||
}) %>
|
||||
Reference in New Issue
Block a user