openvibers/openvibe.wiki Commits

Empty states: an empty wiki space uses the shared kit (#294)

OP OpenVibers committed 2 days ago · b737f91fb6 · 3 files, +29 −3

No pages yet is kit.empty, with Write the first page as a kit button when the reader can edit; New
page, Import pages and Wiki settings are kit buttons rather than bare links. The space route loads
kit.css so the state and its buttons are styled. No comments yet is a kit empty state too, pointing a
signed-in reader at the comment box and everyone else at sign-in.

Checked: ov test test/empty-states.test.js (the editable and read-only space, the buttons, kit.css).

Changes

ddiff --git a/server/http/pages.js b/server/http/pages.js
iindex 5b1f988..3915a43 100644
---- a/server/http/pages.js
++++ b/server/http/pages.js
@@@ -257,6 +257,7 @@ function createPages({ svc, viewers, platform, config, log = console, limits, vi
title: space.name, description: space.description || `${space.name}: a wiki on OpenVibe.Wiki.`, path: svc.spacePath(space),
robots: open ? 'index, follow' : 'noindex, nofollow', cache: open ? 'public' : null,
jsonLd: open ? seo.structuredData.breadcrumbs([{ name: 'Wiki', url: `${config.baseUrl}/` }, { name: space.name, url: `${config.baseUrl}${svc.spacePath(space)}` }]) : null,
++ styles: ['kit.css'],
});
}));
ddiff --git a/server/render/views.js b/server/render/views.js
iindex 5faedeb..818c605 100644
---- a/server/render/views.js
++++ b/server/render/views.js
@@@ -304,9 +304,9 @@ function spacePage({ space, tree, canEdit, canManage, proposals }) {
<section><h1>${space.name}</h1>
<p class="wk-muted">${space.kind === 'official' ? 'Official wiki' : 'Community wiki'} · ${VIS_LABEL[space.visibility]}</p>
${space.description ? html`<p>${space.description}</p>` : ''}
--${canEdit ? html`<p><a class="wk-button" href="/s/${e(space.slug)}/new">New page</a>${canManage ? html` <a href="/s/${e(space.slug)}/import">Import pages</a> <a href="/s/${e(space.slug)}/settings">Wiki settings</a>` : ''}</p>` : ''}
++${canEdit ? html`<p class="wk-actions">${raw(kit.button({ href: `/s/${e(space.slug)}/new`, label: 'New page', icon: 'plus' }))}${canManage ? html` ${raw(kit.button({ href: `/s/${e(space.slug)}/import`, label: 'Import pages', icon: 'upload', kind: 'quiet' }))} ${raw(kit.button({ href: `/s/${e(space.slug)}/settings`, label: 'Wiki settings', icon: 'gear', kind: 'quiet' }))}` : ''}</p>` : ''}
${proposals && proposals.length ? html`<p>${notice('info', `${proposals.length} AI proposal(s) wait for review.`)} <a href="/s/${e(space.slug)}/proposals">Review them</a></p>` : ''}
--<h2>Pages</h2>${tree.length ? raw(treeHtml(tree, space)) : html`<p class="wk-muted">No pages yet.</p>`}
++<h2>Pages</h2>${tree.length ? raw(treeHtml(tree, space)) : raw(kit.empty({ icon: 'book', title: 'No pages yet', text: canEdit ? 'Write the first page: a title, a few lines, and the wiki starts.' : 'The first page appears here once someone writes it.', action: canEdit ? { href: `/s/${e(space.slug)}/new`, label: 'Write the first page', icon: 'plus' } : null }))}
${space.visibility === 'public' ? html`<p class="wk-muted">Follow this wiki: <a href="/s/${e(space.slug)}/feed.atom" type="application/atom+xml">Atom</a> · <a href="/s/${e(space.slug)}/feed.json" type="application/feed+json">JSON Feed</a></p>` : ''}
</section>`;
}
@@@ -384,7 +384,7 @@ function discussionHtml(d, { space, page, actor }) {
? html`<form method="post" action="${wpath(space, page)}/discuss" class="wk-form"><label for="wk-comment">Add a comment (posted to OpenVibe.Community as you)</label><textarea id="wk-comment" name="message" rows="3" maxlength="5000" required></textarea><button type="submit">Comment</button></form>`
: html`<p><a href="/auth/login?next=${e(wpath(space, page))}">Sign in</a> to comment.</p>`;
return html`<section class="wk-discussion" id="discussion">${head}
--${comments.length ? html`<ul class="wk-comments">${comments.map((c) => html`<li><strong>${c.display_name || 'Someone'}</strong> <span class="wk-muted">${t(c.created_at)}${c.origin === 'ai' ? ' · AI' : ''}</span><p>${c.message}</p></li>`)}</ul>` : html`<p class="wk-muted">No comments yet.</p>`}
++${comments.length ? html`<ul class="wk-comments">${comments.map((c) => html`<li><strong>${c.display_name || 'Someone'}</strong> <span class="wk-muted">${t(c.created_at)}${c.origin === 'ai' ? ' · AI' : ''}</span><p>${c.message}</p></li>`)}</ul>` : raw(kit.empty({ icon: 'chat', title: 'No comments yet', text: 'Start the discussion about this page.', action: actor && actor.subject ? { href: '#wk-comment', label: 'Write the first comment', icon: 'plus' } : { href: `/auth/login?next=${e(wpath(space, page))}`, label: 'Sign in to comment', icon: 'user' } }))}
${form}</section>`;
}
ddiff --git a/test/empty-states.test.js b/test/empty-states.test.js
nnew file mode 100644
iindex 0000000..a20edc1
---- /dev/null
++++ b/test/empty-states.test.js
@@@ -0,0 +1,25 @@
++'use strict';
++// An empty wiki space is a kit empty state, not a bare muted line, and the actions that write the first page
++// are kit buttons (openvibe-shared, 4.179.0+). The space route loads kit.css so the state is styled.
++const assert = require('assert');
++const views = require('../server/render/views');
++const fs = require('fs');
++const path = require('path');
++
++const space = { id: 's1', slug: 'demo', name: 'Demo wiki', kind: 'community', visibility: 'public', description: '' };
++const edit = String(views.spacePage({ space, tree: [], canEdit: true, canManage: true, proposals: [] }));
++assert.ok(edit.includes('class="ovk-empty"'), 'the shared kit empty state');
++assert.ok(edit.includes('No pages yet'), 'it says what is empty');
++assert.ok(edit.includes('Write the first page'), 'the next action is named');
++assert.ok(/class="ovk-btn[^"]*"[^>]*href="\/s\/demo\/new"/.test(edit), 'and is a kit button');
++assert.ok(/class="ovk-btn[^"]*"[^>]*href="\/s\/demo\/import"/.test(edit), 'Import pages is a kit button too');
++assert.ok(/class="ovk-btn[^"]*"[^>]*href="\/s\/demo\/settings"/.test(edit), 'Wiki settings is a kit button too');
++
++const readOnly = String(views.spacePage({ space, tree: [], canEdit: false, canManage: false, proposals: [] }));
++assert.ok(readOnly.includes('class="ovk-empty"') && readOnly.includes('No pages yet'), 'a reader sees the state');
++assert.ok(!readOnly.includes('Write the first page'), 'with no action they cannot take');
++
++const pages = fs.readFileSync(path.join(__dirname, '..', 'server', 'http', 'pages.js'), 'utf8');
++assert.ok(/styles: \['kit\.css'\]/.test(pages), 'the space page loads kit.css');
++
++console.log('empty states: the wiki space uses kit.empty and kit.button');