mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 09:41:40 -05:00
945 lines
34 KiB
Text
945 lines
34 KiB
Text
<div class="map-control-panel" data-maps-v2-target="settingsPanel" data-controller="map-panel">
|
|
<!-- Vertical Icon Tabs (Left Side) -->
|
|
<div class="panel-tabs">
|
|
<button class="tab-btn active"
|
|
data-action="click->map-panel#switchTab"
|
|
data-tab="search"
|
|
data-map-panel-target="tabButton"
|
|
title="Search">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tab-icon">
|
|
<circle cx="11" cy="11" r="8"></circle>
|
|
<path d="m21 21-4.35-4.35"></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<button class="tab-btn"
|
|
data-action="click->map-panel#switchTab"
|
|
data-tab="layers"
|
|
data-map-panel-target="tabButton"
|
|
title="Map Layers">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tab-icon">
|
|
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
|
|
<polyline points="2 17 12 22 22 17"></polyline>
|
|
<polyline points="2 12 12 17 22 12"></polyline>
|
|
</svg>
|
|
</button>
|
|
|
|
<button class="tab-btn"
|
|
data-action="click->map-panel#switchTab"
|
|
data-tab="settings"
|
|
data-map-panel-target="tabButton"
|
|
title="Settings">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tab-icon">
|
|
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"></path>
|
|
<circle cx="12" cy="12" r="3"></circle>
|
|
</svg>
|
|
</button>
|
|
|
|
<button class="tab-btn"
|
|
data-action="click->map-panel#switchTab"
|
|
data-tab="tools"
|
|
data-map-panel-target="tabButton"
|
|
title="Tools">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tab-icon">
|
|
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<% if !DawarichSettings.self_hosted? %>
|
|
<button class="tab-btn"
|
|
data-action="click->map-panel#switchTab"
|
|
data-tab="links"
|
|
data-map-panel-target="tabButton"
|
|
title="Links">
|
|
<%= icon 'info' %>
|
|
</button>
|
|
<% end %>
|
|
</div>
|
|
|
|
<!-- Panel Content -->
|
|
<div class="panel-content">
|
|
<!-- Panel Header -->
|
|
<div class="panel-header">
|
|
<h3 class="panel-title" data-map-panel-target="title">Search</h3>
|
|
<button class="btn btn-ghost btn-sm btn-circle"
|
|
data-action="click->maps-v2#toggleSettings"
|
|
title="Close panel">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
|
|
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Panel Body -->
|
|
<div class="panel-body">
|
|
<!-- Search Tab -->
|
|
<div class="tab-content active" data-tab-content="search" data-map-panel-target="tabContent">
|
|
<div class="form-control w-full">
|
|
<label class="label">
|
|
<span class="label-text">Search for a place</span>
|
|
</label>
|
|
<div class="relative">
|
|
<input type="text"
|
|
placeholder="Enter name of a place"
|
|
class="input input-bordered w-full"
|
|
data-maps-v2-target="searchInput"
|
|
autocomplete="off" />
|
|
<!-- Search Results -->
|
|
<div class="absolute z-50 w-full mt-1 bg-base-100 rounded-lg shadow-lg border border-base-300 hidden max-h-full overflow-y-auto"
|
|
data-maps-v2-target="searchResults">
|
|
<!-- Results will be populated by SearchManager -->
|
|
</div>
|
|
</div>
|
|
<p class="text-xs text-base-content/60 mt-2">
|
|
Search for a location to find places you visited
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Layers Tab -->
|
|
<div class="tab-content" data-tab-content="layers" data-map-panel-target="tabContent">
|
|
<div class="space-y-4">
|
|
<!-- Points Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="pointsToggle"
|
|
data-action="change->maps-v2#togglePoints" />
|
|
<span class="label-text font-medium">Points</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show individual location points</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Routes Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="routesToggle"
|
|
data-action="change->maps-v2#toggleRoutes" />
|
|
<span class="label-text font-medium">Routes</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show connected route lines</p>
|
|
</div>
|
|
|
|
<!-- Speed-Colored Routes Options (conditionally shown) -->
|
|
<div class="ml-14 space-y-3" data-maps-v2-target="routesOptions" style="display: none;">
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer py-2">
|
|
<span class="label-text text-sm">Color by speed</span>
|
|
<input type="checkbox"
|
|
class="toggle toggle-sm toggle-primary"
|
|
data-maps-v2-target="speedColoredToggle"
|
|
data-action="change->maps-v2#toggleSpeedColoredRoutes" />
|
|
</label>
|
|
</div>
|
|
|
|
<!-- Speed Color Scale Editor (shown when speed colors enabled) -->
|
|
<div class="hidden" data-maps-v2-target="speedColorScaleContainer">
|
|
<button type="button"
|
|
class="btn btn-sm btn-outline w-full"
|
|
data-action="click->maps-v2#openSpeedColorEditor">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" />
|
|
</svg>
|
|
Edit Color Gradient
|
|
</button>
|
|
<input type="hidden" data-maps-v2-target="speedColorScaleInput" value="" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Heatmap Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="heatmapToggle"
|
|
data-action="change->maps-v2#toggleHeatmap" />
|
|
<span class="label-text font-medium">Heatmap</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show density heatmap</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Visits Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="visitsToggle"
|
|
data-action="change->maps-v2#toggleVisits" />
|
|
<span class="label-text font-medium">Visits</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show detected area visits</p>
|
|
</div>
|
|
|
|
<!-- Visits Search (conditionally shown) -->
|
|
<div class="ml-14 space-y-2" data-maps-v2-target="visitsSearch" style="display: none;">
|
|
<input type="text"
|
|
id="visits-search"
|
|
placeholder="Filter by name..."
|
|
class="input input-sm input-bordered w-full"
|
|
data-action="input->maps-v2#searchVisits" />
|
|
|
|
<select class="select select-bordered w-full"
|
|
data-action="change->maps-v2#filterVisits">
|
|
<option value="all">All Visits</option>
|
|
<option value="confirmed">Confirmed Only</option>
|
|
<option value="suggested">Suggested Only</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Places Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="placesToggle"
|
|
data-action="change->maps-v2#togglePlaces" />
|
|
<span class="label-text font-medium">Places</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show your saved places</p>
|
|
</div>
|
|
|
|
<!-- Places Tags (conditionally shown) -->
|
|
<div class="ml-14 space-y-2" data-maps-v2-target="placesFilters" style="display: none;">
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-2">
|
|
<input type="checkbox"
|
|
class="toggle toggle-sm"
|
|
data-maps-v2-target="enableAllPlaceTagsToggle"
|
|
data-action="change->maps-v2#toggleAllPlaceTags">
|
|
<span class="label-text text-sm">Enable All Tags</span>
|
|
</label>
|
|
</div>
|
|
<div class="form-control">
|
|
<label class="label">
|
|
<span class="label-text text-sm">Filter by Tags</span>
|
|
</label>
|
|
<div class="flex flex-wrap gap-2">
|
|
<!-- Untagged option -->
|
|
<label class="cursor-pointer">
|
|
<input type="checkbox"
|
|
name="place_tag_ids[]"
|
|
value="untagged"
|
|
class="checkbox checkbox-xs hidden peer"
|
|
data-action="change->maps-v2#filterPlacesByTags">
|
|
<span class="badge badge-sm badge-outline transition-all peer-checked:scale-105"
|
|
style="border-color: #94a3b8; color: #94a3b8;"
|
|
data-checked-style="background-color: #94a3b8; color: white;">
|
|
🏷️ Untagged
|
|
</span>
|
|
</label>
|
|
|
|
<% current_user.tags.ordered.each do |tag| %>
|
|
<label class="cursor-pointer">
|
|
<input type="checkbox"
|
|
name="place_tag_ids[]"
|
|
value="<%= tag.id %>"
|
|
class="checkbox checkbox-xs hidden peer"
|
|
data-action="change->maps-v2#filterPlacesByTags">
|
|
<span class="badge badge-sm badge-outline transition-all peer-checked:scale-105"
|
|
style="border-color: <%= tag.color %>; color: <%= tag.color %>;"
|
|
data-checked-style="background-color: <%= tag.color %>; color: white;">
|
|
<%= tag.icon %> #<%= tag.name %>
|
|
</span>
|
|
</label>
|
|
<% end %>
|
|
</div>
|
|
<label class="label">
|
|
<span class="label-text-alt">Click tags to filter places</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Photos Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="photosToggle"
|
|
data-action="change->maps-v2#togglePhotos" />
|
|
<span class="label-text font-medium">Photos</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show geotagged photos</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Areas Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="areasToggle"
|
|
data-action="change->maps-v2#toggleAreas" />
|
|
<span class="label-text font-medium">Areas</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show defined areas</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Tracks Layer -->
|
|
<%# <div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="tracksToggle"
|
|
data-action="change->maps-v2#toggleTracks" />
|
|
<span class="label-text font-medium">Tracks</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show saved tracks</p>
|
|
</div> %>
|
|
|
|
<%# <div class="divider"></div> %>
|
|
|
|
<!-- Fog of War Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="fogToggle"
|
|
data-action="change->maps-v2#toggleFog" />
|
|
<span class="label-text font-medium">Fog of War</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show explored areas</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Scratch Map Layer -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-maps-v2-target="scratchToggle"
|
|
data-action="change->maps-v2#toggleScratch" />
|
|
<span class="label-text font-medium">Scratch Map</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 ml-14">Show scratched countries</p>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Settings Tab -->
|
|
<div class="tab-content" data-tab-content="settings" data-map-panel-target="tabContent">
|
|
<form data-action="submit->maps-v2#updateAdvancedSettings" class="space-y-4">
|
|
<!-- Map Style -->
|
|
<div class="form-control w-full">
|
|
<label class="label">
|
|
<span class="label-text font-medium">Map Style</span>
|
|
</label>
|
|
<select class="select select-bordered w-full"
|
|
name="mapStyle"
|
|
data-action="change->maps-v2#updateMapStyle">
|
|
<option value="light" selected>Light</option>
|
|
<option value="dark">Dark</option>
|
|
<option value="white">White</option>
|
|
<option value="black">Black</option>
|
|
<option value="grayscale">Grayscale</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Route Opacity -->
|
|
<div class="form-control w-full">
|
|
<label class="label">
|
|
<span class="label-text font-medium">Route Opacity</span>
|
|
<span class="label-text-alt">%</span>
|
|
</label>
|
|
<input type="range"
|
|
name="routeOpacity"
|
|
min="10"
|
|
max="100"
|
|
step="10"
|
|
value="100"
|
|
class="range range-sm"
|
|
data-maps-v2-target="routeOpacityRange"
|
|
data-action="input->maps-v2#updateRouteOpacity" />
|
|
<div class="w-full flex justify-between text-xs px-2 mt-1">
|
|
<span>10%</span>
|
|
<span>50%</span>
|
|
<span>100%</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Fog of War Settings -->
|
|
<div class="form-control w-full">
|
|
<label class="label">
|
|
<span class="label-text font-medium">Fog of War Radius</span>
|
|
<span class="label-text-alt" data-maps-v2-target="fogRadiusValue">1000m</span>
|
|
</label>
|
|
<input type="range"
|
|
name="fogOfWarRadius"
|
|
min="5"
|
|
max="2000"
|
|
step="5"
|
|
value="1000"
|
|
class="range range-sm"
|
|
data-action="input->maps-v2#updateFogRadiusDisplay" />
|
|
<div class="w-full flex justify-between text-xs px-2 mt-1">
|
|
<span>5m</span>
|
|
<span>1000m</span>
|
|
<span>2000m</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60 mt-1">Clear radius around visited points</p>
|
|
</div>
|
|
|
|
<div class="form-control w-full">
|
|
<label class="label">
|
|
<span class="label-text font-medium">Fog of War Threshold</span>
|
|
<span class="label-text-alt" data-maps-v2-target="fogThresholdValue">1</span>
|
|
</label>
|
|
<input type="range"
|
|
name="fogOfWarThreshold"
|
|
min="1"
|
|
max="10"
|
|
step="1"
|
|
value="1"
|
|
class="range range-sm"
|
|
data-action="input->maps-v2#updateFogThresholdDisplay" />
|
|
<div class="w-full flex justify-between text-xs px-2 mt-1">
|
|
<span>1</span>
|
|
<span>5</span>
|
|
<span>10</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60 mt-1">Minimum points to clear fog</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Route Generation Settings -->
|
|
<div class="form-control w-full">
|
|
<label class="label">
|
|
<span class="label-text font-medium">Meters Between Routes</span>
|
|
<span class="label-text-alt" data-maps-v2-target="metersBetweenValue">500m</span>
|
|
</label>
|
|
<input type="range"
|
|
name="metersBetweenRoutes"
|
|
min="100"
|
|
max="5000"
|
|
step="100"
|
|
value="500"
|
|
class="range range-sm"
|
|
data-action="input->maps-v2#updateMetersBetweenDisplay" />
|
|
<div class="w-full flex justify-between text-xs px-2 mt-1">
|
|
<span>100m</span>
|
|
<span>2500m</span>
|
|
<span>5000m</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60 mt-1">Distance threshold for route splitting</p>
|
|
</div>
|
|
|
|
<div class="form-control w-full">
|
|
<label class="label">
|
|
<span class="label-text font-medium">Minutes Between Routes</span>
|
|
<span class="label-text-alt" data-maps-v2-target="minutesBetweenValue">60min</span>
|
|
</label>
|
|
<input type="range"
|
|
name="minutesBetweenRoutes"
|
|
min="1"
|
|
max="180"
|
|
step="1"
|
|
value="60"
|
|
class="range range-sm"
|
|
data-action="input->maps-v2#updateMinutesBetweenDisplay" />
|
|
<div class="w-full flex justify-between text-xs px-2 mt-1">
|
|
<span>1min</span>
|
|
<span>90min</span>
|
|
<span>180min</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60 mt-1">Time threshold for route splitting</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Points Rendering Mode -->
|
|
<div class="form-control w-full">
|
|
<label class="label">
|
|
<span class="label-text font-medium">Points Rendering Mode</span>
|
|
</label>
|
|
<div class="flex flex-col gap-2">
|
|
<label class="label cursor-pointer justify-start gap-3 py-1">
|
|
<input type="radio"
|
|
name="pointsRenderingMode"
|
|
value="raw"
|
|
class="radio radio-primary radio-sm"
|
|
checked />
|
|
<span class="label-text">Raw (all points)</span>
|
|
</label>
|
|
<label class="label cursor-pointer justify-start gap-3 py-1">
|
|
<input type="radio"
|
|
name="pointsRenderingMode"
|
|
value="simplified"
|
|
class="radio radio-primary radio-sm" />
|
|
<span class="label-text">Simplified (reduced points)</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Speed-Colored Routes -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
name="speedColoredRoutes"
|
|
class="toggle toggle-primary" />
|
|
<span class="label-text font-medium">Speed-Colored Routes</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 mt-1">Color routes by speed</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Live Mode -->
|
|
<div class="form-control">
|
|
<label class="label cursor-pointer justify-start gap-3">
|
|
<input type="checkbox"
|
|
class="toggle toggle-primary"
|
|
data-action="change->maps-v2-realtime#toggleLiveMode"
|
|
data-maps-v2-realtime-target="liveModeToggle" />
|
|
<span class="label-text font-medium">Live Mode</span>
|
|
</label>
|
|
<p class="text-sm text-base-content/60 mt-1">Show new points in real-time</p>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Update Button -->
|
|
<button type="submit" class="btn btn-sm btn-primary btn-block">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
|
|
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
|
|
<polyline points="12 2 12 12 14.5 14.5"></polyline>
|
|
</svg>
|
|
Apply Settings
|
|
</button>
|
|
|
|
<!-- Reset Settings -->
|
|
<button type="button"
|
|
class="btn btn-sm btn-outline btn-block"
|
|
data-action="click->maps-v2#resetSettings">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
|
|
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
|
|
<path d="M21 3v5h-5"></path>
|
|
<path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path>
|
|
<path d="M3 21v-5h5"></path>
|
|
</svg>
|
|
Reset to Defaults
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Tools Tab -->
|
|
<div class="tab-content" data-tab-content="tools" data-map-panel-target="tabContent">
|
|
<div class="space-y-4">
|
|
<!-- Tools Grid: 2 columns on md+ screens, 1 column on smaller screens -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
|
<!-- Create a Visit Button -->
|
|
<button type="button"
|
|
class="btn btn-sm btn-primary"
|
|
data-action="click->maps-v2#startCreateVisit">
|
|
<%= icon 'map-pin-plus' %>
|
|
Create a Visit
|
|
</button>
|
|
|
|
<!-- Create a Place Button -->
|
|
<button type="button"
|
|
class="btn btn-sm btn-outline"
|
|
data-action="click->maps-v2#startCreatePlace">
|
|
<%= icon 'map-pin-plus' %>
|
|
Create a Place
|
|
</button>
|
|
|
|
<!-- Select Area Button -->
|
|
<button type="button"
|
|
class="btn btn-sm btn-outline"
|
|
data-maps-v2-target="selectAreaButton"
|
|
data-action="click->maps-v2#startSelectArea">
|
|
<%= icon 'square-dashed-mouse-pointer' %>
|
|
Select Area
|
|
</button>
|
|
|
|
<!-- Create Area Button -->
|
|
<button type="button"
|
|
class="btn btn-sm btn-outline"
|
|
data-action="click->maps-v2#startCreateArea">
|
|
<%= icon 'circle-plus' %>
|
|
Create an Area
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Selection Actions (shown after area is selected) -->
|
|
<div class="hidden mt-4 space-y-2" data-maps-v2-target="selectionActions">
|
|
<button type="button"
|
|
class="btn btn-sm btn-outline btn-error btn-block"
|
|
data-action="click->maps-v2#deleteSelectedPoints"
|
|
data-maps-v2-target="deletePointsButton">
|
|
<%= icon 'trash-2' %>
|
|
<span data-maps-v2-target="deleteButtonText">Delete Selected Points</span>
|
|
</button>
|
|
|
|
<!-- Selected Visits Container -->
|
|
<div class="hidden mt-4 max-h-full overflow-y-auto" data-maps-v2-target="selectedVisitsContainer">
|
|
<!-- Visit cards will be dynamically inserted here -->
|
|
</div>
|
|
|
|
<!-- Bulk Actions for Visits -->
|
|
<div class="hidden" data-maps-v2-target="selectedVisitsBulkActions">
|
|
<!-- Bulk action buttons will be dynamically inserted here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<% if !DawarichSettings.self_hosted? %>
|
|
<!-- Links Tab -->
|
|
<div class="tab-content" data-tab-content="links" data-map-panel-target="tabContent">
|
|
<div class="space-y-6">
|
|
<!-- Community Section -->
|
|
<div>
|
|
<h4 class="font-semibold text-base mb-3">Community</h4>
|
|
<div class="flex flex-col gap-2">
|
|
<a href="https://discord.gg/pHsBjpt5J8" target="_blank" class="link-hover text-sm">Discord</a>
|
|
<a href="https://x.com/freymakesstuff" target="_blank" class="link-hover text-sm">X</a>
|
|
<a href="https://github.com/Freika/dawarich" target="_blank" class="link-hover text-sm">Github</a>
|
|
<a href="https://mastodon.social/@dawarich" target="_blank" class="link-hover text-sm">Mastodon</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- Docs Section -->
|
|
<div>
|
|
<h4 class="font-semibold text-base mb-3">Docs</h4>
|
|
<div class="flex flex-col gap-2">
|
|
<a href="https://dawarich.app/docs/intro" target="_blank" class="link-hover text-sm">Tutorial</a>
|
|
<a href="https://dawarich.app/docs/tutorials/import-existing-data" target="_blank" class="link-hover text-sm">Import existing data</a>
|
|
<a href="https://dawarich.app/docs/tutorials/export-your-data" target="_blank" class="link-hover text-sm">Exporting data</a>
|
|
<a href="https://dawarich.app/docs/FAQ" target="_blank" class="link-hover text-sm">FAQ</a>
|
|
<a href="https://dawarich.app/contact" target="_blank" class="link-hover text-sm">Contact</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<!-- More Section -->
|
|
<div>
|
|
<h4 class="font-semibold text-base mb-3">More</h4>
|
|
<div class="flex flex-col gap-2">
|
|
<a href="https://dawarich.app/privacy-policy" target="_blank" class="link-hover text-sm">Privacy policy</a>
|
|
<a href="https://dawarich.app/terms-and-conditions" target="_blank" class="link-hover text-sm">Terms and Conditions</a>
|
|
<a href="https://dawarich.app/refund-policy" target="_blank" class="link-hover text-sm">Refund policy</a>
|
|
<a href="https://dawarich.app/impressum" target="_blank" class="link-hover text-sm">Impressum</a>
|
|
<a href="https://dawarich.app/blog" target="_blank" class="link-hover text-sm">Blog</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.map-control-panel {
|
|
position: absolute;
|
|
top: 0;
|
|
right: -480px; /* Hidden by default */
|
|
width: 480px;
|
|
height: 100%;
|
|
background: oklch(var(--b1));
|
|
box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);
|
|
z-index: 9999;
|
|
transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
display: flex;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.map-control-panel.open {
|
|
right: 0;
|
|
}
|
|
|
|
/* Vertical Tab Bar */
|
|
.panel-tabs {
|
|
width: 64px;
|
|
background: oklch(var(--b2));
|
|
border-right: 1px solid oklch(var(--bc) / 0.1);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 16px 0;
|
|
gap: 8px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.tab-btn {
|
|
width: 48px;
|
|
height: 48px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 8px;
|
|
border: none;
|
|
background: transparent;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
position: relative;
|
|
color: oklch(var(--bc) / 0.6);
|
|
}
|
|
|
|
.tab-btn:hover {
|
|
background: oklch(var(--b3));
|
|
color: oklch(var(--bc));
|
|
}
|
|
|
|
.tab-btn.active {
|
|
background: oklch(var(--p));
|
|
color: oklch(var(--pc));
|
|
}
|
|
|
|
.tab-btn.active::after {
|
|
content: '';
|
|
position: absolute;
|
|
right: -1px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 3px;
|
|
height: 24px;
|
|
background: oklch(var(--p));
|
|
border-radius: 2px 0 0 2px;
|
|
}
|
|
|
|
.tab-icon {
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
|
|
/* Panel Content */
|
|
.panel-content {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
min-width: 0;
|
|
}
|
|
|
|
.panel-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 20px 24px;
|
|
border-bottom: 1px solid oklch(var(--bc) / 0.1);
|
|
background: oklch(var(--b1));
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.panel-title {
|
|
font-size: 1.25rem;
|
|
font-weight: 600;
|
|
margin: 0;
|
|
color: oklch(var(--bc));
|
|
}
|
|
|
|
.panel-body {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 24px;
|
|
}
|
|
|
|
/* Tab Content */
|
|
.tab-content {
|
|
display: none;
|
|
}
|
|
|
|
.tab-content.active {
|
|
display: block;
|
|
}
|
|
|
|
/* Custom Scrollbar */
|
|
.panel-body::-webkit-scrollbar {
|
|
width: 8px;
|
|
}
|
|
|
|
.panel-body::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.panel-body::-webkit-scrollbar-thumb {
|
|
background: oklch(var(--bc) / 0.2);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.panel-body::-webkit-scrollbar-thumb:hover {
|
|
background: oklch(var(--bc) / 0.3);
|
|
}
|
|
|
|
/* Toggle Focus State - Remove all focus indicators */
|
|
.toggle:focus,
|
|
.toggle:focus-visible,
|
|
.toggle:focus-within {
|
|
outline: none !important;
|
|
box-shadow: none !important;
|
|
border-color: inherit !important;
|
|
}
|
|
|
|
/* Override DaisyUI toggle focus styles */
|
|
.toggle:focus-visible:checked,
|
|
.toggle:checked:focus,
|
|
.toggle:checked:focus-visible {
|
|
outline: none !important;
|
|
box-shadow: none !important;
|
|
}
|
|
|
|
/* Ensure no outline on the toggle container */
|
|
.form-control .toggle:focus {
|
|
outline: none !important;
|
|
}
|
|
|
|
/* Prevent indeterminate visual state on toggles */
|
|
.toggle:indeterminate {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Ensure smooth toggle transitions without intermediate states */
|
|
.toggle {
|
|
transition: background-color 0.2s ease, border-color 0.2s ease;
|
|
}
|
|
|
|
.toggle:checked {
|
|
transition: background-color 0.2s ease, border-color 0.2s ease;
|
|
}
|
|
|
|
/* Remove any active/pressed state that might cause intermediate appearance */
|
|
.toggle:active,
|
|
.toggle:active:focus {
|
|
outline: none !important;
|
|
box-shadow: none !important;
|
|
}
|
|
|
|
/* Responsive Breakpoints */
|
|
|
|
/* Large tablets and smaller desktops (1024px - 1280px) */
|
|
@media (max-width: 1280px) {
|
|
.map-control-panel {
|
|
width: 420px;
|
|
right: -420px;
|
|
}
|
|
}
|
|
|
|
/* Tablets (768px - 1024px) */
|
|
@media (max-width: 1024px) {
|
|
.map-control-panel {
|
|
width: 380px;
|
|
right: -380px;
|
|
}
|
|
|
|
.panel-body {
|
|
padding: 20px;
|
|
}
|
|
}
|
|
|
|
/* Small tablets and large phones (640px - 768px) */
|
|
@media (max-width: 768px) {
|
|
.map-control-panel {
|
|
width: 90%;
|
|
right: -90%;
|
|
max-width: 400px;
|
|
}
|
|
|
|
.panel-header {
|
|
padding: 16px 20px;
|
|
}
|
|
|
|
.panel-title {
|
|
font-size: 1.125rem;
|
|
}
|
|
|
|
.panel-body {
|
|
padding: 16px 20px;
|
|
}
|
|
}
|
|
|
|
/* Mobile phones (< 640px) */
|
|
@media (max-width: 640px) {
|
|
.map-control-panel {
|
|
width: 100%;
|
|
right: -100%;
|
|
max-width: none;
|
|
}
|
|
|
|
.panel-tabs {
|
|
width: 56px;
|
|
padding: 12px 0;
|
|
gap: 6px;
|
|
}
|
|
|
|
.tab-btn {
|
|
width: 44px;
|
|
height: 44px;
|
|
}
|
|
|
|
.tab-icon {
|
|
width: 20px;
|
|
height: 20px;
|
|
}
|
|
|
|
.panel-header {
|
|
padding: 14px 16px;
|
|
}
|
|
|
|
.panel-title {
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.panel-body {
|
|
padding: 16px;
|
|
}
|
|
|
|
/* Reduce spacing on mobile */
|
|
.space-y-4 > * + * {
|
|
margin-top: 0.75rem;
|
|
}
|
|
|
|
.space-y-6 > * + * {
|
|
margin-top: 1rem;
|
|
}
|
|
}
|
|
|
|
/* Very small phones (< 375px) */
|
|
@media (max-width: 375px) {
|
|
.panel-tabs {
|
|
width: 52px;
|
|
padding: 10px 0;
|
|
}
|
|
|
|
.tab-btn {
|
|
width: 40px;
|
|
height: 40px;
|
|
}
|
|
|
|
.panel-header {
|
|
padding: 12px;
|
|
}
|
|
|
|
.panel-body {
|
|
padding: 12px;
|
|
}
|
|
}
|
|
</style>
|