Skip to content

Commit 0a5e596

Browse files
committed
add info button for stop times
1 parent 4c137b3 commit 0a5e596

File tree

4 files changed

+51
-32
lines changed

4 files changed

+51
-32
lines changed

src/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<script src="js/filter_vehicles.js"></script>
2727
</head>
2828
<body class="position-relative h-100">
29+
<div popover id="stop-time-popover"></div>
2930
<div id="vehicles-panel" class="panel position-absolute h-100 d-flex flex-column d-none p-2">
3031
<div class="mb-2">
3132
<div class="d-flex flex-row justify-content-between mb-2">

src/js/config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,16 @@ export const BG_TYPES_HTML = {
2323
'bus': `<i class="icon bus-icon"></i>`,
2424
'night': `<i class="icon night-icon"></i>`
2525
};
26+
27+
export const occupancy_mappings = {
28+
'EMPTY': 'Свободен',
29+
'MANY_SEATS_AVAILABLE': 'Много места',
30+
'FEW_SEATS_AVAILABLE': 'Малко места',
31+
'STANDING_ROOM_ONLY': 'Само правостоящи',
32+
'CRUSHED_STANDING_ROOM_ONLY': 'Претъпкан',
33+
'FULL': 'Пълен',
34+
'NOT_ACCEPTING_PASSENGERS': 'Не приема пътници',
35+
'NO_DATA_AVAILABLE': 'Няма данни',
36+
'NOT_BOARDABLE': 'Не превозва пътници',
37+
null: 'Няма данни'
38+
};

src/js/map_stops.js

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { routes, stops_layer } from './app';
2-
import { VIRTUAL_BOARD_URL } from './config';
2+
import { occupancy_mappings, VIRTUAL_BOARD_URL, occupancy_mappings, BG_TYPES } from './config';
33
import { get_route_classes, calculate_diff } from './utils';
44
import { determine_time_ago } from './map';
5+
import { get_vehicle_model, get_model_name } from '/data/models';
56

67
export const stops = new Map();
78

