push to gitea
This commit is contained in:
parent
29fd802cad
commit
fb256fd284
52
frontend/gulpfile.mjs
Normal file
52
frontend/gulpfile.mjs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import gulp from 'gulp';
|
||||||
|
const {src, parallel, dest, watch} = gulp
|
||||||
|
|
||||||
|
import dartSass from 'sass';
|
||||||
|
import gulpSass from 'gulp-sass';
|
||||||
|
const sass = gulpSass(dartSass);
|
||||||
|
|
||||||
|
import concat from 'gulp-concat';
|
||||||
|
import minify from 'gulp-minify';
|
||||||
|
import rename from 'gulp-rename';
|
||||||
|
|
||||||
|
const BUILD_TARGET_DIR = "../public/assets/";
|
||||||
|
|
||||||
|
export const css = () => {
|
||||||
|
return src('./src/scss/global.scss')
|
||||||
|
.pipe(sass())
|
||||||
|
.pipe(dest(BUILD_TARGET_DIR + 'css/'));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const js = () => {
|
||||||
|
return src(['./src/js/**/*.js'])
|
||||||
|
.pipe(concat('app.js'))
|
||||||
|
.pipe(minify())
|
||||||
|
.pipe(rename("app.js"))
|
||||||
|
.pipe(dest(BUILD_TARGET_DIR + 'js/'));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const libs = () => {
|
||||||
|
return src([
|
||||||
|
'./node_modules/bootstrap/dist/js/bootstrap.bundle.js',
|
||||||
|
'./node_modules/jquery/dist/jquery.js',
|
||||||
|
'./node_modules/leaflet/dist/leaflet.js'
|
||||||
|
])
|
||||||
|
.pipe(concat('libs.js'))
|
||||||
|
.pipe(minify())
|
||||||
|
.pipe(rename("libs.js"))
|
||||||
|
.pipe(dest(BUILD_TARGET_DIR + 'js/'));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const w = () => {
|
||||||
|
watch(["./src/scss/**/*.scss", './public/**/*.html'], css);
|
||||||
|
watch("./src/js/**/*.js", js);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const images = () => {
|
||||||
|
return src([
|
||||||
|
'./node_modules/leaflet/dist/images/*.png'
|
||||||
|
])
|
||||||
|
.pipe(dest(BUILD_TARGET_DIR + 'css/images/'))
|
||||||
|
}
|
||||||
|
|
||||||
|
export default parallel(css, js, libs);
|
3411
frontend/package-lock.json
generated
Normal file
3411
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
frontend/package.json
Normal file
28
frontend/package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "frontend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"watch": "./node_modules/.bin/gulp w",
|
||||||
|
"build": "./node_modules/.bin/gulp",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^5.1.0",
|
||||||
|
"jquery": "^3.6.0",
|
||||||
|
"leaflet": "^1.7.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"gulp": "^4.0.2",
|
||||||
|
"gulp-cli": "^2.3.0",
|
||||||
|
"gulp-concat": "^2.6.1",
|
||||||
|
"gulp-minify": "^3.1.0",
|
||||||
|
"gulp-rename": "^2.0.0",
|
||||||
|
"gulp-sass": "^5.0.0",
|
||||||
|
"sass": "^1.39.0"
|
||||||
|
}
|
||||||
|
}
|
301
frontend/src/js/main.js
Normal file
301
frontend/src/js/main.js
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
const api = {
|
||||||
|
url: 'https://verkehr.autobahn.de/o/autobahn/',
|
||||||
|
roadworks: '/services/roadworks',
|
||||||
|
webcams: '/services/webcam',
|
||||||
|
charging: '/services/electric_charging_station',
|
||||||
|
mapbox: {
|
||||||
|
pubToken: 'enter your key here'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(async function onload() {
|
||||||
|
|
||||||
|
let $roadSelection = $('#roadSelection');
|
||||||
|
|
||||||
|
/** Register list sections and hide on load */
|
||||||
|
|
||||||
|
let $roadworks = $('#roadworks');
|
||||||
|
$roadworks.addClass('d-none');
|
||||||
|
let $roadworksList = $('#roadworksList');
|
||||||
|
|
||||||
|
let $webcams = $('#webcams');
|
||||||
|
$webcams.addClass('d-none');
|
||||||
|
let $webcamList = $('#webcamList');
|
||||||
|
|
||||||
|
let $cStations = $('#chargingStations');
|
||||||
|
$cStations.addClass('d-none');
|
||||||
|
let $cStationList = $('#cStationList');
|
||||||
|
|
||||||
|
/** Basic Buttons */
|
||||||
|
|
||||||
|
let $btnRoadworks = $('#btn-roadworks');
|
||||||
|
let $btnWebcams = $('#btn-webcams');
|
||||||
|
let $btnCStations = $('#btn-cStations');
|
||||||
|
|
||||||
|
$btnRoadworks.addClass('disabled').attr('disabled', 'disabled');
|
||||||
|
$btnWebcams.addClass('disabled').attr('disabled', 'disabled');
|
||||||
|
$btnCStations.addClass('disabled').attr('disabled', 'disabled');
|
||||||
|
|
||||||
|
/** register vars for different lists.. */
|
||||||
|
|
||||||
|
let actualRoadworks = null;
|
||||||
|
let actualWebcams = null;
|
||||||
|
let actualChargingStations = null;
|
||||||
|
|
||||||
|
/** request road list from server */
|
||||||
|
let road = await $.get(api.url);
|
||||||
|
|
||||||
|
|
||||||
|
/** create select options for each road
|
||||||
|
* enable / disable Buttons
|
||||||
|
*/
|
||||||
|
|
||||||
|
road.roads.forEach(road => {
|
||||||
|
$roadSelection.append($('<option />').val(road).text(road));
|
||||||
|
});
|
||||||
|
|
||||||
|
$roadSelection.click(() => {
|
||||||
|
if ($roadSelection.val() === null) {
|
||||||
|
$btnRoadworks.addClass('disabled').attr('disabled', 'disabled');
|
||||||
|
$btnWebcams.addClass('disabled').attr('disabled', 'disabled');
|
||||||
|
$btnCStations.addClass('disabled').attr('disabled', 'disabled');
|
||||||
|
} else {
|
||||||
|
$btnRoadworks.removeClass('disabled').removeAttr('disabled');
|
||||||
|
$btnWebcams.removeClass('disabled').removeAttr('disabled');
|
||||||
|
$btnCStations.removeClass('disabled').removeAttr('disabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$btnRoadworks.click(async function () {
|
||||||
|
|
||||||
|
$btnWebcams.removeClass('active');
|
||||||
|
$btnCStations.removeClass('active');
|
||||||
|
$btnRoadworks.addClass('active');
|
||||||
|
|
||||||
|
$webcams.addClass('d-none');
|
||||||
|
$cStations.addClass('d-none');
|
||||||
|
|
||||||
|
if ($roadSelection.val() === null) {
|
||||||
|
$roadworks.addClass('d-none');
|
||||||
|
$roadworksList.empty();
|
||||||
|
} else {
|
||||||
|
actualRoadworks = await $.get(api.url + $roadSelection.val() + api.roadworks);
|
||||||
|
$roadworks.removeClass('d-none');
|
||||||
|
$roadworksList.empty();
|
||||||
|
if (actualRoadworks.roadworks.length === 0) {
|
||||||
|
$roadworksList.append($('<div class="fw-bold" />').text('Keine Einträge zu aktuellen Baustellen auf der ' + $roadSelection.val() + ' gefunden.'));
|
||||||
|
} else {
|
||||||
|
actualRoadworks.roadworks.forEach((roadwork, key) => {
|
||||||
|
$roadworksList.append($('<a href="#" class="list-group-item list-group-item-action btn-roadwork" data-key="' + key + '"/>').append($('<div/>').text(roadwork.title)).append($('<div />').addClass('fw-bold').text(roadwork.subtitle)));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$roadworksList.off('click', '.btn-roadwork').on('click', '.btn-roadwork', async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let target = $(e.currentTarget);
|
||||||
|
|
||||||
|
let roadwork = actualRoadworks.roadworks[target.data('key')];
|
||||||
|
|
||||||
|
let body = $('<div/>').append($('<div />').text(roadwork.subtitle).append($('<hr/>')));
|
||||||
|
roadwork.description.forEach(e => {
|
||||||
|
body.append($('<div />').text(e));
|
||||||
|
});
|
||||||
|
|
||||||
|
await buildModal({
|
||||||
|
modalDialog: 'modal-xl',
|
||||||
|
modalTitle: roadwork.title,
|
||||||
|
modalBody: body
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
$btnWebcams.click(async function () {
|
||||||
|
|
||||||
|
$btnWebcams.addClass('active');
|
||||||
|
$btnRoadworks.removeClass('active');
|
||||||
|
$btnCStations.removeClass('active');
|
||||||
|
|
||||||
|
$roadworks.addClass('d-none');
|
||||||
|
$cStations.addClass('d-none');
|
||||||
|
|
||||||
|
if ($roadSelection.val() === null) {
|
||||||
|
$webcams.addClass('d-none');
|
||||||
|
$webcamList.empty();
|
||||||
|
} else {
|
||||||
|
actualWebcams = await $.get(api.url + $roadSelection.val() + api.webcams);
|
||||||
|
$webcams.removeClass('d-none');
|
||||||
|
$webcamList.empty();
|
||||||
|
if (actualWebcams.webcam.length === 0) {
|
||||||
|
$webcamList.append($('<div class="fw-bold"/>').text('Keine Webcams auf der ' + $roadSelection.val() + ' gefunden.'));
|
||||||
|
} else {
|
||||||
|
actualWebcams.webcam.forEach((webcam, key) => {
|
||||||
|
$webcamList.append($('<a href="#" class="list-group-item list-group-item-action btn-webcam" data-key="' + key + '"/>').append($('<div/>').text(webcam.title)).append($('<div />').addClass('fw-bold').text(webcam.subtitle)));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$webcamList.off('click', '.btn-webcam').on('click', '.btn-webcam', async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let target = $(e.currentTarget);
|
||||||
|
let webcam = actualWebcams.webcam[target.data('key')];
|
||||||
|
|
||||||
|
let body = $('<div class="modalBody"/>').append(
|
||||||
|
$('<div/>')
|
||||||
|
.append($('<div class="row"/>')
|
||||||
|
.append($('<div class="col-6"/>')
|
||||||
|
.append($('<ul class="list-group webcamMetaList"/>')
|
||||||
|
.append($('<li class="list-group-item"/>').text('Bundesland: ' + webcam.operator))
|
||||||
|
.append($('<li class="list-group-item"/>').text('Position Lat: ' + webcam.coordinate.lat + ', Long: ' + webcam.coordinate.long))
|
||||||
|
.append($('<li class="list-group-item"/>').text(webcam.subtitle))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.append($('<div class="col-6"/>')
|
||||||
|
.append($('<div class="img-wrap"/>').append($('<img src="' + webcam.imageurl + '" alt="webcam Image"/>')))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (webcam.isBlocked !== false && webcam.linkurl !== '' && webcam.linkurl !== 'https://#') {
|
||||||
|
body.append($('<div class="d-grid gap-2"/>')
|
||||||
|
.append($('<button class="btn btn-primary btn-sm btnWebcamFrame" data-link="' + target.data('key') + '" />').text('zeige Video')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await buildModal({
|
||||||
|
modalTitle: "Kamera " + webcam.title,
|
||||||
|
modalBody: body,
|
||||||
|
type: 'webcam',
|
||||||
|
additionalData: webcam.linkurl
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$btnCStations.click(async function () {
|
||||||
|
|
||||||
|
$btnCStations.addClass('active');
|
||||||
|
$btnRoadworks.removeClass('active');
|
||||||
|
$btnWebcams.removeClass('active');
|
||||||
|
|
||||||
|
$roadworks.addClass('d-none');
|
||||||
|
$webcams.addClass('d-none');
|
||||||
|
|
||||||
|
if ($roadSelection.val() === null) {
|
||||||
|
$cStations.addClass('d-none');
|
||||||
|
$cStationList.empty();
|
||||||
|
} else {
|
||||||
|
actualChargingStations = await $.get(api.url + $roadSelection.val() + api.charging);
|
||||||
|
$cStations.removeClass('d-none');
|
||||||
|
$cStationList.empty();
|
||||||
|
if (actualChargingStations.electric_charging_station.length === 0) {
|
||||||
|
$cStationList.append($('<div class="fw-bold"/>').text('Keine elektrischen Ladestationen auf der ' + $roadSelection.val() + ' gefunden.'));
|
||||||
|
} else {
|
||||||
|
actualChargingStations.electric_charging_station.forEach((station, key) => {
|
||||||
|
$cStationList.append($('<a href="#" class="list-group-item list-group-item-action btn-cStation" data-key="' + key + '"/>').append($('<div/>').text(station.title)).append($('<div />').addClass('fw-bold').text(station.subtitle)));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$cStationList.off('click', '.btn-cStation').on('click', '.btn-cStation', async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let target = $(e.currentTarget);
|
||||||
|
let cStation = actualChargingStations.electric_charging_station[target.data('key')];
|
||||||
|
|
||||||
|
let body = $('<div class="modalBody" />').append(
|
||||||
|
$('<div />')
|
||||||
|
.append($('<div class="row"/>')
|
||||||
|
.append($('<div class="col-6"/>')
|
||||||
|
.append($('<ul class="list-group cStationMetaList"/>')
|
||||||
|
.append($('<li class="list-group-item"/>').text(cStation.subtitle))
|
||||||
|
.append($('<li class="list-group-item"/>').text('Position Lat: ' + cStation.coordinate.lat + ', Long: ' + cStation.coordinate.long))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.append($('<div class="col-6" id="cStationPos"/>')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
cStation.description.forEach((descr) => {
|
||||||
|
if (descr !== '') {
|
||||||
|
if (descr.match(/(Ladepunkt)/g)) {
|
||||||
|
body.find('.cStationMetaList').append($('<li class="list-group-item fw-bold" />').text(descr));
|
||||||
|
} else {
|
||||||
|
body.find('.cStationMetaList').append($('<li class="list-group-item" />').text(descr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await buildModal({
|
||||||
|
modalTitle: "Ladestation" + cStation.title,
|
||||||
|
modalBody: body,
|
||||||
|
type: 'electric_charging_station',
|
||||||
|
additionalData: cStation.coordinate
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function buildModal(options) {
|
||||||
|
|
||||||
|
|
||||||
|
const modalTemplate = $(await $.get('/templates/modal.standard.html'));
|
||||||
|
let section = $('#modalSection');
|
||||||
|
section.empty();
|
||||||
|
|
||||||
|
if (options.modalDialog) {
|
||||||
|
modalTemplate.find('.modal-dialog').addClass(options.modalDialog);
|
||||||
|
}
|
||||||
|
if (options.modalTitle) {
|
||||||
|
modalTemplate.find('.modal-title').text(options.modalTitle);
|
||||||
|
}
|
||||||
|
if (options.modalBody) {
|
||||||
|
modalTemplate.find('.modal-body').append(options.modalBody);
|
||||||
|
}
|
||||||
|
section.append(modalTemplate);
|
||||||
|
let htmlModal = document.getElementById('myModal');
|
||||||
|
let Modal = new bootstrap.Modal(htmlModal);
|
||||||
|
Modal.show();
|
||||||
|
|
||||||
|
switch (options.type){
|
||||||
|
case 'webcam':
|
||||||
|
await webcamFrame(options.additionalData);
|
||||||
|
break;
|
||||||
|
case 'electric_charging_station':
|
||||||
|
await leafletDiv(options.additionalData)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.debug('default');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function webcamFrame(additionalData) {
|
||||||
|
let btnWebcamFrame = $('.btnWebcamFrame');
|
||||||
|
btnWebcamFrame.click((e) => {
|
||||||
|
$('.modalBody').append($('<iframe src="' + additionalData + '" width="100%" height="500px" class="mt-3"/>'));
|
||||||
|
btnWebcamFrame.addClass('d-none');
|
||||||
|
$('.modal-dialog').addClass('modal-xl');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function leafletDiv (coordinates) {
|
||||||
|
$('.modal-dialog').addClass('modal-xl');
|
||||||
|
console.debug(coordinates);
|
||||||
|
let place = L.map('cStationPos').setView([
|
||||||
|
coordinates.lat,
|
||||||
|
coordinates.long
|
||||||
|
],17);
|
||||||
|
|
||||||
|
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
|
||||||
|
attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
|
||||||
|
maxZoom: 18,
|
||||||
|
id: 'mapbox/streets-v11',
|
||||||
|
tileSize: 512,
|
||||||
|
zoomOffset: -1,
|
||||||
|
accessToken: api.mapbox.pubToken
|
||||||
|
}).addTo(place);
|
||||||
|
L.marker([
|
||||||
|
coordinates.lat,
|
||||||
|
coordinates.long
|
||||||
|
]).addTo(place);
|
||||||
|
}
|
0
frontend/src/scss/_bootstrap_overrides.scss
Normal file
0
frontend/src/scss/_bootstrap_overrides.scss
Normal file
18
frontend/src/scss/_cams.scss
Normal file
18
frontend/src/scss/_cams.scss
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
.img-wrap {
|
||||||
|
width: 200px;
|
||||||
|
height: 150px;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div > img {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
min-height: 100%;
|
||||||
|
min-width: 100%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
24
frontend/src/scss/_main.scss
Normal file
24
frontend/src/scss/_main.scss
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
body {
|
||||||
|
background-color: $dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
//jumbotron
|
||||||
|
$jumbotron-padding: 2rem !default;
|
||||||
|
$jumbotron-bg: $gray-200 !default;
|
||||||
|
|
||||||
|
.jumbotron {
|
||||||
|
padding: $jumbotron-padding ($jumbotron-padding / 2);
|
||||||
|
margin-bottom: $jumbotron-padding;
|
||||||
|
background-color: $jumbotron-bg;
|
||||||
|
@include border-radius($border-radius-lg);
|
||||||
|
|
||||||
|
@include media-breakpoint-up(sm) {
|
||||||
|
padding: ($jumbotron-padding * 2) $jumbotron-padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.jumbotron-fluid {
|
||||||
|
padding-right: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
@include border-radius(0);
|
||||||
|
}
|
3
frontend/src/scss/_map.scss
Normal file
3
frontend/src/scss/_map.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#cStationPos {
|
||||||
|
height: 400px;
|
||||||
|
}
|
9
frontend/src/scss/global.scss
Normal file
9
frontend/src/scss/global.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
@import "../../node_modules/bootstrap/scss/functions";
|
||||||
|
@import "../../node_modules/bootstrap/scss/variables";
|
||||||
|
@import "../../node_modules/bootstrap/scss/mixins";
|
||||||
|
@import "bootstrap_overrides";
|
||||||
|
@import "../../node_modules/bootstrap/scss/bootstrap";
|
||||||
|
@import "../../node_modules/leaflet/dist/leaflet";
|
||||||
|
@import "_main";
|
||||||
|
@import "_cams";
|
||||||
|
@import "_map";
|
11889
public/assets/css/global.css
Normal file
11889
public/assets/css/global.css
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/assets/css/images/layers-2x.png
Normal file
BIN
public/assets/css/images/layers-2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
public/assets/css/images/layers.png
Normal file
BIN
public/assets/css/images/layers.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 696 B |
BIN
public/assets/css/images/marker-icon-2x.png
Normal file
BIN
public/assets/css/images/marker-icon-2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
public/assets/css/images/marker-icon.png
Normal file
BIN
public/assets/css/images/marker-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
public/assets/css/images/marker-shadow.png
Normal file
BIN
public/assets/css/images/marker-shadow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 618 B |
17669
public/assets/js/libs.js
Normal file
17669
public/assets/js/libs.js
Normal file
File diff suppressed because one or more lines are too long
36
public/index.html
Normal file
36
public/index.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>test</title>
|
||||||
|
<link rel="stylesheet" href="assets/css/global.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="mt-5 container jumbotron">
|
||||||
|
<select name="road" id="roadSelection" class="form-select" aria-label="Auswahl der Fernstraße">
|
||||||
|
<option selected disabled>Bitte wählen</option>
|
||||||
|
</select>
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<button type="button" class="mt-3 btn btn-sm btn-primary" id="btn-roadworks">Baustellen</button>
|
||||||
|
<button type="button" class="mt-3 btn btn-sm btn-primary" id="btn-webcams">Webcams</button>
|
||||||
|
<button type="button" class="mt-3 btn btn-sm btn-primary" id="btn-cStations">Ladestationen</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="roadworks" class="mt-5">
|
||||||
|
<div class="list-group" id="roadworksList"></div>
|
||||||
|
</div>
|
||||||
|
<div id="webcams" class="mt-5">
|
||||||
|
<div class="list-group" id="webcamList"></div>
|
||||||
|
</div>
|
||||||
|
<div id="chargingStations" class="mt-5">
|
||||||
|
<div class="list-group" id="cStationList"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<section id="modalSection"></section>
|
||||||
|
|
||||||
|
<script src="/assets/js/libs.js"></script>
|
||||||
|
<script src="/assets/js/app.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
16
public/templates/modal.standard.html
Normal file
16
public/templates/modal.standard.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<div class="modal" tabindex="-1" id="myModal">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Modal title</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body"></div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in New Issue
Block a user