openvibers/openvibe.meme Commits

Meme's home leads with what is real; one 'be the first' row instead of empty sections (#32)

OP OpenVibers committed 13 days ago · 1c5e7e4e52 · 3 files, +49 −8

Changes

ddiff --git a/public/css/meme.css b/public/css/meme.css
iindex 246400d..d300bc2 100644
---- a/public/css/meme.css
++++ b/public/css/meme.css
@@@ -158,3 +158,9 @@ html.ov-motion .mm-demo-bars i { animation: mm-bar .9s cubic-bezier(.2,.7,.2,1)
@media (max-width: 860px) { .mm-make-grid { grid-template-columns: minmax(0, 1fr); } .mm-preview { position: static; order: -1; } }
@media (prefers-reduced-motion: reduce) { .mm-tree-lines path, .mm-sticker, .mm-demo-bars i { animation: none !important; } }
html[data-ov-motion=reduced] .mm-tree-lines path, html[data-ov-motion=reduced] .mm-sticker, html[data-ov-motion=reduced] .mm-demo-bars i { animation: none !important; }
++
++/* Be the first (10-31): what is still missing, one short row below the scenes, never an empty section up top. */
++.mm-first-list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: 10px; }
++.mm-first-list li { display: grid; gap: 4px; padding: 14px 16px; border-radius: 16px; border: 1px dashed color-mix(in srgb, var(--room-accent) 45%, var(--border, #1f2d47)); }
++.mm-first-list span { color: var(--text-secondary, #96a7c2); font-size: 14px; line-height: 1.45; }
++.mm-first-list a { justify-self: start; margin-top: 4px; font-weight: 700; color: var(--room-strong, var(--room-accent)); }
ddiff --git a/server/views/index.js b/server/views/index.js
iindex 57e3aa0..73448e2 100644
---- a/server/views/index.js
++++ b/server/views/index.js
@@@ -73,21 +73,29 @@ function treeMotif() {
function home({ trending = [], week = null, counts = {} } = {}) {
const candidates = week ? week.candidates.slice(0, 3) : [];
-- const live = `<section class="mm-section" id="mm-trending" aria-labelledby="mm-trending-h">
++ // Real first (the owner, 10-31: empty sections made the rooms look unfinished). Trending and the week's teaser show only
++ // when they have entries; while neither does, one short "be the first" row sits below the scenes instead.
++ const trendingSec = trending.length ? `<section class="mm-section" id="mm-trending" aria-labelledby="mm-trending-h">
<div class="mm-head-row"><h2 id="mm-trending-h">Trending</h2><span class="mm-count">${Number(counts.entries) || trending.length} public ${Number(counts.entries) === 1 ? 'entry' : 'entries'}</span></div>
--${trending.length ? `<ol class="mm-entries">${trending.slice(0, 8).map(card).join('')}</ol>` : empty('No entry is public yet. The first proof is being checked against its source.', '/developers', 'How entries are built')}
--</section>
--<section class="mm-section" id="mm-week-teaser" aria-labelledby="mm-week-teaser-h">
++<ol class="mm-entries">${trending.slice(0, 8).map(card).join('')}</ol>
++</section>` : '';
++ const weekSec = candidates.length ? `<section class="mm-section" id="mm-week-teaser" aria-labelledby="mm-week-teaser-h">
<div class="mm-head-row"><h2 id="mm-week-teaser-h">Meme of the week</h2><a class="mm-more" href="/week">The ballot${kit.icon('chevron')}</a></div>
--${candidates.length ? `<ol class="mm-entries mm-entries-week">${candidates.map(card).join('')}</ol>` : empty('No candidate has a use this week yet. The ballot opens as soon as one does.')}
--</section>`;
++<ol class="mm-entries mm-entries-week">${candidates.map(card).join('')}</ol>
++</section>` : '';
++ const firsts = [
++ !trending.length && ['The first entries are on their way', 'Each one is checked against the chat line or VOD second it started from before it is public.', '/developers', 'How entries are built'],
++ !candidates.length && ['Make the first caption', 'Pick a template, write the lines, and it is saved as text anyone can remix.', '/make', 'Open the generator'],
++ ].filter(Boolean);
++ const beFirst = firsts.length ? `<section class="mm-section mm-first" aria-labelledby="mm-first-h"><h2 id="mm-first-h">Be the first</h2><ul class="mm-first-list">${firsts.map(([title, text, href, label]) => `<li><b>${esc(title)}</b><span>${esc(text)}</span><a href="${esc(href)}">${esc(label)}</a></li>`).join('')}</ul></section>` : '';
++ const live = `${trendingSec}${weekSec}`;
const room = sc.room({
room: 'meme',
hero: {
title: 'Every joke has a first time',
lede: 'The open meme database. Each running joke is written down with the moment it happened, a chat line, a VOD second, a Rundown segment, and every later use. People vote for meme of the week, and anyone can caption a template.',
start: { href: '/week', label: 'Vote for meme of the week' },
-- chips: [{ label: 'Make a caption', href: '/make' }, { label: 'Trending', href: '#mm-trending' }, { label: 'The API', href: '/developers' }],
++ chips: [{ label: 'Make a caption', href: '/make' }, ...(trending.length ? [{ label: 'Trending', href: '#mm-trending' }] : []), { label: 'The API', href: '/developers' }],
proof: Number(counts.entries) ? [{ value: Number(counts.entries), label: Number(counts.entries) === 1 ? 'entry' : 'entries' }] : [],
motif: treeMotif(),
},
@@@ -108,8 +116,11 @@ ${candidates.length ? `<ol class="mm-entries mm-entries-week">${candidates.map(c
['Is the database open?', 'Yes: every public entry and citation is in the API, and in OpenVibe\'s Search.'],
] },
});
++ // What is real goes above the scenes; what is still missing goes after them.
const at = room.indexOf('<section class="sc-room-scenes"');
-- return `<div class="mm-wrap mm-home" id="mm-home">${at < 0 ? room : room.slice(0, at) + live + room.slice(at)}</div>`;
++ const end = at < 0 ? -1 : room.indexOf('</section>', at) + '</section>'.length;
++ const page = at < 0 ? live + room + beFirst : room.slice(0, at) + live + room.slice(at, end) + beFirst + room.slice(end);
++ return `<div class="mm-wrap mm-home" id="mm-home">${page}</div>`;
}
function entry({ e, citations = [], signedIn = false, staff = false, reported = false, problem = null } = {}) {
ddiff --git a/test/home-real-first.test.js b/test/home-real-first.test.js
nnew file mode 100644
iindex 0000000..0487a73
---- /dev/null
++++ b/test/home-real-first.test.js
@@@ -0,0 +1,24 @@
++'use strict';
++// Meme's home leads with what is real (the owner, 10-31: empty sections made the rooms look unfinished). With no public
++// entry and no candidate this week, there is no empty Trending or Meme of the week up top: one short "be the first" row
++// sits after the scenes and says how each starts. Once there are entries, they lead above the scenes.
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++const views = require('../server/views');
++
++const src = fs.readFileSync(path.join(__dirname, '..', 'server/views/index.js'), 'utf8');
++assert.match(src, /room\.slice\(0, at\) \+ live \+ room\.slice\(at, end\) \+ beFirst \+ room\.slice\(end\)/, 'the real above the scenes, the missing after them');
++
++const empty = views.home({ trending: [], week: null, counts: {} });
++assert.ok(!empty.includes('id="mm-trending"') && !empty.includes('id="mm-week-teaser"'), 'no empty section');
++assert.ok(!empty.includes('href="#mm-trending"'), 'no chip to a section that is not there');
++const scenes = empty.indexOf('class="sc-room-scenes"');
++assert.ok(scenes > 0 && empty.indexOf('Be the first') > scenes, 'the row follows the scenes');
++assert.ok(empty.includes('href="/make">Open the generator</a>') && empty.includes('href="/developers">How entries are built</a>'), 'each says how it starts');
++
++const entry = { slug: 'robot-offline', title: 'Robot is offline', kind: 'joke', summary: 'When the robot drops.', status: 'rising', uses: 4, citations: [] };
++const some = views.home({ trending: [entry], week: { candidates: [entry] }, counts: { entries: 1 } });
++assert.ok(some.indexOf('id="mm-trending"') > 0 && some.indexOf('id="mm-trending"') < some.indexOf('class="sc-room-scenes"'), 'entries lead above the scenes');
++assert.ok(!some.includes('Be the first'), 'nothing missing, no row');
++console.log('meme home: real first, one "be the first" row after the scenes while nothing is public');