@@ -139,7 +140,7 @@ function display_stop_times(stop_routes) {
139140
const total_diff = calculate_diff(scheduled, actual);
140141

141142
const diff_class = 3 < total_diff || total_diff < -1 ? 'text-danger fw-bold' : 'text-success';
142-
const diff_html = `<span class="${diff_class}">${total_diff > 0 ? '+' : ''}${total_diff}</span>`;
143+
const diff_html = `<span class="${diff_class} text-nowrap">${total_diff > 0 ? '+' : ''}${total_diff == 0 ? 'навреме' : total_diff + ' мин.'}</span>`;
143144

144145
const hour = (Math.floor(actual / 60) % 24);
145146
const minute = (actual % 60).toString().padStart(2, '0');
@@ -151,12 +152,13 @@ function display_stop_times(stop_routes) {
151152

152153
const tbody = document.createElement('tbody');
153154
for(const route of stop_routes) {
154-
const row = document.createElement('tr');
155-
row.classList.add('text-center', 'align-middle');
155+
const row0 = document.createElement('tr');
156+
row0.classList.add('text-center', 'align-middle');
156157

158+
const { type, route_ref } = routes.find(r => r.cgm_id == route.cgm_id);
157159
{
158-
const { type, route_ref } = routes.find(r => r.cgm_id == route.cgm_id);
159160
const td = document.createElement('td');
161+
td.colSpan = '4';
160162
const span = document.createElement('span');
161163
span.setAttribute('class', get_route_classes(type, route_ref).join(' '));
162164
span.textContent = route_ref;
@@ -167,25 +169,39 @@ function display_stop_times(stop_routes) {
167169
td.appendChild(i);
168170

169171
td.appendChild(document.createTextNode(stops.get(route.destination)?.names.bg || 'неизвестна'));
170-
row.appendChild(td);
172+
row0.appendChild(td);
171173
}
174+
const row = document.createElement('tr');
175+
row.classList.add('text-center', 'align-middle');
172176
{
173-
for(const { actual_time, scheduled_time, occupancy: vehicle_occupancy } of route.times) {
177+
for(const { actual_time, scheduled_time, occupancy: vehicle_occupancy, inv_number, next_stop } of route.times) {
174178
const td = document.createElement('td');
175179
const r = display_hours(scheduled_time, actual_time);
176-
let occupancy = '';
177-
if(vehicle_occupancy) {
178-
const mappings = {
179-
'EMPTY': '<i class="bi bi-person text-success" title="Празен"></i>',
180-
'MANY_SEATS_AVAILABLE': '<i class="bi bi-person text-success" title="Много свободни места"></i>',
181-
'FEW_SEATS_AVAILABLE': '<i class="bi bi-people-fill text-success" title="Малко свободни места"></i>',
182-
'STANDING_ROOM_ONLY': '<i class="bi bi-people-fill text-danger" title="Само правостоящи"></i>',
183-
'CRUSHED_STANDING_ROOM_ONLY': '<i class="bi bi-people-fill text-danger" title="Претъпкано"></i>',
184-
'FULL': '<i class="bi bi-people-fill text-danger" title="Пълен"></i>'
185-
};
186-
occupancy = mappings[vehicle_occupancy] || vehicle_occupancy;
180+
const model = inv_number ? get_vehicle_model(type, inv_number) : null;
181+
182+
let popover_content = ``;
183+
popover_content += `${BG_TYPES[type]} ${inv_number ?? 'неизвестен'}<br>`;
184+
popover_content += model ? `Модел: ${get_model_name(model)}<br>` : '';
185+
186+
const extras_icons = {
187+
'ac': '<i class="bi bi-snow"></i>',
188+
'low_floor': '<i class="bi bi-person-wheelchair"></i>'
189+
}
190+
const extras_text = model && model.extras ? model.extras.map(extra => extras_icons[extra] || '').join(' ') : '';
191+
popover_content += `Екстри: ${extras_text}<br>`;
192+
193+
const next_stop_obj = next_stop ? stops.get(next_stop) : null;
194+
if(next_stop_obj) {
195+
popover_content += `Следваща спирка: [${next_stop_obj.code.toString().padStart(4, '0')}] ${next_stop_obj.names.bg}<br>`;
187196
}
188-
td.innerHTML = r[0] + (r[1] ? ` <br>${r[1]}` : '') + (occupancy ? ` ${occupancy}` : '');
197+
198+
let occupancy = occupancy_mappings[vehicle_occupancy];
199+
popover_content += `Запълненост: ${occupancy}<br>`;
200+
201+
popover_content = popover_content.replace(/'/g, "&apos;").replace(/"/g, "&quot;");
202+
203+
const popover_btn = `<i popovertarget="stop-time-popover" onclick="document.querySelector('#stop-time-popover').innerHTML = decodeURI(this.dataset.popoverContent); document.querySelector('#stop-time-popover').showPopover();" data-popover-content='${popover_content}' class="bi bi-info-circle"></i>`;
204+
td.innerHTML = `<span class="text-nowrap">${r[0]} ${r[0] != '-' ? popover_btn : ''}</span><br>${r[1] ? r[1] : ''}`;
189205
row.appendChild(td);
190206
}
191207
for(let i = route.times.length; i < 3; i++) {
@@ -194,6 +210,7 @@ function display_stop_times(stop_routes) {
194210
row.appendChild(td);
195211
}
196212
}
213+
tbody.appendChild(row0);
197214
tbody.appendChild(row);
198215
}
199216
if(stop_routes.length == 0) {

src/js/map_vehicles.js

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { determine_route_colour } from 'sofiatraffic-library';
2-
import { BG_TYPES_HTML, MIN_ACTIVE_SPEED } from './config';
2+
import { BG_TYPES_HTML, MIN_ACTIVE_SPEED, occupancy_mappings } from './config';
33
import { proper_inv_number, get_route_classes, register_vehicle_view } from './utils';
44
import { get_vehicle_model_name } from '/data/models';
55
import { stops } from './map_stops';
@@ -120,18 +120,6 @@ function generate_vehicle_popup_text(vehicle, cache) {
120120
row.appendChild(speed_div);
121121

122122
if(occupancy) {
123-
const occupancy_mappings = {
124-
'EMPTY': 'Свободен',
125-
'MANY_SEATS_AVAILABLE': 'Много места',
126-
'FEW_SEATS_AVAILABLE': 'Малко места',
127-
'STANDING_ROOM_ONLY': 'Само правостоящи',
128-
'CRUSHED_STANDING_ROOM_ONLY': 'Претъпкан',
129-
'FULL': 'Пълен',
130-
'NOT_ACCEPTING_PASSENGERS': 'Не приема пътници',
131-
'NO_DATA_AVAILABLE': 'Няма данни',
132-
'NOT_BOARDABLE': 'Не превозва пътници'
133-
};
134-
135123
const occupancy_text = occupancy_mappings[occupancy] || occupancy || '';
136124
const span = document.createElement('span');
137125
span.className = 'mt-auto text-nowrap';

0 commit comments

Comments
 (0)