// Generated, do not edit. sha256:148777e8a3d0dd6536d8b6d4b8cae6c0c4cbf2ed945fdf8bb8ed57c23e617bd8 import { listBookableAssets } from '../data/assets.js'; import { appSetting, setAppSetting } from '../app-settings.js'; import { t } from '../i18n/index.js'; import { renderNotifications } from '../actions/notifications-widget.js'; import { currentStanding } from '../wealth/data.js'; import { fmtBase, fmtBaseSigned, colouredSigns, fmtUnit, val } from '../ui/format.js'; import { esc } from '../ui/escape.js'; import { assetLabel, assetLabelHtml } from '../ui/asset-label.js'; import { originsHtml } from '../ui/price-origin.js'; import { setPageHint } from '../ui/page-hint.js'; import { CHEVRON_RIGHT } from '../ui/icons.js'; import { renderDashboard } from '../dashboard/dashboard.js'; import { renderSpotWidget, renderSpotSettings } from '../widgets/spot.js'; import { secondCurrencyOf, secondAmount, renderSecondCurrencySetting } from '../widgets/second-currency.js'; import { STANDING_GROUPINGS, standingGroupingOf, groupStanding, standingToday, standingShowsToday } from '../widgets/standing-groups.js'; import { renderMetricsWidget } from '../widgets/metrics.js'; import { renderClocksWidget, renderClocksSettings } from '../widgets/clocks.js'; import { renderReturnWidget, renderReturnSettings } from '../widgets/return.js'; import { registerWidget, availableWidgets } from '../widgets/registry.js'; import { DASHBOARD, TARGETS, targetHash } from '../../shared/config.js'; export const title = () => t('home.title'); registerWidget('notifications', { render: host => renderNotifications(host) }); registerWidget('standing', { render: (host, inst) => renderStandingWidget(host, inst), settings: renderStandingSettings }); registerWidget('spot', { render: (host, inst) => renderSpotWidget(host, inst), settings: renderSpotSettings }); registerWidget('metrics', { render: host => renderMetricsWidget(host) }); registerWidget('clocks', { render: (host, inst) => renderClocksWidget(host, inst), settings: renderClocksSettings }); registerWidget('return', { render: (host, inst) => renderReturnWidget(host, inst), settings: renderReturnSettings }); async function buildCatalog(layout) { const present = new Set(layout.map(it => it.instId)); const persona = appSetting('persona'); const { renderers } = availableWidgets(); const items = []; for (const [type, def] of Object.entries(DASHBOARD.WIDGETS)) { if (def.instanceable || present.has(type) || !renderers[type]) continue; if (def.persona && def.persona !== persona) continue; items.push({ instId: type, type, params: null, label: t(def.label_key) }); } let n = 1; while (present.has(`return-${n}`)) n++; items.push({ instId: `return-${n}`, type: 'return', params: null, label: t('dashboard.widget.return') }); for (const a of await listBookableAssets()) { const instId = `spot-${a.id}`; if (present.has(instId)) continue; items.push({ instId, type: 'spot', params: { assetId: a.id }, label: `${t('dashboard.widget.spot')}: ${assetLabel(a)}`, labelHtml: `${esc(t('dashboard.widget.spot'))}: ${assetLabelHtml(a)}`, }); } return items; } export async function render(el, opts = {}) { if (!el.querySelector('#dashboard-root')) el.innerHTML = '
'; const { renderers, settings } = availableWidgets(); await renderDashboard(el.querySelector('#dashboard-root'), { renderers, settings, edit: !!opts.edit, onEdit: opts.setEdit, catalog: buildCatalog, toolbarHost: document.getElementById('nav-tools') || document.getElementById('page-tools'), }); setPageHint(el, { title: t('home.hintTitle'), rows: [ t('home.hintEdit'), t('home.hintDone'), t('home.hintAdd'), t('home.hintWidget'), t('home.hintProfiles'), ] }); } function standingGroupLabel(g, by) { const r = g.sample; if (by === 'asset') return assetLabelHtml(r.asset); if (by === 'assetKind') return esc(t('enums.asset_kind.' + r.asset.kind)); if (by === 'accountKind') return esc(g.key === 'none' ? t('wealth.noAccount') : t('enums.account_kind.' + g.key)); return esc(r.account.name); } function todayHtml(amount, cls, always = false) { if (amount == null || (!always && Math.abs(amount) < 0.005)) return ''; const tone = amount > 0.005 ? 't-pos' : amount < -0.005 ? 't-neg' : ''; return `${val(fmtBaseSigned(amount, colouredSigns()))}`; } async function renderStandingSettings(host, instance, commit) { host.classList.add('dash-settings--wide'); const huidig = () => standingGroupingOf(instance.params && instance.params.groupBy); const label = { account: 'home.groupAccount', accountKind: 'home.groupAccountKind', asset: 'home.groupAsset', assetKind: 'home.groupAssetKind' }; const chips = () => STANDING_GROUPINGS.map(id => ``).join(''); const block = document.createElement('div'); block.className = 'dash-set-row'; block.innerHTML = `${esc(t('home.groupBy'))}
${chips()}
`; host.appendChild(block); block.addEventListener('click', e => { const chip = e.target.closest('[data-standing-group]'); if (!chip || chip.dataset.standingGroup === huidig()) return; instance.params = { ...(instance.params || {}), groupBy: standingGroupingOf(chip.dataset.standingGroup) }; block.querySelector('.fbar').innerHTML = chips(); commit({ resize: true }); }); const today = document.createElement('div'); today.className = 'dash-set-row'; today.innerHTML = ``; host.appendChild(today); today.addEventListener('change', e => { const box = e.target.closest('[data-standing-today]'); if (!box) return; instance.params = { ...(instance.params || {}), showToday: box.checked }; commit({ resize: true }); }); await renderSecondCurrencySetting(host, instance, commit); } async function renderStandingWidget(host, instance) { const by = standingGroupingOf(instance && instance.params && instance.params.groupBy); const second = secondCurrencyOf(instance); host.innerHTML = `
${t('home.standing')}
${CHEVRON_RIGHT}
…
`; try { const s = await currentStanding(); const body = host.querySelector('#standing-body'); if (s.rows.length === 0) { body.textContent = t('home.standingNone'); return; } const toon = standingShowsToday(instance && instance.params); const perGroup = toon ? standingToday(s.rows, by, s.today) : new Map(); const lines = groupStanding(s.rows, by).map(g => `
${standingGroupLabel(g, by)} ${todayHtml(perGroup.get(g.key), 'stw-today-row')} ${val(fmtBase(g.value))}${originsHtml(g.origins)}
`).join(''); const vandaag = toon && s.today ? `
${todayHtml(s.today.total, '', true)}
` : ''; const tweede = second ? await secondAmount(s.total, second, { decimals: 0 }) : ''; body.className = ''; body.innerHTML = `
${val(fmtBase(s.total))}${tweede ? `${val(tweede)}` : ''}${originsHtml(s.rows.map(r => ({ origin: r.origin, asset: r.asset })))}
${vandaag}
${s.rows.every(r => r.asset.id === s.rows[0].asset.id) ? val(fmtUnit(s.totalSats, s.rows[0].asset)) : ''}
${lines}
`; } catch (err) { console.error('[standing-widget]', err); const body = host.querySelector('#standing-body'); if (body) body.textContent = '⚠ ' + err.message; } }