add other device

This commit is contained in:
2025-12-14 21:08:38 +05:00
parent 61ba40c7d2
commit 7eaf1b3b86
8 changed files with 55 additions and 9 deletions

View File

@@ -20,7 +20,7 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
const [endDeviceId, setEndDeviceId] = useState<string | null>(null);
const isCableTool = ['fiber', 'cat6', 'cat6_poe'].includes(activeTool);
const isDeviceTool = ['switch', 'indoor_ap', 'outdoor_ap', 'info'].includes(activeTool);
const isDeviceTool = ['switch', 'indoor_ap', 'outdoor_ap', 'other_device', 'info'].includes(activeTool);
const isWirelessTool = activeTool === 'wireless_mesh';
// Load all map items for snapping
@@ -39,7 +39,7 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
// Find nearby device for snapping (exclude info markers)
const findNearbyDevice = (lat: number, lng: number, radiusMeters = 5): any | null => {
const devices = allItems.filter(item =>
['switch', 'indoor_ap', 'outdoor_ap'].includes(item.type) &&
['switch', 'indoor_ap', 'outdoor_ap', 'other_device'].includes(item.type) &&
item.geometry.type === 'Point'
);
@@ -116,7 +116,7 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
// Only add port_count and connections if it's not an info marker
if (activeTool !== 'info') {
properties.port_count = activeTool === 'switch' ? 5 : activeTool === 'outdoor_ap' ? 1 : 4;
properties.port_count = activeTool === 'switch' ? 5 : (activeTool === 'outdoor_ap' || activeTool === 'other_device') ? 1 : 4;
properties.connections = [];
}

View File

@@ -27,7 +27,7 @@ export function ItemContextMenu({ item, position, onClose, onUpdate }: ItemConte
const fileInputRef = useRef<HTMLInputElement>(null);
const isSwitch = item.type === 'switch';
const isDevice = ['switch', 'indoor_ap', 'outdoor_ap'].includes(item.type);
const isDevice = ['switch', 'indoor_ap', 'outdoor_ap', 'other_device'].includes(item.type);
const hasConnections = item.properties.connections && item.properties.connections.length > 0;
useEffect(() => {

View File

@@ -88,6 +88,22 @@ const outdoorApIcon = new L.DivIcon({
iconAnchor: [20, 40],
});
const otherDeviceIcon = new L.DivIcon({
html: `<div class="device-icon other-device-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<rect x="4" y="6" width="16" height="12" rx="2" fill="none" stroke="currentColor" stroke-width="2"/>
<circle cx="12" cy="12" r="2"/>
<line x1="7" y1="9" x2="7" y2="9" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="17" y1="9" x2="17" y2="9" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="7" y1="15" x2="7" y2="15" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="17" y1="15" x2="17" y2="15" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</div>`,
className: 'custom-device-marker',
iconSize: [40, 40],
iconAnchor: [20, 40],
});
const infoIcon = new L.DivIcon({
html: `<div class="info-marker-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
@@ -127,7 +143,7 @@ export function MapItemsLayer({ mapId, refreshTrigger, readOnly = false }: MapIt
console.log('Loaded items:', data);
// Log devices with their connections
data.forEach(item => {
if (['switch', 'indoor_ap', 'outdoor_ap'].includes(item.type)) {
if (['switch', 'indoor_ap', 'outdoor_ap', 'other_device'].includes(item.type)) {
console.log(`Device ${item.type} (${item.id}): ${item.properties.connections?.length || 0} / ${item.properties.port_count} ports`);
}
});
@@ -153,6 +169,8 @@ export function MapItemsLayer({ mapId, refreshTrigger, readOnly = false }: MapIt
return indoorApIcon;
case 'outdoor_ap':
return outdoorApIcon;
case 'other_device':
return otherDeviceIcon;
case 'info':
return infoIcon;
default:
@@ -379,7 +397,7 @@ export function MapItemsLayer({ mapId, refreshTrigger, readOnly = false }: MapIt
// Render devices and info markers
if (
['switch', 'indoor_ap', 'outdoor_ap', 'info'].includes(item.type) &&
['switch', 'indoor_ap', 'outdoor_ap', 'other_device', 'info'].includes(item.type) &&
item.geometry.type === 'Point'
) {
const [lng, lat] = item.geometry.coordinates;

View File

@@ -71,6 +71,12 @@ const DEVICE_TOOLS: ToolButton[] = [
icon: 'outdoor_ap',
description: 'Outdoor Access Point',
},
{
id: 'other_device',
label: 'Other Device',
icon: 'other_device',
description: 'Other Device',
},
];
const INFO_TOOL: ToolButton = {
@@ -128,6 +134,19 @@ export function Toolbar({ readOnly = false }: ToolbarProps) {
);
}
if (tool.icon === 'other_device') {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style={{ color: '#6B7280' }}>
<rect x="4" y="6" width="16" height="12" rx="2" fill="none" stroke="currentColor" strokeWidth="2"/>
<circle cx="12" cy="12" r="2"/>
<line x1="7" y1="9" x2="7" y2="9" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
<line x1="17" y1="9" x2="17" y2="9" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
<line x1="7" y1="15" x2="7" y2="15" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
<line x1="17" y1="15" x2="17" y2="15" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
</svg>
);
}
if (tool.icon === 'info') {
return (
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style={{ color: '#6366F1' }}>

View File

@@ -138,6 +138,11 @@
color: #F59E0B;
}
.other-device-icon {
border-color: #6B7280;
color: #6B7280;
}
/* Info marker icon */
.custom-info-marker {
background: transparent !important;

View File

@@ -1,4 +1,4 @@
export type MapItemType = 'cable' | 'switch' | 'indoor_ap' | 'outdoor_ap' | 'wireless_mesh' | 'info';
export type MapItemType = 'cable' | 'switch' | 'indoor_ap' | 'outdoor_ap' | 'other_device' | 'wireless_mesh' | 'info';
export type CableType = 'fiber' | 'cat6' | 'cat6_poe';
@@ -60,6 +60,7 @@ export type DrawingTool =
| 'switch'
| 'indoor_ap'
| 'outdoor_ap'
| 'other_device'
| 'wireless_mesh'
| 'info';