Add dim-period/cols endpoint and replace dim_period_col text input with select
GET /api/dim-period/cols queries information_schema for pf.dim_period columns (excluding sdat/edat/drange/ndays) so the UI always reflects actual columns. Setup col_meta editor now shows a dropdown populated from that endpoint instead of a free-text field, preventing invalid column names like the cash source had. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
54c93c28dd
commit
52be043c1d
@ -280,6 +280,22 @@ module.exports = function(pool) {
|
||||
});
|
||||
|
||||
// deregister a source — does not drop existing forecast tables
|
||||
router.get('/dim-period/cols', async (req, res) => {
|
||||
try {
|
||||
const result = await pool.query(`
|
||||
SELECT column_name
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'pf' AND table_name = 'dim_period'
|
||||
AND column_name NOT IN ('sdat', 'edat', 'drange', 'ndays')
|
||||
ORDER BY ordinal_position
|
||||
`);
|
||||
res.json(result.rows.map(r => r.column_name));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
router.delete('/sources/:id', async (req, res) => {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
|
||||
@ -24,9 +24,11 @@ export default function Setup({ refreshSources }) {
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [generating, setGenerating] = useState(false)
|
||||
const [msg, setMsg] = useState(null)
|
||||
const [dimPeriodCols, setDimPeriodCols] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/api/tables').then(r => r.json()).then(setTables).catch(console.error)
|
||||
fetch('/api/dim-period/cols').then(r => r.json()).then(setDimPeriodCols).catch(console.error)
|
||||
loadSources()
|
||||
}, [])
|
||||
|
||||
@ -324,14 +326,15 @@ export default function Setup({ refreshSources }) {
|
||||
/>
|
||||
</td>
|
||||
<td className="px-3 py-1.5">
|
||||
<input
|
||||
type="text"
|
||||
<select
|
||||
value={col.dim_period_col || ''}
|
||||
onChange={e => updateCol(i, 'dim_period_col', e.target.value || null)}
|
||||
placeholder="—"
|
||||
disabled={col.role !== 'dimension' || !col.dim_group}
|
||||
className="border border-transparent hover:border-gray-200 focus:border-gray-300 rounded px-1.5 py-0.5 w-full outline-none bg-transparent disabled:opacity-20 disabled:cursor-default font-mono text-xs"
|
||||
/>
|
||||
className="text-xs px-1.5 py-0.5 rounded border border-transparent hover:border-gray-200 focus:border-gray-300 outline-none bg-transparent disabled:opacity-20 disabled:cursor-default font-mono w-full"
|
||||
>
|
||||
<option value="">—</option>
|
||||
{dimPeriodCols.map(c => <option key={c} value={c}>{c}</option>)}
|
||||
</select>
|
||||
</td>
|
||||
<td className="px-3 py-1.5">
|
||||
<input
|
||||
|
||||
Loading…
Reference in New Issue
Block a user