feat(tgu-ui): вкладка «Слоты» — расчёт покрытия и бронирование слотов заявки
- новая вкладка: заявки интервала на карте, выбор заявки кликом/инспектором, расчёт слотов покрытия, бронирование и снятие брони - выбор заявки без выпадающего списка (не масштабируется на ~10к): все заявки на карте, панель справа с кнопкой «Выбрать», имя выбранной заявки в тулбаре, кнопка «Сброс», фильтр заявок по интервалу - бронь отмечаем по ответу POST booking/request (by-request отдаёт слот в чужом cycle-фрейме — ключ не совпадал, бейдж «бронь» не появлялся) - подсветка и автоскролл активной строки по клику на слот (ручной scrollBy) - меню выбора при плотном наложении слотов (SlotPickMenu); контур заявки pickable:false, чтобы не «съедать» меню; панель не закрывается при выборе - фильтр отображения по суткам (SlotDaySelector) - gateway: маршрут slots (/api/pcp-slots/**) - карточка полосы обзора (swath): КА и виток в инспекторе
This commit is contained in:
@@ -23,6 +23,14 @@
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.tgu-toolbar__row--range {
|
||||
min-height: 0;
|
||||
padding-top: 0.55rem;
|
||||
padding-bottom: 0.6rem;
|
||||
gap: 0.5rem;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.tgu-toolbar__brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -906,6 +914,215 @@
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* Вкладка «Слоты»: слева список слотов, справа карта. */
|
||||
.tgu-slots-body {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(22rem, 32rem) minmax(0, 1fr);
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.tgu-slots-list {
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
border-right: 1px solid var(--line);
|
||||
background: var(--bg-panel);
|
||||
}
|
||||
|
||||
.tgu-slots-empty {
|
||||
padding: 1rem;
|
||||
color: var(--text-dim);
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
/* Имя выбранной заявки в тулбаре (на месте прежнего выпадающего списка). */
|
||||
.tgu-slots-request {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tgu-slots-request__name {
|
||||
min-height: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: 18rem;
|
||||
padding: 0.38rem 0.55rem;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 6px;
|
||||
background: #101214;
|
||||
color: var(--text);
|
||||
font-size: 0.78rem;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Левая панель в режиме «заявка не выбрана»: фильтр интервала заявок + подсказка. */
|
||||
.tgu-slots-requests-panel {
|
||||
display: grid;
|
||||
gap: 0.6rem;
|
||||
padding: 0.9rem;
|
||||
}
|
||||
|
||||
/* Кнопка «Сброс» — справа над картой (поверх неё). */
|
||||
.tgu-slots-reset {
|
||||
position: absolute;
|
||||
top: 0.55rem;
|
||||
right: 0.55rem;
|
||||
z-index: 21;
|
||||
background: rgba(23, 26, 28, 0.93);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
/* Меню выбора слота при плотном наложении — плавающий список справа над картой (под «Сбросом»). */
|
||||
.tgu-slots-pick {
|
||||
position: absolute;
|
||||
top: 3rem;
|
||||
right: 0.55rem;
|
||||
z-index: 24;
|
||||
width: 22rem;
|
||||
max-width: calc(100% - 1.1rem);
|
||||
max-height: calc(100% - 3.6rem);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: rgba(23, 26, 28, 0.96);
|
||||
backdrop-filter: blur(6px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tgu-slots-pick__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 0.65rem;
|
||||
border-bottom: 1px solid var(--line);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.tgu-slots-pick__list {
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.tgu-slots-pick__item {
|
||||
display: grid;
|
||||
gap: 0.15rem;
|
||||
width: 100%;
|
||||
padding: 0.45rem 0.65rem;
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.tgu-slots-pick__item:hover {
|
||||
background: rgba(104, 195, 189, 0.1);
|
||||
}
|
||||
|
||||
.tgu-slots-pick__item.is-active {
|
||||
background: rgba(104, 195, 189, 0.22);
|
||||
box-shadow: inset 3px 0 0 var(--accent);
|
||||
}
|
||||
|
||||
.tgu-slots-pick__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tgu-slots-pick__meta {
|
||||
font-family: var(--mono);
|
||||
font-size: 0.7rem;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
/* Инспектор заявки — плавающая панель справа над картой (до выбора заявки). */
|
||||
.tgu-slots-inspector {
|
||||
position: absolute;
|
||||
top: 0.55rem;
|
||||
right: 0.55rem;
|
||||
z-index: 25;
|
||||
width: 23rem;
|
||||
max-width: calc(100% - 1.1rem);
|
||||
max-height: calc(100% - 1.1rem);
|
||||
overflow: auto;
|
||||
padding: 0.9rem;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: rgba(23, 26, 28, 0.96);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
.tgu-slots-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.tgu-slots-table th,
|
||||
.tgu-slots-table td {
|
||||
padding: 0.35rem 0.5rem;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.tgu-slots-table thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
background: var(--bg-panel);
|
||||
color: var(--text-dim);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tgu-slots-table tbody tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tgu-slots-table tbody tr:hover {
|
||||
background: rgba(104, 195, 189, 0.08);
|
||||
}
|
||||
|
||||
.tgu-slots-table tbody tr.is-active {
|
||||
background: rgba(104, 195, 189, 0.3);
|
||||
box-shadow: inset 3px 0 0 var(--accent);
|
||||
}
|
||||
|
||||
.tgu-slots-table tbody tr.is-active td {
|
||||
color: var(--text);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tgu-slots-table tbody tr.is-active:hover {
|
||||
background: rgba(104, 195, 189, 0.36);
|
||||
}
|
||||
|
||||
.tgu-slots-badge {
|
||||
display: inline-block;
|
||||
padding: 0.1rem 0.45rem;
|
||||
border-radius: 999px;
|
||||
background: #101214;
|
||||
border: 1px solid var(--line);
|
||||
color: var(--text-muted);
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
.tgu-slots-badge--booked {
|
||||
border-color: rgba(104, 195, 189, 0.58);
|
||||
background: rgba(104, 195, 189, 0.16);
|
||||
color: var(--accent-strong);
|
||||
}
|
||||
|
||||
.tgu-map-stage {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
@@ -1052,6 +1269,75 @@
|
||||
background: var(--bg-panel);
|
||||
color: var(--text);
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tgu-2d-map__zoom button:hover {
|
||||
border-color: rgba(104, 195, 189, 0.5);
|
||||
}
|
||||
|
||||
/* Кнопка-линейка: активный режим подсвечиваем как тумблер. */
|
||||
.tgu-2d-map__zoom-ruler.is-active {
|
||||
border-color: rgba(104, 195, 189, 0.58);
|
||||
background: rgba(104, 195, 189, 0.18);
|
||||
color: var(--accent-strong);
|
||||
}
|
||||
|
||||
/* Замер линейки на оверлее: ломаная, вершины и подписи расстояния. */
|
||||
.tgu-2d-map__ruler-line {
|
||||
stroke: #f0ad2e;
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: 6 4;
|
||||
}
|
||||
|
||||
.tgu-2d-map__ruler-vertex {
|
||||
fill: #f0ad2e;
|
||||
stroke: #1a1305;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.tgu-2d-map__ruler-label {
|
||||
fill: #ffe7b5;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
paint-order: stroke;
|
||||
stroke: rgba(10, 12, 14, 0.85);
|
||||
stroke-width: 3;
|
||||
}
|
||||
|
||||
/* Бейдж итоговой длины — в правом нижнем углу, над кнопками управления. */
|
||||
.tgu-2d-map__ruler-total {
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
bottom: 9rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.3rem 0.55rem;
|
||||
border: 1px solid rgba(240, 173, 46, 0.42);
|
||||
border-radius: 7px;
|
||||
background: rgba(17, 19, 21, 0.9);
|
||||
color: #ffe7b5;
|
||||
font-size: 0.78rem;
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
.tgu-2d-map__ruler-total-label {
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.tgu-2d-map__ruler-total-value {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tgu-2d-map__ruler-reset {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 5px;
|
||||
padding: 0.1rem 0.45rem;
|
||||
background: #101214;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.72rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tgu-map-overlay {
|
||||
|
||||
Reference in New Issue
Block a user