fix(ce): Resolve database schema mismatch and restore docs
- Fixed a critical in the company-explorer by forcing a database re-initialization with a new file (). This ensures the application code is in sync with the database schema. - Documented the schema mismatch incident and its resolution in MIGRATION_PLAN.md. - Restored and enhanced BUILDER_APPS_MIGRATION.md by recovering extensive, valuable content from the git history that was accidentally deleted. The guide now again includes detailed troubleshooting steps and code templates for common migration pitfalls.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import axios from 'axios'
|
||||
import { X, ExternalLink, Bot, Briefcase, Calendar, Globe, Users, DollarSign, MapPin, Tag, RefreshCw as RefreshCwIcon, Search as SearchIcon, Pencil, Check, Download, Clock } from 'lucide-react'
|
||||
import { X, ExternalLink, Bot, Briefcase, Calendar, Globe, Users, DollarSign, MapPin, Tag, RefreshCw as RefreshCwIcon, Search as SearchIcon, Pencil, Check, Download, Clock, Lock, Unlock } from 'lucide-react'
|
||||
import clsx from 'clsx'
|
||||
import { ContactsManager, Contact } from './ContactsManager'
|
||||
|
||||
@@ -204,6 +204,16 @@ export function Inspector({ companyId, initialContactId, onClose, apiBase }: Ins
|
||||
}
|
||||
}
|
||||
|
||||
const handleLockToggle = async (sourceType: string, currentLockStatus: boolean) => {
|
||||
if (!companyId) return
|
||||
try {
|
||||
await axios.post(`${apiBase}/enrichment/${companyId}/${sourceType}/lock?locked=${!currentLockStatus}`)
|
||||
fetchData(true) // Silent refresh
|
||||
} catch (e) {
|
||||
console.error("Lock toggle failed", e)
|
||||
}
|
||||
}
|
||||
|
||||
const handleAddContact = async (contact: Contact) => {
|
||||
if (!companyId) return
|
||||
try {
|
||||
@@ -397,23 +407,39 @@ export function Inspector({ companyId, initialContactId, onClose, apiBase }: Ins
|
||||
<Briefcase className="h-3 w-3" />
|
||||
</div>
|
||||
<span className="text-[10px] uppercase font-bold text-slate-500 tracking-wider">Official Legal Data</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{scrapeDate && (
|
||||
<div className="text-[10px] text-slate-500 flex items-center gap-1">
|
||||
<Clock className="h-3 w-3" /> {new Date(scrapeDate).toLocaleDateString()}
|
||||
</div>
|
||||
)}
|
||||
{!isEditingImpressum ? (
|
||||
<button
|
||||
onClick={() => { setImpressumUrlInput(""); setIsEditingImpressum(true); }}
|
||||
className="p-1 text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors"
|
||||
title="Set Impressum URL Manually"
|
||||
>
|
||||
<Pencil className="h-3 w-3" />
|
||||
</button>
|
||||
) : (
|
||||
<div className="flex items-center gap-1 animate-in fade-in zoom-in duration-200">
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{scrapeDate && (
|
||||
<div className="text-[10px] text-slate-500 flex items-center gap-1">
|
||||
<Clock className="h-3 w-3" /> {new Date(scrapeDate).toLocaleDateString()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Lock Button for Impressum */}
|
||||
{scrapeEntry && (
|
||||
<button
|
||||
onClick={() => handleLockToggle('website_scrape', scrapeEntry.is_locked || false)}
|
||||
className={clsx(
|
||||
"p-1 rounded transition-colors",
|
||||
scrapeEntry.is_locked
|
||||
? "text-green-600 dark:text-green-400 hover:text-green-700"
|
||||
: "text-slate-400 hover:text-slate-900 dark:hover:text-white"
|
||||
)}
|
||||
title={scrapeEntry.is_locked ? "Data Locked (Safe from auto-overwrite)" : "Unlocked (Auto-overwrite enabled)"}
|
||||
>
|
||||
{scrapeEntry.is_locked ? <Lock className="h-3.5 w-3.5" /> : <Unlock className="h-3.5 w-3.5" />}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{!isEditingImpressum ? (
|
||||
<button
|
||||
onClick={() => { setImpressumUrlInput(""); setIsEditingImpressum(true); }}
|
||||
className="p-1 text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors"
|
||||
title="Set Impressum URL Manually"
|
||||
>
|
||||
<Pencil className="h-3 w-3" />
|
||||
</button>
|
||||
) : ( <div className="flex items-center gap-1 animate-in fade-in zoom-in duration-200">
|
||||
<button
|
||||
onClick={handleImpressumOverride}
|
||||
className="p-1 bg-green-100 dark:bg-green-900/50 text-green-600 dark:text-green-400 rounded hover:bg-green-200 dark:hover:bg-green-900 transition-colors"
|
||||
@@ -510,22 +536,71 @@ export function Inspector({ companyId, initialContactId, onClose, apiBase }: Ins
|
||||
<Globe className="h-4 w-4" /> Company Profile (Wikipedia)
|
||||
</h3>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{wikiDate && (
|
||||
<div className="text-[10px] text-slate-500 flex items-center gap-1 mr-2">
|
||||
<Clock className="h-3 w-3" /> {new Date(wikiDate).toLocaleDateString()}
|
||||
</div>
|
||||
)}
|
||||
{!isEditingWiki ? (
|
||||
<button
|
||||
onClick={() => { setWikiUrlInput(wiki?.url || ""); setIsEditingWiki(true); }}
|
||||
className="p-1 text-slate-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||
title="Edit / Override URL"
|
||||
>
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
) : (
|
||||
<div className="flex items-center gap-1">
|
||||
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
{wikiDate && (
|
||||
|
||||
<div className="text-[10px] text-slate-500 flex items-center gap-1 mr-2">
|
||||
|
||||
<Clock className="h-3 w-3" /> {new Date(wikiDate).toLocaleDateString()}
|
||||
|
||||
</div>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
|
||||
{/* Lock Button for Wiki */}
|
||||
|
||||
{wikiEntry && (
|
||||
|
||||
<button
|
||||
|
||||
onClick={() => handleLockToggle('wikipedia', wikiEntry.is_locked || false)}
|
||||
|
||||
className={clsx(
|
||||
|
||||
"p-1 rounded transition-colors mr-1",
|
||||
|
||||
wikiEntry.is_locked
|
||||
|
||||
? "text-green-600 dark:text-green-400 hover:text-green-700"
|
||||
|
||||
: "text-slate-400 hover:text-slate-900 dark:hover:text-white"
|
||||
|
||||
)}
|
||||
|
||||
title={wikiEntry.is_locked ? "Wiki Data Locked" : "Wiki Data Unlocked"}
|
||||
|
||||
>
|
||||
|
||||
{wikiEntry.is_locked ? <Lock className="h-3.5 w-3.5" /> : <Unlock className="h-3.5 w-3.5" />}
|
||||
|
||||
</button>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
|
||||
{!isEditingWiki ? (
|
||||
|
||||
<button
|
||||
|
||||
onClick={() => { setWikiUrlInput(wiki?.url || ""); setIsEditingWiki(true); }}
|
||||
|
||||
className="p-1 text-slate-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||
|
||||
title="Edit / Override URL"
|
||||
|
||||
>
|
||||
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
|
||||
</button>
|
||||
|
||||
) : ( <div className="flex items-center gap-1">
|
||||
<button
|
||||
onClick={handleWikiOverride}
|
||||
className="p-1 bg-green-100 dark:bg-green-900/50 text-green-600 dark:text-green-400 rounded hover:bg-green-200 dark:hover:bg-green-900 transition-colors"
|
||||
|
||||
Reference in New Issue
Block a user