mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added frontend code for authentication
This commit is contained in:
parent
865be6283c
commit
57b74bd1b1
@ -3,6 +3,7 @@ var path = require('path');
|
||||
var cookieParser = require('cookie-parser');
|
||||
var logger = require('morgan');
|
||||
var fs = require('fs');
|
||||
var basicAuth = require('express-basic-auth')
|
||||
|
||||
var atcRouter = require('./routes/api/atc');
|
||||
var indexRouter = require('./routes/index');
|
||||
@ -11,6 +12,10 @@ var usersRouter = require('./routes/users');
|
||||
|
||||
var app = express();
|
||||
|
||||
app.use('/demo', basicAuth({
|
||||
users: { 'admin': 'socks' }
|
||||
}))
|
||||
|
||||
app.use(logger('dev'));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
@ -38,3 +43,5 @@ app.get('/demo/bullseyes', (req, res) => demoDataGenerator.bullseyes(req, res));
|
||||
app.get('/demo/airbases', (req, res) => demoDataGenerator.airbases(req, res));
|
||||
app.get('/demo/mission', (req, res) => demoDataGenerator.mission(req, res));
|
||||
|
||||
|
||||
|
||||
|
||||
19
client/package-lock.json
generated
19
client/package-lock.json
generated
@ -31,6 +31,7 @@
|
||||
"browserify": "^17.0.0",
|
||||
"concurrently": "^7.6.0",
|
||||
"esmify": "^2.1.1",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"nodemon": "^2.0.20",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tsify": "^5.0.4",
|
||||
@ -3283,6 +3284,15 @@
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express-basic-auth": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz",
|
||||
"integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"basic-auth": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/cookie": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||
@ -8148,6 +8158,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"express-basic-auth": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz",
|
||||
"integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"basic-auth": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"fast-safe-stringify": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
"browserify": "^17.0.0",
|
||||
"concurrently": "^7.6.0",
|
||||
"esmify": "^2.1.1",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"nodemon": "^2.0.20",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tsify": "^5.0.4",
|
||||
|
||||
@ -16,12 +16,13 @@
|
||||
|
||||
#olympus-toolbar-summary {
|
||||
background-image: url("/images/icon-round.png");
|
||||
background-position: 25px 20px;
|
||||
background-position: 20px 22px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 36px 36px;
|
||||
background-size: 45px 45px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-indent: 44px;
|
||||
text-indent: 60px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
dl.ol-data-grid {
|
||||
|
||||
@ -251,13 +251,14 @@ form>div {
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
padding: 5px;
|
||||
border-radius: var(--border-radius-sm);
|
||||
}
|
||||
|
||||
.ol-select>.ol-select-options>div a:hover,
|
||||
.ol-select>.ol-select-options>div button:hover {
|
||||
background-color: #FFF3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ol-panel-list {
|
||||
@ -725,21 +726,21 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit {
|
||||
#splash-screen {
|
||||
background-image: url("/images/splash/splash_pic_ship.png");
|
||||
background-position: 100% 50%;
|
||||
background-size: 320px;
|
||||
background-size: 60%;
|
||||
border-radius: var(--border-radius-lg);
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
width: 700px;
|
||||
width: 1200px;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
#splash-content {
|
||||
background-color: var(--background-steel);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
padding: 30px;
|
||||
position: relative;
|
||||
row-gap: 10px;
|
||||
width: 55%;
|
||||
width: 50%;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@ -747,7 +748,7 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit {
|
||||
background-color: var(--background-steel);
|
||||
content: "";
|
||||
display: block;
|
||||
height: 250px;
|
||||
height: 800px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
@ -775,20 +776,84 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit {
|
||||
line-height: 25px;
|
||||
white-space: nowrap;
|
||||
width: fit-content;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#splash-content .app-version {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#splash-content #legal-stuff h4 {
|
||||
#splash-content #legal-stuff h5 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#splash-content #legal-stuff p {
|
||||
font-size: 10px;
|
||||
color:#FFF7;
|
||||
width: 120%;
|
||||
}
|
||||
|
||||
#splash-content.ol-dialog-content {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.feature-splashScreen #splash-screen {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#gray-out {
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
z-index: 9999;
|
||||
background-color: #000A;
|
||||
}
|
||||
|
||||
#authentication-form {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
column-gap: 10px;
|
||||
margin: 10px 0px;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#authentication-form>div {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
row-gap: 4px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#authentication-form>div>input {
|
||||
height: 35px;
|
||||
border-radius: var(--border-radius-sm);
|
||||
border: 0px solid transparent;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#splash-content a {
|
||||
color: #FFFB;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#connection-status {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#connection-status[data-status="connecting"]::before {
|
||||
content: "Connecting...";
|
||||
animation: blinker 1s linear infinite;
|
||||
}
|
||||
|
||||
#connection-status[data-status="failed"]::before {
|
||||
content: "Incorrect username/password!";
|
||||
color: var(--primary-red);
|
||||
}
|
||||
|
||||
@keyframes blinker {
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@ -90,7 +90,7 @@ export class FeatureSwitches {
|
||||
}),
|
||||
|
||||
new FeatureSwitch({
|
||||
"defaultEnabled": false,
|
||||
"defaultEnabled": true,
|
||||
"label": "Show splash screen",
|
||||
"masterSwitch": true,
|
||||
"name": "splashScreen"
|
||||
@ -116,36 +116,24 @@ export class FeatureSwitches {
|
||||
|
||||
|
||||
#testSwitches() {
|
||||
|
||||
for ( const featureSwitch of this.#featureSwitches ) {
|
||||
|
||||
if ( featureSwitch.isEnabled() ) {
|
||||
|
||||
if ( typeof featureSwitch.onEnabled === "function" ) {
|
||||
featureSwitch.onEnabled();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
document.querySelectorAll( "[data-feature-switch='" + featureSwitch.name + "']" ).forEach( el => {
|
||||
|
||||
if ( featureSwitch.removeArtifactsIfDisabled === false ) {
|
||||
el.remove();
|
||||
} else {
|
||||
el.classList.add( "hide" );
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
document.body.classList.toggle( "feature-" + featureSwitch.name, featureSwitch.isEnabled() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
savePreferences() {
|
||||
|
||||
let preferences:any = {};
|
||||
|
||||
@ -9,7 +9,7 @@ import { AIC } from "./aic/aic";
|
||||
import { ATC } from "./atc/atc";
|
||||
import { FeatureSwitches } from "./featureswitches";
|
||||
import { LogPanel } from "./panels/logpanel";
|
||||
import { getAirbases, getBullseye as getBullseyes, getConfig, getMission, getUnits, setAddress, toggleDemoEnabled } from "./server/server";
|
||||
import { getAirbases, getBullseye, getConfig, getFreezed, getMission, getUnits, setAddress, setCredentials, setFreezed, startUpdate, toggleDemoEnabled } from "./server/server";
|
||||
import { UnitDataTable } from "./units/unitdatatable";
|
||||
import { keyEventWasInInput } from "./other/utils";
|
||||
import { Popup } from "./popups/popup";
|
||||
@ -31,11 +31,8 @@ var logPanel: LogPanel;
|
||||
|
||||
var infoPopup: Popup;
|
||||
|
||||
var connected: boolean = false;
|
||||
var paused: boolean = false;
|
||||
var activeCoalition: string = "blue";
|
||||
|
||||
var sessionHash: string | null = null;
|
||||
var unitDataTable: UnitDataTable;
|
||||
|
||||
var featureSwitches;
|
||||
@ -49,15 +46,18 @@ function setup() {
|
||||
missionHandler = new MissionHandler();
|
||||
|
||||
/* Panels */
|
||||
unitInfoPanel = new UnitInfoPanel("unit-info-panel");
|
||||
unitControlPanel = new UnitControlPanel("unit-control-panel");
|
||||
connectionStatusPanel = new ConnectionStatusPanel("connection-status-panel");
|
||||
mouseInfoPanel = new MouseInfoPanel("mouse-info-panel");
|
||||
unitInfoPanel = new UnitInfoPanel("unit-info-panel");
|
||||
unitControlPanel = new UnitControlPanel("unit-control-panel");
|
||||
connectionStatusPanel = new ConnectionStatusPanel("connection-status-panel");
|
||||
mouseInfoPanel = new MouseInfoPanel("mouse-info-panel");
|
||||
//logPanel = new LogPanel("log-panel");
|
||||
|
||||
/* Popups */
|
||||
infoPopup = new Popup("info-popup");
|
||||
|
||||
/* Controls */
|
||||
new Dropdown("app-icon", () => { });
|
||||
|
||||
/* Unit data table */
|
||||
unitDataTable = new UnitDataTable("unit-data-table");
|
||||
|
||||
@ -65,7 +65,6 @@ function setup() {
|
||||
let aicFeatureSwitch = featureSwitches.getSwitch("aic");
|
||||
if (aicFeatureSwitch?.isEnabled()) {
|
||||
aic = new AIC();
|
||||
// TODO: add back buttons
|
||||
}
|
||||
|
||||
/* ATC */
|
||||
@ -75,82 +74,23 @@ function setup() {
|
||||
atc.startUpdates();
|
||||
}
|
||||
|
||||
new Dropdown( "app-icon", () => {} );
|
||||
|
||||
/* Setup event handlers */
|
||||
setupEvents();
|
||||
|
||||
getConfig(readConfig)
|
||||
/* Load the config file */
|
||||
getConfig(readConfig);
|
||||
}
|
||||
|
||||
function readConfig(config: any)
|
||||
{
|
||||
if (config && config["server"] != undefined && config["server"]["address"] != undefined && config["server"]["port"] != undefined)
|
||||
{
|
||||
function readConfig(config: any) {
|
||||
if (config && config["server"] != undefined && config["server"]["address"] != undefined && config["server"]["port"] != undefined) {
|
||||
const address = config["server"]["address"];
|
||||
const port = config["server"]["port"];
|
||||
if (typeof address === 'string' && typeof port == 'number')
|
||||
setAddress(address == "*"? window.location.hostname: address, <number>port);
|
||||
|
||||
/* On the first connection, force request of full data */
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {getMissionData()?.update(data)});
|
||||
getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */);
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
startPeriodicUpdate();
|
||||
setAddress(address == "*" ? window.location.hostname : address, <number>port);
|
||||
}
|
||||
else {
|
||||
throw new Error('Could not read configuration file!');
|
||||
}
|
||||
}
|
||||
|
||||
function startPeriodicUpdate() {
|
||||
requestUpdate();
|
||||
requestRefresh();
|
||||
}
|
||||
|
||||
function requestUpdate() {
|
||||
/* Main update rate = 250ms is minimum time, equal to server update time. */
|
||||
getUnits((data: UnitsData) => {
|
||||
if (!getPaused()){
|
||||
getUnitsManager()?.update(data);
|
||||
checkSessionHash(data.sessionHash);
|
||||
}
|
||||
}, false);
|
||||
window.setTimeout(() => requestUpdate(), getConnected() ? 250 : 1000);
|
||||
|
||||
getConnectionStatusPanel()?.update(getConnected());
|
||||
}
|
||||
|
||||
function requestRefresh() {
|
||||
/* Main refresh rate = 5000ms. */
|
||||
getUnits((data: UnitsData) => {
|
||||
if (!getPaused()){
|
||||
getUnitsManager()?.update(data);
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {
|
||||
getMissionData()?.update(data)
|
||||
});
|
||||
|
||||
// Update the list of existing units
|
||||
getUnitDataTable()?.update();
|
||||
|
||||
checkSessionHash(data.sessionHash);
|
||||
}
|
||||
}, true);
|
||||
window.setTimeout(() => requestRefresh(), 5000);
|
||||
}
|
||||
|
||||
function checkSessionHash(newSessionHash: string) {
|
||||
if (sessionHash != null) {
|
||||
if (newSessionHash != sessionHash)
|
||||
location.reload();
|
||||
}
|
||||
else
|
||||
sessionHash = newSessionHash;
|
||||
}
|
||||
|
||||
function setupEvents() {
|
||||
@ -164,7 +104,7 @@ function setupEvents() {
|
||||
}
|
||||
|
||||
const triggerElement = target.closest("[data-on-click]");
|
||||
|
||||
|
||||
if (triggerElement instanceof HTMLElement) {
|
||||
const eventName: string = triggerElement.dataset.onClick || "";
|
||||
let params = JSON.parse(triggerElement.dataset.onClickParams || "{}");
|
||||
@ -181,7 +121,7 @@ function setupEvents() {
|
||||
|
||||
/* Keyup events */
|
||||
document.addEventListener("keyup", ev => {
|
||||
if ( keyEventWasInInput( ev ) ) {
|
||||
if (keyEventWasInInput(ev)) {
|
||||
return;
|
||||
}
|
||||
switch (ev.code) {
|
||||
@ -195,13 +135,13 @@ function setupEvents() {
|
||||
unitDataTable.toggle();
|
||||
break
|
||||
case "Space":
|
||||
setPaused(!getPaused());
|
||||
setFreezed(!getFreezed());
|
||||
break;
|
||||
case "KeyW":
|
||||
case "KeyA":
|
||||
case "KeyS":
|
||||
case "KeyD":
|
||||
case "ArrowLeft":
|
||||
case "ArrowLeft":
|
||||
case "ArrowRight":
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
@ -212,7 +152,7 @@ function setupEvents() {
|
||||
|
||||
/* Keydown events */
|
||||
document.addEventListener("keydown", ev => {
|
||||
if ( keyEventWasInInput( ev ) ) {
|
||||
if (keyEventWasInInput(ev)) {
|
||||
return;
|
||||
}
|
||||
switch (ev.code) {
|
||||
@ -220,7 +160,7 @@ function setupEvents() {
|
||||
case "KeyA":
|
||||
case "KeyS":
|
||||
case "KeyD":
|
||||
case "ArrowLeft":
|
||||
case "ArrowLeft":
|
||||
case "ArrowRight":
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
@ -229,15 +169,31 @@ function setupEvents() {
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener( "closeDialog", (ev: CustomEventInit) => {
|
||||
ev.detail._element.closest( ".ol-dialog" ).classList.add( "hide" );
|
||||
document.addEventListener("closeDialog", (ev: CustomEventInit) => {
|
||||
ev.detail._element.closest(".ol-dialog").classList.add("hide");
|
||||
});
|
||||
|
||||
document.addEventListener( "toggleElements", (ev: CustomEventInit) => {
|
||||
document.querySelectorAll( ev.detail.selector ).forEach( el => {
|
||||
el.classList.toggle( "hide" );
|
||||
document.addEventListener("toggleElements", (ev: CustomEventInit) => {
|
||||
document.querySelectorAll(ev.detail.selector).forEach(el => {
|
||||
el.classList.toggle("hide");
|
||||
})
|
||||
});
|
||||
|
||||
document.addEventListener("tryConnection", () => {
|
||||
const form = document.querySelector("#splash-content")?.querySelector("#authentication-form");
|
||||
const username = (<HTMLInputElement> (form?.querySelector("#username"))).value;
|
||||
const password = (<HTMLInputElement> (form?.querySelector("#password"))).value;
|
||||
setCredentials(username, btoa("admin" + ":" + password));
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
startUpdate();
|
||||
|
||||
setConnectionStatus("connecting");
|
||||
})
|
||||
|
||||
document.addEventListener("reloadPage", () => {
|
||||
location.reload();
|
||||
})
|
||||
}
|
||||
|
||||
export function getMap() {
|
||||
@ -285,23 +241,10 @@ export function getActiveCoalition() {
|
||||
return activeCoalition;
|
||||
}
|
||||
|
||||
export function setConnected(newConnected: boolean) {
|
||||
if (connected != newConnected)
|
||||
newConnected? getInfoPopup().setText("Connected to DCS Olympus server"): getInfoPopup().setText("Disconnected from DCS Olympus server");
|
||||
connected = newConnected;
|
||||
}
|
||||
|
||||
export function getConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
export function setPaused(newPaused: boolean) {
|
||||
paused = newPaused;
|
||||
paused? getInfoPopup().setText("Paused"): getInfoPopup().setText("Unpaused");
|
||||
}
|
||||
|
||||
export function getPaused() {
|
||||
return paused;
|
||||
export function setConnectionStatus(status: string) {
|
||||
const el = document.querySelector("#connection-status") as HTMLElement;
|
||||
if (el)
|
||||
el.dataset["status"] = status;
|
||||
}
|
||||
|
||||
export function getInfoPopup() {
|
||||
|
||||
@ -316,7 +316,7 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
this.setView(bounds.getCenter(), 8);
|
||||
this.setMaxBounds(bounds);
|
||||
//this.setMaxBounds(bounds);
|
||||
|
||||
if (this.#miniMap)
|
||||
this.#miniMap.remove();
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import * as L from 'leaflet'
|
||||
import { setConnected } from '..';
|
||||
import { getConnectionStatusPanel, getInfoPopup, getMissionData, getUnitDataTable, getUnitsManager, setConnectionStatus } from '..';
|
||||
import { SpawnOptions } from '../controls/mapcontextmenu';
|
||||
|
||||
var connected: boolean = false;
|
||||
var freezed: boolean = false;
|
||||
|
||||
var REST_ADDRESS = "http://localhost:30000/olympus";
|
||||
var DEMO_ADDRESS = window.location.href + "demo";
|
||||
const UNITS_URI = "units";
|
||||
@ -10,29 +13,46 @@ const AIRBASES_URI = "airbases";
|
||||
const BULLSEYE_URI = "bullseyes";
|
||||
const MISSION_URI = "mission";
|
||||
|
||||
var username = "";
|
||||
var credentials = "";
|
||||
|
||||
var sessionHash: string | null = null;
|
||||
var lastUpdateTime = 0;
|
||||
var demoEnabled = false;
|
||||
|
||||
export function toggleDemoEnabled()
|
||||
{
|
||||
export function toggleDemoEnabled() {
|
||||
demoEnabled = !demoEnabled;
|
||||
}
|
||||
|
||||
export function GET(callback: CallableFunction, uri: string, options?: string){
|
||||
export function setCredentials(newUsername: string, newCredentials: string) {
|
||||
username = newUsername;
|
||||
credentials = newCredentials;
|
||||
}
|
||||
|
||||
export function GET(callback: CallableFunction, uri: string, options?: string) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("GET", `${demoEnabled? DEMO_ADDRESS: REST_ADDRESS}/${uri}${options? options: ''}`, true);
|
||||
if (credentials)
|
||||
xmlHttp.setRequestHeader("Authorization", "Basic " + credentials);
|
||||
xmlHttp.onload = function (e) {
|
||||
var data = JSON.parse(xmlHttp.responseText);
|
||||
if (uri !== UNITS_URI || parseInt(data.time) > lastUpdateTime)
|
||||
{
|
||||
callback(data);
|
||||
lastUpdateTime = parseInt(data.time);
|
||||
if (isNaN(lastUpdateTime))
|
||||
lastUpdateTime = 0;
|
||||
setConnected(true);
|
||||
if (xmlHttp.status == 200) {
|
||||
var data = JSON.parse(xmlHttp.responseText);
|
||||
if (uri !== UNITS_URI || parseInt(data.time) > lastUpdateTime)
|
||||
{
|
||||
callback(data);
|
||||
lastUpdateTime = parseInt(data.time);
|
||||
if (isNaN(lastUpdateTime))
|
||||
lastUpdateTime = 0;
|
||||
setConnected(true);
|
||||
}
|
||||
} else if (xmlHttp.status == 401) {
|
||||
console.error("Incorrect username/password");
|
||||
setConnectionStatus("failed");
|
||||
} else {
|
||||
setConnected(false);
|
||||
}
|
||||
};
|
||||
xmlHttp.onerror = function () {
|
||||
xmlHttp.onerror = function (res) {
|
||||
console.error("An error occurred during the XMLHttpRequest");
|
||||
setConnected(false);
|
||||
};
|
||||
@ -40,13 +60,15 @@ export function GET(callback: CallableFunction, uri: string, options?: string){
|
||||
}
|
||||
|
||||
export function POST(request: object, callback: CallableFunction){
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", demoEnabled? DEMO_ADDRESS: REST_ADDRESS);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("PUT", demoEnabled? DEMO_ADDRESS: REST_ADDRESS);
|
||||
xmlHttp.setRequestHeader("Content-Type", "application/json");
|
||||
if (credentials)
|
||||
xmlHttp.setRequestHeader("Authorization", "Basic " + credentials);
|
||||
xmlHttp.onreadystatechange = () => {
|
||||
callback();
|
||||
};
|
||||
xhr.send(JSON.stringify(request));
|
||||
xmlHttp.send(JSON.stringify(request));
|
||||
}
|
||||
|
||||
export function getConfig(callback: CallableFunction) {
|
||||
@ -208,4 +230,81 @@ export function setAdvacedOptions(ID: number, isTanker: boolean, isAWACS: boolea
|
||||
|
||||
var data = { "setAdvancedOptions": command };
|
||||
POST(data, () => { });
|
||||
}
|
||||
|
||||
export function startUpdate() {
|
||||
/* On the first connection, force request of full data */
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseye((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => { getMissionData()?.update(data) });
|
||||
getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */);
|
||||
|
||||
requestUpdate();
|
||||
requestRefresh();
|
||||
}
|
||||
|
||||
export function requestUpdate() {
|
||||
/* Main update rate = 250ms is minimum time, equal to server update time. */
|
||||
getUnits((data: UnitsData) => {
|
||||
if (!getFreezed()) {
|
||||
getUnitsManager()?.update(data);
|
||||
checkSessionHash(data.sessionHash);
|
||||
}
|
||||
}, false);
|
||||
window.setTimeout(() => requestUpdate(), getConnected() ? 250 : 1000);
|
||||
|
||||
getConnectionStatusPanel()?.update(getConnected());
|
||||
}
|
||||
|
||||
export function requestRefresh() {
|
||||
/* Main refresh rate = 5000ms. */
|
||||
getUnits((data: UnitsData) => {
|
||||
if (!getFreezed()) {
|
||||
getUnitsManager()?.update(data);
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseye((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {
|
||||
getMissionData()?.update(data)
|
||||
});
|
||||
|
||||
// Update the list of existing units
|
||||
getUnitDataTable()?.update();
|
||||
|
||||
checkSessionHash(data.sessionHash);
|
||||
}
|
||||
}, true);
|
||||
window.setTimeout(() => requestRefresh(), 5000);
|
||||
}
|
||||
|
||||
export function checkSessionHash(newSessionHash: string) {
|
||||
if (sessionHash != null) {
|
||||
if (newSessionHash != sessionHash)
|
||||
location.reload();
|
||||
}
|
||||
else
|
||||
sessionHash = newSessionHash;
|
||||
}
|
||||
|
||||
export function setConnected(newConnected: boolean) {
|
||||
if (connected != newConnected)
|
||||
newConnected ? getInfoPopup().setText("Connected to DCS Olympus server") : getInfoPopup().setText("Disconnected from DCS Olympus server");
|
||||
connected = newConnected;
|
||||
|
||||
if (connected) {
|
||||
document.querySelector("#splash-screen")?.classList.add("hide");
|
||||
document.querySelector("#gray-out")?.classList.add("hide");
|
||||
}
|
||||
}
|
||||
|
||||
export function getConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
export function setFreezed(newFreezed: boolean) {
|
||||
freezed = newFreezed;
|
||||
freezed ? getInfoPopup().setText("Freezed") : getInfoPopup().setText("Unfreezed");
|
||||
}
|
||||
|
||||
export function getFreezed() {
|
||||
return freezed;
|
||||
}
|
||||
@ -1,20 +1,25 @@
|
||||
<div id="splash-screen" class="ol-dialog" data-on-click="closeDialog" oncontextmenu="return false;">
|
||||
|
||||
<div id="splash-screen" class="ol-dialog" oncontextmenu="return false;">
|
||||
<div id="splash-content" class="ol-dialog-content">
|
||||
|
||||
<div id="app-summary">
|
||||
<h2>DCS Olympus</h2>
|
||||
<h4>Dynamic Unit Command</h4>
|
||||
<div class="app-version">Version <span class="app-version-number">v0.2.0</span></div>
|
||||
</div>
|
||||
|
||||
<div id="legal-stuff">
|
||||
<h4>Disclaimer</h4>
|
||||
<p>We ain't no friends with no Eagle Dynamics.</p>
|
||||
<div id="authentication-form">
|
||||
<div><h5>Username</h5> <input type="text" id="username" name="username" required autocomplete="username" placeholder="Enter username..."></div>
|
||||
<div><h5>Password</h5> <input type="password" id="password" name="password" minlength="8" required autocomplete="current-password" placeholder="Enter password..."></div>
|
||||
<button id="connection-button" class="ol-button-apply" data-on-click="tryConnection">Connect</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<h5 id="connection-status"><br></h5>
|
||||
|
||||
<div id="legal-stuff">
|
||||
<h5>DISCLAIMER</h5>
|
||||
<p> DCS Olympus (the "MATERIAL" or "Software") is provided completely free to users subject to the terms of the <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0 Licence</a> except where such terms conflict with this disclaimer, in which case, the terms of this disclaimer shall prevail.
|
||||
The authors and/or copyright holders of the Software have not received any financial benefit in connection with the Software. In any event, the Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non-infringement. In no event shall the authors and/or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software. Any party making use of the Software in any manner agrees to be bound by the terms set out in this disclaimer. THIS MATERIAL IS NOT MADE OR SUPPORTED BY EAGLE DYNAMICS SA.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="advanced-settings-dialog" class="ol-panel ol-dialog olympus-dialog-close hide" oncontextmenu="return false;">
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
<%- include('dialogs.ejs') %>
|
||||
<%- include('unitdatatable.ejs') %>
|
||||
<%- include('popups.ejs') %>
|
||||
|
||||
<div id="gray-out"></div>
|
||||
|
||||
<% /* %>
|
||||
<%- include('log.ejs') %>
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
</div>
|
||||
<div class="ol-select-options">
|
||||
<div id="olympus-toolbar-summary">
|
||||
<h3>Olympus</h3>
|
||||
<div class="accent-green app-version-number">v0.2.0</div>
|
||||
<h3>DCS Olympus</h3>
|
||||
<div class="accent-green app-version-number">version v0.2.0</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://www.discord.com" target="_blank">Discord</a>
|
||||
@ -15,6 +15,9 @@
|
||||
<div>
|
||||
<a href="https://github.com/Pax1601/DCSOlympus" target="_blank">Github</a>
|
||||
</div>
|
||||
<div data-on-click="reloadPage">
|
||||
<a href="" target="_blank" data-on-click="reloadPage">Restart Olyumpus</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user