diff --git a/plugins/guides/frontend/components/GuideBlocks.vue b/plugins/guides/frontend/components/GuideBlocks.vue
index 3ddd31b9..ebc24551 100644
--- a/plugins/guides/frontend/components/GuideBlocks.vue
+++ b/plugins/guides/frontend/components/GuideBlocks.vue
@@ -50,14 +50,26 @@
{{ block.language || 'text' }}
{{ block.caption }}
-
-
- {{ copied === block.id ? 'Copied' : 'Copy' }}
+
+
+ {{ selected === block.id ? 'Selected - press Ctrl+C' : 'Select' }}
- {{ block.text }}
+ {{ block.text }}
@@ -96,7 +108,9 @@ const props = defineProps({
})
const emit = defineEmits(['toggle'])
-const copied = ref('')
+const selected = ref('')
+const codeNodes = {}
+function registerCode (id, el) { if (el) codeNodes[id] = el }
function inline (text) {
return renderInline(text)
@@ -138,23 +152,16 @@ function anchorFor (block) {
return 'g-' + (block.id || '')
}
-async function copy (block) {
- try {
- await navigator.clipboard.writeText(block.text || '')
- copied.value = block.id
- setTimeout(() => { copied.value = '' }, 2000)
- } catch (err) {
- // Clipboard needs a secure context. Select the text instead of failing
- // silently, so the tech can copy it by hand.
- const node = document.querySelector('.gb-code pre')
- if (node && window.getSelection) {
- const range = document.createRange()
- range.selectNodeContents(node)
- const selection = window.getSelection()
- selection.removeAllRanges()
- selection.addRange(range)
- }
- }
+function select (block) {
+ const node = codeNodes[block.id]
+ if (!node || !window.getSelection) return
+ const range = document.createRange()
+ range.selectNodeContents(node)
+ const selection = window.getSelection()
+ selection.removeAllRanges()
+ selection.addRange(range)
+ selected.value = block.id
+ setTimeout(() => { selected.value = '' }, 4000)
}
diff --git a/plugins/guides/frontend/utils/templates.js b/plugins/guides/frontend/utils/templates.js
new file mode 100644
index 00000000..1a166f81
--- /dev/null
+++ b/plugins/guides/frontend/utils/templates.js
@@ -0,0 +1,74 @@
+/**
+ * Starting points for a new guide.
+ *
+ * The blank page is the real barrier to somebody writing a procedure down. A
+ * skeleton with the right SHAPE - what you need first, the steps, how you know
+ * it worked, what to do when it does not - gets a half-decent guide out of
+ * somebody who would otherwise have written nothing.
+ *
+ * The shape is lifted from the KB articles the team already writes, so guides
+ * written here read like the ones written before them.
+ */
+
+function id (prefix, n) {
+ return prefix + n
+}
+
+export const templates = [
+ {
+ key: 'blank',
+ name: 'Blank',
+ description: 'Start with nothing',
+ blocks: () => [],
+ },
+ {
+ key: 'procedure',
+ name: 'Procedure',
+ description: 'Before you start, numbered steps, how to check it worked',
+ blocks: () => [
+ { id: id('t', 1), type: 'paragraph',
+ text: 'What this covers, and when somebody would need it.' },
+ { id: id('t', 2), type: 'callout', variant: 'warning', title: 'Before you start',
+ text: 'Anything that has to be true first, or that will bite halfway through.' },
+ { id: id('t', 3), type: 'heading', text: 'Steps' },
+ { id: id('t', 4), type: 'step', title: 'First step', text: '' },
+ { id: id('t', 5), type: 'step', title: 'Second step', text: '' },
+ { id: id('t', 6), type: 'heading', text: 'Check it worked' },
+ { id: id('t', 7), type: 'checklist', items: [
+ { id: id('ti', 1), text: '' },
+ { id: id('ti', 2), text: '' },
+ ] },
+ ],
+ },
+ {
+ key: 'troubleshooting',
+ name: 'Troubleshooting',
+ description: 'Symptom, likely causes, what to check first',
+ blocks: () => [
+ { id: id('t', 1), type: 'paragraph', text: 'The symptom, as somebody would describe it.' },
+ { id: id('t', 2), type: 'heading', text: 'Check these first' },
+ { id: id('t', 3), type: 'checklist', items: [
+ { id: id('ti', 1), text: '' },
+ { id: id('ti', 2), text: '' },
+ ] },
+ { id: id('t', 4), type: 'heading', text: 'Likely causes' },
+ { id: id('t', 5), type: 'table',
+ header: ['What you see', 'What it usually means'], rows: [['', '']] },
+ { id: id('t', 6), type: 'callout', variant: 'info',
+ text: 'The thing that looks like the cause and is not.' },
+ ],
+ },
+ {
+ key: 'checklist',
+ name: 'Checklist',
+ description: 'A list to work through, nothing else',
+ blocks: () => [
+ { id: id('t', 1), type: 'paragraph', text: 'When to use this list.' },
+ { id: id('t', 2), type: 'checklist', items: [
+ { id: id('ti', 1), text: '' },
+ { id: id('ti', 2), text: '' },
+ { id: id('ti', 3), text: '' },
+ ] },
+ ],
+ },
+]
diff --git a/plugins/guides/frontend/views/GuideEditor.vue b/plugins/guides/frontend/views/GuideEditor.vue
index 220c6a58..1413f69a 100644
--- a/plugins/guides/frontend/views/GuideEditor.vue
+++ b/plugins/guides/frontend/views/GuideEditor.vue
@@ -3,6 +3,10 @@
@@ -23,86 +25,138 @@
{{ error }}
-
- Title
-
-
-
- Summary
-
-
-
- Tags
-
-
+
+
+
-
-
-
-
{{ block.type }}
-
- info
- warning
- success
-
-
-
-
-
Up
-
Down
-
Remove
+
+
+ Start from:
+
+ {{ tpl.name }}
+ {{ tpl.description }}
+
+
+
+
+
+
+
+
{{ block.type }}
+
+ info
+ warning
+ success
+
+
+
+
+
+
+ B
+ I
+ <>
+ link
+
+
+
+ ^
+ v
+ copy
+ x
+
+
+
+
+
+
+
+
+
+
+ {{ block.type === 'numbers' ? (i + 1) + '.' : '-' }}
+
+ x
+
+
+ Add item
+
+
+
+
+
+
+
-
-
-
-
-
-
-
- x
-
-
Add item
+
+ Add:
+ {{ type }}
+
+ image
+
+
-
+
+ Paste or drag an image anywhere to drop it in below the block you are working on.
+ Text supports **bold**, *italic*, `code` and [links](https://example.com) -
+ or use the buttons.
+
+
-
-
-
+
+
+
Preview
+
{{ guide.title || 'Untitled guide' }}
+
{{ guide.summary }}
+
-
- Add:
- {{ type }}
-
- image file
-
-
-
-
-
- Paste or drag an image straight onto this page to add it. Text supports
- **bold**, *italic*, `code` and [links](https://example.com).
-
-
Version history
@@ -117,11 +171,13 @@