mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-09-10 09:35:39 +00:00
24bf48d391
Introduced a new pagination feature allowing users to select the number of devices displayed per page. Added a context menu for device actions, enhancing user interaction with device management. Updated the CSS for better layout and usability, including a floating horizontal scrollbar for improved navigation. This update aims to streamline the device management experience.
204 lines
12 KiB
HTML
204 lines
12 KiB
HTML
<%- include('layouts/main', {
|
|
title: _('nav.devices'),
|
|
pageStyles: ['devices', 'device-detail'],
|
|
pageScripts: ['devices', 'deviceDetail'],
|
|
currentPage: 'devices',
|
|
breadcrumb: [{ label: _('nav.devices') }],
|
|
body: `
|
|
<div class="devices-page">
|
|
<!-- Header -->
|
|
<div class="devices-header">
|
|
<div class="devices-title">
|
|
<h1>${_('devices.title')}</h1>
|
|
<span class="devices-count" id="devices-count">0</span>
|
|
</div>
|
|
<div class="devices-actions">
|
|
<button class="btn btn-secondary btn-sm" id="sync-btn">
|
|
<span class="material-icons">sync</span>
|
|
<span class="btn-label">${_('devices.sync_status')}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Folder Tiles -->
|
|
<div class="folders-bar" id="folders-bar">
|
|
<div class="folders-chips" id="folders-chips">
|
|
<button class="folder-chip active" data-folder="all">
|
|
<span class="material-icons chip-icon">devices</span>
|
|
<span class="chip-label">${_('folders.all_devices')}</span>
|
|
<span class="chip-count" id="folder-count-all">0</span>
|
|
</button>
|
|
<button class="folder-chip" data-folder="unassigned">
|
|
<span class="material-icons chip-icon">folder_off</span>
|
|
<span class="chip-label">${_('folders.unassigned')}</span>
|
|
<span class="chip-count" id="folder-count-unassigned">0</span>
|
|
</button>
|
|
<span id="custom-folders"></span>
|
|
<button class="folder-chip chip-add" id="add-folder-btn" title="${_('folders.create')}">
|
|
<span class="material-icons">add</span>
|
|
<span class="chip-label">${_('folders.create')}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Device Group Tiles -->
|
|
<div class="groups-bar" id="groups-bar">
|
|
<div class="groups-chips" id="groups-chips">
|
|
<button class="group-chip active" data-group="all">
|
|
<span class="material-icons chip-icon">hub</span>
|
|
<span class="chip-label">${_('devices.all_groups')}</span>
|
|
<span class="chip-count" id="group-count-all">0</span>
|
|
</button>
|
|
<span id="custom-device-groups"></span>
|
|
<button class="group-chip chip-add" id="add-device-group-btn" title="${_('devices.create_group')}">
|
|
<span class="material-icons">add</span>
|
|
<span class="chip-label">${_('devices.create_group')}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Toolbar -->
|
|
<div class="devices-toolbar">
|
|
<div class="toolbar-search search-wrapper">
|
|
<span class="material-icons">search</span>
|
|
<input type="text" class="form-input" id="search-input"
|
|
placeholder="${_('devices.search_placeholder')}">
|
|
</div>
|
|
<div class="toolbar-filters">
|
|
<button class="filter-btn active" data-filter="all">${_('devices.filter_all')}</button>
|
|
<button class="filter-btn" data-filter="online">${_('devices.filter_online')}</button>
|
|
<button class="filter-btn" data-filter="offline">${_('devices.filter_offline')}</button>
|
|
<button class="filter-btn" data-filter="banned">${_('devices.filter_banned')}</button>
|
|
</div>
|
|
<div class="tag-filter-dropdown">
|
|
<button class="btn-icon toolbar-icon" id="tags-filter-btn" title="${_('devices.filter_by_tags')}">
|
|
<span class="material-icons">sell</span>
|
|
</button>
|
|
<div class="tag-filter-menu" id="tags-filter-menu">
|
|
<div class="tag-filter-empty">${_('devices.no_tags')}</div>
|
|
</div>
|
|
</div>
|
|
<div class="column-visibility-dropdown">
|
|
<button class="btn-icon toolbar-icon" id="columns-btn" title="${_('devices.toggle_columns')}">
|
|
<span class="material-icons">view_column</span>
|
|
</button>
|
|
<div class="column-visibility-menu" id="columns-menu">
|
|
<label class="column-toggle">
|
|
<input type="checkbox" data-column="device_type" checked>
|
|
<span>${_('devices.device_type')}</span>
|
|
</label>
|
|
<label class="column-toggle">
|
|
<input type="checkbox" data-column="platform" checked>
|
|
<span>${_('devices.platform')}</span>
|
|
</label>
|
|
<label class="column-toggle">
|
|
<input type="checkbox" data-column="last_online" checked>
|
|
<span>${_('devices.last_seen')}</span>
|
|
</label>
|
|
<label class="column-toggle">
|
|
<input type="checkbox" data-column="status" checked>
|
|
<span>${_('devices.status')}</span>
|
|
</label>
|
|
<label class="column-toggle">
|
|
<input type="checkbox" data-column="tags" checked>
|
|
<span>${_('devices.tags')}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Table -->
|
|
<div class="devices-table-container">
|
|
<div class="devices-table-scroll" id="devices-table-scroll">
|
|
<table class="devices-table" id="devices-table">
|
|
<thead>
|
|
<tr>
|
|
<th class="sortable" data-sort="id" data-column="id">${_('devices.id')}</th>
|
|
<th class="sortable" data-sort="hostname" data-column="hostname">${_('devices.hostname')}</th>
|
|
<th class="sortable" data-sort="device_type" data-column="device_type">${_('devices.device_type')}</th>
|
|
<th class="sortable" data-sort="platform" data-column="platform">${_('devices.platform')}</th>
|
|
<th class="sortable" data-sort="last_online" data-column="last_online">${_('devices.last_seen')}</th>
|
|
<th data-column="status">${_('devices.status')}</th>
|
|
<th data-column="tags">${_('devices.tags')}</th>
|
|
<th class="col-actions" data-column="actions"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="devices-tbody">
|
|
<tr class="loading-row">
|
|
<td colspan=\"8\" style=\"text-align: center; padding: 40px;\">
|
|
<span class="skeleton skeleton-text" style="width: 200px;"></span>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="devices-pagination" id="pagination">
|
|
<div class="pagination-info">
|
|
<span id="pagination-info">${_('devices.showing')} 0-0 ${_('devices.of')} 0</span>
|
|
</div>
|
|
<div class="pagination-per-page">
|
|
<label for="per-page-select">${_('devices.per_page')}</label>
|
|
<select id="per-page-select" class="pagination-per-page-select" aria-label="${_('devices.per_page')}">
|
|
<option value="10">10</option>
|
|
<option value="20" selected>20</option>
|
|
<option value="50">50</option>
|
|
<option value="100">100</option>
|
|
</select>
|
|
</div>
|
|
<div class="pagination-controls" id="pagination-controls"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Shared context menu (devices, folders, groups) -->
|
|
<div class="devices-context-menu" id="devices-context-menu" role="menu" hidden> </div>
|
|
|
|
<!-- Floating horizontal scrollbar (fixed to visible content area) -->
|
|
<div class="devices-hscroll-float" id="devices-hscroll-float" aria-hidden="true">
|
|
<div class="devices-hscroll-spacer" id="devices-hscroll-spacer"></div>
|
|
</div>
|
|
|
|
<!-- Empty state -->
|
|
<div class="devices-empty hidden" id="devices-empty">
|
|
<span class="material-icons devices-empty-icon">devices_other</span>
|
|
<h3 class="devices-empty-title">${_('devices.empty_title')}</h3>
|
|
<p class="devices-empty-text">${_('devices.empty_text')}</p>
|
|
</div>
|
|
|
|
<!-- Kebab overlay for mobile bottom sheet -->
|
|
<div class="kebab-overlay" id="kebab-overlay"></div>
|
|
</div>
|
|
|
|
<!-- Folder Form Template -->
|
|
<template id="folder-form-template">
|
|
<form id="folder-form" class="folder-form">
|
|
<div class="form-group">
|
|
<label for="folder-name">${_('folders.name')}</label>
|
|
<input type="text" id="folder-name" name="name" class="form-input"
|
|
maxlength="50" required placeholder="${_('folders.name_placeholder')}">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>${_('folders.color')}</label>
|
|
<div class="color-picker" id="folder-color-picker">
|
|
<button type="button" class="color-option active" data-color="#6366f1" style="background:#6366f1"></button>
|
|
<button type="button" class="color-option" data-color="#22c55e" style="background:#22c55e"></button>
|
|
<button type="button" class="color-option" data-color="#f59e0b" style="background:#f59e0b"></button>
|
|
<button type="button" class="color-option" data-color="#ef4444" style="background:#ef4444"></button>
|
|
<button type="button" class="color-option" data-color="#8b5cf6" style="background:#8b5cf6"></button>
|
|
<button type="button" class="color-option" data-color="#06b6d4" style="background:#06b6d4"></button>
|
|
<button type="button" class="color-option" data-color="#ec4899" style="background:#ec4899"></button>
|
|
<button type="button" class="color-option" data-color="#64748b" style="background:#64748b"></button>
|
|
</div>
|
|
<input type="hidden" id="folder-color" name="color" value="#6366f1">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="folder-allowed-users">${_('devices.group_allowed_users')}</label>
|
|
<input type="text" id="folder-allowed-users" name="allowed_users" class="form-input"
|
|
placeholder="operator1, operator2">
|
|
<p class="form-hint">${_('devices.group_allowed_users_hint')}</p>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
`
|
|
}) %>
|