openvibers/openvibe.trade Commits
The shared update system and one account UI, on the OpenVibe Frame (openvibe-shared 1.11.0, openvibe/frame): the home shows what shipped, /updates is the shared log and the footer links it; the shared navbar handles sign in and out (logoutUrl ends this site's session) and carries this site's account links in its menu, while the page's own account bar is only for no-JS visitors
Changes
@@@ -16,9 +16,9 @@"express-rate-limit": "^7.5.0","helmet": "^8.1.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",-- "openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.2.2",++ "openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.3.2","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.1"++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0"},"devDependencies": {"jsonwebtoken": "^9.0.2"@@@ -1031,12 +1031,12 @@}},"node_modules/openvibe-publishing": {-- "version": "0.2.2",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.2.2",-- "integrity": "sha512-+aX5lcXQfvfczCY4Ca89B5uYugCS/uncu4gYI7U/mQoOioXZMHk/mCu2f1/+qxM1Ehi6EA2eB/0TCRv7jbuHbA==",++ "version": "0.3.2",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.3.2",++ "integrity": "sha512-XNpM7JJHCWlk2SZRzRqpu2kmWF9kMj6+tS3433hRKdyAB3jubi7Xzeav0OGX1wtqlKk4k00R186XiFmx1igTDg==","license": "MIT","dependencies": {-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.1"++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0"},"engines": {"node": ">=20"@@@ -1060,9 +1060,9 @@}},"node_modules/openvibe-shared": {-- "version": "1.5.1",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.1",-- "integrity": "sha512-1XWRFwN8br3iiy2Z8fmnXQMgR76VlfMpHjP1xr5uKLCJmtvtNSWO1BgA1kQmVtyBY7g+1n6YFIjahaD4qWbD/Q==",++ "version": "1.11.0",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0",++ "integrity": "sha512-edMW0I25HNFReLcfZ9ak+4q5sy2t7qq7EPG52tOerTBV2fU994C5we/02AD/9i2Vuq0+ayNBBisW0cg60L6DLQ==","license": "MIT","dependencies": {"jsonwebtoken": "^9.0.0"@@@ -21,9 +21,9 @@"express-rate-limit": "^7.5.0","helmet": "^8.1.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",-- "openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.2.2",++ "openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.3.2","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.1"++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0"},"devDependencies": {"jsonwebtoken": "^9.0.2"@@@ -95,7 +95,7 @@ function createApp(opts = {}) {contentSecurityPolicy: {directives: {defaultSrc: ["'self'"],-- // The shared chrome (theme-loader, navbar) comes from the Network; the inline init is ours.++ // The OpenVibe Frame (theme-loader, navbar, footer) comes from the Network; the inline init is ours.scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network'],styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com', 'https://cdnjs.cloudflare.com'],fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com', 'https://cdnjs.cloudflare.com'],@@@ -13,6 +13,7 @@* A lower-case symbol or a ticker alias answers 301 to the canonical /i/:SYMBOL.*/const express = require('express');++const frame = require('openvibe-shared/frame');const seo = require('openvibe-publishing/seo');const { paginate } = require('openvibe-publishing/ssr');const views = require('../render/views');@@@ -23,6 +24,11 @@ function createPages(ctx) {const router = express.Router();const listing = (path) => seo.evaluate({ state: 'published', visibility: 'public', canonicalUrl: urls.abs(path), wordCount: 0 }, { policy: { minWords: 0 } });++ // What shipped on OpenVibe.Trade: the shared update log every OpenVibe site has.++ define(router, 'get', '/updates', 'showUpdates', (req, res) => common.page(req, res, {++ title: 'What shipped on OpenVibe.Trade', canonical: urls.abs('/updates'), decision: listing('/updates'),++ body: frame.updatesBody({ service: 'trade', siteName: 'OpenVibe.Trade' }) + frame.shippedScript(),++ }));define(router, 'get', '/', 'showHome', (req, res) => {const pageNo = Math.max(parseInt(req.query.page, 10) || 1, 1);const per = 50;@@@ -7,7 +7,7 @@* Open Graph, JSON-LD from real fields only, feed links, the shared app icon* - the persistent disclaimer, above the content on every page:* "Information only — not investment advice; no trading here."-- * - the shared chrome: navbar.js and theme-loader.js from the Network (progressive), a++ * - the OpenVibe Frame: navbar.js and theme-loader.js from the Network (progressive), a* <noscript> navigation bar and the server-rendered shared footer (openvibe-shared)*/const crypto = require('crypto');@@@ -16,7 +16,7 @@ const path = require('path');const seo = require('openvibe-publishing/seo');const { escapeHtml: esc } = require('openvibe-publishing/ssr');const appIcon = require('openvibe-shared/app-icon');--const chrome = require('openvibe-shared/chrome-ssr');++const frame = require('openvibe-shared/frame');const NETWORK_URL = 'https://openvibe.network';const SITE_NAME = 'OpenVibe.Trade';@@@ -65,7 +65,12 @@ function renderPage(o) {silentLogin: `${o.config.baseUrl}/auth/login?silent=1&next={url}`,sessionUrl: '/auth/me',loginUrl: `/auth/login?next=${loginNext}`,++ logoutUrl: '/auth/logout?next={path}', // Sign out in the shared navbar ends this site's session too};++ // This site's own account links live in the shared navbar's account menu (the page's account++ // bar below is only for visitors without JavaScript).++ if (signedIn) nav.menu = { before: [...(viewer.editor ? [{ label: 'Editor', href: '/editor', icon: 'fa-pen' }] : []), { label: 'Your watchlists', href: '/watchlists', icon: 'fa-list' }] };++ const footer = { service: 'trade', variant: 'full', mount: '#ov-footer', brandName: SITE_NAME, updates: '/updates' };const account = signedIn? `${viewer.editor ? '<a href="/editor">Editor</a> · ' : ''}<a href="/watchlists">Your watchlists</a> · <a href="/auth/logout?next=${loginNext}">Sign out</a>`: `<a href="/auth/login?next=${loginNext}">Sign in with OpenVibe</a>`;@@@ -80,22 +85,25 @@ ${appIcon.headTags({ site: 'trade' })}<link rel="stylesheet" href="${asset('css/trade.css')}"><script src="${NETWORK_URL}/shared/theme-loader.js" defer></script><script src="${NETWORK_URL}/shared/navbar.js" defer></script>++<script src="${NETWORK_URL}/shared/footer.js" defer></script></head><body class="${esc(o.bodyClass || '')}"><a class="skip" href="#main">Skip to content</a><div id="navbar-mount"></div>--${chrome.noscriptNav({ name: SITE_NAME, home: '/', links: NAV_LINKS })}--<div class="account-bar" role="navigation" aria-label="Account">${account}</div>++${frame.noscriptNav({ name: SITE_NAME, home: '/', links: NAV_LINKS })}++<noscript><div class="account-bar" role="navigation" aria-label="Account">${account}</div></noscript><p class="disclaimer" role="note"><strong>${esc(DISCLAIMER)}</strong> Every number shows when it was observed and where it came from; stale sources are labelled as stale.</p><main id="main" class="page">${o.body || ''}++${o.path === '/' ? frame.shipped({ service: 'trade', title: `Recently shipped on ${SITE_NAME}` }) : ''}</main><p class="disclaimer disclaimer-foot" role="note">${esc(DISCLAIMER)} OpenVibe.Trade holds no money or assets, takes no orders and gives no personal recommendations.</p>--${chrome.footer({ service: 'trade', variant: 'full' })}++${frame.footer(footer)}<script>--window.__OV_PAGE = ${JSON.stringify({ navbar: nav }).replace(/</g, '\\u003c')};++window.__OV_PAGE = ${JSON.stringify({ navbar: nav, footer }).replace(/</g, '\\u003c')};document.addEventListener('DOMContentLoaded', function () {-- try { if (window.OpenVibeNavbar) OpenVibeNavbar.init(window.__OV_PAGE.navbar); } catch (e) { /* the chrome is optional */ }++ try { if (window.OpenVibeNavbar) OpenVibeNavbar.init(window.__OV_PAGE.navbar); } catch (e) { /* the Frame is optional */ }++ try { if (window.OpenVibeFooter) OpenVibeFooter.init(window.__OV_PAGE.footer); } catch (e) { /* */ }});</script></body>
@@ -16,9 +16,9 @@
@@ -16,9 +16,9 @@
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
- "openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.2.2",
+ "openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.3.2",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.1"
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0"
},
},
"devDependencies": {
"devDependencies": {
"jsonwebtoken": "^9.0.2"
"jsonwebtoken": "^9.0.2"
@@ -1031,12 +1031,12 @@
@@ -1031,12 +1031,12 @@
}
}
},
},
"node_modules/openvibe-publishing": {
"node_modules/openvibe-publishing": {
- "version": "0.2.2",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.2.2",
- "integrity": "sha512-+aX5lcXQfvfczCY4Ca89B5uYugCS/uncu4gYI7U/mQoOioXZMHk/mCu2f1/+qxM1Ehi6EA2eB/0TCRv7jbuHbA==",
+ "version": "0.3.2",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.3.2",
+ "integrity": "sha512-XNpM7JJHCWlk2SZRzRqpu2kmWF9kMj6+tS3433hRKdyAB3jubi7Xzeav0OGX1wtqlKk4k00R186XiFmx1igTDg==",
"license": "MIT",
"license": "MIT",
"dependencies": {
"dependencies": {
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.1"
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0"
},
},
"engines": {
"engines": {
"node": ">=20"
"node": ">=20"
@@ -1060,9 +1060,9 @@
@@ -1060,9 +1060,9 @@
}
}
},
},
"node_modules/openvibe-shared": {
"node_modules/openvibe-shared": {
- "version": "1.5.1",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.1",
- "integrity": "sha512-1XWRFwN8br3iiy2Z8fmnXQMgR76VlfMpHjP1xr5uKLCJmtvtNSWO1BgA1kQmVtyBY7g+1n6YFIjahaD4qWbD/Q==",
+ "version": "1.11.0",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0",
+ "integrity": "sha512-edMW0I25HNFReLcfZ9ak+4q5sy2t7qq7EPG52tOerTBV2fU994C5we/02AD/9i2Vuq0+ayNBBisW0cg60L6DLQ==",
"license": "MIT",
"license": "MIT",
"dependencies": {
"dependencies": {
"jsonwebtoken": "^9.0.0"
"jsonwebtoken": "^9.0.0"
@@ -21,9 +21,9 @@
@@ -21,9 +21,9 @@
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
- "openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.2.2",
+ "openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v0.3.2",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.1"
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0"
},
},
"devDependencies": {
"devDependencies": {
"jsonwebtoken": "^9.0.2"
"jsonwebtoken": "^9.0.2"
@@ -95,7 +95,7 @@ function createApp(opts = {}) {
@@ -95,7 +95,7 @@ function createApp(opts = {}) {
contentSecurityPolicy: {
contentSecurityPolicy: {
directives: {
directives: {
defaultSrc: ["'self'"],
defaultSrc: ["'self'"],
- // The shared chrome (theme-loader, navbar) comes from the Network; the inline init is ours.
+ // The OpenVibe Frame (theme-loader, navbar, footer) comes from the Network; the inline init is ours.
scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network'],
scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network'],
styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com', 'https://cdnjs.cloudflare.com'],
styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com', 'https://cdnjs.cloudflare.com'],
fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com', 'https://cdnjs.cloudflare.com'],
fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com', 'https://cdnjs.cloudflare.com'],
@@ -13,6 +13,7 @@
@@ -13,6 +13,7 @@
* A lower-case symbol or a ticker alias answers 301 to the canonical /i/:SYMBOL.
* A lower-case symbol or a ticker alias answers 301 to the canonical /i/:SYMBOL.
*/
*/
const express = require('express');
const express = require('express');
+const frame = require('openvibe-shared/frame');
const seo = require('openvibe-publishing/seo');
const seo = require('openvibe-publishing/seo');
const { paginate } = require('openvibe-publishing/ssr');
const { paginate } = require('openvibe-publishing/ssr');
const views = require('../render/views');
const views = require('../render/views');
@@ -23,6 +24,11 @@ function createPages(ctx) {
@@ -23,6 +24,11 @@ function createPages(ctx) {
const router = express.Router();
const router = express.Router();
const listing = (path) => seo.evaluate({ state: 'published', visibility: 'public', canonicalUrl: urls.abs(path), wordCount: 0 }, { policy: { minWords: 0 } });
const listing = (path) => seo.evaluate({ state: 'published', visibility: 'public', canonicalUrl: urls.abs(path), wordCount: 0 }, { policy: { minWords: 0 } });
+ // What shipped on OpenVibe.Trade: the shared update log every OpenVibe site has.
+ define(router, 'get', '/updates', 'showUpdates', (req, res) => common.page(req, res, {
+ title: 'What shipped on OpenVibe.Trade', canonical: urls.abs('/updates'), decision: listing('/updates'),
+ body: frame.updatesBody({ service: 'trade', siteName: 'OpenVibe.Trade' }) + frame.shippedScript(),
+ }));
define(router, 'get', '/', 'showHome', (req, res) => {
define(router, 'get', '/', 'showHome', (req, res) => {
const pageNo = Math.max(parseInt(req.query.page, 10) || 1, 1);
const pageNo = Math.max(parseInt(req.query.page, 10) || 1, 1);
const per = 50;
const per = 50;
@@ -7,7 +7,7 @@
@@ -7,7 +7,7 @@
* Open Graph, JSON-LD from real fields only, feed links, the shared app icon
* Open Graph, JSON-LD from real fields only, feed links, the shared app icon
* - the persistent disclaimer, above the content on every page:
* - the persistent disclaimer, above the content on every page:
* "Information only — not investment advice; no trading here."
* "Information only — not investment advice; no trading here."
- * - the shared chrome: navbar.js and theme-loader.js from the Network (progressive), a
+ * - the OpenVibe Frame: navbar.js and theme-loader.js from the Network (progressive), a
* <noscript> navigation bar and the server-rendered shared footer (openvibe-shared)
* <noscript> navigation bar and the server-rendered shared footer (openvibe-shared)
*/
*/
const crypto = require('crypto');
const crypto = require('crypto');
@@ -16,7 +16,7 @@ const path = require('path');
@@ -16,7 +16,7 @@ const path = require('path');
const seo = require('openvibe-publishing/seo');
const seo = require('openvibe-publishing/seo');
const { escapeHtml: esc } = require('openvibe-publishing/ssr');
const { escapeHtml: esc } = require('openvibe-publishing/ssr');
const appIcon = require('openvibe-shared/app-icon');
const appIcon = require('openvibe-shared/app-icon');
-const chrome = require('openvibe-shared/chrome-ssr');
+const frame = require('openvibe-shared/frame');
const NETWORK_URL = 'https://openvibe.network';
const NETWORK_URL = 'https://openvibe.network';
const SITE_NAME = 'OpenVibe.Trade';
const SITE_NAME = 'OpenVibe.Trade';
@@ -65,7 +65,12 @@ function renderPage(o) {
@@ -65,7 +65,12 @@ function renderPage(o) {
silentLogin: `${o.config.baseUrl}/auth/login?silent=1&next={url}`,
silentLogin: `${o.config.baseUrl}/auth/login?silent=1&next={url}`,
sessionUrl: '/auth/me',
sessionUrl: '/auth/me',
loginUrl: `/auth/login?next=${loginNext}`,
loginUrl: `/auth/login?next=${loginNext}`,
+ logoutUrl: '/auth/logout?next={path}', // Sign out in the shared navbar ends this site's session too
};
};
+ // This site's own account links live in the shared navbar's account menu (the page's account
+ // bar below is only for visitors without JavaScript).
+ if (signedIn) nav.menu = { before: [...(viewer.editor ? [{ label: 'Editor', href: '/editor', icon: 'fa-pen' }] : []), { label: 'Your watchlists', href: '/watchlists', icon: 'fa-list' }] };
+ const footer = { service: 'trade', variant: 'full', mount: '#ov-footer', brandName: SITE_NAME, updates: '/updates' };
const account = signedIn
const account = signedIn
? `${viewer.editor ? '<a href="/editor">Editor</a> · ' : ''}<a href="/watchlists">Your watchlists</a> · <a href="/auth/logout?next=${loginNext}">Sign out</a>`
? `${viewer.editor ? '<a href="/editor">Editor</a> · ' : ''}<a href="/watchlists">Your watchlists</a> · <a href="/auth/logout?next=${loginNext}">Sign out</a>`
: `<a href="/auth/login?next=${loginNext}">Sign in with OpenVibe</a>`;
: `<a href="/auth/login?next=${loginNext}">Sign in with OpenVibe</a>`;
@@ -80,22 +85,25 @@ ${appIcon.headTags({ site: 'trade' })}
@@ -80,22 +85,25 @@ ${appIcon.headTags({ site: 'trade' })}
<link rel="stylesheet" href="${asset('css/trade.css')}">
<link rel="stylesheet" href="${asset('css/trade.css')}">
<script src="${NETWORK_URL}/shared/theme-loader.js" defer></script>
<script src="${NETWORK_URL}/shared/theme-loader.js" defer></script>
<script src="${NETWORK_URL}/shared/navbar.js" defer></script>
<script src="${NETWORK_URL}/shared/navbar.js" defer></script>
+<script src="${NETWORK_URL}/shared/footer.js" defer></script>
</head>
</head>
<body class="${esc(o.bodyClass || '')}">
<body class="${esc(o.bodyClass || '')}">
<a class="skip" href="#main">Skip to content</a>
<a class="skip" href="#main">Skip to content</a>
<div id="navbar-mount"></div>
<div id="navbar-mount"></div>
-${chrome.noscriptNav({ name: SITE_NAME, home: '/', links: NAV_LINKS })}
-<div class="account-bar" role="navigation" aria-label="Account">${account}</div>
+${frame.noscriptNav({ name: SITE_NAME, home: '/', links: NAV_LINKS })}
+<noscript><div class="account-bar" role="navigation" aria-label="Account">${account}</div></noscript>
<p class="disclaimer" role="note"><strong>${esc(DISCLAIMER)}</strong> Every number shows when it was observed and where it came from; stale sources are labelled as stale.</p>
<p class="disclaimer" role="note"><strong>${esc(DISCLAIMER)}</strong> Every number shows when it was observed and where it came from; stale sources are labelled as stale.</p>
<main id="main" class="page">
<main id="main" class="page">
${o.body || ''}
${o.body || ''}
+${o.path === '/' ? frame.shipped({ service: 'trade', title: `Recently shipped on ${SITE_NAME}` }) : ''}
</main>
</main>
<p class="disclaimer disclaimer-foot" role="note">${esc(DISCLAIMER)} OpenVibe.Trade holds no money or assets, takes no orders and gives no personal recommendations.</p>
<p class="disclaimer disclaimer-foot" role="note">${esc(DISCLAIMER)} OpenVibe.Trade holds no money or assets, takes no orders and gives no personal recommendations.</p>
-${chrome.footer({ service: 'trade', variant: 'full' })}
+${frame.footer(footer)}
<script>
<script>
-window.__OV_PAGE = ${JSON.stringify({ navbar: nav }).replace(/</g, '\\u003c')};
+window.__OV_PAGE = ${JSON.stringify({ navbar: nav, footer }).replace(/</g, '\\u003c')};
document.addEventListener('DOMContentLoaded', function () {
document.addEventListener('DOMContentLoaded', function () {
- try { if (window.OpenVibeNavbar) OpenVibeNavbar.init(window.__OV_PAGE.navbar); } catch (e) { /* the chrome is optional */ }
+ try { if (window.OpenVibeNavbar) OpenVibeNavbar.init(window.__OV_PAGE.navbar); } catch (e) { /* the Frame is optional */ }
+ try { if (window.OpenVibeFooter) OpenVibeFooter.init(window.__OV_PAGE.footer); } catch (e) { /* */ }
});
});
</script>
</script>
</body>
</body>