Separate mapping changes from view-stale: show Reprocess prompt instead of Generate
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ca266f2839
commit
9ab2052f2b
@ -33,6 +33,7 @@ export default function App() {
|
||||
// Sets of names whose dfv view is out of sync with current definitions
|
||||
const [staleSources, setStaleSources] = useState(new Set())
|
||||
const [staleStacks, setStaleStacks] = useState(new Set())
|
||||
const [reprocessSources, setReprocessSources] = useState(new Set())
|
||||
const [generating, setGenerating] = useState({}) // { 'source:name': true }
|
||||
|
||||
async function handleLogin(user, pass) {
|
||||
@ -56,6 +57,7 @@ export default function App() {
|
||||
setSources([])
|
||||
setStaleSources(new Set())
|
||||
setStaleStacks(new Set())
|
||||
setReprocessSources(new Set())
|
||||
}
|
||||
|
||||
// Load initial stale state from DB once on login
|
||||
@ -70,6 +72,17 @@ export default function App() {
|
||||
function markSourceStale(name) {
|
||||
setStaleSources(prev => new Set([...prev, name]))
|
||||
}
|
||||
function markNeedsReprocess(name) {
|
||||
setReprocessSources(prev => new Set([...prev, name]))
|
||||
}
|
||||
async function handleReprocessSource(name) {
|
||||
setGenerating(g => ({ ...g, [`rp:${name}`]: true }))
|
||||
try {
|
||||
await api.reprocess(name)
|
||||
setReprocessSources(prev => { const n = new Set(prev); n.delete(name); return n })
|
||||
} catch (e) { alert(e.message) }
|
||||
finally { setGenerating(g => { const n = { ...g }; delete n[`rp:${name}`]; return n }) }
|
||||
}
|
||||
function markStackStale(name) {
|
||||
setStaleStacks(prev => new Set([...prev, name]))
|
||||
}
|
||||
@ -214,6 +227,23 @@ export default function App() {
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{reprocessSources.size > 0 && (
|
||||
<div className="bg-blue-50 border-b border-blue-200 px-4 py-1.5 text-xs text-blue-800 flex flex-wrap items-center gap-x-3 gap-y-1">
|
||||
<span className="font-medium">Mappings updated:</span>
|
||||
{[...reprocessSources].map(name => (
|
||||
<span key={name} className="flex items-center gap-1">
|
||||
{name}
|
||||
<button
|
||||
onClick={() => handleReprocessSource(name)}
|
||||
disabled={generating[`rp:${name}`]}
|
||||
className="px-1.5 py-0.5 rounded bg-blue-200 hover:bg-blue-300 disabled:opacity-50 font-medium"
|
||||
>
|
||||
{generating[`rp:${name}`] ? '…' : 'Reprocess'}
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex-1 overflow-auto">
|
||||
<Routes>
|
||||
@ -221,7 +251,7 @@ export default function App() {
|
||||
<Route path="/sources" element={<Sources source={source} sources={sources} setSources={setSources} setSource={setSource} />} />
|
||||
<Route path="/import" element={<Import source={source} />} />
|
||||
<Route path="/rules" element={<Rules source={source} onStale={markSourceStale} />} />
|
||||
<Route path="/mappings" element={<Mappings source={source} onStale={markSourceStale} />} />
|
||||
<Route path="/mappings" element={<Mappings source={source} onNeedsReprocess={markNeedsReprocess} />} />
|
||||
<Route path="/remap" element={<Remap />} />
|
||||
<Route path="/records" element={<Records source={source} />} />
|
||||
<Route path="/pivot" element={<Pivot source={source} />} />
|
||||
|
||||
@ -109,7 +109,7 @@ function SortHeader({ col, label, sortBy, onSort, className = '' }) {
|
||||
)
|
||||
}
|
||||
|
||||
export default function Mappings({ source, onStale }) {
|
||||
export default function Mappings({ source, onNeedsReprocess }) {
|
||||
const [rules, setRules] = useState([])
|
||||
const [selectedRule, setSelectedRule] = useState('')
|
||||
const [allValues, setAllValues] = useState([])
|
||||
@ -268,7 +268,7 @@ export default function Mappings({ source, onStale }) {
|
||||
valueKey(x.extracted_value) === k ? { ...x, is_mapped: true, mapping_id: created.id, output } : x
|
||||
))
|
||||
}
|
||||
onStale?.(source)
|
||||
onNeedsReprocess?.(source)
|
||||
setDrafts(d => { const n = { ...d }; delete n[k]; return n })
|
||||
} catch (err) {
|
||||
alert(err.message)
|
||||
@ -315,7 +315,7 @@ export default function Mappings({ source, onStale }) {
|
||||
setSaving(s => ({ ...s, [k]: false }))
|
||||
}
|
||||
}))
|
||||
onStale?.(source)
|
||||
onNeedsReprocess?.(source)
|
||||
setSelected(new Set())
|
||||
setBulkDraft({})
|
||||
}
|
||||
@ -324,7 +324,7 @@ export default function Mappings({ source, onStale }) {
|
||||
if (!row.mapping_id) return
|
||||
try {
|
||||
await api.deleteMapping(row.mapping_id)
|
||||
onStale?.(source)
|
||||
onNeedsReprocess?.(source)
|
||||
setAllValues(av => av.map(x =>
|
||||
valueKey(x.extracted_value) === valueKey(row.extracted_value)
|
||||
? { ...x, is_mapped: false, mapping_id: null, output: null }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user