/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /** * Model metadata panel - displays file info, schema version, entity counts, * coordinate system info, and project information. */ import { useMemo } from 'react'; import { Layers, FileText, Tag, FileBox, Clock, HardDrive, Hash, Database, Building2, Ruler, } from 'lucide-react'; import { ScrollArea } from '@/components/ui/scroll-area'; import { PropertySetCard } from './PropertySetCard'; import { GeoreferencingPanel } from './GeoreferencingPanel'; import type { PropertySet } from './encodingUtils'; import type { FederatedModel } from '@/store/types'; import { extractGeoreferencingOnDemand, extractLengthUnitScale, type IfcDataStore } from '@ifc-lite/parser'; /** Model metadata panel - displays file info, schema version, entity counts, etc. */ export function ModelMetadataPanel({ model }: { model: FederatedModel }) { const dataStore = model.ifcDataStore; // Format file size const formatFileSize = (bytes: number): string => { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; return `${(bytes / (1024 * 1024)).toFixed(2)} MB`; }; // Format date const formatDate = (timestamp: number): string => { return new Date(timestamp).toLocaleString(); }; // Get IfcProject data if available const projectData = useMemo(() => { if (!dataStore?.spatialHierarchy?.project) return null; const project = dataStore.spatialHierarchy.project; const projectId = project.expressId; // Get project entity attributes const name = dataStore.entities.getName(projectId); const globalId = dataStore.entities.getGlobalId(projectId); const description = dataStore.entities.getDescription(projectId); // Get project properties const properties: PropertySet[] = []; if (dataStore.properties) { for (const pset of dataStore.properties.getForEntity(projectId)) { properties.push({ name: pset.name, properties: pset.properties.map(p => ({ name: p.name, value: p.value })), }); } } return { name, globalId, description, properties }; }, [dataStore]); // Count storeys and elements const stats = useMemo(() => { if (!dataStore?.spatialHierarchy) { return { storeys: 0, elementsWithGeometry: 0 }; } const storeys = dataStore.spatialHierarchy.byStorey.size; let elementsWithGeometry = 0; for (const elements of dataStore.spatialHierarchy.byStorey.values()) { elementsWithGeometry += (elements as number[]).length; } return { storeys, elementsWithGeometry }; }, [dataStore]); // Extract georeferencing info const georef = useMemo(() => { if (!dataStore) return null; const info = extractGeoreferencingOnDemand(dataStore as IfcDataStore); return info?.hasGeoreference ? info : null; }, [dataStore]); // Extract length unit scale const unitInfo = useMemo(() => { if (!dataStore?.source?.length || !dataStore?.entityIndex) return null; const scale = extractLengthUnitScale(dataStore.source, dataStore.entityIndex); let unitName = 'Meters'; if (Math.abs(scale - 0.001) < 0.0001) unitName = 'Millimeters'; else if (Math.abs(scale - 0.01) < 0.001) unitName = 'Centimeters'; else if (Math.abs(scale - 0.0254) < 0.001) unitName = 'Inches'; else if (Math.abs(scale - 0.3048) < 0.01) unitName = 'Feet'; return { scale, unitName }; }, [dataStore]); return (
IFC Model
{projectData.globalId}