Symbol-Funktion in Elemente-Panel (Phase S1+S2)
Schema (library.py): - Item-Format erweitert: files2d + files3d (Backwards-compat zu 'files') - _build_variant_block + _place_instance + Layer-Routing pro Variante - import_item akzeptiert at_point + layer2d/layer3d - _ensure_block_definition mit variant-Suffix (dossier_lib_<id>_2d/_3d) Backend (elemente.py): - _layer_path_symbole(geschoss_name, variant) → <geschoss>::40_SYMBOLE:: SYMBOLE_2D bzw. SYMBOLE_3D - Default-Ebene 40 SYMBOLE via _find_ebene_sublayer_name - LIST_LIBRARY-Handler: sendet Library-Manifest als LIBRARY_LIST - CREATE_SYMBOL-Handler: interactive GetPoint im aktiven Viewport, laedt Block-Def + platziert Instanz(en) auf den richtigen Ebenen - Pair-Items (2D+3D) werden an gleichem Punkt beidseitig platziert → Top zeigt 2D-Layer, Persp zeigt 3D-Layer wenn User entsprechend Sichtbarkeit setzt Frontend: - SymbolPicker Modal-Component: Grid mit Symbol/Object-Cards, Search, Type-Filter (Alle/Symbole/Objekte), Doppelklick = Pick - Symbol-Button in ElementeApp (PillGroup "Library") oeffnet Modal + triggert listLibrary() fuer aktuelle Items - createSymbol(id) → Backend → GetPoint → Place Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,9 @@ import {
|
||||
openSwisstopo, openSwisstopoDialog, openOsmDialog,
|
||||
updateElement, deleteElement, openElementeUebersicht, openElementeProperties,
|
||||
saveOeffStyle, deleteOeffStyle,
|
||||
listLibrary, createSymbol,
|
||||
} from './lib/rhinoBridge'
|
||||
import SymbolPicker from './components/SymbolPicker'
|
||||
|
||||
const labelXs = {
|
||||
fontSize: 10, fontWeight: 600, color: 'var(--text-muted)',
|
||||
@@ -327,7 +329,16 @@ function NeuesElementSection({ noGeschoss, activeName, elementsCount }) {
|
||||
const [treppeMenuOpen, setTreppeMenuOpen] = useState(false)
|
||||
const [stuetzeMenuOpen, setStuetzeMenuOpen] = useState(false)
|
||||
const [traegerMenuOpen, setTraegerMenuOpen] = useState(false)
|
||||
const [symbolPickerOpen, setSymbolPickerOpen] = useState(false)
|
||||
const [libraryItems, setLibraryItems] = useState([])
|
||||
const treppeWrapperRef = useRef(null)
|
||||
|
||||
// Library-Items kommen via LIBRARY_LIST message vom Backend nach LIST_LIBRARY.
|
||||
useEffect(() => {
|
||||
onMessage('LIBRARY_LIST', ({ items }) => {
|
||||
if (Array.isArray(items)) setLibraryItems(items)
|
||||
})
|
||||
}, [])
|
||||
const dis = noGeschoss
|
||||
const baseHint = (label) =>
|
||||
noGeschoss ? 'Erst im Ebenen-Manager ein Geschoss aktivieren'
|
||||
@@ -477,6 +488,14 @@ function NeuesElementSection({ noGeschoss, activeName, elementsCount }) {
|
||||
onClick={() => createRaum({})} />
|
||||
</PillGroup>
|
||||
|
||||
<PillGroup label="Library">
|
||||
<PillButton icon="inventory_2" label="Symbol"
|
||||
hint={dis ? baseHint('Symbol') :
|
||||
'Library-Item auswählen · im Viewport Punkt klicken zum Platzieren'}
|
||||
disabled={dis}
|
||||
onClick={() => { listLibrary(); setSymbolPickerOpen(true) }} />
|
||||
</PillGroup>
|
||||
|
||||
<PillGroup label="Importer">
|
||||
<PillButton icon="download" label="Swisstopo"
|
||||
hint="Vollautomatischer Import via swisstopo STAC-API: Adresse suchen, Radius wählen, Gebäude + Terrain + Luftbild holen"
|
||||
@@ -488,6 +507,16 @@ function NeuesElementSection({ noGeschoss, activeName, elementsCount }) {
|
||||
hint="Öffnet map.geo.admin.ch im Browser zur visuellen Inspektion"
|
||||
onClick={() => openSwisstopo('both')} />
|
||||
</PillGroup>
|
||||
|
||||
{symbolPickerOpen && (
|
||||
<SymbolPicker
|
||||
items={libraryItems}
|
||||
onPick={(id) => {
|
||||
setSymbolPickerOpen(false)
|
||||
createSymbol(id)
|
||||
}}
|
||||
onClose={() => setSymbolPickerOpen(false)} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user