Files
chrani-bot-tng/bot/modules/locations/templates/webmap/location_shapes.html
2025-11-21 07:26:02 +01:00

144 lines
6.4 KiB
HTML

// Helper function to create location shape based on type
function createLocationShape(locationId, loc) {
const coords = loc.coordinates;
const centerLatLng = [coords.x, coords.z]; // 7D2D coordinates (x, z)
const dims = loc.dimensions || {};
const shape = loc.shape || 'circle';
const isEnabled = loc.is_enabled;
const is3D = (shape === 'box' || shape === 'spherical');
// Color scheme
const fillColor = isEnabled ? '#ff9900' : '#666666';
const strokeColor = isEnabled ? '#ffcc00' : '#999999';
const fillOpacity = isEnabled ? 0.3 : 0.15;
let leafletShape;
if (shape === 'circle') {
const radius = parseFloat(dims.radius || 10);
leafletShape = L.circle(centerLatLng, {
radius: radius,
fillColor: fillColor,
color: strokeColor,
weight: 2,
opacity: 0.8,
fillOpacity: fillOpacity
});
} else if (shape === 'spherical') {
const radius = parseFloat(dims.radius || 10);
leafletShape = L.circle(centerLatLng, {
radius: radius,
fillColor: fillColor,
color: strokeColor,
weight: 2,
opacity: 0.8,
fillOpacity: fillOpacity,
dashArray: '5, 5' // Dashed to indicate 3D
});
} else if (shape === 'rectangular') {
const width = parseFloat(dims.width || 10);
const length = parseFloat(dims.length || 10);
// Rectangle bounds: from center, extend width/length in both directions
const bounds = [
[coords.x - width, coords.z - length],
[coords.x + width, coords.z + length]
];
leafletShape = L.rectangle(bounds, {
fillColor: fillColor,
color: strokeColor,
weight: 2,
opacity: 0.8,
fillOpacity: fillOpacity
});
} else if (shape === 'box') {
const width = parseFloat(dims.width || 10);
const length = parseFloat(dims.length || 10);
const bounds = [
[coords.x - width, coords.z - length],
[coords.x + width, coords.z + length]
];
leafletShape = L.rectangle(bounds, {
fillColor: fillColor,
color: strokeColor,
weight: 2,
opacity: 0.8,
fillOpacity: fillOpacity,
dashArray: '5, 5' // Dashed to indicate 3D
});
} else {
// Fallback to circle
leafletShape = L.circle(centerLatLng, {
radius: 10,
fillColor: fillColor,
color: strokeColor,
weight: 2,
opacity: 0.8,
fillOpacity: fillOpacity
});
}
// Build popup content
const dimensionText = shape === 'circle' || shape === 'spherical'
? `Radius: ${dims.radius || 'N/A'}`
: `Width: ${dims.width || 'N/A'}, Length: ${dims.length || 'N/A'}${shape === 'box' ? ', Height: ' + (dims.height || 'N/A') : ''}`;
// Parse locationId to extract components
// Format: {dataset}_{owner}_{identifier}
const locationIdParts = locationId.split('_');
const dataset = locationIdParts.slice(0, -2).join('_'); // Handle datasets with underscores
const owner = locationIdParts[locationIdParts.length - 2];
const identifier = locationIdParts[locationIdParts.length - 1];
const teleportEntry = loc.teleport_entry || {};
const hasTeleport = teleportEntry.x !== undefined && teleportEntry.y !== undefined && teleportEntry.z !== undefined;
const teleportText = hasTeleport
? `TP: ${parseFloat(teleportEntry.x || 0).toFixed(0)}, ${parseFloat(teleportEntry.y || 0).toFixed(0)}, ${parseFloat(teleportEntry.z || 0).toFixed(0)}`
: 'TP: Not set';
// Use template literal for clean HTML
const popupContent = `
<div style="min-width: 250px; font-family: monospace;">
<b style="font-size: 1.1em;">${loc.name}</b>
<br><span style="font-size: 0.9em; color: #888;">${is3D ? '🎲 3D' : '⬜ 2D'} - ${shape}</span>
<br><hr style="margin: 5px 0; border-color: #333;">
<b>Type:</b> ${loc.type && loc.type.length > 0 ? loc.type.join(', ') : 'None'}
<br><b>Owner:</b> ${loc.owner}
<br><b>Status:</b> ${isEnabled ? '✅ Enabled' : '❌ Disabled'}
<br><b>Position:</b> ${coords.x.toFixed(0)}, ${coords.y.toFixed(0)}, ${coords.z.toFixed(0)}
<br><b>Dimensions:</b> ${dimensionText}
<br><b>${teleportText}</b>
<br><hr style="margin: 8px 0; border-color: #333;">
<div style="display: flex; gap: 5px; justify-content: space-between; align-items: center; margin-bottom: 5px;">
<button onclick="editLocationFromMap('${dataset}', '${owner}', '${identifier}')"
style="flex: 1; padding: 6px 12px; background: var(--lcars-hopbush); color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold;">
✏️ Edit</button>
<label style="display: flex; align-items: center; gap: 5px; cursor: pointer; white-space: nowrap;">
<input type="checkbox"
id="enable_${locationId}"
${isEnabled ? 'checked' : ''}
onchange="toggleLocationEnabled('${dataset}', '${owner}', '${identifier}', this.checked)"
style="cursor: pointer; width: 18px; height: 18px;" />
<span style="font-weight: bold;">Enabled</span>
</label>
</div>
<div style="display: flex; gap: 5px;">
<button onclick="moveLocationFromMap('${locationId}')"
style="flex: 1; padding: 6px 10px; background: var(--lcars-anakiwa); color: #000; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 0.9em;">
📍 Move</button>
<button onclick="setTeleportFromMap('${locationId}')"
style="flex: 1; padding: 6px 10px; background: var(--lcars-golden-tanoi); color: #000; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 0.9em;">
🎯 Set TP</button>
</div>
</div>
`;
leafletShape.bindPopup(popupContent);
leafletShape.addTo(map);
return leafletShape;
}
// Location shapes are now loaded dynamically via Socket.IO
// Initial loading is handled by location_update events
// See location_update_handler.html for shape creation logic