Add phần create map by upload
Some checks failed
Test / test (push) Has been cancelled

This commit is contained in:
2026-06-19 11:52:21 +07:00
parent 098e1b2b69
commit a6cf06d7eb
27 changed files with 4960 additions and 129 deletions

View File

@@ -326,13 +326,49 @@
</div>
<div id="dashboardDesignerView" class="dashboardDesignerView" hidden>
<header class="dashboardDesignerHeader">
<button id="dashboardBackToListBtn" type="button" class="btn subtle dashboardBackBtn" data-i18n="dashboard.list.back">← Danh sách</button>
<h2 id="dashboardDesignerTitle" class="dashboardDesignerTitle"></h2>
<header class="dashboardMirDesignerBar">
<button id="dashboardBackToListBtn" type="button" class="dashboardMirBarBtn dashboardMirBarBtn--back" data-i18n="dashboard.list.back">← Danh sách</button>
<h2 id="dashboardDesignerTitle" class="dashboardMirDesignerTitle"></h2>
<div class="dashboardMirDesignerBarActions">
<button id="dashboardSaveBtn" type="button" class="dashboardMirSaveBtn" hidden data-i18n="dashboard.designer.save">Lưu</button>
<button id="dashboardEditModeBtn" type="button" class="dashboardMirBarBtn dashboardMirBarBtn--edit" hidden data-i18n="dashboard.editLayout">Sửa layout</button>
</div>
</header>
<div class="dashboardDesignerBody">
<div id="dashboardGrid" class="dashboardGrid"></div>
<p id="dashboardDesignerEmpty" class="mutedNote dashboardDesignerEmpty" data-i18n="dashboard.designer.empty">Chưa có widget. Phase B sẽ thêm designer đầy đủ.</p>
<nav id="dashboardDesignerToolbar" class="dashboardMirWidgetBar" hidden aria-label="Widget menus">
<div class="dashboardMirWidgetTabs" role="tablist">
<button type="button" class="dashboardMirWidgetTab" role="tab" data-widget-tab="maps" data-i18n="dashboard.menu.maps">Maps</button>
<button type="button" class="dashboardMirWidgetTab is-active" role="tab" data-widget-tab="missions" data-i18n="dashboard.menu.missions">Missions</button>
<button type="button" class="dashboardMirWidgetTab" role="tab" data-widget-tab="plc" data-i18n="dashboard.menu.plc">PLC Registers</button>
<button type="button" class="dashboardMirWidgetTab" role="tab" data-widget-tab="io" data-i18n="dashboard.menu.io">I/O</button>
<button type="button" class="dashboardMirWidgetTab" role="tab" data-widget-tab="misc" data-i18n="dashboard.menu.misc">Miscellaneous</button>
</div>
<div class="dashboardMirWidgetPanels">
<div class="dashboardMirWidgetPanel" data-panel="maps" hidden>
<button type="button" class="dashboardMirWidgetPick" data-add-widget="map_locked" data-i18n="dashboard.widget.map_locked">Locked map</button>
<button type="button" class="dashboardMirWidgetPick" data-add-widget="map" data-i18n="dashboard.widget.map">Map</button>
</div>
<div class="dashboardMirWidgetPanel" data-panel="missions">
<button type="button" class="dashboardMirWidgetPick" data-add-widget="mission_button" data-i18n="dashboard.widget.mission_button">Mission button</button>
<button type="button" class="dashboardMirWidgetPick" data-add-widget="mission_group" data-i18n="dashboard.widget.mission_group">Mission group</button>
<button type="button" class="dashboardMirWidgetPick" data-add-widget="mission_queue" data-i18n="dashboard.widget.mission_queue">Mission queue</button>
<button type="button" class="dashboardMirWidgetPick" data-add-widget="pause_continue" data-i18n="dashboard.widget.pause_continue">Pause / Continue</button>
<button type="button" class="dashboardMirWidgetPick" data-add-widget="mission_action_log" data-i18n="dashboard.widget.mission_action_log">Mission action log</button>
</div>
<div class="dashboardMirWidgetPanel" data-panel="plc" hidden>
<p class="dashboardMirWidgetPanelNote" data-i18n="dashboard.menu.comingSoon">Widget nhóm này sẽ có trong bản cập nhật sau.</p>
</div>
<div class="dashboardMirWidgetPanel" data-panel="io" hidden>
<p class="dashboardMirWidgetPanelNote" data-i18n="dashboard.menu.comingSoon">I/O widgets — sắp có.</p>
</div>
<div class="dashboardMirWidgetPanel" data-panel="misc" hidden>
<button type="button" class="dashboardMirWidgetPick" data-add-widget="robot_summary" data-i18n="dashboard.widget.robot_summary">Robot summary</button>
<button type="button" class="dashboardMirWidgetPick" data-add-widget="logout_button" data-i18n="dashboard.widget.logout_button">Log-out button</button>
</div>
</div>
</nav>
<div class="dashboardMirCanvasWrap">
<div id="dashboardGrid" class="dashboardGrid dashboardMirGrid"></div>
<p id="dashboardDesignerEmpty" class="dashboardMirCanvasEmpty" data-i18n="dashboard.designer.empty">Chưa có widget trên dashboard này.</p>
</div>
</div>
</div>
@@ -827,6 +863,331 @@
</div>
</div>
<div class="page" id="pageMaps" data-page-content="maps" hidden>
<div id="mapsListView" class="mapsMirPage">
<header class="mapsMirHeader">
<div class="mapsMirHeaderText">
<h1 class="mapsMirTitle" data-i18n="maps.title">Maps</h1>
<p class="mapsMirSubtitle">
<span data-i18n="maps.subtitle">Create and edit maps.</span>
<button type="button" class="mapsMirHelpBtn" id="mapsHelpBtn" data-i18n-title="maps.helpTitle" aria-label="Help">
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="7" fill="none" stroke="currentColor" stroke-width="1.5"/><text x="8" y="11.5" text-anchor="middle" font-size="10" font-weight="700" fill="currentColor">?</text></svg>
</button>
</p>
</div>
<div class="mapsMirHeaderActions">
<button type="button" class="mapsMirBtn mapsMirBtn--green" id="mapsCreateOpenBtn">
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M7 1v12M1 7h12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<span data-i18n="maps.create">Create map</span>
</button>
<button type="button" class="mapsMirBtn mapsMirBtn--green" id="mapsImportSiteBtn">
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 2v8M5 7l3 3 3-3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M3 12h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
<span data-i18n="maps.importSite">Import site</span>
</button>
<button type="button" class="mapsMirBtn mapsMirBtn--outline" id="mapsClearFiltersBtn">
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><circle cx="7" cy="7" r="5.5" fill="none" stroke="currentColor" stroke-width="1.3"/><path d="M4.5 4.5l5 5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
<span data-i18n="maps.clearFilters">Clear filters</span>
</button>
</div>
</header>
<div id="mapsActiveHint" class="mapsMirActiveHint" hidden></div>
<div class="mapsMirFilterBar">
<label class="mapsMirFilterLabel" for="mapsFilterInput" data-i18n="maps.filterLabel">Filter:</label>
<input type="search" id="mapsFilterInput" class="mapsMirFilterInput" data-i18n-placeholder="maps.filterPlaceholder" placeholder="Write name to filter by..." autocomplete="off" />
<span id="mapsFilterCount" class="mapsMirFilterCount">0 item(s) found</span>
<div class="mapsMirPager">
<button type="button" class="mapsMirPageBtn" id="mapsPageFirst" aria-label="First page">&laquo;</button>
<button type="button" class="mapsMirPageBtn" id="mapsPagePrev" aria-label="Previous page">&lsaquo;</button>
<span id="mapsPageLabel" class="mapsMirPageLabel">Page 1 of 1</span>
<button type="button" class="mapsMirPageBtn" id="mapsPageNext" aria-label="Next page">&rsaquo;</button>
<button type="button" class="mapsMirPageBtn" id="mapsPageLast" aria-label="Last page">&raquo;</button>
</div>
</div>
<div class="mapsMirTableWrap">
<table class="mapsMirTable" id="mapsTable">
<thead>
<tr>
<th data-i18n="maps.colName">Name</th>
<th data-i18n="maps.colCreatedBy">Created by</th>
<th class="mapsMirThFunctions" data-i18n="maps.colFunctions">Functions</th>
</tr>
</thead>
<tbody id="mapsList"></tbody>
</table>
<div id="mapsListEmpty" class="mapsMirEmpty" hidden></div>
</div>
</div>
<div id="mapsCreateView" class="mapsMirCreatePage" hidden>
<header class="mapsMirCreateHeader">
<div class="mapsMirCreateHeaderIntro">
<h1 class="mapsMirCreateTitle" data-i18n="maps.createPage.title">Create map</h1>
<p class="mapsMirCreateSubtitle">
<span data-i18n="maps.createPage.subtitle">Create a new map.</span>
<button type="button" class="mapsMirHelpBtn" id="mapsCreateHelpBtn" data-i18n-title="maps.helpTitle" aria-label="Help">
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="7" fill="none" stroke="currentColor" stroke-width="1.5"/><text x="8" y="11.5" text-anchor="middle" font-size="10" font-weight="700" fill="currentColor">?</text></svg>
</button>
</p>
</div>
<button type="button" class="mapsMirGoBackBtn" id="mapsCreateGoBackBtn">
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M9 3L5 7l4 4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
<span data-i18n="maps.createPage.goBack">Go back</span>
</button>
</header>
<form id="mapsCreateForm" class="mapsMirCreateForm">
<div class="mapsMirCreatePanel">
<label class="mapsMirCreateField" for="mapsCreateName">
<span class="mapsMirCreateFieldLabel">
<span data-i18n="maps.createPage.name">Name</span>
<button type="button" class="mapsMirFieldHelpBtn" tabindex="-1" data-i18n-title="maps.createPage.nameHelp" title="Help">?</button>
</span>
<input type="text" id="mapsCreateName" required autocomplete="off" data-i18n-placeholder="maps.createPage.namePlaceholder" placeholder="Enter the map's name..." />
</label>
<div class="mapsMirCreateField">
<span class="mapsMirCreateFieldLabel">
<span data-i18n="maps.createPage.site">Site</span>
<button type="button" class="mapsMirFieldHelpBtn" tabindex="-1" data-i18n-title="maps.createPage.siteHelp" title="Help">?</button>
</span>
<div class="mapsMirSitePicker">
<select id="mapsCreateSite" required></select>
<button type="button" class="mapsMirSiteManageBtn" id="mapsCreateSiteBtn" data-i18n="maps.createPage.siteManage">Create / Edit</button>
</div>
</div>
<div class="mapsMirCreateActions">
<button type="submit" class="mapsMirCreateSubmitBtn">
<span class="mapsMirCircleIcon mapsMirCircleIcon--ok" aria-hidden="true"></span>
<span data-i18n="maps.createPage.submit">Create map</span>
</button>
<button type="button" class="mapsMirCreateCancelBtn" id="mapsCreateCancelBtn">
<span class="mapsMirCircleIcon" aria-hidden="true"></span>
<span data-i18n="maps.createPage.cancel">Cancel</span>
</button>
</div>
</div>
</form>
</div>
<div id="mapEditorView" class="mapEditorPage" hidden>
<header class="mapEditorHeader">
<div class="mapEditorHeaderIntro">
<div class="mapEditorTitleRow">
<h1 class="mapEditorTitle" id="mapEditorTitle"></h1>
<button type="button" class="mapEditorGearBtn" id="mapEditorSettingsBtn" data-i18n-title="maps.editor.settings" aria-label="Settings">
<svg width="18" height="18" viewBox="0 0 18 18" aria-hidden="true"><circle cx="9" cy="9" r="2.5" fill="none" stroke="currentColor" stroke-width="1.3"/><path d="M9 1.5v2M9 14.5v2M1.5 9h2M14.5 9h2M3.4 3.4l1.4 1.4M13.2 13.2l1.4 1.4M3.4 14.6l1.4-1.4M13.2 4.8l1.4-1.4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
</button>
<span id="mapEditorDirty" class="mapEditorDirtyBadge" hidden data-i18n="maps.editor.unsaved">Unsaved</span>
</div>
<p class="mapEditorSubtitle">
<span data-i18n="maps.editor.subtitle">Edit and draw the map.</span>
<button type="button" class="mapsMirHelpBtn" id="mapEditorHelpBtn" data-i18n-title="maps.editor.helpTitle" aria-label="Help">
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="7" fill="none" stroke="currentColor" stroke-width="1.5"/><text x="8" y="11.5" text-anchor="middle" font-size="10" font-weight="700" fill="currentColor">?</text></svg>
</button>
</p>
</div>
<button type="button" class="mapEditorGoBackBtn" id="mapEditorBackBtn">
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M9 3L5 7l4 4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
<span data-i18n="maps.editor.goBack">Go back</span>
</button>
</header>
<div class="mapEditorMappingBar" role="toolbar" data-i18n-aria="maps.editor.toolbarAria">
<button type="button" class="mapEditorMapTool" id="mapEditorSearchBtn" disabled data-i18n-title="maps.editor.tool.search" title="Search">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><circle cx="8.5" cy="8.5" r="5.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12.5 12.5L17 17" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorMenuBtn" data-i18n-title="maps.editor.menu" title="Menu">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><circle cx="4" cy="10" r="1.6" fill="currentColor"/><circle cx="10" cy="10" r="1.6" fill="currentColor"/><circle cx="16" cy="10" r="1.6" fill="currentColor"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorUndoBtn" disabled data-i18n-title="maps.editor.undo" title="Undo">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M7 6H4v3" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M4 9a6.5 6.5 0 1 0 1.6 4.3" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorSaveBtn" disabled data-i18n-title="maps.editor.tool.save" title="Save">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M4 3h9l3 3v11H4V3z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/><path d="M6 3v5h7V3" fill="none" stroke="currentColor" stroke-width="1.2"/><rect x="6" y="12" width="8" height="5" rx="0.5" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>
</button>
<button type="button" class="mapEditorMapTool is-active" id="mapEditorPanBtn" data-tool="pan" data-i18n-title="maps.editor.tool.pan" title="Pan">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2.5v15M2.5 10h15" stroke="currentColor" stroke-width="1.2"/><path d="M10 2.5L8 5.5h4L10 2.5zM10 17.5l-2-3h4l-2 3zM2.5 10l3-2v4l-3-2zM17.5 10l-3-2v4l3-2z" fill="currentColor"/></svg>
</button>
<div class="mapEditorMappingBarSpacer" aria-hidden="true"></div>
<select class="mapEditorObjectSelect" id="mapEditorObjectSelect" disabled>
<option value="" data-i18n="maps.editor.objectTypesNone">No object-type selected</option>
</select>
<button type="button" class="mapEditorMapTool" id="mapEditorCrosshairBtn" disabled data-i18n-title="maps.editor.tool.crosshair" title="Crosshair">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><circle cx="10" cy="10" r="6" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M10 4v12M4 10h12" stroke="currentColor" stroke-width="1.3"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorFitBtn" data-i18n-title="maps.editor.fit" title="Fit">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M3 7V3h4M13 3h4v4M17 13h-4v4M7 17H3v-4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorCenterBtn" data-i18n-title="maps.editor.tool.center" title="Center">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M8 3v3H3M12 3h5v5M17 12h-5v5M3 12h5v5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorLidarBtn" disabled data-i18n-title="maps.editor.tool.lidar" title="LiDAR">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M3.5 14a6.5 6.5 0 0 1 13 0" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M10 14V7M6.5 12.5L10 7l3.5 5.5M4.5 11l5.5-4 5.5 4" stroke="currentColor" stroke-width="1.1" stroke-linecap="round"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorWaypointsBtn" disabled data-i18n-title="maps.editor.tool.waypoints" title="Positions">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 3v14" stroke="currentColor" stroke-width="1.3"/><path d="M10 4l4 2.5-1.2 2.4L10 8.2 7.2 8.9 6 6.5 10 4z" fill="currentColor"/><path d="M10 9l4 2.5-1.2 2.4L10 13.2 7.2 13.9 6 11.5 10 9z" fill="currentColor"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorZoomInBtn" data-i18n-title="maps.editor.zoomIn" title="Zoom in">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><circle cx="8.5" cy="8.5" r="5.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12.5 12.5L17 17M8.5 6v5M6 8.5h5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
</button>
<button type="button" class="mapEditorMapTool" id="mapEditorZoomOutBtn" data-i18n-title="maps.editor.zoomOut" title="Zoom out">
<svg width="20" height="20" viewBox="0 0 20 20" aria-hidden="true"><circle cx="8.5" cy="8.5" r="5.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12.5 12.5L17 17M6 8.5h5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
</button>
</div>
<div class="mapEditorCanvasWrap" id="mapEditorCanvasWrap">
<div class="mapEditorCanvasTip" id="mapEditorCanvasTip" role="status" data-i18n="maps.editor.canvasTip">Drag the map to move your view or use the zoom-in and -out buttons to zoom.</div>
<div class="mapEditorViewport">
<div class="mapEditorCanvasInner" id="mapEditorCanvasInner">
<div class="mapEditorSheet" id="mapEditorSheet">
<img id="mapEditorImage" class="mapEditorImage" alt="" hidden />
<div id="mapEditorEmpty" class="mapEditorEmpty" hidden data-i18n="maps.editor.noData">No map data — open ⋮ menu to upload a PNG.</div>
</div>
</div>
</div>
</div>
</div>
<dialog id="mapsSitesDialog" class="mapsMirSitesDialog">
<div class="mapsMirSitesDialogInner">
<header class="mapsMirSitesHeader">
<h2 class="mapsMirSitesTitle" data-i18n="maps.sitesDialog.title">Sites</h2>
<button type="button" class="mapsMirSitesCreateBtn" id="mapsSitesCreateBtn" data-i18n="maps.sitesDialog.createSite">Create site</button>
</header>
<p class="mapsMirSitesHelp" data-i18n="maps.sitesDialog.description">A site is a container for maps and other facility data on the robot.</p>
<div class="mapsMirSitesDivider" role="separator"></div>
<ul class="mapsMirSitesList" id="mapsSitesList" aria-label="Sites"></ul>
<div class="mapsMirSitesFooter">
<button type="button" class="mapsMirSitesOkBtn" id="mapsSitesOkBtn">
<span class="mapsMirCircleIcon mapsMirCircleIcon--ok" aria-hidden="true"></span>
<span data-i18n="common.ok">OK</span>
</button>
<button type="button" class="mapsMirSitesCancelBtn" id="mapsSitesCancelBtn">
<span data-i18n="common.cancel">Cancel</span>
</button>
</div>
</div>
</dialog>
<dialog id="mapsSiteFormDialog" class="mapsMirDialog">
<form id="mapsSiteForm" method="dialog">
<h2 class="mapsMirDialogTitle" id="mapsSiteFormTitle" data-i18n="maps.siteForm.create">Create site</h2>
<label class="mapsMirField">
<span class="mapsMirFieldLabel" data-i18n="maps.siteForm.name">Name *</span>
<input type="text" id="mapsSiteName" required autocomplete="off" />
</label>
<div class="mapsMirDialogFooter">
<button type="button" class="mapsMirBtn mapsMirBtn--outline" data-close-dialog="mapsSiteFormDialog" data-i18n="common.cancel">Cancel</button>
<button type="submit" class="mapsMirBtn mapsMirBtn--green" data-i18n="common.save">Save</button>
</div>
</form>
</dialog>
<dialog id="mapEditorMenuDialog" class="mapsMirDialog mapsMirDialog--mapMenu">
<h2 class="mapsMirDialogTitle mapsMirMapMenuTitle" data-i18n="maps.menu.title">Upload, download and record maps</h2>
<div class="mapsMirMapMenuGrid">
<button type="button" class="mapsMirMapMenuAction" id="mapMenuUploadOverwrite">
<span class="mapsMirMapMenuIcon mapsMirMapMenuIcon--file" aria-hidden="true">
<svg width="32" height="32" viewBox="0 0 32 32"><path fill="#5cae4c" d="M22.5 24H8.5a5.5 5.5 0 0 1-.9-10.9A6.5 6.5 0 0 1 23.5 14a4.5 4.5 0 0 1 .5 9.2V24z"/><path fill="#fff" d="M16 12v7.5M13.5 16.5 16 19l2.5-2.5"/><path stroke="#fff" stroke-width="2.2" stroke-linecap="round" d="M11.5 21.5 20.5 12.5"/></svg>
</span>
<span class="mapsMirMapMenuText">
<span class="mapsMirMapMenuLabel" data-i18n="maps.menu.uploadOverwrite">Upload and overwrite</span>
<span class="mapsMirMapMenuDesc" data-i18n="maps.menu.uploadOverwriteDesc">Replace existing map with uploaded map.</span>
</span>
</button>
<button type="button" class="mapsMirMapMenuAction" id="mapMenuRecordOverwrite" disabled>
<span class="mapsMirMapMenuIcon mapsMirMapMenuIcon--record" aria-hidden="true">
<svg width="32" height="32" viewBox="0 0 32 32"><circle cx="16" cy="16" r="10" fill="#d9534f"/><path stroke="#fff" stroke-width="2.5" stroke-linecap="round" d="M10.5 21.5 21.5 10.5"/></svg>
</span>
<span class="mapsMirMapMenuText">
<span class="mapsMirMapMenuLabel" data-i18n="maps.menu.recordOverwrite">Record and overwrite</span>
<span class="mapsMirMapMenuDesc" data-i18n="maps.menu.recordOverwriteDesc">Replace existing map with new recording of map.</span>
</span>
</button>
<button type="button" class="mapsMirMapMenuAction" id="mapMenuUploadAppend" disabled>
<span class="mapsMirMapMenuIcon mapsMirMapMenuIcon--file" aria-hidden="true">
<svg width="32" height="32" viewBox="0 0 32 32"><path fill="#5cae4c" d="M22.5 24H8.5a5.5 5.5 0 0 1-.9-10.9A6.5 6.5 0 0 1 23.5 14a4.5 4.5 0 0 1 .5 9.2V24z"/><path fill="#fff" d="M16 12v7.5M13.5 16.5 16 19l2.5-2.5"/></svg>
</span>
<span class="mapsMirMapMenuText">
<span class="mapsMirMapMenuLabel" data-i18n="maps.menu.uploadAppend">Upload and append</span>
<span class="mapsMirMapMenuDesc" data-i18n="maps.menu.uploadAppendDesc">Upload a new map and append it to current map.</span>
</span>
</button>
<button type="button" class="mapsMirMapMenuAction" id="mapMenuRecordAppend" disabled>
<span class="mapsMirMapMenuIcon mapsMirMapMenuIcon--record" aria-hidden="true">
<svg width="32" height="32" viewBox="0 0 32 32"><circle cx="16" cy="16" r="10" fill="#d9534f"/></svg>
</span>
<span class="mapsMirMapMenuText">
<span class="mapsMirMapMenuLabel" data-i18n="maps.menu.recordAppend">Record and append</span>
<span class="mapsMirMapMenuDesc" data-i18n="maps.menu.recordAppendDesc">Record a new map and append it to current map.</span>
</span>
</button>
<button type="button" class="mapsMirMapMenuAction" id="mapMenuDownload" disabled>
<span class="mapsMirMapMenuIcon mapsMirMapMenuIcon--file" aria-hidden="true">
<svg width="32" height="32" viewBox="0 0 32 32"><path fill="#5cae4c" d="M22.5 24H8.5a5.5 5.5 0 0 1-.9-10.9A6.5 6.5 0 0 1 23.5 14a4.5 4.5 0 0 1 .5 9.2V24z"/><path fill="#fff" d="M16 19V11.5M13.5 16.5 16 14l2.5 2.5"/></svg>
</span>
<span class="mapsMirMapMenuText">
<span class="mapsMirMapMenuLabel" data-i18n="maps.menu.download">Download map</span>
<span class="mapsMirMapMenuDesc" data-i18n="maps.menu.downloadDesc">Download the current map.</span>
</span>
</button>
</div>
<div class="mapsMirDialogFooter mapsMirMapMenuFooter">
<button type="button" class="mapsMirBtn mapsMirMapMenuCancelBtn" id="mapMenuCancelBtn" data-i18n="common.cancel">Cancel</button>
</div>
</dialog>
<dialog id="mapEditorSettingsDialog" class="mapsMirDialog">
<form id="mapEditorSettingsForm" method="dialog">
<h2 class="mapsMirDialogTitle" data-i18n="maps.settings.title">Map settings</h2>
<label class="mapsMirField">
<span class="mapsMirFieldLabel" data-i18n="maps.settings.name">Name</span>
<input type="text" id="mapSettingsName" required autocomplete="off" />
</label>
<label class="mapsMirField">
<span class="mapsMirFieldLabel" data-i18n="maps.settings.description">Description</span>
<textarea id="mapSettingsDesc" rows="2"></textarea>
</label>
<div class="mapsMirFieldRow">
<label class="mapsMirField">
<span class="mapsMirFieldLabel" data-i18n="maps.settings.resolution">Resolution (m/px)</span>
<input type="number" id="mapSettingsResolution" step="0.001" min="0.001" />
</label>
<label class="mapsMirField">
<span class="mapsMirFieldLabel" data-i18n="maps.settings.originX">Origin X</span>
<input type="number" id="mapSettingsOriginX" step="0.01" />
</label>
</div>
<div class="mapsMirFieldRow">
<label class="mapsMirField">
<span class="mapsMirFieldLabel" data-i18n="maps.settings.originY">Origin Y</span>
<input type="number" id="mapSettingsOriginY" step="0.01" />
</label>
<label class="mapsMirField">
<span class="mapsMirFieldLabel" data-i18n="maps.settings.originYaw">Origin yaw</span>
<input type="number" id="mapSettingsOriginYaw" step="0.01" />
</label>
</div>
<div class="mapsMirDialogFooter">
<button type="button" class="mapsMirBtn mapsMirBtn--outline" data-close-dialog="mapEditorSettingsDialog" data-i18n="common.cancel">Cancel</button>
<button type="submit" class="mapsMirBtn mapsMirBtn--green" data-i18n="common.apply">Apply</button>
</div>
</form>
</dialog>
<dialog id="mapActivateDialog" class="mapsMirDialog">
<h2 class="mapsMirDialogTitle" data-i18n="maps.activateDialog.title">Activate map?</h2>
<p id="mapActivateDialogText" class="mapsMirDialogText"></p>
<div class="mapsMirDialogFooter">
<button type="button" class="mapsMirBtn mapsMirBtn--outline" id="mapActivateNoBtn" data-i18n="common.no">No</button>
<button type="button" class="mapsMirBtn mapsMirBtn--green" id="mapActivateYesBtn" data-i18n="common.yes">Yes</button>
</div>
</dialog>
<input type="file" id="mapEditorUploadInput" accept="image/png,.png" hidden />
</div>
<div class="page" id="pageIntegrations" data-page-content="integrations" hidden>
<div class="integrationsPage">
<section class="card">
@@ -1123,6 +1484,8 @@ GET /api/v2.0.0/status</pre>
<option value="mission_group">Mission group</option>
<option value="mission_queue">Mission queue</option>
<option value="pause_continue">Pause / Continue</option>
<option value="mission_action_log">Mission action log</option>
<option value="logout_button">Log-out button</option>
</select>
</div>
<div id="dashboardAddWidgetFields" class="missionConfigGrid"></div>
@@ -1282,6 +1645,8 @@ GET /api/v2.0.0/status</pre>
<script src="/auth.js"></script>
<script src="/nav.js"></script>
<script src="/missions.js"></script>
<script src="/maps.js"></script>
<script src="/map-editor.js"></script>
<script src="/topbar.js"></script>
<script src="/dashboard.js"></script>
<script src="/integrations.js"></script>