guest role; guide section ticking
This commit is contained in:
@@ -2,14 +2,36 @@
|
||||
<div class="gb-blocks" :class="{ 'gb-interactive': interactive }">
|
||||
<template v-for="(block, index) in blocks" :key="block.id || index">
|
||||
|
||||
<!--
|
||||
A heading and a step can be ticked off while reading, not just a
|
||||
checklist item. On a long procedure the question is not "what have I
|
||||
done" so much as "where was I" - somebody looks away to do the thing
|
||||
the guide asked for, and looks back at a wall of text. A struck-through
|
||||
section is where they were.
|
||||
|
||||
Reading only: in the editor a tick would be an edit.
|
||||
-->
|
||||
<h2 v-if="block.type === 'heading'" :id="anchorFor(block)" class="gb-heading"
|
||||
v-html="inline(block.text)"></h2>
|
||||
:class="{ 'gb-sectiondone': isTicked(block.id) }">
|
||||
<input v-if="interactive" type="checkbox" class="gb-sectiontick"
|
||||
:checked="isTicked(block.id)"
|
||||
:aria-label="'Mark this section done'"
|
||||
@change="toggle(block.id, $event.target.checked)">
|
||||
<span v-html="inline(block.text)"></span>
|
||||
</h2>
|
||||
|
||||
<p v-else-if="block.type === 'paragraph'" class="gb-para"
|
||||
v-html="inline(block.text)"></p>
|
||||
|
||||
<div v-else-if="block.type === 'step'" class="gb-step">
|
||||
<span class="gb-stepnum">Step {{ stepNumber(index) }}</span>
|
||||
<div v-else-if="block.type === 'step'" class="gb-step"
|
||||
:class="{ 'gb-sectiondone': isTicked(block.id) }">
|
||||
<label class="gb-stepnum">
|
||||
<input v-if="interactive" type="checkbox" class="gb-sectiontick"
|
||||
:checked="isTicked(block.id)"
|
||||
:aria-label="'Mark step ' + stepNumber(index) + ' done'"
|
||||
@change="toggle(block.id, $event.target.checked)">
|
||||
Step {{ stepNumber(index) }}
|
||||
</label>
|
||||
<h3 v-if="block.title" v-html="inline(block.title)"></h3>
|
||||
<div v-if="block.text" v-html="inline(block.text)"></div>
|
||||
</div>
|
||||
@@ -193,6 +215,20 @@ function select (block) {
|
||||
dark mode work with no dark-mode code. */
|
||||
.gb-blocks { line-height: 1.65; }
|
||||
.gb-heading { margin: 1.6rem 0 0.6rem; font-size: 1.35rem; color: var(--text); }
|
||||
|
||||
/* A ticked section is struck through and faded, not hidden: somebody scanning
|
||||
back up the page has to be able to read what they already did. */
|
||||
.gb-sectiondone { text-decoration: line-through; opacity: 0.55; }
|
||||
.gb-sectiondone .gb-stepnum { text-decoration: none; }
|
||||
.gb-sectiontick {
|
||||
/* Touch-sized: a guide is read on a shopfloor PC, often with gloves on. */
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
margin-right: 0.5rem;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
}
|
||||
.gb-heading .gb-sectiontick { text-decoration: none; }
|
||||
.gb-para { margin: 0 0 0.9rem; color: var(--text); }
|
||||
|
||||
.gb-step {
|
||||
|
||||
@@ -6,15 +6,20 @@
|
||||
* checkboxes are live in exactly one of them.
|
||||
*
|
||||
* meta.plugin = 'guides' so the ADR-009 router guard redirects when the backend
|
||||
* plugin is disabled. Every route requires auth because every guides API route
|
||||
* is behind JWT plus a guides.* permission.
|
||||
* plugin is disabled.
|
||||
*
|
||||
* READING does not require auth; WRITING does. The read routes are gated on
|
||||
* guides.view, and a signed-out visitor holds whatever the GUEST role has been
|
||||
* granted - so the role decides, not the router. Sending a guest to /login when
|
||||
* the site has granted them guides.view would make the grant look broken;
|
||||
* letting them through when it has not costs one 401 the view already handles.
|
||||
*/
|
||||
export default [
|
||||
{
|
||||
path: 'guides',
|
||||
name: 'guides',
|
||||
component: () => import('./views/GuidesList.vue'),
|
||||
meta: { requiresAuth: true, plugin: 'guides' }
|
||||
meta: { plugin: 'guides' }
|
||||
},
|
||||
{
|
||||
path: 'guides/new',
|
||||
@@ -26,7 +31,7 @@ export default [
|
||||
path: 'guides/:slug',
|
||||
name: 'guide-view',
|
||||
component: () => import('./views/GuideView.vue'),
|
||||
meta: { requiresAuth: true, plugin: 'guides' }
|
||||
meta: { plugin: 'guides' }
|
||||
},
|
||||
{
|
||||
path: 'guides/:guideid/edit',
|
||||
|
||||
@@ -122,10 +122,14 @@ function resetProgress () {
|
||||
saveProgress()
|
||||
}
|
||||
|
||||
// Everything that can be ticked: checklist items, and the sections a reader
|
||||
// crosses off to keep their place - a step, or a heading on a guide that has
|
||||
// no steps at all (a converted article often has fifty headings and none).
|
||||
const totalChecks = computed(() => {
|
||||
let total = 0
|
||||
for (const block of guide.value?.blocks || []) {
|
||||
if (block.type === 'checklist') total += (block.items || []).length
|
||||
else if (block.type === 'step' || block.type === 'heading') total += 1
|
||||
}
|
||||
return total
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user