openvibers/openvibe.exchange Commits
Exchange's home leads with what is real; one 'be the first' row instead of an empty box (#28)
Changes
@@@ -128,3 +128,9 @@ html.ov-motion .ex-motif-passport { animation: ex-stamp .5s cubic-bezier(.2,.9,.@media (max-width: 759px) { .sc-room-pic .ex-motif-item, .sc-room-pic .ex-motif-passport { display: none; } }@media (prefers-reduced-motion: reduce) { .ex-motif-arrows path, .ex-motif-passport { animation: none !important; } }html[data-ov-motion=reduced] .ex-motif-arrows path, html[data-ov-motion=reduced] .ex-motif-passport { animation: none !important; }++++/* Be the first (10-31): an empty market is one short row after the scenes, never an empty box up top. */++.ex-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; }++.ex-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, #2c3d5c)); }++.ex-first-list span { color: var(--text-secondary, #a8b3c4); font-size: 14px; line-height: 1.45; }++.ex-first-list a { justify-self: start; margin-top: 4px; font-weight: 700; color: var(--room-strong, var(--room-accent)); }@@@ -92,10 +92,14 @@ function motif() {}function home({ listings = [], counts = {} } = {}) {-- const live = `<section class="ex-section" id="ex-listings" aria-labelledby="ex-listings-h">++ // Real first (the owner, 10-31: empty sections made the rooms look unfinished): Fresh listings shows only with listings++ // in it; an empty market is one short "be the first" row after the scenes.++ const live = listings.length ? `<section class="ex-section" id="ex-listings" aria-labelledby="ex-listings-h"><div class="ex-section-head"><h2 id="ex-listings-h">Fresh listings</h2><a class="ex-more" href="/listings">All listings${kit.icon('chevron')}</a></div>--${listings.length ? `<ol class="ex-grid">${listings.slice(0, 8).map(card).join('')}</ol>` : empty('Nothing is listed yet. The first proof is a licensed template, tried in the sandbox, installed and revoked.')}--</section>`;++<ol class="ex-grid">${listings.slice(0, 8).map(card).join('')}</ol>++</section>` : '';++ const beFirst = listings.length ? '' : `<section class="ex-section ex-first" aria-labelledby="ex-first-h"><h2 id="ex-first-h">Be the first</h2>++<ul class="ex-first-list"><li><b>List the first thing you made</b><span>A template, a theme, an agent or a tool, with the passport that says what it can touch. Free and swap only in v1.</span><a href="/submit">List something</a></li></ul></section>`;const room = sc.room({room: 'exchange',hero: {@@@ -141,8 +145,11 @@ ${listings.length ? `<ol class="ex-grid">${listings.slice(0, 8).map(card).join('],},});++ // 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="ex-wrap ex-home" id="ex-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="ex-wrap ex-home" id="ex-home">${page}</div>`;}function filtersBar(filters = {}) {nnew file mode 100644@@@ -0,0 +1,17 @@++'use strict';++// Exchange's home leads with what is real (the owner, 10-31: empty sections made the rooms look unfinished). With nothing++// listed there is no empty "Fresh listings" box under the hero: one short "be the first" row follows 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');++assert.ok(!src.includes('Nothing is listed yet'), 'no empty box under the hero');++++const empty = views.home({ listings: [], counts: {} });++assert.ok(!empty.includes('id="ex-listings"'), 'no empty Fresh listings');++assert.ok(empty.indexOf('Be the first') > empty.indexOf('class="sc-room-scenes"'), 'the row follows the scenes');++assert.ok(empty.includes('href="/submit">List something</a>'), 'it says how the first one starts');++console.log('exchange home: real first, one "be the first" row while nothing is listed');
@@ -128,3 +128,9 @@ html.ov-motion .ex-motif-passport { animation: ex-stamp .5s cubic-bezier(.2,.9,.
@@ -128,3 +128,9 @@ html.ov-motion .ex-motif-passport { animation: ex-stamp .5s cubic-bezier(.2,.9,.
@media (max-width: 759px) { .sc-room-pic .ex-motif-item, .sc-room-pic .ex-motif-passport { display: none; } }
@media (max-width: 759px) { .sc-room-pic .ex-motif-item, .sc-room-pic .ex-motif-passport { display: none; } }
@media (prefers-reduced-motion: reduce) { .ex-motif-arrows path, .ex-motif-passport { animation: none !important; } }
@media (prefers-reduced-motion: reduce) { .ex-motif-arrows path, .ex-motif-passport { animation: none !important; } }
html[data-ov-motion=reduced] .ex-motif-arrows path, html[data-ov-motion=reduced] .ex-motif-passport { animation: none !important; }
html[data-ov-motion=reduced] .ex-motif-arrows path, html[data-ov-motion=reduced] .ex-motif-passport { animation: none !important; }
+
+/* Be the first (10-31): an empty market is one short row after the scenes, never an empty box up top. */
+.ex-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; }
+.ex-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, #2c3d5c)); }
+.ex-first-list span { color: var(--text-secondary, #a8b3c4); font-size: 14px; line-height: 1.45; }
+.ex-first-list a { justify-self: start; margin-top: 4px; font-weight: 700; color: var(--room-strong, var(--room-accent)); }
@@ -92,10 +92,14 @@ function motif() {
@@ -92,10 +92,14 @@ function motif() {
}
}
function home({ listings = [], counts = {} } = {}) {
function home({ listings = [], counts = {} } = {}) {
- const live = `<section class="ex-section" id="ex-listings" aria-labelledby="ex-listings-h">
+ // Real first (the owner, 10-31: empty sections made the rooms look unfinished): Fresh listings shows only with listings
+ // in it; an empty market is one short "be the first" row after the scenes.
+ const live = listings.length ? `<section class="ex-section" id="ex-listings" aria-labelledby="ex-listings-h">
<div class="ex-section-head"><h2 id="ex-listings-h">Fresh listings</h2><a class="ex-more" href="/listings">All listings${kit.icon('chevron')}</a></div>
<div class="ex-section-head"><h2 id="ex-listings-h">Fresh listings</h2><a class="ex-more" href="/listings">All listings${kit.icon('chevron')}</a></div>
-${listings.length ? `<ol class="ex-grid">${listings.slice(0, 8).map(card).join('')}</ol>` : empty('Nothing is listed yet. The first proof is a licensed template, tried in the sandbox, installed and revoked.')}
-</section>`;
+<ol class="ex-grid">${listings.slice(0, 8).map(card).join('')}</ol>
+</section>` : '';
+ const beFirst = listings.length ? '' : `<section class="ex-section ex-first" aria-labelledby="ex-first-h"><h2 id="ex-first-h">Be the first</h2>
+<ul class="ex-first-list"><li><b>List the first thing you made</b><span>A template, a theme, an agent or a tool, with the passport that says what it can touch. Free and swap only in v1.</span><a href="/submit">List something</a></li></ul></section>`;
const room = sc.room({
const room = sc.room({
room: 'exchange',
room: 'exchange',
hero: {
hero: {
@@ -141,8 +145,11 @@ ${listings.length ? `<ol class="ex-grid">${listings.slice(0, 8).map(card).join('
@@ -141,8 +145,11 @@ ${listings.length ? `<ol class="ex-grid">${listings.slice(0, 8).map(card).join('
],
],
},
},
});
});
+ // What is real goes above the scenes; what is still missing goes after them.
const at = room.indexOf('<section class="sc-room-scenes"');
const at = room.indexOf('<section class="sc-room-scenes"');
- return `<div class="ex-wrap ex-home" id="ex-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="ex-wrap ex-home" id="ex-home">${page}</div>`;
}
}
function filtersBar(filters = {}) {
function filtersBar(filters = {}) {
new file mode 100644
new file mode 100644
@@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
+'use strict';
+// Exchange's home leads with what is real (the owner, 10-31: empty sections made the rooms look unfinished). With nothing
+// listed there is no empty "Fresh listings" box under the hero: one short "be the first" row follows 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');
+assert.ok(!src.includes('Nothing is listed yet'), 'no empty box under the hero');
+
+const empty = views.home({ listings: [], counts: {} });
+assert.ok(!empty.includes('id="ex-listings"'), 'no empty Fresh listings');
+assert.ok(empty.indexOf('Be the first') > empty.indexOf('class="sc-room-scenes"'), 'the row follows the scenes');
+assert.ok(empty.includes('href="/submit">List something</a>'), 'it says how the first one starts');
+console.log('exchange home: real first, one "be the first" row while nothing is listed');