cleanup: drop dead upload.html + soften broker-only marketing copy
- Delete app/templates/upload.html. The /upload route redirected to /settings#import (302) and never rendered this template; the file was carrying stale Trading-212-only copy. - Landing + pricing pages: replace "Trading 212 today, more brokers planned" with "Trading 212 natively, other formats auto-detected" to reflect the LLM-fallback parser that's been live for a few days. The /upload redirect route in app/routers/pages.py stays — it remains a useful bookmark-forwarder for users with old links. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
11662c0ea8
commit
1ecc527118
3 changed files with 5 additions and 109 deletions
|
|
@ -116,10 +116,10 @@
|
||||||
<section class="public-section">
|
<section class="public-section">
|
||||||
<p style="font-size: 13.5px; color: var(--muted);">
|
<p style="font-size: 13.5px; color: var(--muted);">
|
||||||
Paid users can also drop a portfolio CSV from their broker
|
Paid users can also drop a portfolio CSV from their broker
|
||||||
(Trading 212 today, more brokers planned) for an AI sense-check on
|
— Trading 212 natively, other formats auto-detected —
|
||||||
concentration, regime fit, and currency exposure. Holdings stay in
|
for an AI sense-check on concentration, regime fit, and currency
|
||||||
your browser by default; opt in to encrypted cloud sync to restore
|
exposure. Holdings stay in your browser by default; opt in to
|
||||||
on another device.
|
encrypted cloud sync to restore on another device.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
<li><strong>Strategic log refreshed every hour</strong> instead of every six — track intraday moves as they unfold</li>
|
<li><strong>Strategic log refreshed every hour</strong> instead of every six — track intraday moves as they unfold</li>
|
||||||
<li><strong>Follow-up chat on any past log</strong> — ask the model a question against the day’s full context</li>
|
<li><strong>Follow-up chat on any past log</strong> — ask the model a question against the day’s full context</li>
|
||||||
<li><strong>Daily email digest</strong> (Mon–Sat) — ~600-word read of the session ahead, on top of the Sunday recap</li>
|
<li><strong>Daily email digest</strong> (Mon–Sat) — ~600-word read of the session ahead, on top of the Sunday recap</li>
|
||||||
<li><strong>Portfolio import</strong> from a broker CSV (Trading 212 supported today; more brokers planned)</li>
|
<li><strong>Portfolio import</strong> from any broker CSV — Trading 212 natively, other formats auto-detected</li>
|
||||||
<li><strong>AI portfolio read</strong> — diversification, sector and currency concentration, macro-regime fit on your holdings</li>
|
<li><strong>AI portfolio read</strong> — diversification, sector and currency concentration, macro-regime fit on your holdings</li>
|
||||||
<li><strong>Optional encrypted cloud sync</strong> — PIN-derived encryption in your browser, second-layer wrap on the server, no plaintext holdings server-side</li>
|
<li><strong>Optional encrypted cloud sync</strong> — PIN-derived encryption in your browser, second-layer wrap on the server, no plaintext holdings server-side</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
{% block title %}{{ BRAND_NAME }} · Import Portfolio{% endblock %}
|
|
||||||
|
|
||||||
{% block main %}
|
|
||||||
<section class="panel" style="grid-column: 1 / -1; max-width: 760px; margin: 0 auto;">
|
|
||||||
<div class="panel-header">
|
|
||||||
<span class="title">Import portfolio (Trading 212 CSV)</span>
|
|
||||||
<span class="meta">held locally · optional encrypted cloud sync (paid)</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel-body" style="padding: 18px clamp(16px, 4vw, 32px) 24px;">
|
|
||||||
<p style="color: var(--muted); font-size: 12.5px; margin: 0 0 14px; line-height: 1.6;">
|
|
||||||
Export your pie from the T212 web app
|
|
||||||
(<span class="neu">Trading 212 → Investing → Your Pie → ⋯ → Export</span>)
|
|
||||||
and drop the CSV here. Each Slice is resolved to its Yahoo ticker;
|
|
||||||
the parsed pie is kept in <em>this browser's localStorage</em>.
|
|
||||||
The server learns only which tickers exist (anonymously) so it can
|
|
||||||
fetch their prices. If you have <a href="/settings">cloud sync</a>
|
|
||||||
enabled, an <strong>encrypted</strong> copy is also pushed to the
|
|
||||||
server — only your PIN can decrypt it.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<form id="upload-form" autocomplete="off">
|
|
||||||
<div id="drop-zone" class="dz">
|
|
||||||
<input type="file" id="file-input" name="file" accept=".csv,text/csv" hidden>
|
|
||||||
<div class="dz__icon">▱</div>
|
|
||||||
<div class="dz__label">Drop a T212 pie CSV here</div>
|
|
||||||
<div class="dz__hint">or <a href="#" id="browse-link">browse</a> · max 1 MB</div>
|
|
||||||
<div class="dz__filename" id="dz-filename"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button id="submit-btn" type="submit" disabled style="margin-top:18px;">Parse</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div id="result" class="result" hidden></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<script src="{{ url_for('static', path='/js/portfolio-sync.js') }}" defer></script>
|
|
||||||
<script src="{{ url_for('static', path='/js/portfolio.js') }}" defer></script>
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
function ready(fn) {
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', fn);
|
|
||||||
} else { fn(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
ready(function () {
|
|
||||||
var dropZone = document.getElementById('drop-zone');
|
|
||||||
var fileInput = document.getElementById('file-input');
|
|
||||||
var browseLink = document.getElementById('browse-link');
|
|
||||||
var filenameEl = document.getElementById('dz-filename');
|
|
||||||
var submitBtn = document.getElementById('submit-btn');
|
|
||||||
var form = document.getElementById('upload-form');
|
|
||||||
var resultEl = document.getElementById('result');
|
|
||||||
|
|
||||||
function setFile(file) {
|
|
||||||
if (!file) return;
|
|
||||||
var dt = new DataTransfer();
|
|
||||||
dt.items.add(file);
|
|
||||||
fileInput.files = dt.files;
|
|
||||||
filenameEl.textContent = file.name + ' (' + Math.round(file.size / 1024) + ' KB)';
|
|
||||||
submitBtn.disabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
browseLink.addEventListener('click', function (e) { e.preventDefault(); fileInput.click(); });
|
|
||||||
fileInput.addEventListener('change', function () {
|
|
||||||
if (fileInput.files[0]) setFile(fileInput.files[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
['dragenter', 'dragover'].forEach(function (ev) {
|
|
||||||
dropZone.addEventListener(ev, function (e) {
|
|
||||||
e.preventDefault(); e.stopPropagation();
|
|
||||||
dropZone.classList.add('dz--over');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
['dragleave', 'drop'].forEach(function (ev) {
|
|
||||||
dropZone.addEventListener(ev, function (e) {
|
|
||||||
e.preventDefault(); e.stopPropagation();
|
|
||||||
dropZone.classList.remove('dz--over');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
dropZone.addEventListener('drop', function (e) {
|
|
||||||
if (e.dataTransfer.files && e.dataTransfer.files[0]) setFile(e.dataTransfer.files[0]);
|
|
||||||
});
|
|
||||||
dropZone.addEventListener('click', function (e) {
|
|
||||||
if (e.target.tagName !== 'A') fileInput.click();
|
|
||||||
});
|
|
||||||
|
|
||||||
form.addEventListener('submit', async function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (!fileInput.files[0]) return;
|
|
||||||
submitBtn.disabled = true;
|
|
||||||
submitBtn.textContent = 'Parsing…';
|
|
||||||
// CassandraPortfolio is exposed by /static/js/portfolio.js.
|
|
||||||
var ok = await window.CassandraPortfolio.handleUpload(form, fileInput.files[0], resultEl);
|
|
||||||
submitBtn.textContent = ok ? 'Parsed' : 'Parse';
|
|
||||||
submitBtn.disabled = !ok;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue