diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index 756ef17..532f6d6 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -1,6 +1,9 @@ name: Changelog generation -on: [push, pull_request] +on: + push: + branches: + - '**-release-build' jobs: generate-changelog: @@ -42,3 +45,7 @@ jobs: removedLabels: 'removed' unreleasedLabel: '### Unreleased' addSections: '{"documentation":{"prefix":"### Documentation","labels":["documentation"]},"tests":{"prefix":"### Testing","labels":["tests"]}}' + - uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Update Changelog for PR + file_pattern: CHANGELOG.md \ No newline at end of file diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml new file mode 100644 index 0000000..c1a098d --- /dev/null +++ b/.github/workflows/electron-build.yml @@ -0,0 +1,34 @@ +name: Electron Build + +on: + push: + branches: + - master + +defaults: + run: + working-directory: frontendApp + +jobs: + release: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + + steps: + - name: Check out Git repository + uses: actions/checkout@v2 + + - name: Install Node.js, NPM and Yarn + uses: actions/setup-node@v2 + with: + node-version: '14' + - run: | + npm install + npm install -g yarn + - run: yarn add electron-builder --dev + - run: yarn dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/electron-ci.yml b/.github/workflows/electron-ci.yml index f8843cb..5ec6a6a 100644 --- a/.github/workflows/electron-ci.yml +++ b/.github/workflows/electron-ci.yml @@ -20,5 +20,5 @@ jobs: uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - - run: npm ci - - run: npm run test + - run: yarn install --frozen-lockfile + - run: npm test diff --git a/CHANGELOG.md b/CHANGELOG.md index 325bca2..c0af6b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,67 @@ # -## [###](https://github.com/DIT112-V21/group-09/tree/HEAD) +## [v0.4.5](https://github.com/DIT112-V21/group-09/tree/v0.4.5) (2021-05-29) -[Full Changelog](https://github.com/DIT112-V21/group-09/compare/v0.3.0-alpha...HEAD) +[Full Changelog](https://github.com/DIT112-V21/group-09/compare/v0.3.0-alpha...v0.4.5) ### Enhancements +- Detect mission targets [\#107](https://github.com/DIT112-V21/group-09/issues/107) - Initial config files [\#87](https://github.com/DIT112-V21/group-09/issues/87) +- The SmartRover 3D model [\#79](https://github.com/DIT112-V21/group-09/issues/79) - Custom Mars terrain package [\#78](https://github.com/DIT112-V21/group-09/issues/78) - Release and test alpha-1 version [\#57](https://github.com/DIT112-V21/group-09/issues/57) +- Implement Mission save, load [\#121](https://github.com/DIT112-V21/group-09/pull/121) +- User registration and login [\#116](https://github.com/DIT112-V21/group-09/pull/116) +- Implement SmartRover 3D model [\#105](https://github.com/DIT112-V21/group-09/pull/105) +- Update changelog-generator.yml [\#99](https://github.com/DIT112-V21/group-09/pull/99) +- Update changelog generator [\#98](https://github.com/DIT112-V21/group-09/pull/98) - Implement changelog workflow [\#97](https://github.com/DIT112-V21/group-09/pull/97) - Implement Electron config [\#92](https://github.com/DIT112-V21/group-09/pull/92) - Update README.md [\#91](https://github.com/DIT112-V21/group-09/pull/91) +### Bug fixes + +- \[BUGFIX\] Throttle and turn angle limits [\#101](https://github.com/DIT112-V21/group-09/issues/101) +- Implement bugfixes [\#117](https://github.com/DIT112-V21/group-09/pull/117) + +### Deprecated + +- Frontend theme settings [\#35](https://github.com/DIT112-V21/group-09/issues/35) + +### Documentation + +- Instructions for users [\#33](https://github.com/DIT112-V21/group-09/issues/33) +- Add Setup Guides [\#104](https://github.com/DIT112-V21/group-09/pull/104) + ### +- Mission target area signpost [\#90](https://github.com/DIT112-V21/group-09/issues/90) - \[Task\] Install database system and connect to Frontend app [\#89](https://github.com/DIT112-V21/group-09/issues/89) +- User registration and login [\#88](https://github.com/DIT112-V21/group-09/issues/88) +- Mission terrain map [\#77](https://github.com/DIT112-V21/group-09/issues/77) +- Mission table data processing [\#76](https://github.com/DIT112-V21/group-09/issues/76) +- Mission preset templates [\#75](https://github.com/DIT112-V21/group-09/issues/75) +- Mission visual feedback [\#74](https://github.com/DIT112-V21/group-09/issues/74) +- Persistent settings page [\#64](https://github.com/DIT112-V21/group-09/issues/64) - Update README.md to reflect project development [\#58](https://github.com/DIT112-V21/group-09/issues/58) +- Save and load missions [\#27](https://github.com/DIT112-V21/group-09/issues/27) +- Retrieve data after software restart [\#26](https://github.com/DIT112-V21/group-09/issues/26) +- Track mission progress [\#25](https://github.com/DIT112-V21/group-09/issues/25) +- Create user stories for Sprint 4 [\#21](https://github.com/DIT112-V21/group-09/issues/21) +- Create user stories for Sprint 3 [\#20](https://github.com/DIT112-V21/group-09/issues/20) ### +- Implement mission tracking [\#122](https://github.com/DIT112-V21/group-09/pull/122) +- Implement mission control [\#119](https://github.com/DIT112-V21/group-09/pull/119) +- Implement restore session [\#118](https://github.com/DIT112-V21/group-09/pull/118) +- Implement settings page [\#115](https://github.com/DIT112-V21/group-09/pull/115) +- Implement mission templates [\#114](https://github.com/DIT112-V21/group-09/pull/114) +- Add QR Code Feature [\#108](https://github.com/DIT112-V21/group-09/pull/108) +- Implement mission targets [\#106](https://github.com/DIT112-V21/group-09/pull/106) +- Add user Input into an array [\#103](https://github.com/DIT112-V21/group-09/pull/103) +- mission-map-update [\#102](https://github.com/DIT112-V21/group-09/pull/102) - Update settings layout [\#96](https://github.com/DIT112-V21/group-09/pull/96) - Connect database with the frontend app [\#95](https://github.com/DIT112-V21/group-09/pull/95) - Connect the frontend with the database [\#94](https://github.com/DIT112-V21/group-09/pull/94) diff --git a/frontendApp/assets/css/mission.css b/frontendApp/assets/css/mission.css index e065769..83a3528 100644 --- a/frontendApp/assets/css/mission.css +++ b/frontendApp/assets/css/mission.css @@ -150,8 +150,8 @@ div[id='stream-guide panel-body'] { .stream-button { position: relative; display: inline-block; - width: 80px; - height: 80px; + width: 64px; + height: 64px; margin: 0 auto; -webkit-border-radius: 10px; @@ -249,8 +249,8 @@ div[id='stream-guide panel-body'] { filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f6f6f6',GradientType=0 ); /* IE6-9 */ display: inline-block; - width: 80px; - height: 80px; + width: 64px; + height: 64px; color: #3A474D; text-transform: uppercase; @@ -282,6 +282,10 @@ div[id='stream-guide panel-body'] { color: var(--power-btn-color); } +#missionControlPad i.fas { + font-size: 1.5em; +} + #streamButton .disconnected { color: red; text-shadow: 0px -1px #97A63A; diff --git a/frontendApp/assets/css/user-profile.css b/frontendApp/assets/css/user-profile.css index a445729..4067589 100644 --- a/frontendApp/assets/css/user-profile.css +++ b/frontendApp/assets/css/user-profile.css @@ -1,9 +1,3 @@ -.modal-header{ - font-family:Georgia, 'Times New Roman', Times, serif; - color: rgb(211, 17, 59); - background-color: blanchedalmond; -} - .user-profile { grid-area: profile; width: 90px; @@ -110,4 +104,73 @@ background-repeat: no-repeat; background-position: right calc(.375em + .1875rem) center; background-size: calc(.75em + .375rem) calc(.75em + .375rem); +} + +/* Generic modal styling */ + +.modal-header { + color: #fff; + background: #feccb1; /* Old browsers */ + background: -moz-linear-gradient(-45deg, #feccb1 0%, #f17432 50%, #ea5507 51%, #fb955e 100%); /* FF3.6-15 */ + background: -webkit-linear-gradient(-45deg, #feccb1 0%,#f17432 50%,#ea5507 51%,#fb955e 100%); /* Chrome10-25,Safari5.1-6 */ + background: linear-gradient(135deg, #feccb1 0%,#f17432 50%,#ea5507 51%,#fb955e 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#feccb1', endColorstr='#fb955e',GradientType=1); /* IE6-9 fallback on horizontal gradient */ +} + +.modal-header > h5 { + color: #f8f8f8; + font-family: 'Open Sans', 'Lato', 'Roboto', Helvetica, Arial, "sans-serif"; + font-weight: 400; + text-shadow: 1px 1px 2px #451804; + font-size: 18pt; + text-transform: uppercase; +} + +.modal-body { + color: #451804; + text-shadow: 1px 1px 2px #f0e7e7; + +} + +.modal-footer { + background-color: #f0e7e7; +} + +#warningPower .modal-footer > button { + font-family: 'Lato', 'Roboto', Helvetica, Arial, "sans-serif"; + font-weight: 800; + font-size: 12pt; + text-shadow: 1px 1px 1px #451804; +} + +#missionLoadList .modal-content, +#missionWarning .modal-content, +#userModal .modal-content, +#warningPower .modal-content { + -webkit-box-shadow: 0px 10px 13px -7px #000000, 0px 12px 13px 6px rgba(0,0,0,0.5); + box-shadow: 0px 10px 13px -7px #000000, 0px 12px 13px 6px rgba(0,0,0,0.5); +} + +#missionLoadList .btn-primary, +#missionWarning .btn-primary, +#warningPower .btn-primary, +#userModal .btn-primary { + background-color: #c1440e; +} + +#missionLoadList .btn-light { + background-color: #f0e7e7; + color: #451804; + border: 1px inset rgb(253, 166, 0, 0.3); +} + +#missionLoadList .btn-light:hover { + background-color: #f5f5f5; +} + +#missionLoadList .btn-primary:hover, +#missionWarning .btn-primary:hover, +#warningPower .btn-primary:hover, +#userModal .btn-primary:hover { + background-color: #e77d11; } \ No newline at end of file diff --git a/frontendApp/assets/js/communication.js b/frontendApp/assets/js/communication.js index 2f9a9d8..d455c86 100644 --- a/frontendApp/assets/js/communication.js +++ b/frontendApp/assets/js/communication.js @@ -1,6 +1,6 @@ const mqtt = require('mqtt') -let config = require('electron-node-config'); -let mqttConfig = config.get('mqtt.brokerConfig'); +//let mqttConfig = config.get('mqtt.brokerConfig'); +let mqttConfig = = store.get('localMqttSettings'); const QrScanner = require('./assets/js/qr-scanner.umd.min.js'); QrScanner.WORKER_PATH = './assets/js/qr-scanner-worker.min.js'; @@ -114,11 +114,11 @@ function onConnect () { var n = 0; for (var i = 0; i < message.length; i += 3) { - n += 4; pixels[n] = message[i]; pixels[n + 1] = message[i + 1]; pixels[n + 2] = message[i + 2]; pixels[n + 3] = 255; + n += 4; } const imageData = new ImageData(pixels, width, height); ctx.putImageData(imageData, 0, 0); @@ -587,8 +587,8 @@ const showModal = (title, description, yesBtnLabel = 'Yes', noBtnLabel = 'Cancel - diff --git a/frontendApp/assets/js/db_connection.js b/frontendApp/assets/js/db_connection.js deleted file mode 100644 index c92898a..0000000 --- a/frontendApp/assets/js/db_connection.js +++ /dev/null @@ -1,37 +0,0 @@ -let config = require('electron-node-config'); -let dbConfig = config.get('database.dbConfig'); -const {Connection}= require ('postgresql-client') -const {Client}= require('pg') -const client = new Client({ - - host: dbConfig.host, - port: dbConfig.port, - database: dbConfig.dbName, - user: dbConfig.dbUser, - password: dbConfig.dbPassword - -}) - -execute() - -async function execute(){ -try{ - - - await client.connect() - console.log("Connect successfuly") - const results= await client.query("select * from public.missions") - console.table(results.rows) - - -} -catch{ - console.log("Error") -} -finally{ -await client.end() -console.log("disconnected") -} - -} - diff --git a/frontendApp/assets/js/map.js b/frontendApp/assets/js/map.js index 84615d4..99a356a 100644 --- a/frontendApp/assets/js/map.js +++ b/frontendApp/assets/js/map.js @@ -303,9 +303,9 @@ const missionModal = (title, description, yesBtnLabel, noBtnLabel, action) => { - @@ -428,14 +428,9 @@ function executeMission() { document.getElementById("map-tab").classList.remove("show"); document.getElementById("missionTabs-stream-tab").classList.add("active"); document.getElementById("missionTabs-map-tab").classList.remove("active"); - switchPane('stream'); - sendMission(missionContent) - .catch((e) => - console.log(e) - ); - + store.set('missionContent', missionContent); }; function loadMission(missionId) { diff --git a/frontendApp/assets/js/mission.js b/frontendApp/assets/js/mission.js index 5e70b26..e68b3a0 100644 --- a/frontendApp/assets/js/mission.js +++ b/frontendApp/assets/js/mission.js @@ -171,12 +171,9 @@ function executeMissionTable() { document.getElementById("table-tab").classList.remove("show"); document.getElementById("missionTabs-stream-tab").classList.add("active"); document.getElementById("missionTabs-table-tab").classList.remove("active"); - switchPane('stream'); - sendMission(missionContent) - .catch((e) => - console.log(e) - ); + + store.set('missionContent', missionContent); } function switchPane(pane) { diff --git a/frontendApp/assets/js/missionControl.js b/frontendApp/assets/js/missionControl.js index 283ab6a..41ae6d0 100644 --- a/frontendApp/assets/js/missionControl.js +++ b/frontendApp/assets/js/missionControl.js @@ -1,6 +1,6 @@ const mqtt = require('mqtt') let config = require('electron-node-config'); -let mqttConfig = config.get('mqtt.brokerConfig'); +let mqttConfig = = store.get('localMqttSettings'); const QrScanner = require('./assets/js/qr-scanner.umd.min.js'); QrScanner.WORKER_PATH = './assets/js/qr-scanner-worker.min.js'; @@ -38,100 +38,104 @@ const options = { const powerBtn = document.getElementById('powerBtn') const streamBtn = document.getElementById('streamBtn') +const sendBtn = document.getElementById('sendBtn') powerBtn.addEventListener('click', function(){ onConnect() }, false) streamBtn.addEventListener('click', function(){ onSub() }, false) +sendBtn.addEventListener('click', function(){ sendMission() }, false) -async function onConnect() { +function onConnect() { // const { host, port, clientId, username, password } = connection if (client == null || !client.connected) { - console.log('connecting mqtt client') - client = mqtt.connect(options.connectUrl, options) - client.on('error', (err) => { - console.error('Connection error: ', err) + console.log('connecting mqtt client'); + client = mqtt.connect(options.connectUrl, options) + client.on('error', (err) => { + console.error('Connection error: ', err); client.end() - }) - client.on('reconnect', () => { + }) + client.on('reconnect', () => { console.log('Reconnecting...') - }) - client.on('connect', () => { - console.log('Client connected:' + options.clientId) - addTextToSerial('Rover powered up!'); - // connectBtn.innerText = 'Connected'; - updateTimestamp(); - document.getElementById("powerbutton").classList.remove('disconnected'); - document.getElementById("powerbutton").classList.add('connected'); - document.getElementById("powerbutton").style.setProperty('--power-btn-color', '#18ff00', 'important'); - document.getElementById("nasaStream").style.setProperty('display', 'none', 'important') - document.getElementById("roverStream").style.setProperty('display', 'flex', 'important') - //document.getElementById("streamButton").style.setProperty('color', 'red', 'important'); - }) + }) + client.on('connect', () => { + console.log('Client connected:' + options.clientId) + addTextToSerial('Rover powered up!'); + + updateTimestamp(); + document.getElementById("powerbutton").classList.remove('disconnected'); + document.getElementById("powerbutton").classList.add('connected'); + document.getElementById("powerbutton").style.setProperty('--power-btn-color', '#18ff00', 'important'); + document.getElementById("nasaStream").style.setProperty('display', 'none', 'important') + document.getElementById("roverStream").style.setProperty('display', 'flex', 'important') + document.getElementById("streamButton").style.setProperty('color', 'red', 'important'); + }) client.on('message', (topic, message) => { - if (topic.includes("mission/status")) { - addTextToSerial(message); - } else if (topic.includes("mission/step")) { - addTextToSerial(message); - } else if (topic.includes("camera")) { - console.log("Camera") - canvas = document.getElementById('missionStream'); - ctx = canvas.getContext('2d'); + if (topic.includes("mission/status")) { + addTextToSerial(message); + } else if (topic.includes("mission/step")) { + addTextToSerial(message); + } else if (topic.includes("rover/ready")) { + sendMission(); + document.getElementById("sendbutton").style.setProperty('color', 'orange', 'important'); + } else if (topic.includes("camera")) { + console.log("Camera") + canvas = document.getElementById('missionStream'); + ctx = canvas.getContext('2d'); + + const width = 640; + const height = 480; + const arrayBuffer = new ArrayBuffer(width * height * 4); + const pixels = new Uint8ClampedArray(arrayBuffer); + var n = 0; - const width = 640; - const height = 480; - const arrayBuffer = new ArrayBuffer(width * height * 4); - const pixels = new Uint8ClampedArray(arrayBuffer); - var n = 0; + for (var i = 0; i < message.length; i += 3) { + pixels[n] = message[i]; + pixels[n + 1] = message[i + 1]; + pixels[n + 2] = message[i + 2]; + pixels[n + 3] = 255; + n += 4; + } + const imageData = new ImageData(pixels, width, height); + ctx.putImageData(imageData, 0, 0); - for (var i = 0; i < message.length; i += 3) { - n += 4; - pixels[n] = message[i]; - pixels[n + 1] = message[i + 1]; - pixels[n + 2] = message[i + 2]; - pixels[n + 3] = 255; - } - const imageData = new ImageData(pixels, width, height); - ctx.putImageData(imageData, 0, 0); + frameCount++; - frameCount++; - - if (frameCount > 20) { - var scanData = canvas.toDataURL('image/bmp'); - QrScanner.scanImage(scanData) - .then(result => { - var qrMessage = "Found target area: " + result; + if (frameCount > 20) { + var scanData = canvas.toDataURL('image/bmp'); + QrScanner.scanImage(scanData) + .then(result => { + var qrMessage = "Found target area: " + result; addTextToSerial(qrMessage); endMission(); - }) - .catch(error => console.log(error || 'No QR code found.')); - frameCount = 0; - } + }) + .catch(error => console.log(error || 'No QR code found.')); + frameCount = 0; + } - } else { + } else { const msg = `${message.toString()}\nOn topic: ${topic}` - addTextToSerial(msg); - } - }) + addTextToSerial(msg); + } + }) return client.connected = true; } else if (client.connected) { - onUnsub(); - client.end() - client.on('close', () => { - console.log(options.clientId + ' disconnected') - }) - addTextToSerial('Rover turned off!'); - document.getElementById("powerbutton").classList.add('disconnected'); - document.getElementById("powerbutton").classList.remove('connected'); - document.getElementById("powerbutton").style.setProperty('--power-btn-color', '#ff0000', 'important'); - document.getElementById("nasaStream").style.setProperty('display', 'flex', 'important') - document.getElementById("roverStream").style.setProperty('display', 'none', 'important') - document.getElementById("streamButton").style.setProperty('color', '#3A474D', 'important'); - - return client.connected = false; - } + onUnsub(); + client.end() + client.on('close', () => { + console.log(options.clientId + ' disconnected') + }) + addTextToSerial('Rover turned off!'); + document.getElementById("powerbutton").classList.add('disconnected'); + document.getElementById("powerbutton").classList.remove('connected'); + document.getElementById("powerbutton").style.setProperty('--power-btn-color', '#ff0000', 'important'); + document.getElementById("nasaStream").style.setProperty('display', 'flex', 'important') + document.getElementById("roverStream").style.setProperty('display', 'none', 'important') + document.getElementById("streamButton").style.setProperty('color', '#3A474D', 'important'); + return client.connected = false; + } } function onDisconnect () { @@ -145,7 +149,7 @@ function onDisconnect () { } } -async function onSub () { +function onSub () { if ((client == null || !client.connected || client.connected == false)) { var desc = "The SmartRover is not powered up!
Please turn on Rover by pressing Power button." saveModal("Rover power", desc, noBtnLabel = 'Close', false) @@ -195,33 +199,18 @@ function onUnsub () { } -function sendMission(content) { - - onConnect() - .catch((e) => - console.log(e) - ); - - onSub() - .catch((e) => - console.log(e) - ); - - if (subscribed) { - document.getElementById("streamButton").classList.add('connected'); - document.getElementById("streamButton").classList.remove('disconnected'); - document.getElementById("streamButton").style.removeProperty('color'); - document.getElementById("streamButton").style.setProperty('color', '#18ff00', 'important'); - } - +function sendMission() { if ((client == null || !client.connected || client.connected == false)) { - var desc = "The SmartRover is not powered up!
Please turn on Rover by pressing Power button.
Also please connect to "Mars Orbiter" satellite for updates." - saveModal("Rover power", desc, noBtnLabel = 'Close', false) + var desc = "The SmartRover is not powered up!
Please turn on Rover by pressing Power button.
Also please connect to "Mars Orbiter" satellite for updates.

Once everything is ready, click "Send mession" button." + saveModal("Rover power", desc, noBtnLabel = 'Close', false); + } else { + + var messageContent = store.get('missionContent'); + if (messageContent == null) { + var descNoContent = "Cannot load mission content. Please make sure your mission is properly setup either on the map or table. Once ready, click "Execute mission" to process and send mission content." + saveModal("Mission setup", descNoContent, noBtnLabel = 'Close', false); } else { - - var missionSteps = content.steps.length; - var messageContent = ''; - + var missionSteps = messageContent.content.steps.length; for (var i = 0; i < missionSteps; i++) { var step = String(i) + ';' + String(content.steps[i].parameters.heading) + ';' + @@ -229,9 +218,9 @@ function sendMission(content) { String(content.steps[i].parameters.distance) + ';' messageContent += step; } - + console.log(messageContent); - + client.publish( 'mission/content', messageContent, { qos: 2, retain: false @@ -242,6 +231,7 @@ function sendMission(content) { }) addTextToSerial('Mission successfully sent!'); } + } } function endMission() { @@ -257,8 +247,6 @@ function endMission() { var missionEndDesc = "Mission had completed. We have reached a target area and detected target code.

Congratulations!"; saveModal('Mission complete', missionEndDesc, 'Close'); } - - } function addTextToSerial(textToAdd) { diff --git a/frontendApp/assets/js/settings.js b/frontendApp/assets/js/settings.js index 4036e22..2884f94 100644 --- a/frontendApp/assets/js/settings.js +++ b/frontendApp/assets/js/settings.js @@ -1,5 +1,3 @@ -const config = require('electron-node-config'); - const mqttSaveBtn = document.getElementById('mqttSaveBtn') const mqttReloadBtn = document.getElementById('mqttReloadBtn') const dbSaveBtn = document.getElementById('dbSaveBtn') @@ -13,99 +11,51 @@ dbSaveBtn.addEventListener('click', function(){ saveDbSettings(); }, false) dbReloadBtn.addEventListener('click', function(){ loadDbSettings(); }, false) function loadMqttSettings() { - let mqttConfig = config.get('mqtt.brokerConfig'); - - document.getElementById("mqtt-hostname").value = mqttConfig.host; - document.getElementById("mqtt-port").value = mqttConfig.port; - document.getElementById("mqtt-username").value = mqttConfig.username; - document.getElementById("mqtt-password").value = mqttConfig.password; - document.getElementById("mqtt-clientid").value = mqttConfig.clientId; + var localMqttSettings = store.get('localMqttSettings'); + document.getElementById("mqtt-hostname").value = localMqttSettings.host; + document.getElementById("mqtt-port").value = localMqttSettings.port; + document.getElementById("mqtt-username").value = localMqttSettings.username; + document.getElementById("mqtt-password").value = localMqttSettings.password; + document.getElementById("mqtt-clientid").value = localMqttSettings.clientId; } function loadDbSettings() { - let fs = require('fs'); - var db = null; - try { - const jsonString = fs.readFileSync("./config/dbConfig.json"); - db = JSON.parse(jsonString); - document.getElementById('settings-msg').style.display = "block"; - document.getElementById("settings-msg").innerHTML="Settings successfully loaded."; - - document.getElementById("db-hostname").value = db.host; - document.getElementById("db-port").value = db.port; - document.getElementById("db-username").value = db.dbUser; - document.getElementById("db-password").value = db.dbPassword; - document.getElementById("db-name").value = db.dbName; - - } catch (err) { - document.getElementById('settings-msg').style.display = "block"; - document.getElementById("settings-msg").innerHTML="Error loading settings"; - return; - } - - setTimeout(function(){ - document.getElementById('settings-msg').style.display = "none"; - }, 5000); + var localDbSettings = store.get('localDbSettings'); + document.getElementById("db-hostname").value = localDbSettings.host; + document.getElementById("db-port").value = localDbSettings.port; + document.getElementById("db-username").value = localDbSettings.user; + document.getElementById("db-password").value = localDbSettings.password; + document.getElementById("db-name").value = localDbSettings.database; } function saveDbSettings() { - let fs = require('fs'); updateTimestamp(); const newDbSettings = { - host: document.getElementById("db-hostname").value, - port: parseInt(document.getElementById("db-port").value), - dbUser: document.getElementById("db-username").value, - dbPassword: document.getElementById("db-password").value, - dbName: document.getElementById("db-name").value + "host": document.getElementById("db-hostname").value, + "port": parseInt(document.getElementById("db-port").value), + "dbUser": document.getElementById("db-username").value, + "dbPassword": document.getElementById("db-password").value, + "dbName": document.getElementById("db-name").value, + "local": true } - const jsonString = JSON.stringify(newDbSettings, null, 2) - fs.writeFile("./config/dbConfig.json", jsonString, err => { - if (err) { - document.getElementById('settings-msg').style.display = "block"; - document.getElementById("settings-msg").innerHTML="Error updating settings"; - } else { - /*document.getElementById('settings-msg').style.display = "block"; - document.getElementById("settings-msg").innerHTML="Settings successfully saved.";*/ - systemToast('dbSettingsSaveSuccess'); - } - setTimeout(function(){ - document.getElementById('settings-msg').style.display = "none"; - }, 5000); - }) + + store.set('localDbSettings', newDbSettings); + systemToast('dbSettingsSaveSuccess'); } function saveMqttSettings() { - let fs = require('fs'); updateTimestamp(); var connectionUrl = "mqtt://" + document.getElementById("mqtt-hostname").value + ":" + document.getElementById("mqtt-port").value; - - const newMqttSettings = { - "mqtt": { - "_comment": "MQTT Broker connection settings here", - "brokerConfig": { - "connectUrl": connectionUrl, + + var newMqttSettings = { + "connectUrl": connectionUrl, "host": document.getElementById("mqtt-hostname").value, "port": parseInt(document.getElementById("mqtt-port").value), "username": document.getElementById("mqtt-username").value, "password": document.getElementById("mqtt-password").value, "clientId": document.getElementById("mqtt-clientid").value - } - } - } - - const jsonString = JSON.stringify(newMqttSettings, null, 2) - fs.writeFile("./config/default.json", jsonString, err => { - if (err) { - document.getElementById('settings-msg').style.display = "block"; - document.getElementById("settings-msg").innerHTML="Error updating settings"; - } else { - /*document.getElementById('settings-msg').style.display = "block"; - document.getElementById("settings-msg").innerHTML="Settings successfully saved.";*/ - systemToast('mqttSettingsSaveSuccess'); - } - setTimeout(function(){ - document.getElementById('settings-msg').style.display = "none"; - }, 5000); - }) + }; + store.set('localMqttSettings', newMqttSettings); + systemToast('mqttSettingsSaveSuccess'); } \ No newline at end of file diff --git a/frontendApp/assets/js/user.js b/frontendApp/assets/js/user.js index 011fb27..581f761 100644 --- a/frontendApp/assets/js/user.js +++ b/frontendApp/assets/js/user.js @@ -1,25 +1,60 @@ const { Client } = require('pg'); const Store = require('electron-store'); +let config = require('electron-node-config'); const fs = require('fs'); - const store = new Store({ configName: 'user-store' }); -const jsonString = fs.readFileSync("./config/dbConfig.json"); - db = JSON.parse(jsonString); - -const clientConfig = { - user: db.dbUser, - host: db.host, - database: db.dbName, - password: db.dbPassword, - port: db.port - }; +var clientConfig = {}; document.addEventListener("DOMContentLoaded", function() { initializeUser()}, false); +function validateDBSettings() { + initializeSettings(); + const client = new Client(clientConfig); + client.connect() + client + .query('SELECT NOW()') + .then(result => { + return true; + }) + .catch(e => { + console.error(e.stack); + systemToast('dbError'); + return false; + }) + .then(() => client.end()); +} + +function initializeSettings() { + var localDbSettings = store.get('localDbSettings'); + if (localDbSettings.local) { + clientConfig = { + user: localDbSettings.dbUser, + host: localDbSettings.host, + database: localDbSettings.dbName, + password: localDbSettings.dbPassword, + port: localDbSettings.port + }; + } else if (localDbSettings.local == false || localDbSettings == null || localDbSettings == undefined) { + let dbConfig = config.get('database.dbConfig'); + clientConfig = { + user: dbConfig.dbUser, + host: dbConfig.host, + database: dbConfig.dbName, + password: dbConfig.dbPassword, + port: dbConfig.port + }; + } else { + console.log('DB settings missing ...'); + systemToast('Database settings missing.
Please check Settings page.'); + } +} + function initializeUser() { + validateDBSettings(); + var loggedTime = store.get('loggedTimestamp'); if (loggedTime != null) { console.log("Checking time diff ...") @@ -99,8 +134,8 @@ function userModal(type) { @@ -149,8 +184,8 @@ function userModal(type) {
@@ -420,9 +455,9 @@ function loadMissionList() {
@@ -496,7 +531,7 @@ const saveModal = (title, description, closeBtnLabel) => { } modalWrap = document.createElement('div'); modalWrap.innerHTML = ` -