mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Committing so I don't lose work.
This commit is contained in:
26
client/package-lock.json
generated
26
client/package-lock.json
generated
@@ -21,9 +21,11 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/gtag.js": "^0.0.12",
|
"@types/gtag.js": "^0.0.12",
|
||||||
|
"@types/sortablejs": "^1.15.0",
|
||||||
"browserify": "^17.0.0",
|
"browserify": "^17.0.0",
|
||||||
"concurrently": "^7.6.0",
|
"concurrently": "^7.6.0",
|
||||||
"nodemon": "^2.0.20",
|
"nodemon": "^2.0.20",
|
||||||
|
"sortablejs": "^1.15.0",
|
||||||
"tsify": "^5.0.4",
|
"tsify": "^5.0.4",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^4.9.4",
|
||||||
"watchify": "^4.0.0"
|
"watchify": "^4.0.0"
|
||||||
@@ -48,6 +50,12 @@
|
|||||||
"@types/geojson": "*"
|
"@types/geojson": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/sortablejs": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-qrhtM7M41EhH4tZQTNw2/RJkxllBx3reiJpTbgWCM2Dx0U1sZ6LwKp9lfNln9uqE26ZMKUaPEYaD4rzvOWYtZw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/abbrev": {
|
"node_modules/abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
@@ -2621,6 +2629,12 @@
|
|||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sortablejs": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.5.7",
|
"version": "0.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||||
@@ -3248,6 +3262,12 @@
|
|||||||
"@types/geojson": "*"
|
"@types/geojson": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/sortablejs": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-qrhtM7M41EhH4tZQTNw2/RJkxllBx3reiJpTbgWCM2Dx0U1sZ6LwKp9lfNln9uqE26ZMKUaPEYaD4rzvOWYtZw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"abbrev": {
|
"abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
@@ -5329,6 +5349,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sortablejs": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.5.7",
|
"version": "0.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||||
|
|||||||
@@ -23,9 +23,11 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/gtag.js": "^0.0.12",
|
"@types/gtag.js": "^0.0.12",
|
||||||
|
"@types/sortablejs": "^1.15.0",
|
||||||
"browserify": "^17.0.0",
|
"browserify": "^17.0.0",
|
||||||
"concurrently": "^7.6.0",
|
"concurrently": "^7.6.0",
|
||||||
"nodemon": "^2.0.20",
|
"nodemon": "^2.0.20",
|
||||||
|
"sortablejs": "^1.15.0",
|
||||||
"tsify": "^5.0.4",
|
"tsify": "^5.0.4",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^4.9.4",
|
||||||
"watchify": "^4.0.0"
|
"watchify": "^4.0.0"
|
||||||
|
|||||||
27
client/public/images/buttons/atc.svg
Normal file
27
client/public/images/buttons/atc.svg
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="64.000000pt" height="64.000000pt" viewBox="0 0 64.000000 64.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
|
||||||
|
<g transform="translate(0.000000,64.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M285 590 c-11 -12 -31 -20 -51 -20 -23 0 -37 -6 -44 -20 -6 -11 -17
|
||||||
|
-20 -25 -20 -7 0 -16 -4 -20 -10 -10 -16 14 -174 28 -185 7 -5 16 -18 20 -27
|
||||||
|
3 -10 16 -18 27 -18 13 0 20 -7 20 -20 0 -11 5 -20 10 -20 6 0 10 -43 10 -110
|
||||||
|
l0 -110 60 0 60 0 0 110 c0 67 4 110 10 110 6 0 10 9 10 20 0 13 7 20 20 20
|
||||||
|
11 0 24 8 27 18 4 9 13 22 20 27 14 11 38 169 28 185 -4 6 -13 10 -20 10 -8 0
|
||||||
|
-19 9 -25 20 -7 14 -21 20 -44 20 -20 0 -40 8 -51 20 -10 11 -26 20 -35 20 -9
|
||||||
|
0 -25 -9 -35 -20z m60 -10 c4 -6 -7 -10 -25 -10 -18 0 -29 4 -25 10 3 6 15 10
|
||||||
|
25 10 10 0 22 -4 25 -10z m90 -40 c4 -6 -37 -10 -115 -10 -78 0 -119 4 -115
|
||||||
|
10 4 6 53 10 115 10 62 0 111 -4 115 -10z m-205 -110 c0 -78 -1 -80 -24 -80
|
||||||
|
-22 0 -25 5 -31 48 -3 26 -8 62 -11 80 -5 31 -4 32 31 32 l35 0 0 -80z m80 0
|
||||||
|
l0 -80 -30 0 -30 0 0 80 0 80 30 0 30 0 0 -80z m80 0 l0 -80 -30 0 -30 0 0 80
|
||||||
|
0 80 30 0 30 0 0 -80z m86 48 c-3 -18 -8 -54 -11 -80 -6 -43 -9 -48 -31 -48
|
||||||
|
-23 0 -24 2 -24 80 l0 80 35 0 c35 0 36 -1 31 -32z m-46 -158 c0 -6 -43 -10
|
||||||
|
-110 -10 -67 0 -110 4 -110 10 0 6 43 10 110 10 67 0 110 -4 110 -10z m-50
|
||||||
|
-40 c0 -6 -27 -10 -60 -10 -33 0 -60 4 -60 10 0 6 27 10 60 10 33 0 60 -4 60
|
||||||
|
-10z m-20 -130 l0 -100 -40 0 -40 0 0 100 0 100 40 0 40 0 0 -100z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
21
client/public/images/buttons/reorder.svg
Normal file
21
client/public/images/buttons/reorder.svg
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="96.000000pt" height="96.000000pt" viewBox="0 0 96.000000 96.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
|
||||||
|
<g transform="translate(0.000000,96.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M411 846 c-77 -78 -70 -86 69 -86 139 0 146 8 69 86 -29 30 -60 54
|
||||||
|
-69 54 -9 0 -40 -24 -69 -54z"/>
|
||||||
|
<path d="M132 668 c-16 -16 -15 -43 2 -57 9 -8 110 -11 351 -9 309 3 339 4
|
||||||
|
349 21 8 12 8 22 0 35 -10 16 -40 17 -350 20 -256 2 -343 -1 -352 -10z"/>
|
||||||
|
<path d="M132 508 c-16 -16 -15 -43 2 -57 9 -8 110 -11 351 -9 309 3 339 4
|
||||||
|
349 21 8 12 8 22 0 35 -10 16 -40 17 -350 20 -256 2 -343 -1 -352 -10z"/>
|
||||||
|
<path d="M132 348 c-16 -16 -15 -43 2 -57 9 -8 110 -11 351 -9 309 3 339 4
|
||||||
|
349 21 8 12 8 22 0 35 -10 16 -40 17 -350 20 -256 2 -343 -1 -352 -10z"/>
|
||||||
|
<path d="M363 184 c-7 -18 92 -124 117 -124 25 0 124 106 117 124 -9 24 -225
|
||||||
|
24 -234 0z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
211
client/public/stylesheets/atc.css
Normal file
211
client/public/stylesheets/atc.css
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/*** Control panel ***/
|
||||||
|
|
||||||
|
#atc-control-panel {
|
||||||
|
align-self: flex-end;
|
||||||
|
background: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
display:flex;
|
||||||
|
margin: 0 0 50px 100px;
|
||||||
|
padding:5px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-tool {
|
||||||
|
align-self: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
display:none;
|
||||||
|
justify-self: center;
|
||||||
|
padding: 10px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.atc-enabled .atc-tool {
|
||||||
|
display:flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#atc-flight-list {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#atc-flight-list table {
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#atc-flight-list table td {
|
||||||
|
padding:0 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#atc-flight-list table td:first-of-type {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#atc-flight-list table tr[data-status='checkedIn'] td {
|
||||||
|
background-color:goldenrod;
|
||||||
|
}
|
||||||
|
|
||||||
|
#atc-flight-list table tr[data-status='readyToTaxi'] td {
|
||||||
|
background-color:darkgreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
#atc-flight-list table button {
|
||||||
|
background-color: #666;
|
||||||
|
border:1px solid white;
|
||||||
|
color:white;
|
||||||
|
font-weight: bold;
|
||||||
|
margin:2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.atc-strip-board {
|
||||||
|
align-self: center;
|
||||||
|
display:flex;
|
||||||
|
justify-self: center;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 9999 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-header {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strip {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
.atc-strip-board-header {
|
||||||
|
background:black;
|
||||||
|
color:white;
|
||||||
|
display:none;
|
||||||
|
justify-content: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.atc-strip-board {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding:10px;
|
||||||
|
row-gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips > div {
|
||||||
|
align-items: center;
|
||||||
|
color:white;
|
||||||
|
column-gap: 2px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-header > div, .atc-strip-board-strips > div > div {
|
||||||
|
text-align: center;
|
||||||
|
width: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-header > .name {
|
||||||
|
width:150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-header > div, .atc-strip-board-strips > div > div {
|
||||||
|
text-align: center;
|
||||||
|
width: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips > div > .name {
|
||||||
|
text-align: left;
|
||||||
|
width:150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips > div {
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 5px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size:12px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 5px;
|
||||||
|
row-gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
.atc-strip-board-header, .atc-strip-board-strips > div {
|
||||||
|
align-items: center;
|
||||||
|
background:#FFF3;
|
||||||
|
color:white;
|
||||||
|
column-gap: 5px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size:12px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 5px;
|
||||||
|
row-gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-header {
|
||||||
|
background:black;
|
||||||
|
color:white;
|
||||||
|
display:none;
|
||||||
|
justify-content: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips > div {
|
||||||
|
border-bottom:1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-header > div, .atc-strip-board-strips > div > div {
|
||||||
|
text-align: center;
|
||||||
|
width: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-header > .name {
|
||||||
|
width:150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips > div > .handle {
|
||||||
|
background: black;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor:grab;
|
||||||
|
height:10px;
|
||||||
|
width:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips > div > .name {
|
||||||
|
text-align: left;
|
||||||
|
width:150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips > div > .warning {
|
||||||
|
background:red;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atc-strip-board-strips > div > .link-warning {
|
||||||
|
border: 1px solid red;
|
||||||
|
color: red;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
106
client/public/stylesheets/olympus.css
Normal file
106
client/public/stylesheets/olympus.css
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/* Variables definitions */
|
||||||
|
:root {
|
||||||
|
--active-coalition-color: var(--blue-coalition-color);
|
||||||
|
--background-color-dark: #202831;
|
||||||
|
--background-color-light: #AAA;
|
||||||
|
--blue-coalition-color: #247be2;
|
||||||
|
--highlight-color: #FFF5;
|
||||||
|
--neutral-coalition-color: whitesmoke;
|
||||||
|
--neutral-coalition-text: #202831;
|
||||||
|
--red-coalition-color: #f32121;
|
||||||
|
--text-color: white;
|
||||||
|
--title-color: #d3e9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
* {
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.ol-panel {
|
||||||
|
background-color: var(--background-color-dark);
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0px 2px 5px #000A;
|
||||||
|
color:white;
|
||||||
|
font-size: 12px;
|
||||||
|
height:fit-content;
|
||||||
|
padding:10px;
|
||||||
|
width:fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ol-panel-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: fit-content;
|
||||||
|
row-gap: 5px;
|
||||||
|
text-align: center;
|
||||||
|
width: fit-content;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-panel-list .list-item {
|
||||||
|
border-radius: 10px;
|
||||||
|
display:flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 6px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-panel-list.sortable > .sortable-item {
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 5px;
|
||||||
|
display:flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-panel-list.sortable > .sortable-item > .handle {
|
||||||
|
cursor:grab;
|
||||||
|
filter:invert(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-panel-list.sortable > .sortable-item > .handle img {
|
||||||
|
max-width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ol-panel-info {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-panel-info > .panel-section {
|
||||||
|
border-right: 1px solid #555;
|
||||||
|
padding:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-panel-info > .panel-section:last-of-type {
|
||||||
|
border-right-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.highlight-primary {
|
||||||
|
background-color: var(--highlight-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-bluefor {
|
||||||
|
background-color: var(--blue-coalition-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-redfor {
|
||||||
|
background-color: var(--red-coalition-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-neutral {
|
||||||
|
background-color: var(--neutral-coalition-color);
|
||||||
|
color: var(--neutral-coalition-text)
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
@import url("mouseinfopanel.css");
|
@import url("mouseinfopanel.css");
|
||||||
|
|
||||||
@import url( "aic.css" );
|
@import url( "aic.css" );
|
||||||
|
@import url( "atc.css" );
|
||||||
|
|
||||||
@import url("layout.css");
|
@import url("layout.css");
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
* {
|
* {
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
|||||||
54
client/public/stylesheets/uikit.css
Normal file
54
client/public/stylesheets/uikit.css
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
body {
|
||||||
|
background-color:#eaeaea;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content-wrapper {
|
||||||
|
row-gap: 5px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
height:100%;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
column-gap: 20px;
|
||||||
|
display:flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
font-size:125%;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 1vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background:white;
|
||||||
|
border-radius: 10px;
|
||||||
|
height:fit-content;
|
||||||
|
margin-bottom:4vh;
|
||||||
|
padding:20px;
|
||||||
|
width:fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-header {
|
||||||
|
color:#666;
|
||||||
|
letter-spacing:1px;
|
||||||
|
margin-bottom: 1vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-body {
|
||||||
|
column-gap: 20px;
|
||||||
|
display:flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caption {
|
||||||
|
margin:2vh 0 1vh 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#paragraph {
|
||||||
|
max-width: 750px;
|
||||||
|
}
|
||||||
181
client/public/uikit.html
Normal file
181
client/public/uikit.html
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Olympus UI Kit</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheets/olympus.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="stylesheets/uikit.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="content-wrapper">
|
||||||
|
|
||||||
|
<h1>Olympus UI Kit</h1>
|
||||||
|
|
||||||
|
<div class="section-header">Typeography</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<div class="content-header">Headings</div>
|
||||||
|
<div class="content-body">
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<h1>h1 | open sans | 32px</h1>
|
||||||
|
<h2>h2 | open sans | 24px</h2>
|
||||||
|
<h3>h3 | open sans | 18.72px</h3>
|
||||||
|
<h4>h4 | open sans | 16px</h4>
|
||||||
|
<h5>h5 | open sans | 13.28px</h5>
|
||||||
|
<h6>h6 | open sans | 10.72px</h6>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="paragraph" class="content">
|
||||||
|
|
||||||
|
<div class="content-header">Paragraph</div>
|
||||||
|
<div class="content-body">
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<div class="caption">Plain</div>
|
||||||
|
<p>Nullam iaculis nisi sed mi tincidunt pretium blandit tempus urna. Vestibulum non ex vitae massa tristique auctor. Praesent orci justo, porttitor pellentesque convallis non, commodo at augue.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<div class="caption">In a panel</div>
|
||||||
|
<div class="ol-panel">
|
||||||
|
<p>Donec nibh est, fringilla sed pharetra eu, varius vel sem. Aliquam ac libero leo. Sed consectetur enim aliquam dui pellentesque luctus. Pellentesque vel iaculis quam.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="section-header">.ol-panel</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<div class="content-header">Plain panel</div>
|
||||||
|
|
||||||
|
<div class="content-body">
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
|
||||||
|
<div class="ol-panel">
|
||||||
|
Disconnected
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<div class="content-header">Panel list</div>
|
||||||
|
|
||||||
|
<div class="content-body">
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
|
||||||
|
<div class="caption">Basic list</div>
|
||||||
|
|
||||||
|
<div class="ol-panel">
|
||||||
|
<div class="ol-panel-list">
|
||||||
|
<div class="list-item">List item 1</div>
|
||||||
|
<div class="list-item">List item 2</div>
|
||||||
|
<div class="list-item">List item 3</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
|
||||||
|
<div class="caption">List with .highlight-primary</div>
|
||||||
|
|
||||||
|
<div class="ol-panel">
|
||||||
|
<div class="ol-panel-list">
|
||||||
|
<div class="list-item highlight-primary">List item with highlight-primary</div>
|
||||||
|
<div class="list-item highlight-bluefor">List item with highlight-bluefor</div>
|
||||||
|
<div class="list-item highlight-redfor">List item with highlight-redfor</div>
|
||||||
|
<div class="list-item highlight-neutral">List item with highlight-neutral</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
|
||||||
|
<div class="caption">Sortable list</div>
|
||||||
|
|
||||||
|
<div class="ol-panel">
|
||||||
|
<div class="ol-panel-list sortable">
|
||||||
|
<div class="sortable-item">
|
||||||
|
<div class="handle"><img src="images/buttons/reorder.svg" /></div>
|
||||||
|
<div class="list-item">List item 1</div>
|
||||||
|
</div>
|
||||||
|
<div class="sortable-item">
|
||||||
|
<div class="handle"><img src="images/buttons/reorder.svg" /></div>
|
||||||
|
<div class="list-item">List item 2</div>
|
||||||
|
</div>
|
||||||
|
<div class="sortable-item">
|
||||||
|
<div class="handle"><img src="images/buttons/reorder.svg" /></div>
|
||||||
|
<div class="list-item">List item 3</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- JavaScript: new Sortable( element:HTMLElement, [ options:object ]) -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<div class="content-header">.ol-panel > .ol-panel-info</div>
|
||||||
|
|
||||||
|
<div class="content-body">
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
|
||||||
|
<div class="ol-panel">
|
||||||
|
<div class="ol-panel-info">
|
||||||
|
<div class="panel-section">
|
||||||
|
Info panel number 1
|
||||||
|
</div>
|
||||||
|
<div class="panel-section">
|
||||||
|
Info panel number 2
|
||||||
|
</div>
|
||||||
|
<div class="panel-section">
|
||||||
|
Info panel number 3
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
77
client/src/FeatureSwitches.ts
Normal file
77
client/src/FeatureSwitches.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
export interface FeatureSwitchInterface {
|
||||||
|
"enabled": boolean,
|
||||||
|
"label": string,
|
||||||
|
"name": string,
|
||||||
|
"options"?: object,
|
||||||
|
"removeArtifactsIfDisabled"?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureSwitch {
|
||||||
|
enabled;
|
||||||
|
label;
|
||||||
|
name;
|
||||||
|
removeArtifactsIfDisabled = true;
|
||||||
|
|
||||||
|
constructor( config:FeatureSwitchInterface ) {
|
||||||
|
|
||||||
|
this.enabled = config.enabled;
|
||||||
|
this.label = config.label;
|
||||||
|
this.name = config.name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isEnabled() {
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FeatureSwitches {
|
||||||
|
|
||||||
|
#featureSwitches:FeatureSwitch[] = [
|
||||||
|
|
||||||
|
new FeatureSwitch({
|
||||||
|
"enabled": false,
|
||||||
|
"label": "AIC",
|
||||||
|
"name": "aic"
|
||||||
|
}),
|
||||||
|
|
||||||
|
new FeatureSwitch({
|
||||||
|
"enabled": false,
|
||||||
|
"label": "ATC",
|
||||||
|
"name": "atc",
|
||||||
|
"options": {
|
||||||
|
"key": "value"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
this.#removeArtifacts();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getSwitch( switchName:string ) {
|
||||||
|
|
||||||
|
return this.#featureSwitches.find( featureSwitch => featureSwitch.name === switchName );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#removeArtifacts() {
|
||||||
|
|
||||||
|
for ( const featureSwitch of this.#featureSwitches ) {
|
||||||
|
if ( !featureSwitch.isEnabled() && featureSwitch.removeArtifactsIfDisabled !== false ) {
|
||||||
|
document.querySelectorAll( "[data-feature-switch='" + featureSwitch.name + "']" ).forEach( el => el.remove() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
35
client/src/ToggleableFeature.ts
Normal file
35
client/src/ToggleableFeature.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
export abstract class ToggleableFeature {
|
||||||
|
|
||||||
|
#status:boolean = false;
|
||||||
|
|
||||||
|
|
||||||
|
constructor( defaultStatus:boolean ) {
|
||||||
|
|
||||||
|
this.#status = defaultStatus;
|
||||||
|
|
||||||
|
this.onStatusUpdate();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getStatus() : boolean {
|
||||||
|
return this.#status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected onStatusUpdate() {}
|
||||||
|
|
||||||
|
|
||||||
|
toggleStatus( force?:boolean ) : void {
|
||||||
|
|
||||||
|
if ( force ) {
|
||||||
|
this.#status = force;
|
||||||
|
} else {
|
||||||
|
this.#status = !this.#status;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onStatusUpdate();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
|
import { ToggleableFeature } from "../ToggleableFeature";
|
||||||
import { AICFormation_Azimuth } from "./AICFormation/Azimuth";
|
import { AICFormation_Azimuth } from "./AICFormation/Azimuth";
|
||||||
import { AICFormation_Range } from "./AICFormation/Range";
|
import { AICFormation_Range } from "./AICFormation/Range";
|
||||||
import { AICFormation_Single } from "./AICFormation/Single";
|
import { AICFormation_Single } from "./AICFormation/Single";
|
||||||
import { AICFormationDescriptorSection } from "./AICFormationDescriptorSection";
|
import { AICFormationDescriptorSection } from "./AICFormationDescriptorSection";
|
||||||
|
|
||||||
|
|
||||||
export class AIC {
|
export class AIC extends ToggleableFeature {
|
||||||
|
|
||||||
#status:boolean = true;
|
|
||||||
|
|
||||||
#formations = [
|
#formations = [
|
||||||
|
|
||||||
@@ -18,8 +17,10 @@ export class AIC {
|
|||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
|
super( false );
|
||||||
|
|
||||||
this.#onStatusUpdate();
|
this.onStatusUpdate();
|
||||||
|
|
||||||
// This feels kind of dirty
|
// This feels kind of dirty
|
||||||
let $aicFormationList = document.getElementById( "aic-formation-list" );
|
let $aicFormationList = document.getElementById( "aic-formation-list" );
|
||||||
@@ -80,30 +81,10 @@ export class AIC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getStatus() {
|
onStatusUpdate() {
|
||||||
return this.#status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#onStatusUpdate() {
|
|
||||||
|
|
||||||
const status:boolean = this.getStatus();
|
|
||||||
|
|
||||||
// Update the DOM
|
// Update the DOM
|
||||||
document.body.classList.toggle( "aic-enabled", status );
|
document.body.classList.toggle( "aic-enabled", this.getStatus() );
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
toggleStatus(force?:boolean) {
|
|
||||||
|
|
||||||
if ( force ) {
|
|
||||||
this.#status = force;
|
|
||||||
} else {
|
|
||||||
this.#status = !this.#status;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#onStatusUpdate();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
87
client/src/atc/ATC.ts
Normal file
87
client/src/atc/ATC.ts
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import { ToggleableFeature } from "../ToggleableFeature";
|
||||||
|
import Sortable from 'sortablejs';
|
||||||
|
import { ATCFLightList } from "./FlightList";
|
||||||
|
|
||||||
|
export class ATC extends ToggleableFeature {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
super( true );
|
||||||
|
|
||||||
|
//this.#generateFlightList();
|
||||||
|
|
||||||
|
let $list = document.getElementById( "atc-strip-board-arrivals" );
|
||||||
|
|
||||||
|
if ( $list instanceof HTMLElement ) {
|
||||||
|
Sortable.create( $list, {
|
||||||
|
"handle": ".handle"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#generateFlightList() {
|
||||||
|
|
||||||
|
const flightList = new ATCFLightList();
|
||||||
|
const flights:any = flightList.getFlights( true );
|
||||||
|
|
||||||
|
const $tbody = document.getElementById( "atc-flight-list-table-body" );
|
||||||
|
|
||||||
|
if ( $tbody instanceof HTMLElement ) {
|
||||||
|
|
||||||
|
if ( flights.length > 0 ) {
|
||||||
|
|
||||||
|
let flight:any = {};
|
||||||
|
|
||||||
|
let $button, i;
|
||||||
|
|
||||||
|
for ( [ i, flight ] of flights.entries() ) {
|
||||||
|
|
||||||
|
const $row = document.createElement( "tr" );
|
||||||
|
$row.dataset.status = flight.status
|
||||||
|
|
||||||
|
let $td = document.createElement( "td" );
|
||||||
|
$td.innerText = flight.name;
|
||||||
|
$row.appendChild( $td );
|
||||||
|
|
||||||
|
$td = document.createElement( "td" );
|
||||||
|
$td.innerText = flight.takeOffTime;
|
||||||
|
$row.appendChild( $td );
|
||||||
|
|
||||||
|
$td = document.createElement( "td" );
|
||||||
|
$td.innerText = "00:0" + ( 5 + i );
|
||||||
|
$row.appendChild( $td );
|
||||||
|
|
||||||
|
$td = document.createElement( "td" );
|
||||||
|
$td.innerText = flight.status;
|
||||||
|
$row.appendChild( $td );
|
||||||
|
|
||||||
|
|
||||||
|
$td = document.createElement( "td" );
|
||||||
|
$button = document.createElement( "button" );
|
||||||
|
$button.innerText = "...";
|
||||||
|
|
||||||
|
$td.appendChild( $button );
|
||||||
|
|
||||||
|
$row.appendChild( $td );
|
||||||
|
|
||||||
|
|
||||||
|
$tbody.appendChild( $row );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected onStatusUpdate(): void {
|
||||||
|
|
||||||
|
document.body.classList.toggle( "atc-enabled", this.getStatus() );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
export interface ATCAPIInterface {
|
|
||||||
get: CallableFunction
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class ATCAPI {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
7
client/src/atc/ATCMockAPI.ts
Normal file
7
client/src/atc/ATCMockAPI.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export abstract class ATCMockAPI {
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
generateMockData() {}
|
||||||
|
|
||||||
|
}
|
||||||
40
client/src/atc/ATCMockAPI/Flights.ts
Normal file
40
client/src/atc/ATCMockAPI/Flights.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { ATCMockAPI } from "../ATCMockAPI";
|
||||||
|
|
||||||
|
export class ATCMockAPI_Flights extends ATCMockAPI {
|
||||||
|
|
||||||
|
|
||||||
|
generateMockData() {
|
||||||
|
|
||||||
|
let data = [];
|
||||||
|
const statuses = [ "unknown", "checkedIn", "readyToTaxi" ]
|
||||||
|
|
||||||
|
for ( const [ i, flightName ] of [ "Shark", "Whale", "Dolphin" ].entries() ) {
|
||||||
|
|
||||||
|
data.push({
|
||||||
|
"name": flightName,
|
||||||
|
"status": statuses[ i ],
|
||||||
|
"takeOffTime": "18:0" + i
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem( "flightList", JSON.stringify( data ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get( generateMockDataIfEmpty?:boolean ) : object {
|
||||||
|
|
||||||
|
generateMockDataIfEmpty = generateMockDataIfEmpty || false;
|
||||||
|
|
||||||
|
let data = localStorage.getItem( "flightList" ) || "[]";
|
||||||
|
|
||||||
|
if ( data === "[]" && generateMockDataIfEmpty ) {
|
||||||
|
this.generateMockData();
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse( data );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
client/src/atc/FlightList.ts
Normal file
18
client/src/atc/FlightList.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { ATCMockAPI_Flights } from "./ATCMockAPI/Flights";
|
||||||
|
|
||||||
|
export class ATCFLightList {
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getFlights( generateMockDataIfEmpty?:boolean ) {
|
||||||
|
let api = new ATCMockAPI_Flights();
|
||||||
|
return api.get( generateMockDataIfEmpty );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ import { Slider } from "./controls/slider";
|
|||||||
import { AIC } from "./aic/AIC";
|
import { AIC } from "./aic/AIC";
|
||||||
|
|
||||||
import { VisibilityControlPanel } from "./panels/visibilitycontrolpanel";
|
import { VisibilityControlPanel } from "./panels/visibilitycontrolpanel";
|
||||||
|
import { ATC } from "./atc/ATC";
|
||||||
|
import { FeatureSwitches } from "./FeatureSwitches";
|
||||||
|
|
||||||
/* TODO: should this be a class? */
|
/* TODO: should this be a class? */
|
||||||
var map: Map;
|
var map: Map;
|
||||||
@@ -41,13 +43,22 @@ var aic: AIC;
|
|||||||
var aicToggleButton: Button;
|
var aicToggleButton: Button;
|
||||||
var aicHelpButton: Button;
|
var aicHelpButton: Button;
|
||||||
|
|
||||||
|
|
||||||
|
var atc: ATC;
|
||||||
|
var atcToggleButton: Button;
|
||||||
|
|
||||||
var altitudeSlider: Slider;
|
var altitudeSlider: Slider;
|
||||||
var airspeedSlider: Slider;
|
var airspeedSlider: Slider;
|
||||||
|
|
||||||
var connected: boolean;
|
var connected: boolean;
|
||||||
var activeCoalition: string;
|
var activeCoalition: string;
|
||||||
|
|
||||||
|
var featureSwitches;
|
||||||
|
|
||||||
function setup() {
|
function setup() {
|
||||||
|
|
||||||
|
featureSwitches = new FeatureSwitches();
|
||||||
|
|
||||||
/* Initialize */
|
/* Initialize */
|
||||||
map = new Map('map-container');
|
map = new Map('map-container');
|
||||||
unitsManager = new UnitsManager();
|
unitsManager = new UnitsManager();
|
||||||
@@ -63,9 +74,6 @@ function setup() {
|
|||||||
mouseInfoPanel = new MouseInfoPanel("mouse-info-panel");
|
mouseInfoPanel = new MouseInfoPanel("mouse-info-panel");
|
||||||
visibilityControlPanel = new VisibilityControlPanel("visibility-control-panel");
|
visibilityControlPanel = new VisibilityControlPanel("visibility-control-panel");
|
||||||
|
|
||||||
scenarioDropdown = new Dropdown("scenario-dropdown", ["Caucasus", "Syria", "Marianas", "Nevada", "South Atlantic", "The channel"], () => { });
|
|
||||||
mapSourceDropdown = new Dropdown("map-source-dropdown", map.getLayers(), (option: string) => map.setLayer(option));
|
|
||||||
|
|
||||||
missionData = new MissionData();
|
missionData = new MissionData();
|
||||||
|
|
||||||
/* Unit control buttons */
|
/* Unit control buttons */
|
||||||
@@ -79,15 +87,20 @@ function setup() {
|
|||||||
airspeedSlider = new Slider("airspeed-slider", 0, 100, "kts", (value: number) => getUnitsManager().selectedUnitsSetSpeed(value / 1.94384));
|
airspeedSlider = new Slider("airspeed-slider", 0, 100, "kts", (value: number) => getUnitsManager().selectedUnitsSetSpeed(value / 1.94384));
|
||||||
|
|
||||||
/* AIC */
|
/* AIC */
|
||||||
aic = new AIC();
|
|
||||||
|
|
||||||
aicToggleButton = new Button( "toggle-aic-button", ["images/buttons/radar.svg"], () => {
|
let aicFeatureSwitch = featureSwitches.getSwitch( "aic" );
|
||||||
aic.toggleStatus();
|
|
||||||
});
|
|
||||||
|
|
||||||
aicHelpButton = new Button( "aic-help-button", [ "images/buttons/question-mark.svg" ], () => {
|
if ( aicFeatureSwitch?.isEnabled() ) {
|
||||||
aic.toggleHelp();
|
aic = new AIC();
|
||||||
});
|
|
||||||
|
aicToggleButton = new Button( "toggle-aic-button", ["images/buttons/radar.svg"], () => {
|
||||||
|
aic.toggleStatus();
|
||||||
|
});
|
||||||
|
|
||||||
|
aicHelpButton = new Button( "aic-help-button", [ "images/buttons/question-mark.svg" ], () => {
|
||||||
|
aic.toggleHelp();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Generic clicks */
|
/* Generic clicks */
|
||||||
@@ -104,6 +117,22 @@ function setup() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*** ATC ***/
|
||||||
|
|
||||||
|
let atcFeatureSwitch = featureSwitches.getSwitch( "atc" );
|
||||||
|
|
||||||
|
if ( atcFeatureSwitch?.isEnabled() ) {
|
||||||
|
|
||||||
|
atc = new ATC();
|
||||||
|
|
||||||
|
atcToggleButton = new Button( "atc-toggle-button", [ "images/buttons/atc.svg" ], () => {
|
||||||
|
atc.toggleStatus();
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Default values */
|
/* Default values */
|
||||||
activeCoalition = "blue";
|
activeCoalition = "blue";
|
||||||
connected = false;
|
connected = false;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<div class="ol-panel aic-panel" id="aic-control-panel">
|
<div class="ol-panel aic-panel" id="aic-control-panel" data-feature-switch="aic">
|
||||||
<div class="olympus-button" id="toggle-aic-button"></div>
|
<div class="olympus-button" id="toggle-aic-button"></div>
|
||||||
<div class="olympus-button" id="aic-help-button"></div>
|
<div class="olympus-button" id="aic-help-button"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="aic-help" class="olympus-dialog hide">
|
<div id="aic-help" class="olympus-dialog hide" data-feature-switch="aic">
|
||||||
<div class="olympus-dialog-close">×</div>
|
<div class="olympus-dialog-close">×</div>
|
||||||
<div class="olympus-dialog-header">AIC Help</div>
|
<div class="olympus-dialog-header">AIC Help</div>
|
||||||
<div class="olympus-dialog-content">
|
<div class="olympus-dialog-content">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div id="aic-callsign-panel" class="aic-panel">
|
<div id="aic-callsign-panel" class="aic-panel" data-feature-switch="aic">
|
||||||
|
|
||||||
<div class="aic-panel">
|
<div class="aic-panel">
|
||||||
<h2>My callsign</h2>
|
<h2>My callsign</h2>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="aic-toolbox" class="aic-panel">
|
<div id="aic-toolbox" class="aic-panel" data-feature-switch="aic">
|
||||||
|
|
||||||
<div id="aic-control-type" class="aic-toolbox-panel">
|
<div id="aic-control-type" class="aic-toolbox-panel">
|
||||||
<h2>Control</h2>
|
<h2>Control</h2>
|
||||||
|
|||||||
105
client/views/atc.ejs
Normal file
105
client/views/atc.ejs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<div id="atc-control-panel" data-feature-switch="atc">
|
||||||
|
<div class="ol-button" id="atc-toggle-button"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="atc-flight-list" class="atc-tool hide" data-feature-switch="atc">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Flight</th>
|
||||||
|
<th>T/O</th>
|
||||||
|
<th>TTG</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="atc-flight-list-table-body"></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="atc-strip-board" data-feature-switch="atc">
|
||||||
|
|
||||||
|
<div class="atc-strip-board-header">
|
||||||
|
<div class="name">Name</div>
|
||||||
|
<div class="bearing-range">BR</div>
|
||||||
|
<div class="target-altitude">t. Alt</div>
|
||||||
|
<div class="current-altitude">Alt</div>
|
||||||
|
<div class="target-speed">t. Spd</div>
|
||||||
|
<div class="current-speed">Speed</div>
|
||||||
|
<div class="runway">RWY</div>
|
||||||
|
<div class="line">Line</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="atc-strip-board-arrivals" class="atc-strip-board-strips ol-panel">
|
||||||
|
<div class="atc-strip-board-strip">
|
||||||
|
<div class="handle"></div>
|
||||||
|
<div class="rectangular-container">
|
||||||
|
<div class="name">Shark 3</div>
|
||||||
|
<div class="bearing-range">250 / 28</div>
|
||||||
|
<div class="target-altitude">-</div>
|
||||||
|
<div class="current-altitude">10000</div>
|
||||||
|
<div class="target-speed">-</div>
|
||||||
|
<div class="current-speed">421</div>
|
||||||
|
<div class="runway">-</div>
|
||||||
|
<div class="line">-</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="atc-strip-board-strip">
|
||||||
|
<div class="handle"></div>
|
||||||
|
<div class="rectangular-container">
|
||||||
|
<div class="name">Shark 2</div>
|
||||||
|
<div class="bearing-range">250 / 24</div>
|
||||||
|
<div class="target-altitude">6000</div>
|
||||||
|
<div class="current-altitude">6000</div>
|
||||||
|
<div class="target-speed">-</div>
|
||||||
|
<div class="current-speed">400</div>
|
||||||
|
<div class="runway">-</div>
|
||||||
|
<div class="line">-</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="atc-strip-board-strip">
|
||||||
|
<div class="handle"></div>
|
||||||
|
<div class="rectangular-container">
|
||||||
|
<div class="name">Shark 1</div>
|
||||||
|
<div class="bearing-range link-warning">262 / 12</div>
|
||||||
|
<div class="target-altitude">5000</div>
|
||||||
|
<div class="current-altitude">5100</div>
|
||||||
|
<div class="target-speed">-</div>
|
||||||
|
<div class="current-speed">367</div>
|
||||||
|
<div class="runway warning">-</div>
|
||||||
|
<div class="line">-</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="atc-strip-board-strip">
|
||||||
|
<div class="handle"></div>
|
||||||
|
<div class="rectangular-container">
|
||||||
|
<div class="name">Dolphin 1</div>
|
||||||
|
<div class="bearing-range">250 / 4</div>
|
||||||
|
<div class="target-altitude link-warning">3000</div>
|
||||||
|
<div class="current-altitude warning">4100</div>
|
||||||
|
<div class="target-speed">-</div>
|
||||||
|
<div class="current-speed">511</div>
|
||||||
|
<div class="runway">25L</div>
|
||||||
|
<div class="line">2nd</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="atc-strip-board-strip">
|
||||||
|
<div class="handle"></div>
|
||||||
|
<div class="rectangular-container">
|
||||||
|
<div class="name">Whale 1</div>
|
||||||
|
<div class="bearing-range">070 / 2</div>
|
||||||
|
<div class="target-altitude">1500</div>
|
||||||
|
<div class="current-altitude">1650</div>
|
||||||
|
<div class="target-speed link-warning">350</div>
|
||||||
|
<div class="current-speed warning">312</div>
|
||||||
|
<div class="runway">25L</div>
|
||||||
|
<div class="line">1st</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -31,9 +31,12 @@
|
|||||||
<%- include('visibilitycontrolpanel.ejs') %>
|
<%- include('visibilitycontrolpanel.ejs') %>
|
||||||
<%- include('connectionstatuspanel.ejs') %>
|
<%- include('connectionstatuspanel.ejs') %>
|
||||||
<%- include('mouseinfopanel.ejs') %>
|
<%- include('mouseinfopanel.ejs') %>
|
||||||
|
|
||||||
<%- include('aiccontrolpanel.ejs') %>
|
<%- include('aiccontrolpanel.ejs') %>
|
||||||
<%- include('aicformationpanel.ejs') %>
|
<%- include('aicformationpanel.ejs') %>
|
||||||
|
|
||||||
|
<%- include( 'atc.ejs' ) %>
|
||||||
|
|
||||||
<script src="javascripts/bundle.js"></script>
|
<script src="javascripts/bundle.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -6,7 +6,8 @@
|
|||||||
"": {
|
"": {
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"mocha": "^10.2.0"
|
"mocha": "^10.2.0",
|
||||||
|
"sortablejs": "^1.15.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ansi-colors": {
|
"node_modules/ansi-colors": {
|
||||||
@@ -827,6 +828,12 @@
|
|||||||
"randombytes": "^2.1.0"
|
"randombytes": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sortablejs": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/string-width": {
|
"node_modules/string-width": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"mocha": "^10.2.0"
|
"mocha": "^10.2.0",
|
||||||
|
"sortablejs": "^1.15.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user