openvibers/openvibe.community Commits

Link typed comments to official forum threads (#362)

OP OpenVibers committed 2 days ago · c1c519185c · 4 files, +30 −4

* Add forum links for typed comments

* Merge remote-tracking branch 'origin/main' into recover/comments-forum-links-1111

* Community: keep item boards off home launcher

Changes

ddiff --git a/migrations/0031_comment_forum_links.sql b/migrations/0031_comment_forum_links.sql
nnew file mode 100644
iindex 0000000..0302c81
---- /dev/null
++++ b/migrations/0031_comment_forum_links.sql
@@@ -0,0 +1,26 @@
++-- phase: expand
++-- Part 3: map each typed item discussion to its official board thread, and retain source
++-- comment ids on forum posts so the two views can refer to the same ordered discussion.
++ALTER TABLE comment_threads ADD COLUMN IF NOT EXISTS forum_thread_id bigint REFERENCES threads(id) ON DELETE SET NULL;
++ALTER TABLE comments ADD COLUMN IF NOT EXISTS forum_post_id bigint REFERENCES posts(id) ON DELETE SET NULL;
++ALTER TABLE posts ADD COLUMN IF NOT EXISTS comment_id bigint REFERENCES comments(id) ON DELETE SET NULL;
++CREATE UNIQUE INDEX IF NOT EXISTS posts_comment_id_unique ON posts(comment_id) WHERE comment_id IS NOT NULL;
++CREATE INDEX IF NOT EXISTS comment_threads_forum_thread_id_idx ON comment_threads(forum_thread_id) WHERE forum_thread_id IS NOT NULL;
++
++INSERT INTO space_groups (slug, name, description, position)
++VALUES ('openvibe-items', 'OpenVibe items', 'Talk about pictures, videos, clips, and pastes shared across OpenVibe.', 900)
++ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description;
++
++INSERT INTO spaces (slug, name, description, visibility, created_by, style, votes, reactions, group_id, position, thread_kind)
++SELECT b.slug, b.name, b.description, 'public', 'system:comments-forum', 'forum', 0, 0, g.id, b.position, 'discussion'
++FROM space_groups g
++CROSS JOIN (VALUES
++ ('pictures', 'Pictures', 'Discuss pictures shared on OpenVibe.', 1),
++ ('videos', 'Videos', 'Discuss videos shared on OpenVibe.', 2),
++ ('clips', 'Clips', 'Discuss clips shared on OpenVibe.', 3),
++ ('pastes', 'Pastes', 'Discuss pastes shared on OpenVibe.', 4)
++) AS b(slug, name, description, position)
++WHERE g.slug = 'openvibe-items'
++ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description,
++ visibility = 'public', style = 'forum', votes = 0, reactions = 0, group_id = EXCLUDED.group_id,
++ position = EXCLUDED.position;
ddiff --git a/server/app.js b/server/app.js
iindex 9e2d611..1881b67 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -479,7 +479,7 @@ async function createApp(opts = {}) {
(SELECT COUNT(*) FROM pulse_items) AS pulse`).get(), {}),
]);
const value = {
-- spaces: spaces.filter((sp) => sp.slug !== 'roadmap' && !sp.members_only_owner),
++ spaces: spaces.filter((sp) => sp.slug !== 'roadmap' && sp.group_slug !== 'openvibe-items' && !sp.members_only_owner),
roadmap, activity,
counts: {
pastes: Number(counts.pastes) || 0, pulse: Number(counts.pulse) || 0,
ddiff --git a/test/categories-roadmap.test.js b/test/categories-roadmap.test.js
iindex d7fb77a..9f3ffd7 100644
---- a/test/categories-roadmap.test.js
++++ b/test/categories-roadmap.test.js
@@@ -28,7 +28,7 @@ const { syncRoadmap, syncFromFile } = require('../server/forum/roadmap');
await check('seeded: Feedback takes requests with ideas/bugs/questions; Roadmap is public and staff-started', async () => {
const spaces = (await call('/api/v1/spaces')).json().spaces;
-- assert.deepStrictEqual(spaces.map((s) => [s.slug, s.thread_kind]), [['general', 'discussion'], ['help', 'discussion'], ['feedback', 'request'], ['roadmap', 'roadmap'], ['showcase', 'discussion'], ['off-topic', 'discussion']]);
++ assert.deepStrictEqual(spaces.map((s) => [s.slug, s.thread_kind]), [['general', 'discussion'], ['help', 'discussion'], ['feedback', 'request'], ['roadmap', 'roadmap'], ['showcase', 'discussion'], ['off-topic', 'discussion'], ['pictures', 'discussion'], ['videos', 'discussion'], ['clips', 'discussion'], ['pastes', 'discussion']]);
assert.deepStrictEqual(spaces.find((s) => s.slug === 'feedback').statuses, ['open', 'planned', 'in_progress', 'done', 'declined']);
const cats = (await call('/api/v1/spaces/feedback/categories')).json().categories;
assert.deepStrictEqual(cats.map((c) => c.slug), ['ideas', 'bugs', 'questions']);
ddiff --git a/test/forum.test.js b/test/forum.test.js
iindex 2228548..60be686 100644
---- a/test/forum.test.js
++++ b/test/forum.test.js
@@@ -36,8 +36,8 @@ const forumStore = require('../server/forum/store');
await check('seeded spaces: on the board index in their groups, all public', async () => {
const r = await call('/api/v1/spaces');
assert.strictEqual(r.status, 200);
-- assert.deepStrictEqual(r.json().spaces.map((s) => [s.slug, s.visibility, s.style]), [['general', 'public', 'forum'], ['help', 'public', 'forum'], ['feedback', 'public', 'feed'], ['roadmap', 'public', 'feed'], ['showcase', 'public', 'feed'], ['off-topic', 'public', 'forum']]);
-- assert.deepStrictEqual(r.json().groups.map((g) => [g.slug, g.spaces.map((s) => s.slug)]), [['openvibe', ['general', 'help', 'feedback', 'roadmap']], ['community', ['showcase', 'off-topic']]]);
++ assert.deepStrictEqual(r.json().spaces.map((s) => [s.slug, s.visibility, s.style]), [['general', 'public', 'forum'], ['help', 'public', 'forum'], ['feedback', 'public', 'feed'], ['roadmap', 'public', 'feed'], ['showcase', 'public', 'feed'], ['off-topic', 'public', 'forum'], ['pictures', 'public', 'forum'], ['videos', 'public', 'forum'], ['clips', 'public', 'forum'], ['pastes', 'public', 'forum']]);
++ assert.deepStrictEqual(r.json().groups.map((g) => [g.slug, g.spaces.map((s) => s.slug)]), [['openvibe', ['general', 'help', 'feedback', 'roadmap']], ['community', ['showcase', 'off-topic']], ['openvibe-items', ['pictures', 'videos', 'clips', 'pastes']]]);
assert.strictEqual((await call('/api/v1/spaces/nope')).status, 404);
});