Offset Type: [Year|Month|Week|Day] Offset Value: [n] Cleaner UX, handles all interval types uniformly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
274 lines
14 KiB
HTML
274 lines
14 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Pivot Forecast</title>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community@31.0.0/styles/ag-grid.css">
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community@31.0.0/styles/ag-theme-alpine.css">
|
||
<link rel="stylesheet" href="styles.css">
|
||
</head>
|
||
<body>
|
||
<div id="app">
|
||
|
||
<!-- Sidebar -->
|
||
<nav id="sidebar">
|
||
<div class="sidebar-brand">Pivot Forecast</div>
|
||
<ul class="nav-links">
|
||
<li data-view="sources" class="active">Sources</li>
|
||
<li data-view="versions">Versions</li>
|
||
<li data-view="baseline">Baseline</li>
|
||
<li data-view="forecast">Forecast</li>
|
||
<li data-view="log">Log</li>
|
||
</ul>
|
||
<div class="sidebar-context">
|
||
<div id="ctx-source" class="ctx-item hidden">
|
||
<span class="ctx-label">Source</span>
|
||
<span id="ctx-source-name"></span>
|
||
</div>
|
||
<div id="ctx-version" class="ctx-item hidden">
|
||
<span class="ctx-label">Version</span>
|
||
<span id="ctx-version-name"></span>
|
||
<span id="ctx-version-status" class="status-badge"></span>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-user">
|
||
<label>User</label>
|
||
<input type="text" id="input-pf-user" placeholder="your name" />
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- Main content -->
|
||
<main id="content">
|
||
<div id="status-bar" class="hidden"></div>
|
||
|
||
<!-- ===== SOURCES VIEW ===== -->
|
||
<div id="view-sources" class="view active">
|
||
<div class="two-col-layout">
|
||
<div class="panel">
|
||
<div class="panel-header">
|
||
<span>Database Tables</span>
|
||
<div class="header-actions">
|
||
<button id="btn-register" class="btn btn-primary hidden">Register Table</button>
|
||
</div>
|
||
</div>
|
||
<div id="tables-grid" class="ag-theme-alpine grid-fill"></div>
|
||
</div>
|
||
<div class="panel">
|
||
<div class="panel-header">
|
||
<span id="right-panel-title">Registered Sources</span>
|
||
<div class="header-actions">
|
||
<button id="btn-back-sources" class="btn hidden">← Sources</button>
|
||
<button id="btn-save-cols" class="btn hidden">Save Columns</button>
|
||
<button id="btn-generate-sql" class="btn btn-primary hidden">Generate SQL</button>
|
||
</div>
|
||
</div>
|
||
<div id="sources-list-grid" class="ag-theme-alpine grid-fill"></div>
|
||
<div id="col-meta-grid" class="ag-theme-alpine grid-fill hidden"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== VERSIONS VIEW ===== -->
|
||
<div id="view-versions" class="view hidden">
|
||
<div class="view-toolbar">
|
||
<span id="versions-source-label"></span>
|
||
<button id="btn-new-version" class="btn btn-primary">New Version</button>
|
||
</div>
|
||
<div id="new-version-form" class="inline-form hidden">
|
||
<h3>Create Version</h3>
|
||
<div class="form-row">
|
||
<label>Name<input type="text" id="ver-name" placeholder="e.g. FY2025 v1" /></label>
|
||
<label>Description<input type="text" id="ver-desc" placeholder="optional" /></label>
|
||
</div>
|
||
<div class="form-actions">
|
||
<button id="btn-create-version" class="btn btn-primary">Create</button>
|
||
<button id="btn-cancel-version" class="btn">Cancel</button>
|
||
</div>
|
||
</div>
|
||
<div id="versions-grid" class="ag-theme-alpine"></div>
|
||
<div id="version-actions" class="version-actions hidden">
|
||
<span id="version-actions-label"></span>
|
||
<button class="btn btn-primary" id="vbtn-forecast">Open Forecast</button>
|
||
<button class="btn" id="vbtn-baseline">Load Baseline</button>
|
||
<button class="btn" id="vbtn-reference">Load Reference</button>
|
||
<button class="btn" id="vbtn-toggle">Close Version</button>
|
||
<button class="btn btn-danger" id="vbtn-delete">Delete</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== BASELINE WORKBENCH VIEW ===== -->
|
||
<div id="view-baseline" class="view hidden">
|
||
<div class="workbench-toolbar">
|
||
<span id="baseline-label">No version selected</span>
|
||
<button id="btn-clear-baseline" class="btn btn-danger">Clear Baseline</button>
|
||
</div>
|
||
<div class="baseline-layout">
|
||
<div class="baseline-form-panel">
|
||
<div class="panel-section-title">Add Segment</div>
|
||
<div class="baseline-form">
|
||
<label class="baseline-field-label">Description
|
||
<input type="text" id="seg-description" placeholder="e.g. All orders FY2024" />
|
||
</label>
|
||
<div class="offset-row">
|
||
<label class="baseline-field-label">Offset Type
|
||
<select id="seg-offset-type">
|
||
<option value="">— none —</option>
|
||
<option value="year">Year</option>
|
||
<option value="month">Month</option>
|
||
<option value="week">Week</option>
|
||
<option value="day">Day</option>
|
||
</select>
|
||
</label>
|
||
<label class="baseline-field-label">Offset Value
|
||
<input type="number" id="seg-offset-value" min="0" value="0" />
|
||
</label>
|
||
</div>
|
||
<div class="filter-section">
|
||
<div class="filter-section-label">Filters <span class="required-star">*</span></div>
|
||
<div id="seg-filter-rows"></div>
|
||
<button id="btn-add-filter-row" class="btn btn-sm">+ Add Filter</button>
|
||
</div>
|
||
<div id="seg-timeline" class="timeline-preview hidden"></div>
|
||
<button id="btn-load-segment" class="btn btn-primary">Load Segment</button>
|
||
</div>
|
||
</div>
|
||
<div class="baseline-segments-panel">
|
||
<div class="panel-section-title">Loaded Segments</div>
|
||
<div id="baseline-segments-list">
|
||
<div class="segments-empty">No segments loaded yet.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== FORECAST VIEW ===== -->
|
||
<div id="view-forecast" class="view hidden">
|
||
<div class="forecast-toolbar">
|
||
<span id="forecast-label">No version selected</span>
|
||
<button id="btn-forecast-refresh" class="btn">Refresh</button>
|
||
<button id="btn-expand-all" class="btn">Expand All</button>
|
||
<button id="btn-collapse-all" class="btn">Collapse All</button>
|
||
</div>
|
||
<div class="forecast-layout">
|
||
<div id="pivot-panel">
|
||
<div id="pivot-grid" class="ag-theme-alpine"></div>
|
||
</div>
|
||
<div id="operation-panel">
|
||
<div class="op-section">
|
||
<div class="op-title">Slice</div>
|
||
<div id="slice-display">
|
||
<span class="op-hint">Click a row to select a slice</span>
|
||
</div>
|
||
<button id="btn-clear-slice" class="btn btn-sm hidden">Clear</button>
|
||
</div>
|
||
<div id="op-forms-area" class="hidden">
|
||
<div class="op-tabs">
|
||
<button class="op-tab active" data-op="scale">Scale</button>
|
||
<button class="op-tab" data-op="recode">Recode</button>
|
||
<button class="op-tab" data-op="clone">Clone</button>
|
||
</div>
|
||
<!-- Scale -->
|
||
<div id="op-scale" class="op-form">
|
||
<label>Value Δ<input type="number" id="scale-value-incr" step="any" placeholder="0" /></label>
|
||
<label>Units Δ<input type="number" id="scale-units-incr" step="any" placeholder="0" /></label>
|
||
<label class="label-inline"><input type="checkbox" id="scale-pct" /> Treat as %</label>
|
||
<label>Note<input type="text" id="scale-note" placeholder="optional" /></label>
|
||
<button id="btn-submit-scale" class="btn btn-primary">Apply Scale</button>
|
||
</div>
|
||
<!-- Recode -->
|
||
<div id="op-recode" class="op-form hidden">
|
||
<div class="op-hint">Enter new values for dimensions to replace:</div>
|
||
<div id="recode-fields"></div>
|
||
<label>Note<input type="text" id="recode-note" placeholder="optional" /></label>
|
||
<button id="btn-submit-recode" class="btn btn-primary">Apply Recode</button>
|
||
</div>
|
||
<!-- Clone -->
|
||
<div id="op-clone" class="op-form hidden">
|
||
<div class="op-hint">Override dimension values on cloned rows:</div>
|
||
<div id="clone-fields"></div>
|
||
<label>Scale Factor<input type="number" id="clone-scale" step="any" value="1" /></label>
|
||
<label>Note<input type="text" id="clone-note" placeholder="optional" /></label>
|
||
<button id="btn-submit-clone" class="btn btn-primary">Apply Clone</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== LOG VIEW ===== -->
|
||
<div id="view-log" class="view hidden">
|
||
<div id="log-grid" class="ag-theme-alpine grid-fill"></div>
|
||
</div>
|
||
|
||
</main>
|
||
</div>
|
||
|
||
<!-- Load baseline / reference modal -->
|
||
<div id="load-data-modal" class="modal-overlay hidden">
|
||
<div class="modal load-data-modal">
|
||
<div class="modal-header">
|
||
<span id="load-data-title">Load Baseline</span>
|
||
<button id="btn-load-close" class="btn-icon">×</button>
|
||
</div>
|
||
<div id="load-data-body">
|
||
<div class="load-form-fields">
|
||
<label>Date From<input type="date" id="load-date-from" /></label>
|
||
<label>Date To<input type="date" id="load-date-to" /></label>
|
||
<div id="load-offset-fields">
|
||
<div class="load-offset-row">
|
||
<label>Offset Years<input type="number" id="load-offset-years" min="0" value="0" /></label>
|
||
<label>Offset Months<input type="number" id="load-offset-months" min="0" value="0" /></label>
|
||
</div>
|
||
</div>
|
||
<label>Note<input type="text" id="load-note" placeholder="optional" /></label>
|
||
</div>
|
||
<div id="load-date-preview" class="load-date-preview hidden">
|
||
<!-- reference: single chip list -->
|
||
<div id="load-preview-simple">
|
||
<div class="load-preview-label"></div>
|
||
<div id="load-date-chips" class="date-chips"></div>
|
||
</div>
|
||
<!-- baseline: before → after -->
|
||
<div id="load-preview-offset" class="hidden">
|
||
<div class="load-preview-columns">
|
||
<div class="load-preview-col">
|
||
<div class="load-preview-label">Source</div>
|
||
<div id="load-chips-source" class="date-chips"></div>
|
||
</div>
|
||
<div class="load-preview-arrow">→</div>
|
||
<div class="load-preview-col">
|
||
<div class="load-preview-label">Projected</div>
|
||
<div id="load-chips-projected" class="date-chips"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button id="btn-load-submit" class="btn btn-primary">Load</button>
|
||
<button id="btn-load-cancel" class="btn">Cancel</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Table preview modal -->
|
||
<div id="modal-overlay" class="modal-overlay hidden">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<span id="modal-title">Preview</span>
|
||
<button id="modal-close" class="btn-icon">×</button>
|
||
</div>
|
||
<div id="modal-body"></div>
|
||
<div class="modal-footer">
|
||
<button id="btn-modal-register" class="btn btn-primary">Register This Table</button>
|
||
<button id="btn-modal-close" class="btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/ag-grid-enterprise@31.0.0/dist/ag-grid-enterprise.min.js"></script>
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|