Update: GTM Architect v2.6.2 (Edit Specs, Report Fix) & Company Explorer v0.4 (Export, Timestamps)
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 } from 'lucide-react'
|
||||
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 clsx from 'clsx'
|
||||
|
||||
interface InspectorProps {
|
||||
@@ -20,6 +20,7 @@ type EnrichmentData = {
|
||||
source_type: string
|
||||
content: any
|
||||
is_locked?: boolean
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
type CompanyDetail = {
|
||||
@@ -110,6 +111,38 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) {
|
||||
}
|
||||
}
|
||||
|
||||
const handleExport = () => {
|
||||
if (!data) return;
|
||||
|
||||
// Prepare full export object
|
||||
const exportData = {
|
||||
metadata: {
|
||||
id: data.id,
|
||||
exported_at: new Date().toISOString(),
|
||||
source: "Company Explorer (Robotics Edition)"
|
||||
},
|
||||
company: {
|
||||
name: data.name,
|
||||
website: data.website,
|
||||
status: data.status,
|
||||
industry_ai: data.industry_ai,
|
||||
created_at: data.created_at
|
||||
},
|
||||
enrichment: data.enrichment_data,
|
||||
signals: data.signals
|
||||
};
|
||||
|
||||
const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `company-export-${data.id}-${data.name.replace(/[^a-z0-9]/gi, '_').toLowerCase()}.json`;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
const handleWikiOverride = async () => {
|
||||
if (!companyId) return
|
||||
setIsProcessing(true)
|
||||
@@ -145,11 +178,16 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) {
|
||||
const wikiEntry = data?.enrichment_data?.find(e => e.source_type === 'wikipedia')
|
||||
const wiki = wikiEntry?.content
|
||||
const isLocked = wikiEntry?.is_locked
|
||||
const wikiDate = wikiEntry?.created_at
|
||||
|
||||
const aiAnalysis = data?.enrichment_data?.find(e => e.source_type === 'ai_analysis')?.content
|
||||
const aiAnalysisEntry = data?.enrichment_data?.find(e => e.source_type === 'ai_analysis')
|
||||
const aiAnalysis = aiAnalysisEntry?.content
|
||||
const aiDate = aiAnalysisEntry?.created_at
|
||||
|
||||
const scrapeData = data?.enrichment_data?.find(e => e.source_type === 'website_scrape')?.content
|
||||
const scrapeEntry = data?.enrichment_data?.find(e => e.source_type === 'website_scrape')
|
||||
const scrapeData = scrapeEntry?.content
|
||||
const impressum = scrapeData?.impressum
|
||||
const scrapeDate = scrapeEntry?.created_at
|
||||
|
||||
return (
|
||||
<div className="fixed inset-y-0 right-0 w-[550px] bg-slate-900 border-l border-slate-800 shadow-2xl transform transition-transform duration-300 ease-in-out z-40 overflow-y-auto">
|
||||
@@ -164,6 +202,13 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) {
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<h2 className="text-xl font-bold text-white leading-tight">{data.name}</h2>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={handleExport}
|
||||
className="p-1.5 text-slate-500 hover:text-blue-400 transition-colors"
|
||||
title="Export JSON"
|
||||
>
|
||||
<Download className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => fetchData(true)}
|
||||
className="p-1.5 text-slate-500 hover:text-white transition-colors"
|
||||
@@ -261,11 +306,18 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) {
|
||||
{/* Impressum / Legal Data (NEW) */}
|
||||
{impressum && (
|
||||
<div className="bg-slate-950 rounded-lg p-4 border border-slate-800 flex flex-col gap-2">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<div className="p-1 bg-slate-800 rounded text-slate-400">
|
||||
<Briefcase className="h-3 w-3" />
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1 bg-slate-800 rounded text-slate-400">
|
||||
<Briefcase className="h-3 w-3" />
|
||||
</div>
|
||||
<span className="text-[10px] uppercase font-bold text-slate-500 tracking-wider">Official Legal Data</span>
|
||||
</div>
|
||||
<span className="text-[10px] uppercase font-bold text-slate-500 tracking-wider">Official Legal Data</span>
|
||||
{scrapeDate && (
|
||||
<div className="text-[10px] text-slate-600 flex items-center gap-1">
|
||||
<Clock className="h-3 w-3" /> {new Date(scrapeDate).toLocaleDateString()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="text-sm font-medium text-white">
|
||||
@@ -293,9 +345,16 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) {
|
||||
{/* AI Analysis Dossier (NEW) */}
|
||||
{aiAnalysis && (
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-sm font-semibold text-slate-400 uppercase tracking-wider flex items-center gap-2">
|
||||
<Bot className="h-4 w-4" /> AI Strategic Dossier
|
||||
</h3>
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-sm font-semibold text-slate-400 uppercase tracking-wider flex items-center gap-2">
|
||||
<Bot className="h-4 w-4" /> AI Strategic Dossier
|
||||
</h3>
|
||||
{aiDate && (
|
||||
<div className="text-[10px] text-slate-600 flex items-center gap-1">
|
||||
<Clock className="h-3 w-3" /> {new Date(aiDate).toLocaleDateString()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="bg-slate-800/30 rounded-xl p-5 border border-slate-800/50 space-y-4">
|
||||
<div>
|
||||
<div className="text-[10px] text-blue-400 uppercase font-bold tracking-tight mb-1">Business Model</div>
|
||||
@@ -317,32 +376,40 @@ export function Inspector({ companyId, onClose, apiBase }: InspectorProps) {
|
||||
<h3 className="text-sm font-semibold text-slate-400 uppercase tracking-wider flex items-center gap-2">
|
||||
<Globe className="h-4 w-4" /> Company Profile (Wikipedia)
|
||||
</h3>
|
||||
{!isEditingWiki ? (
|
||||
<button
|
||||
onClick={() => { setWikiUrlInput(wiki?.url || ""); setIsEditingWiki(true); }}
|
||||
className="p-1 text-slate-500 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-600 flex items-center gap-1 mr-2">
|
||||
<Clock className="h-3 w-3" /> {new Date(wikiDate).toLocaleDateString()}
|
||||
</div>
|
||||
)}
|
||||
{!isEditingWiki ? (
|
||||
<button
|
||||
onClick={handleWikiOverride}
|
||||
className="p-1 bg-green-900/50 text-green-400 rounded hover:bg-green-900 transition-colors"
|
||||
title="Save & Rescan"
|
||||
onClick={() => { setWikiUrlInput(wiki?.url || ""); setIsEditingWiki(true); }}
|
||||
className="p-1 text-slate-500 hover:text-blue-400 transition-colors"
|
||||
title="Edit / Override URL"
|
||||
>
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsEditingWiki(false)}
|
||||
className="p-1 text-slate-500 hover:text-red-400 transition-colors"
|
||||
title="Cancel"
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
) : (
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
onClick={handleWikiOverride}
|
||||
className="p-1 bg-green-900/50 text-green-400 rounded hover:bg-green-900 transition-colors"
|
||||
title="Save & Rescan"
|
||||
>
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsEditingWiki(false)}
|
||||
className="p-1 text-slate-500 hover:text-red-400 transition-colors"
|
||||
title="Cancel"
|
||||
>
|
||||
<X className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isEditingWiki && (
|
||||
|
||||
Reference in New Issue
Block a user