161 lines
7.1 KiB
HTML
161 lines
7.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Settings - CSV Master Editor</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
|
<style>
|
|
body { background-color: #f8f9fa; font-family: 'Segoe UI', Tahoma, sans-serif; overflow-x: hidden; }
|
|
|
|
/* Forces the table to stay within the browser width */
|
|
.table-container { width: 100%; overflow: hidden; }
|
|
|
|
.table {
|
|
table-layout: fixed; /* Crucial for 60/40 ratio */
|
|
width: 100%;
|
|
}
|
|
|
|
/* Column Widths */
|
|
.col-name { width: 50%; }
|
|
.col-cusip { width: 33%; }
|
|
.col-provider { width: 10%; }
|
|
.col-manage { width: 7%; }
|
|
|
|
/* Compact Input styling (2/3 height) */
|
|
.form-control, .form-select {
|
|
width: 100%;
|
|
font-size: 0.9rem;
|
|
border: 1px solid #dee2e6;
|
|
padding: 2px 8px !important; /* Reduced vertical padding */
|
|
height: auto !important;
|
|
min-height: 30px;
|
|
}
|
|
|
|
.form-control:focus {
|
|
border-color: #0d6efd;
|
|
box-shadow: none;
|
|
background-color: #fffdf7;
|
|
}
|
|
|
|
/* Compact Table Cells */
|
|
#settingsTable td {
|
|
padding: 3px 4px !important;
|
|
}
|
|
#settingsTable th {
|
|
padding: 6px 8px !important;
|
|
font-size: 0.85rem;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="container-fluid px-3 mt-4">
|
|
<div class="card shadow border-0">
|
|
<div class="card-header bg-dark text-white d-flex justify-content-between align-items-center py-3">
|
|
<div>
|
|
<h5 class="mb-0"><i class="bi bi-gear-fill me-2"></i>CSV Master Editor</h5>
|
|
<small class="text-secondary">instruments.csv</small>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<input type="text" id="searchInput" class="form-control form-control-sm" placeholder="Search..." onkeyup="filterTable()" style="width: 200px;">
|
|
<button type="button" class="btn btn-primary btn-sm px-3" onclick="addRow()">
|
|
<i class="bi bi-plus-lg"></i> Add Ticker
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body p-0">
|
|
<form action="/settings/save" method="POST">
|
|
<div class="table-responsive" style="max-height: 75vh; overflow-y: auto; overflow-x: hidden;">
|
|
<table class="table table-hover align-middle mb-0" id="settingsTable">
|
|
<thead class="table-light sticky-top">
|
|
<tr>
|
|
<th class="col-name">Name</th>
|
|
<th class="col-cusip">cusips / symbols</th>
|
|
<th class="col-provider">Provider</th>
|
|
<th class="col-manage text-center">Manage</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for item in instruments %}
|
|
<tr>
|
|
<td><input type="text" name="name[]" class="form-control fw-bold" value="{{ item.name }}"></td>
|
|
<td><input type="text" name="cusip[]" class="form-control" value="{{ item.cusip }}"></td>
|
|
<td>
|
|
<select name="provider[]" class="form-select">
|
|
<option value="yahoo" {% if item.provider == 'yahoo' %}selected{% endif %}>Yahoo</option>
|
|
<option value="agi" {% if item.provider == 'agi' %}selected{% endif %}>Allianz</option>
|
|
<option value="jpm" {% if item.provider == 'jpm' %}selected{% endif %}>JPM</option>
|
|
<option value="ft" {% if item.provider == 'ft' %}selected{% endif %}>FT</option>
|
|
</select>
|
|
</td>
|
|
<td class="text-center">
|
|
<button type="button" class="btn btn-outline-danger btn-sm border-0 py-0" onclick="confirmDelete(this)">
|
|
<i class="bi bi-trash3"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card-footer bg-light p-3 d-flex justify-content-between align-items-center">
|
|
<div class="text-muted small">
|
|
<i class="bi bi-hdd-fill me-1"></i> Disk Updated: <span class="text-primary">{{ last_updated }}</span>
|
|
</div>
|
|
<div>
|
|
<a href="/" class="btn btn-outline-secondary btn-sm me-2">Cancel</a>
|
|
<button type="submit" class="btn btn-success btn-sm px-4 shadow-sm">
|
|
<i class="bi bi-cloud-arrow-up-fill me-1"></i> Save Changes
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function confirmDelete(btn) {
|
|
if (confirm("Permanently remove this entry?")) {
|
|
btn.closest('tr').remove();
|
|
}
|
|
}
|
|
|
|
function addRow() {
|
|
const tbody = document.querySelector('#settingsTable tbody');
|
|
// Updated names to name[] and cusip[] to match CSV mapping
|
|
const row = `<tr>
|
|
<td><input type="text" name="name[]" class="form-control fw-bold" placeholder="New Name"></td>
|
|
<td><input type="text" name="cusip[]" class="form-control" placeholder="CUSIP/Ticker"></td>
|
|
<td>
|
|
<select name="provider[]" class="form-select">
|
|
<option value="yahoo">Yahoo</option>
|
|
<option value="agi">Allianz</option>
|
|
<option value="jpm">JPM</option>
|
|
<option value="ft">FT</option>
|
|
</select>
|
|
</td>
|
|
<td class="text-center">
|
|
<button type="button" class="btn btn-outline-danger btn-sm border-0 py-0" onclick="this.closest('tr').remove()">
|
|
<i class="bi bi-trash3"></i>
|
|
</button>
|
|
</td>
|
|
</tr>`;
|
|
tbody.insertAdjacentHTML('afterbegin', row);
|
|
}
|
|
|
|
function filterTable() {
|
|
let input = document.getElementById("searchInput").value.toUpperCase();
|
|
let rows = document.querySelector("#settingsTable tbody").rows;
|
|
for (let i = 0; i < rows.length; i++) {
|
|
let n = rows[i].cells[0].querySelector('input').value.toUpperCase();
|
|
let c = rows[i].cells[1].querySelector('input').value.toUpperCase();
|
|
rows[i].style.display = (n.includes(input) || c.includes(input)) ? "" : "none";
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |