diff --git a/.electron-vue/webpack.renderer.config.js b/.electron-vue/webpack.renderer.config.js index e95ac70..6f4a90d 100644 --- a/.electron-vue/webpack.renderer.config.js +++ b/.electron-vue/webpack.renderer.config.js @@ -125,6 +125,18 @@ let rendererConfig = { new HtmlWebpackPlugin({ filename: 'index.html', template: path.resolve(__dirname, '../src/index.ejs'), + templateParameters(compilation, assets, options) { + return { + compilation: compilation, + webpack: compilation.getStats().toJson(), + webpackConfig: compilation.options, + htmlWebpackPlugin: { + files: assets, + options: options + }, + process, + }; + }, minify: { collapseWhitespace: true, removeAttributeQuotes: true, diff --git a/.electron-vue/webpack.web.config.js b/.electron-vue/webpack.web.config.js index bde6701..497e512 100644 --- a/.electron-vue/webpack.web.config.js +++ b/.electron-vue/webpack.web.config.js @@ -97,7 +97,18 @@ let webConfig = { new HtmlWebpackPlugin({ filename: 'index.html', template: path.resolve(__dirname, '../src/index.ejs'), - minify: { + templateParameters(compilation, assets, options) { + return { + compilation: compilation, + webpack: compilation.getStats().toJson(), + webpackConfig: compilation.options, + htmlWebpackPlugin: { + files: assets, + options: options + }, + process, + }; + }, minify: { collapseWhitespace: true, removeAttributeQuotes: true, removeComments: true diff --git a/.travis.yml b/.travis.yml index 24bd5dd..f57985c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,14 +4,14 @@ dist: xenial language: node_js workspaces: use: - - binaries + - binaries cache: directories: - node_modules - "$HOME/.electron" - - "$HOME/.cache" -addons: -before_install: + - "$HOME/.cache" +addons: +before_install: install: - source ~/.bashrc - npm install -g xvfb-maybe @@ -23,64 +23,60 @@ jobs: - stage: Build binaries os: windows script: - - npm run build - - mkdir windows-binaries - - mv -v build/flightgear-airports* windows-binaries/ - - ls -l windows-binaries + - npm run build + - mkdir windows-binaries + - mv -v build/flightgear-airports* windows-binaries/ + - ls -l windows-binaries workspaces: create: name: windows-binaries paths: windows-binaries - os: linux script: - - npm run build - - mkdir linux-binaries - - mv -v build/flightgear-airports* linux-binaries/ - - ls -l linux-binaries + - npm run build + - mkdir linux-binaries + - mv -v build/flightgear-airports* linux-binaries/ + - ls -l linux-binaries workspaces: create: name: linux-binaries paths: linux-binaries - os: osx script: - - npm run build - - mkdir osx-binaries - - mv -v build/flightgear-airports* osx-binaries/ - - ls -l osx-binaries + - npm run build + - mkdir osx-binaries + - mv -v build/flightgear-airports* osx-binaries/ + - ls -l osx-binaries workspaces: create: name: osx-binaries paths: osx-binaries - stage: Deploy install: - - pwd - - tar -xzf ${CASHER_DIR}/osx-binaries-fetch.tgz - - find -name flightgear-airports* -# - find -name windows-binaries -# - find -name osx-binaries -# - find -name linux-binaries -# - ls -l | grep "^d" -# - ls -l "C:" - - cp ./Users/travis/build/Portree-Kid/flightgear-airports/osx-binaries/*.dmg build/ - - cp ./C:/Users/travis/build/Portree-Kid/flightgear-airports/windows-binaries/*.exe build/ - - cp ./linux-binaries/*.AppImage build/ - - ls -l "build/" + - pwd + - find -name *osx-binaries* + - tar -xzf ${CASHER_DIR}/osx-binaries-fetch.tgz + - find -name flightgear-airports* + - cp ./Users/travis/build/Portree-Kid/flightgear-airports/osx-binaries/*.dmg build/ + - cp ./C:/Users/travis/build/Portree-Kid/flightgear-airports/windows-binaries/*.exe build/ + - cp ./linux-binaries/*.AppImage build/ + - ls -l "build/" script: skip workspaces: use: - - windows-binaries - - linux-binaries - - osx-binaries + - windows-binaries + - linux-binaries + - osx-binaries deploy: skip_cleanup: true overwrite: true draft: true - name: '0.0.20' + name: '0.0.33' provider: releases api_key: secure: ECdYNrvCA7+qSnbktJPstwXrluqKZTWDD7K3X/dyoxRO4+ZL/K19r60LXF9g90troWgdZSN3tFxNktkGeIOuTo83Q3B6qjXnKtdW3JhefvztlHQadUIf2p8Ype2spicNAl2629Mwr7ksqJuV0rR0T4zYT1SIFWkuwGYhR+tmS94m6QmnocGPzjset3y23lJ/rczJiiWIkaLrOfeCj5VjWtSaVQEWWlolmuji0qGHvOT/mq1X+jfI9RIlJTpV2ZNYaa3fr+M+8tIreaHDjbKrYAuIA/JzpDxmXtWGnxkxLbDxonp6OhzcJ7z9hpdkg38HKxNTL9Bdv0LpZKCTo2C+0G6yR3kQqXhoIzbfFeTX0G6d7I8oYxL1JGCsrnmU3OyhCLMRcOWL294hhDIUMWveBRNVRGVaOzeXRphO4nnMhGNd4KxwxvRPBMNeguhL/ZBwjcw6puYL3m86UT5iwjMuYvcbEVEDXwHSyi96zjHzolkMUn8hPOIUfgmCOIsqIMMpbCXJqdyha0pu9x1qKrXbF+hQ5JXPvTN8/ZG4dLXhvsZJdD50vZu+GW33vU96c+mwIkCz0CS5t+vuHfdT/OOuBN7HV46q/9WrZMSlz5ZD+A2dY57QVL+CucjMZlVoU/iJhfRpV5XPYvLlYI+tpH0yX5JQqtcRdZJzKsYknwZNj5o= file_glob: true file: build/* on: - branches: '0.0.20' + branches: '0.0.33' repo: Portree-Kid/flightgear-airports diff --git a/build/installer.nsh b/build/installer.nsh new file mode 100644 index 0000000..9886d3d --- /dev/null +++ b/build/installer.nsh @@ -0,0 +1,8 @@ +!macro preInit + SetRegView 64 + WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$PROGRAMFILES64\flightgear-airports" + WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$PROGRAMFILES64\flightgear-airports" + SetRegView 32 + WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$PROGRAMFILES32\flightgear-airports" + WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$PROGRAMFILES32\flightgear-airports" +!macroend diff --git a/package-lock.json b/package-lock.json index 46daddd..10caf37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "flightgear-airports", - "version": "0.0.18", + "version": "0.0.33", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -158,19 +158,39 @@ } }, "@develar/schema-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.1.0.tgz", - "integrity": "sha512-qjCqB4ctMig9Gz5bd6lkdFr3bO6arOdQqptdBSpF1ZpCnjofieCciEzkoS9ujY9cMGyllYSCSmBJ3x9OKHXzoA==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } } }, "@electron/get": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.2.tgz", - "integrity": "sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg==", + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.4.tgz", + "integrity": "sha512-6nr9DbJPUR9Xujw6zD3y+rS95TyItEVM0NVjt1EehY2vUWfIgPiIPVHxCvaTS0xr2B+DRxovYVKbuOWqC35kjg==", "dev": true, "requires": { "debug": "^4.1.1", @@ -180,25 +200,72 @@ "global-tunnel-ng": "^2.7.1", "got": "^9.6.0", "progress": "^2.0.3", - "sanitize-filename": "^1.6.2", + "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "env-paths": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", - "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@electron/universal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.4.tgz", + "integrity": "sha512-ajZoumi4XwqwmZe8YVhu4XGkZBCPyWZsVCQONPTIe9TUlleSN+dic3YpXlaWcilx/HOzTdldTKtabNTeI0gDoA==", + "dev": true, + "requires": { + "@malept/cross-spawn-promise": "^1.1.0", + "asar": "^3.0.3", + "debug": "^4.3.1", + "dir-compare": "^2.4.0", + "fs-extra": "^9.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -213,6 +280,58 @@ "integrity": "sha512-vKDJUuE2GAdBERaQWmmtsciAMzjwNrROXA5KTGSZvayAsmuTGjam5z6QNqNPCwDfVljLWuov1nEC3mEQf/n6fQ==", "dev": true }, + "@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -1640,6 +1759,15 @@ "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", "dev": true }, + "@types/fs-extra": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.6.tgz", + "integrity": "sha512-ecNRHw4clCkowNOBJH1e77nvbPxHYnWIXMv1IAoG/9+MYGkgoyr3Ppxr7XYFNL41V422EDhyV4/4SSK8L2mlig==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/glob": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", @@ -1663,6 +1791,39 @@ "integrity": "sha512-iZeh1EgupfmAAOASk580R1SL5lWF3CsBVgVH0395qyNF8fhO16xy1UwAav2PdGxIIsYRn7RzJgMGjdsvam6YYg==", "dev": true }, + "@types/plist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.2.tgz", + "integrity": "sha512-ULqvZNGMv0zRFvqn8/4LSPtnmN4MfhlPNtJCTpKuIIxGVGZ2rYWzFXrvEBoh9CVyqSE7D6YFRJ1hydLHI6kbWw==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "@types/verror": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.4.tgz", + "integrity": "sha512-OjJdqx6QlbyZw9LShPwRW+Kmiegeg3eWNI41MQQKaG3vjdU2L9SRElntM51HmHBY1cu7izxQJ1lMYioQh3XMBg==", + "dev": true, + "optional": true + }, + "@types/yargs": { + "version": "15.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.12.tgz", + "integrity": "sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", + "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", + "dev": true + }, "@vue/component-compiler-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz", @@ -1936,9 +2097,9 @@ "dev": true }, "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", "dev": true }, "acorn-jsx": { @@ -1976,6 +2137,7 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, + "optional": true, "requires": { "es6-promisify": "^5.0.0" } @@ -2427,48 +2589,49 @@ } }, "app-builder-bin": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.3.tgz", - "integrity": "sha512-qMhayIwi3juerQEVJMQ76trObEbfQT0nhUdxZz9a26/3NLT3pE6awmQ8S1cEnrGugaaM5gYqR8OElcDezfmEsg==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.12.tgz", + "integrity": "sha512-lQARM2AielmFoBeIo6LZigAe+58Wwe07ZWkt+wVeDxzyieNmeWjlvz/V5dKzinydwdHd+CNswN86sww46yijjA==", "dev": true }, "app-builder-lib": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.2.0.tgz", - "integrity": "sha512-aOX/nv77/Bti6NymJDg7p9T067xD8m1ipIEJR7B4Mm1GsJWpMm9PZdXtCRiMNRjHtQS5KIljT0g17781y6qn5A==", + "version": "22.10.4", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.10.4.tgz", + "integrity": "sha512-q7B1cr8Ry4a7o08EKShLfwsnIVf5By7YhVwcoqgEwPKxtoj1qF0kB4wyBP79rJylYi0Zj2cSkJJ/gD/ef9xhoQ==", "dev": true, "requires": { "7zip-bin": "~5.0.3", - "@develar/schema-utils": "~2.1.0", + "@develar/schema-utils": "~2.6.5", + "@electron/universal": "1.0.4", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "21.2.0", - "builder-util-runtime": "8.3.0", + "builder-util": "22.10.4", + "builder-util-runtime": "8.7.3", "chromium-pickle-js": "^0.2.0", - "debug": "^4.1.1", - "ejs": "^2.6.2", - "electron-publish": "21.2.0", - "fs-extra": "^8.1.0", - "hosted-git-info": "^2.7.1", + "debug": "^4.3.1", + "ejs": "^3.1.5", + "electron-publish": "22.10.4", + "fs-extra": "^9.0.1", + "hosted-git-info": "^3.0.7", "is-ci": "^2.0.0", - "isbinaryfile": "^4.0.2", - "js-yaml": "^3.13.1", + "isbinaryfile": "^4.0.6", + "js-yaml": "^3.14.1", "lazy-val": "^1.0.4", "minimatch": "^3.0.4", - "normalize-package-data": "^2.5.0", - "read-config-file": "5.0.0", - "sanitize-filename": "^1.6.2", - "semver": "^6.3.0", - "temp-file": "^3.3.4" + "normalize-package-data": "^3.0.0", + "read-config-file": "6.0.0", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.4", + "temp-file": "^3.3.7" }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "esprima": { @@ -2477,37 +2640,75 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "hosted-git-info": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", + "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==", "dev": true, "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "lru-cache": "^6.0.0" } }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "normalize-package-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", + "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "resolve": "^1.17.0", + "semver": "^7.3.2", + "validate-npm-package-license": "^3.0.1" + } + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } @@ -2649,6 +2850,41 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "asar": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.0.3.tgz", + "integrity": "sha512-k7zd+KoR+n8pl71PvgElcoKHrVNiSXtw7odKbyNpmgKe7EGRF9Pnu3uLOukD37EvavKwVFxOUpqXTIZC5B5Pmw==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "chromium-pickle-js": "^0.2.0", + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -2768,6 +3004,11 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -2813,12 +3054,18 @@ "dev": true }, "axios": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", - "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" + "follow-redirects": "^1.10.0" + }, + "dependencies": { + "follow-redirects": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", + "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==" + } } }, "babel-code-frame": { @@ -4229,72 +4476,129 @@ "dev": true }, "boolean": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.1.tgz", - "integrity": "sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA==", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.3.tgz", + "integrity": "sha512-EqrTKXQX6Z3A2nRmMEIlAIfjQOgFnVO2nqZGpbcsPnYGWBwpFqzlrozU1dy+S2iqfYDLh26ef4KrgTxu9xQrxA==", + "dev": true, + "optional": true }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, + "optional": true, "requires": { "hoek": "2.x.x" } }, "boxen": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", - "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", "dev": true, "requires": { "ansi-align": "^3.0.0", "camelcase": "^5.3.1", - "chalk": "^2.4.2", + "chalk": "^3.0.0", "cli-boxes": "^2.2.0", - "string-width": "^3.0.0", - "term-size": "^1.2.0", - "type-fest": "^0.3.0", - "widest-line": "^2.0.0" + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } @@ -4445,6 +4749,12 @@ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -4467,7 +4777,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==", - "dev": true + "dev": true, + "optional": true }, "buffer-xor": { "version": "1.0.3", @@ -4476,33 +4787,68 @@ "dev": true }, "builder-util": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.2.0.tgz", - "integrity": "sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A==", + "version": "22.10.4", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.10.4.tgz", + "integrity": "sha512-XdcbFG3otEkNRKxW2wS1npNviCb/IrzusEQ55lMB+6YEHxBOfTbf8vnPt0pDumfwmxls9xczABU+mfqN/W4uDw==", "dev": true, "requires": { "7zip-bin": "~5.0.3", - "@types/debug": "^4.1.4", - "app-builder-bin": "3.4.3", + "@types/debug": "^4.1.5", + "@types/fs-extra": "^9.0.5", + "app-builder-bin": "3.5.12", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "8.3.0", - "chalk": "^2.4.2", - "debug": "^4.1.1", - "fs-extra": "^8.1.0", + "builder-util-runtime": "8.7.3", + "chalk": "^4.1.0", + "debug": "^4.3.1", + "fs-extra": "^9.0.1", "is-ci": "^2.0.0", - "js-yaml": "^3.13.1", - "source-map-support": "^0.5.13", - "stat-mode": "^0.3.0", - "temp-file": "^3.3.4" + "js-yaml": "^3.14.1", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.3.7" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "ms": "^2.1.1" + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" } }, "esprima": { @@ -4511,21 +4857,16 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -4545,34 +4886,43 @@ "dev": true }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, "builder-util-runtime": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz", - "integrity": "sha512-CSOdsYqf4RXIHh1HANPbrZHlZ9JQJXSuDDloblZPcWQVN62inyYoTQuSmY3KrgefME2Sv3Kn2MxHvbGQHRf8Iw==", + "version": "8.7.3", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.7.3.tgz", + "integrity": "sha512-1Q2ReBqFblimF5g/TLg2+0M5Xzv0Ih5LxJ/BMWXvEy/e6pQKeeEpbkPMGsN6OiQgkygaZo5VXCXIjOkOQG5EoQ==", "dev": true, "requires": { - "debug": "^4.1.1", + "debug": "^4.3.2", "sax": "^1.2.4" }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -5235,9 +5585,9 @@ } }, "cli-boxes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", - "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true }, "cli-cursor": { @@ -5249,6 +5599,54 @@ "restore-cursor": "^2.0.0" } }, + "cli-truncate": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-1.1.0.tgz", + "integrity": "sha512-bAtZo0u82gCfaAGfSNxUdTI9mNyza7D8w4CVCcaOsy7sgwDzvx6ekr6cuWJqY3UGzgnQ1+4wgENup5eIhgxEYA==", + "dev": true, + "optional": true, + "requires": { + "slice-ansi": "^1.0.0", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "optional": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "optional": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -5623,17 +6021,61 @@ } }, "configstore": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", - "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", "dev": true, "requires": { - "dot-prop": "^4.1.0", + "dot-prop": "^5.2.0", "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } } }, "connect": { @@ -5930,9 +6372,9 @@ } }, "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, "css": { @@ -6205,6 +6647,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -6531,6 +6974,35 @@ "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz", "integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs=" }, + "dir-compare": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz", + "integrity": "sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==", + "dev": true, + "requires": { + "buffer-equal": "1.0.0", + "colors": "1.0.3", + "commander": "2.9.0", + "minimatch": "3.0.4" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + } + } + }, "dir-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", @@ -6552,18 +7024,18 @@ } }, "dmg-builder": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-21.2.0.tgz", - "integrity": "sha512-9cJEclnGy7EyKFCoHDYDf54pub/t92CQapyiUxU0w9Bj2vUvfoDagP1PMiX4XD5rPp96141h9A+QN0OB4VgvQg==", + "version": "22.10.4", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.10.4.tgz", + "integrity": "sha512-+28HZgKAuyCQnQwLSAwkHUqtMB/egHF5ACUABCB4Nev02/ZfjFPUTF/WloTaEbue34zLLUGxPXh+BJF8Xw26ow==", "dev": true, "requires": { - "app-builder-lib": "~21.2.0", - "bluebird-lst": "^1.0.9", - "builder-util": "~21.2.0", - "fs-extra": "^8.1.0", - "iconv-lite": "^0.5.0", - "js-yaml": "^3.13.1", - "sanitize-filename": "^1.6.2" + "app-builder-lib": "22.10.4", + "builder-util": "22.10.4", + "dmg-license": "^1.0.8", + "fs-extra": "^9.0.1", + "iconv-lite": "^0.6.2", + "js-yaml": "^3.14.1", + "sanitize-filename": "^1.6.3" }, "dependencies": { "esprima": { @@ -6572,30 +7044,19 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "iconv-lite": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz", - "integrity": "sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -6604,6 +7065,24 @@ } } }, + "dmg-license": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.8.tgz", + "integrity": "sha512-47GOb6b4yVzpovXC34heXElpH++ICg9GuWBeOTaokUNLAoAdWpE4VehudYEEtu96j2jXsgQWYf78nW7r+0Y3eg==", + "dev": true, + "optional": true, + "requires": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "cli-truncate": "^1.1.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.5", + "plist": "^3.0.1", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + } + }, "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -6790,15 +7269,18 @@ "dev": true }, "ejs": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", - "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==", - "dev": true + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", + "dev": true, + "requires": { + "jake": "^10.6.1" + } }, "electron": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/electron/-/electron-7.2.4.tgz", - "integrity": "sha512-Z+R692uTzXgP8AHrabE+kkrMlQJ6pnAYoINenwj9QSqaD2YbO8IuXU9DMCcUY0+VpA91ee09wFZJNUKYPMnCKg==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/electron/-/electron-7.3.3.tgz", + "integrity": "sha512-PrJEsuRiaAhTDHtbH3EM+RIne+nZ6ifGChUadmtmPqHUQ+rIhf4jSi2ZN768IgBDw4SidMJiCrvQRiuDha9+Ew==", "dev": true, "requires": { "@electron/get": "^1.0.1", @@ -6807,43 +7289,82 @@ }, "dependencies": { "@types/node": { - "version": "12.12.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.48.tgz", - "integrity": "sha512-m3Nmo/YaDUfYzdCQlxjF5pIy7TNyDTAJhIa//xtHcF0dlgYIBKULKnmloCPtByDxtZXrWV8Pge1AKT6/lRvVWg==", + "version": "12.20.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.8.tgz", + "integrity": "sha512-uxDkaUGwXNDHu5MHqs+FAsmOjNoNibDF1cu4668QG96mQldQfgV3M+UyntXWWrtXSh13jFxEdNUdoLWH46mLKQ==", "dev": true } } }, "electron-builder": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-21.2.0.tgz", - "integrity": "sha512-x8EXrqFbAb2L3N22YlGar3dGh8vwptbB3ovo3OF6K7NTpcsmM2zEoJv7GhFyX73rNzSG2HaWpXwGAtOp2JWiEw==", + "version": "22.10.4", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.10.4.tgz", + "integrity": "sha512-V+JtiizJd3kt24TT+0OHG7+oPAzjhhjmQVn9G6OC2WE7VBJxrDuD6lMVRgo6WlU8uvDCh7fTRUsdh0Tnu0GeQA==", "dev": true, "requires": { - "app-builder-lib": "21.2.0", + "@types/yargs": "^15.0.12", + "app-builder-lib": "22.10.4", "bluebird-lst": "^1.0.9", - "builder-util": "21.2.0", - "builder-util-runtime": "8.3.0", - "chalk": "^2.4.2", - "dmg-builder": "21.2.0", - "fs-extra": "^8.1.0", + "builder-util": "22.10.4", + "builder-util-runtime": "8.7.3", + "chalk": "^4.1.0", + "dmg-builder": "22.10.4", + "fs-extra": "^9.0.1", "is-ci": "^2.0.0", "lazy-val": "^1.0.4", - "read-config-file": "5.0.0", - "sanitize-filename": "^1.6.2", - "update-notifier": "^3.0.1", - "yargs": "^13.3.0" + "read-config-file": "6.0.0", + "sanitize-filename": "^1.6.3", + "update-notifier": "^5.0.1", + "yargs": "^16.2.0" }, "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } @@ -6981,29 +7502,74 @@ } }, "electron-publish": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.2.0.tgz", - "integrity": "sha512-mWavuoWJe87iaeKd0I24dNWIaR+0yRzshjNVqGyK019H766fsPWl3caQJnVKFaEyrZRP397v4JZVG0e7s16AxA==", + "version": "22.10.4", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.10.4.tgz", + "integrity": "sha512-cjVM0+9DQoV4TWfH8lVWoelJ89O2i5yDARVp5GCMHrB43XEU0Nr5eKYysgsbOSnZk5W8z1vfGpFWHj+AeAEDYg==", "dev": true, "requires": { + "@types/fs-extra": "^9.0.5", "bluebird-lst": "^1.0.9", - "builder-util": "~21.2.0", - "builder-util-runtime": "8.3.0", - "chalk": "^2.4.2", - "fs-extra": "^8.1.0", + "builder-util": "22.10.4", + "builder-util-runtime": "8.7.3", + "chalk": "^4.1.0", + "fs-extra": "^9.0.1", "lazy-val": "^1.0.4", - "mime": "^2.4.4" + "mime": "^2.4.7" }, "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "mime": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz", + "integrity": "sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } @@ -7023,9 +7589,9 @@ "dev": true }, "element-ui": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.13.2.tgz", - "integrity": "sha512-r761DRPssMPKDiJZWFlG+4e4vr0cRG/atKr3Eqr8Xi0tQMNbtmYU1QXvFnKiFPFFGkgJ6zS6ASkG+sellcoHlQ==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.1.tgz", + "integrity": "sha512-TqlScAKGH97XndSScUDeEHIzL1x7yg7DvQdKPEOUdiDcyIz3y3FJJBlpHYaJT96FOn1xpIcUZb+I2FJeU9EcrQ==", "requires": { "async-validator": "~1.8.1", "babel-helper-vue-jsx-merge-props": "^2.0.0", @@ -7267,13 +7833,15 @@ "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true + "dev": true, + "optional": true }, "es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, + "optional": true, "requires": { "es6-promise": "^4.0.3" } @@ -7298,6 +7866,18 @@ "through": "~2.3.6" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -7439,9 +8019,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -7706,6 +8286,11 @@ "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", "dev": true }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" + }, "espree": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", @@ -7723,12 +8308,20 @@ "dev": true }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "esrecurse": { @@ -7789,34 +8382,6 @@ "safe-buffer": "^5.1.1" } }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } - } - }, "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", @@ -8126,6 +8691,15 @@ "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==" }, + "filelist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", + "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -8537,6 +9111,7 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, "requires": { "debug": "=3.1.0" } @@ -8621,14 +9196,37 @@ "dev": true }, "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", "requires": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "dependencies": { + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + } + } + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" + } } }, "fs-write-stream-atomic": { @@ -8669,7 +9267,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -8690,12 +9289,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8710,17 +9311,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -8837,7 +9441,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -8849,6 +9454,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -8863,6 +9469,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -8870,12 +9477,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -8894,6 +9503,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -8974,7 +9584,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -8986,6 +9597,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -9071,7 +9683,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -9107,6 +9720,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -9126,6 +9740,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -9169,12 +9784,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -9337,12 +9954,6 @@ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, "get-uri": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", @@ -9419,9 +10030,9 @@ } }, "global-agent": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.12.tgz", - "integrity": "sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.2.0.tgz", + "integrity": "sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg==", "dev": true, "optional": true, "requires": { @@ -9435,28 +10046,56 @@ }, "dependencies": { "core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.1.tgz", + "integrity": "sha512-pwCxEXnj27XG47mu7SXAwhLP3L5CrlvCB91ANUkIz40P27kUcvNfSdvyZJ9CLHiVoKSp+TTChMQMSKQEH/IQxA==", "dev": true, "optional": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "optional": true } } }, "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", "dev": true, "requires": { - "ini": "^1.3.4" + "ini": "1.3.7" + }, + "dependencies": { + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + } } }, "global-modules": { @@ -9520,9 +10159,9 @@ "dev": true }, "globalthis": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz", - "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", + "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", "dev": true, "optional": true, "requires": { @@ -9876,7 +10515,8 @@ "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true + "dev": true, + "optional": true }, "home-or-tmp": { "version": "2.0.0", @@ -10059,6 +10699,7 @@ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "dev": true, + "optional": true, "requires": { "agent-base": "4", "debug": "3.1.0" @@ -10379,6 +11020,7 @@ "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", "dev": true, + "optional": true, "requires": { "httpreq": ">=0.4.22", "underscore": "~1.7.0" @@ -10388,7 +11030,8 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true + "dev": true, + "optional": true }, "https-browserify": { "version": "1.0.0", @@ -10413,6 +11056,16 @@ "integrity": "sha1-pls0RZrWNnrbs3B6gqPJ+RYWcDA=", "dev": true }, + "iconv-corefoundation": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.5.tgz", + "integrity": "sha512-hI4m7udfV04OcjleOmDaR4gwXnH4xumxN+ZmywHDiKf2CmAzsT9SVYe7Y4pdnQbyZfXwAQyrElykbE5PrPRfmQ==", + "dev": true, + "optional": true, + "requires": { + "cli-truncate": "^1.1.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -10564,9 +11217,9 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "in-publish": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", + "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", "dev": true }, "indent-string": { @@ -10723,12 +11376,6 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -10790,11 +11437,6 @@ "binary-extensions": "^1.0.0" } }, - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" - }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", @@ -10810,6 +11452,15 @@ "ci-info": "^2.0.0" } }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -10906,13 +11557,21 @@ } }, "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", "dev": true, "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + }, + "dependencies": { + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true + } } }, "is-lower-case": { @@ -10946,9 +11605,9 @@ } }, "is-npm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", - "integrity": "sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", "dev": true }, "is-number": { @@ -11034,7 +11693,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true + "dev": true, + "optional": true }, "is-regex": { "version": "1.0.4", @@ -11120,9 +11780,9 @@ "dev": true }, "isbinaryfile": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.3.tgz", - "integrity": "sha512-GQ9Gjhp3AsEbo8/L/pA+MYl/c4hRm5O/+uCkF4LMx1a556Wh4/d75H13qu9LldmhU4yKnlfNKBmEcCaze3b2Gw==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz", + "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==", "dev": true }, "isexe": { @@ -11260,6 +11920,26 @@ "semver": "^5.3.0" } }, + "jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "dev": true, + "requires": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, "javascript-natural-sort": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", @@ -11628,15 +12308,6 @@ "readable-stream": "^2.0.5" } }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, "leaflet": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.5.1.tgz", @@ -11660,6 +12331,14 @@ "resolved": "https://registry.npmjs.org/leaflet-rotatedmarker/-/leaflet-rotatedmarker-0.2.0.tgz", "integrity": "sha1-RGf0n5jRv9VpWb2cZwUgPdJgEnc=" }, + "leaflet-search": { + "version": "2.9.9", + "resolved": "https://registry.npmjs.org/leaflet-search/-/leaflet-search-2.9.9.tgz", + "integrity": "sha512-sGPjkMz9gQP+CKrY0G/RjQFWHdt1/KDJQiouv1dWogtN66rcE/aPR/DOduCXM3Um+VgsAmr5+jRQ0iK3Fs9I8A==", + "requires": { + "leaflet": "*" + } + }, "leaflet-sidebar-v2": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/leaflet-sidebar-v2/-/leaflet-sidebar-v2-3.2.1.tgz", @@ -11670,6 +12349,21 @@ "resolved": "https://registry.npmjs.org/leaflet-textpath/-/leaflet-textpath-1.2.0.tgz", "integrity": "sha512-anLGWptWb916MhEXi4WewYe08YKCawRvEXsMGj9fuYnUGd+irV3VG4UXcdW1l+Oa/TZoCTLQsg3LNwvFcroVog==" }, + "leaflet.pattern": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/leaflet.pattern/-/leaflet.pattern-0.1.0.tgz", + "integrity": "sha512-E4sxvvK0XHi1EhE1yUTG1bzafXZoXUPqWPjHz5fSpv/pOcT4CtS0qR1lhFSRtSUYios8OwlZmUGB9n91zQEgcw==", + "requires": { + "leaflet": "~0.7.1" + }, + "dependencies": { + "leaflet": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-0.7.7.tgz", + "integrity": "sha1-HjUrpU5j0HZFH6NjyQCJDLLPde4=" + } + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -11684,13 +12378,15 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true + "dev": true, + "optional": true }, "libmime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, + "optional": true, "requires": { "iconv-lite": "0.4.15", "libbase64": "0.1.0", @@ -11701,7 +12397,8 @@ "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true + "dev": true, + "optional": true } } }, @@ -11709,7 +12406,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true + "dev": true, + "optional": true }, "lineclip": { "version": "1.1.5", @@ -12870,7 +13568,8 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "multicast-dns": { "version": "6.2.3", @@ -13155,9 +13854,9 @@ "dev": true }, "node-sass": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz", - "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", "dev": true, "requires": { "async-foreach": "^0.1.3", @@ -13167,14 +13866,14 @@ "get-stdin": "^4.0.1", "glob": "^7.0.3", "in-publish": "^2.0.0", - "lodash": "^4.17.11", + "lodash": "^4.17.15", "meow": "^3.7.0", "mkdirp": "^0.5.1", "nan": "^2.13.2", "node-gyp": "^3.8.0", "npmlog": "^4.0.0", "request": "^2.88.0", - "sass-graph": "^2.2.4", + "sass-graph": "2.2.5", "stdout-stream": "^1.4.0", "true-case-path": "^1.0.2" }, @@ -13255,13 +13954,15 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true + "dev": true, + "optional": true }, "nodemailer-shared": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", "dev": true, + "optional": true, "requires": { "nodemailer-fetch": "1.6.0" } @@ -13294,7 +13995,8 @@ "version": "0.1.10", "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true + "dev": true, + "optional": true }, "nopt": { "version": "3.0.6", @@ -13726,15 +14428,6 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -13865,7 +14558,8 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "optional": true } } }, @@ -14196,6 +14890,27 @@ "find-up": "^2.1.0" } }, + "plist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", + "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", + "dev": true, + "optional": true, + "requires": { + "base64-js": "^1.2.3", + "xmlbuilder": "^9.0.7", + "xmldom": "0.1.x" + }, + "dependencies": { + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true, + "optional": true + } + } + }, "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", @@ -14975,6 +15690,15 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -15117,16 +15841,15 @@ } }, "read-config-file": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-5.0.0.tgz", - "integrity": "sha512-jIKUu+C84bfnKxyJ5j30CxCqgXWYjZLXuVE/NYlMEpeni+dhESgAeZOZd0JZbg1xTkMmnCdxksDoarkOyfEsOg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.0.0.tgz", + "integrity": "sha512-PHjROSdpceKUmqS06wqwP92VrM46PZSTubmNIMJ5DrMwg1OgenSTSEHIkCa6TiOJ+y/J0xnG1fFwG3M+Oi1aNA==", "dev": true, "requires": { - "dotenv": "^8.0.0", + "dotenv": "^8.2.0", "dotenv-expand": "^5.1.0", - "fs-extra": "^8.1.0", "js-yaml": "^3.13.1", - "json5": "^2.1.0", + "json5": "^2.1.2", "lazy-val": "^1.0.4" }, "dependencies": { @@ -15136,21 +15859,10 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -15158,18 +15870,18 @@ } }, "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minimist": "^1.2.5" } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true } } @@ -15671,13 +16383,12 @@ } }, "registry-auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz", - "integrity": "sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", "dev": true, "requires": { - "rc": "^1.2.8", - "safe-buffer": "^5.0.1" + "rc": "^1.2.8" } }, "registry-url": { @@ -15965,13 +16676,13 @@ } }, "roarr": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.3.tgz", - "integrity": "sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA==", + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", "dev": true, "optional": true, "requires": { - "boolean": "^3.0.0", + "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", @@ -16082,90 +16793,130 @@ } }, "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", "dev": true, "requires": { "glob": "^7.0.0", "lodash": "^4.0.0", "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" + "yargs": "^13.3.2" }, "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "find-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "locate-path": "^3.0.0" } }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" } }, "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { - "camelcase": "^3.0.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -16268,12 +17019,20 @@ "optional": true }, "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", "dev": true, "requires": { - "semver": "^5.0.3" + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "send": { @@ -16569,13 +17328,15 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==", - "dev": true + "dev": true, + "optional": true }, "smtp-connection": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", "dev": true, + "optional": true, "requires": { "httpntlm": "1.6.1", "nodemailer-shared": "1.1.0" @@ -16885,6 +17646,7 @@ "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz", "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==", "dev": true, + "optional": true, "requires": { "ip": "^1.1.5", "smart-buffer": "4.0.2" @@ -16895,6 +17657,7 @@ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", "dev": true, + "optional": true, "requires": { "agent-base": "~4.2.1", "socks": "~2.3.2" @@ -16905,6 +17668,7 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "dev": true, + "optional": true, "requires": { "es6-promisify": "^5.0.0" } @@ -17139,9 +17903,9 @@ } }, "stat-mode": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.3.0.tgz", - "integrity": "sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", "dev": true }, "static-extend": { @@ -17406,12 +18170,12 @@ }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -17563,9 +18327,9 @@ } }, "temp-file": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.3.6.tgz", - "integrity": "sha512-7TPldi8QJqRlPIF/Y33mVvo8+xDfi6+aVTCK4CrCaLqCoaOnVtf3SA4hCU0T5nhYDdOC7erw7o2uWfvijlk4Ug==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.3.7.tgz", + "integrity": "sha512-9tBJKt7GZAQt/Rg0QzVWA8Am8c1EFl+CAv04/aBVqlx5oyfQ508sFIABshQ0xbZu6mBrFLWIUXO/bbLYghW70g==", "dev": true, "requires": { "async-exit-hook": "^2.0.1", @@ -17586,13 +18350,10 @@ } }, "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, - "requires": { - "execa": "^0.7.0" - } + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true }, "terser": { "version": "4.3.9", @@ -17899,6 +18660,14 @@ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" }, + "tiny-worker": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tiny-worker/-/tiny-worker-2.3.0.tgz", + "integrity": "sha512-pJ70wq5EAqTAEl9IkGzA+fN0836rycEuz2Cn6yeZ6FRzlVS5IDOkFHpIoEsksPRQV34GDqXm65+OlnZqUSyK2g==", + "requires": { + "esm": "^3.2.25" + } + }, "tinyqueue": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-1.2.3.tgz", @@ -18167,9 +18936,9 @@ "dev": true }, "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, "type-is": { @@ -18193,6 +18962,15 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, "uglify-js": { "version": "3.4.10", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", @@ -18233,7 +19011,8 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true + "dev": true, + "optional": true }, "union-value": { "version": "1.0.1", @@ -18278,12 +19057,12 @@ } }, "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, "requires": { - "crypto-random-string": "^1.0.0" + "crypto-random-string": "^2.0.0" } }, "universalify": { @@ -18351,23 +19130,100 @@ "dev": true }, "update-notifier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz", - "integrity": "sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.0.1.tgz", + "integrity": "sha512-BuVpRdlwxeIOvmc32AGYvO1KVdPlsmqSh8KDDBxS6kDE5VR7R8OMP1d8MdhaVBvxl4H3551k9akXr0Y1iIB2Wg==", "dev": true, "requires": { - "boxen": "^3.0.0", - "chalk": "^2.0.1", - "configstore": "^4.0.0", + "boxen": "^4.2.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", "has-yarn": "^2.1.0", "import-lazy": "^2.1.0", "is-ci": "^2.0.0", - "is-installed-globally": "^0.1.0", - "is-npm": "^3.0.0", + "is-installed-globally": "^0.3.2", + "is-npm": "^5.0.0", "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.2", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } } }, "upper-case": { @@ -20083,43 +20939,50 @@ } }, "widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dev": true, "requires": { - "string-width": "^2.1.1" + "string-width": "^4.0.0" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } } } @@ -20279,9 +21142,9 @@ } }, "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, "xml-char-classes": { @@ -20300,6 +21163,13 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==" }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "dev": true, + "optional": true + }, "xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", @@ -20332,103 +21202,115 @@ "dev": true }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "color-convert": "^2.0.1" } }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true } } }, diff --git a/package.json b/package.json index 4782736..c418caa 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,14 @@ { "name": "flightgear-airports", - "version": "0.0.20", + "version": "0.0.34", "author": "portree_kid ", "description": "An software to design Flightgear groundnets", - "license": "GPL v3", + "license": "GPL-3.0", "main": "./dist/electron/main.js", "scripts": { "build": "node .electron-vue/build.js && electron-builder", "build:dir": "node .electron-vue/build.js && electron-builder --dir", "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js", - "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js", "dev": "SET NODE_ENV=development&& node .electron-vue/dev-runner.js", "e2e": "npm run pack && mocha test/e2e", "lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src test", @@ -18,6 +17,7 @@ "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js", "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js", "test": "npm run unit && npm run e2e", + "mocha": "SET NODE_ENV=mocha&& mocha test/mocha/**/*.js", "unit": "karma start test/unit/karma.conf.js", "postinstall": "" }, @@ -70,30 +70,35 @@ ] }, "mac": { - "icon": "build/icons/icon.icns" + "icon": "build/icons/icon.icns", + "publish": [] }, "win": { - "icon": "build/icons/icon.ico" + "icon": "build/icons/icon.ico", + "publish": [] }, "nsis": { "oneClick": false, + "perMachine": true, "allowToChangeInstallationDirectory": true }, "linux": { "icon": "build/icons", - "target": "AppImage" + "target": "AppImage", + "publish": [] } }, "dependencies": { "@turf/intersect": "^6.1.3", "@turf/turf": "^5.1.6", - "axios": "^0.18.1", + "axios": "^0.21.1", "coordinate-parser": "^1.0.3", "dijkstrajs": "^1.0.1", "electron-debug": "^3.0.1", - "element-ui": "^2.13.2", + "element-ui": "^2.15.1", "file-url": "^3.0.0", "fs": "0.0.1-security", + "fs-extra": "^9.0.1", "geo-coordinates-parser": "^1.2.4", "geodesy": "^2.2.0", "idb": "^4.0.5", @@ -101,11 +106,14 @@ "leaflet": "^1.5.1", "leaflet-editable": "^1.2.0", "leaflet-polylinedecorator": "^1.6.0", + "leaflet-search": "^2.9.9", "leaflet-sidebar-v2": "^3.2.1", "leaflet-textpath": "^1.2.0", + "leaflet.pattern": "^0.1.0", "lokijs": "^1.5.8", "mathjs": "^6.2.5", "path": "^0.12.7", + "tiny-worker": "^2.3.0", "vue": "^2.5.16", "vue-electron": "^1.0.6", "vue-idb": "^0.2.0", @@ -134,7 +142,7 @@ "babel-register": "^6.26.0", "babili-webpack-plugin": "^0.1.2", "cfonts": "^2.1.2", - "chai": "^4.1.2", + "chai": "^4.2.0", "chalk": "^2.4.1", "copy-webpack-plugin": "^4.5.1", "cross-env": "^5.1.6", @@ -142,7 +150,7 @@ "del": "^3.0.0", "devtron": "^1.4.0", "electron": "^7.2.4", - "electron-builder": "^21.2.0", + "electron-builder": "^22.10.4", "electron-devtools-installer": "^2.2.4", "eslint": "^4.19.1", "eslint-config-standard": "^11.0.0", @@ -168,7 +176,7 @@ "mocha": "^5.2.0", "multispinner": "^0.2.1", "node-loader": "^0.6.0", - "node-sass": "^4.9.2", + "node-sass": "^4.14.1", "require-dir": "^1.0.0", "sass-loader": "^7.0.3", "spectron": "^3.8.0", diff --git a/src/index.ejs b/src/index.ejs index 1749ec7..6172fbc 100644 --- a/src/index.ejs +++ b/src/index.ejs @@ -6,7 +6,7 @@ <% if (htmlWebpackPlugin.options.nodeModules) { %> <% } %> diff --git a/src/main/index.js b/src/main/index.js index 6412511..a9e236c 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,6 +1,6 @@ 'use strict' -import { app, BrowserWindow } from 'electron' +import { app, BrowserWindow, Menu } from 'electron' const { ipcMain } = require('electron') ipcMain.on('OpenDebugger', (event, arg) => { @@ -20,6 +20,7 @@ const winURL = process.env.NODE_ENV === 'development' : `file://${__dirname}/index.html` function createWindow () { + Menu.setApplicationMenu(null) /** * Initial window options */ @@ -30,6 +31,7 @@ function createWindow () { nodeIntegration: true, nodeIntegrationInWorker: true }, + closable: true, width: 1000 }) mainWindow.loadURL(winURL) diff --git a/src/renderer/check/mapper.js b/src/renderer/check/mapper.js new file mode 100644 index 0000000..6c9209c --- /dev/null +++ b/src/renderer/check/mapper.js @@ -0,0 +1,67 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + +/* eslint-disable */ +var L = require('leaflet'); + +export function checkMapper(o) { + if (o instanceof L.ParkingSpot) { + /* + if( o.box === undefined ) { + debugger; + } */ + return { + 'index': Number(o['id']), + '_leaflet_id': o._leaflet_id, + 'type': 'parking', + 'parkingType': o.options.attributes.type, + 'name': o.options.attributes.name, + 'radius': String(o.options.attributes.radius), + 'lat': o._latlng.lat, + 'lng': o._latlng.lng, + 'box': o.box !== undefined ? o.box.getLatLngs() : null + }; + } else if (o instanceof L.RunwayNode) { + console.log(o) + return { 'index': Number(o['glueindex']), '_leaflet_id': o._leaflet_id, 'lat': o._latlng.lat, 'lng': o._latlng.lng, 'type': 'runway' }; + } else if (o instanceof L.HoldNode) { + console.log(o) + return { 'index': Number(o['glueindex']), '_leaflet_id': o._leaflet_id, 'type': o.holdPointType }; + } else if (o instanceof L.RunwayPolygon) { + return { + 'type': 'runway_poly', + 'pavement': o.getLatLngs() + } + } else if (o instanceof L.TakeoffPolygon) { + return { + 'type': 'takeoffpad_poly', + 'pavement': o.getLatLngs() + } + } else if (o instanceof L.Polyline) { + console.log(o) + var latLngs = o.getLatLngs().map(l => ({ lat: l.lat, lng: l.lng, index: l.glueindex })); + if (o.options.attributes===undefined) { + return null; + } + return { 'start': Number(o['begin']), 'end': Number(o['end']), '_leaflet_id': o._leaflet_id, 'type': 'poly', 'direction': o.options.attributes.direction, 'isPushBackRoute': o.options.attributes.isPushBackRoute, latLngs: latLngs }; + } + else { + console.log('Unknown Type ') + console.log(typeof o) + } +} + +export function groMapper(o) { + if (o instanceof L.Polygon) { + + } +} diff --git a/src/renderer/components/AiLayer.vue b/src/renderer/components/AiLayer.vue index 82cf7b2..e9cf055 100644 --- a/src/renderer/components/AiLayer.vue +++ b/src/renderer/components/AiLayer.vue @@ -10,7 +10,9 @@ props: [], mounted () { this.aiLayer = aiLayer({url: this.$store.state.Settings.settings.phi_url}) - this.aiLayer.addTo(this.$parent.mapObject) + if(this.aiLayer) { + this.aiLayer.addTo(this.$parent.mapObject) + } }, data () { return { diff --git a/src/renderer/components/AirlineItem.vue b/src/renderer/components/AirlineItem.vue new file mode 100644 index 0000000..507cf06 --- /dev/null +++ b/src/renderer/components/AirlineItem.vue @@ -0,0 +1,100 @@ + + + + + + + + diff --git a/src/renderer/components/Airport.vue b/src/renderer/components/Airport.vue index 5b44f15..2509fc6 100644 --- a/src/renderer/components/Airport.vue +++ b/src/renderer/components/Airport.vue @@ -58,9 +58,12 @@ You should have received a copy of the GNU General Public License along with FG const $ = require('jquery'); import 'element-ui/lib/theme-chalk/index.css' import {removeWip} from '../loaders/groundnet_functions' + import Vue from 'vue' + import { EventBus } from './event-bus.js'; export default { name: 'airport', + components: { }, props: {airport: Object, editing: Boolean}, mounted () { this.$forceUpdate(); @@ -83,7 +86,14 @@ You should have received a copy of the GNU General Public License along with FG this.$store.dispatch('removeWip', this.airport.icao); }, upload() { - + let airports = this.$store.state.Airports.airports + .filter(a => a.properties.icao.match(this.airport.icao)) + if (airports.length > 0) { + this.$store.commit('CENTER', [airports[0].geometry.coordinates[1], airports[0].geometry.coordinates[0]]) + } + Vue.set(this.$parent.$parent.$parent, 'uploadVisible', true) + this.$parent.$parent.$parent.$refs.upload.status() + this.$parent.$parent.$parent.$refs.upload.check() } }, computed: { diff --git a/src/renderer/components/AirportEdit.vue b/src/renderer/components/AirportEdit.vue index 2b262a1..96928cb 100644 --- a/src/renderer/components/AirportEdit.vue +++ b/src/renderer/components/AirportEdit.vue @@ -1,95 +1,231 @@ + diff --git a/src/renderer/components/ThresholdEdit.vue b/src/renderer/components/ThresholdEdit.vue new file mode 100644 index 0000000..7b2710c --- /dev/null +++ b/src/renderer/components/ThresholdEdit.vue @@ -0,0 +1,95 @@ + + + + + + diff --git a/src/renderer/components/ThresholdLayer.vue b/src/renderer/components/ThresholdLayer.vue index a6f75e7..0828478 100644 --- a/src/renderer/components/ThresholdLayer.vue +++ b/src/renderer/components/ThresholdLayer.vue @@ -3,8 +3,10 @@ diff --git a/src/renderer/components/TowerLayer.vue b/src/renderer/components/TowerLayer.vue new file mode 100644 index 0000000..fd13e54 --- /dev/null +++ b/src/renderer/components/TowerLayer.vue @@ -0,0 +1,154 @@ + + + + + + diff --git a/src/renderer/components/TrafficList.vue b/src/renderer/components/TrafficList.vue new file mode 100644 index 0000000..362086d --- /dev/null +++ b/src/renderer/components/TrafficList.vue @@ -0,0 +1,97 @@ + + + + + + + + diff --git a/src/renderer/components/Upload.vue b/src/renderer/components/Upload.vue index a7df017..d9b58f1 100644 --- a/src/renderer/components/Upload.vue +++ b/src/renderer/components/Upload.vue @@ -1,15 +1,31 @@ + + @@ -21,40 +37,91 @@ import axios from 'axios' const fs = require('fs') const path = require('path') + const mapper = require('../check/mapper'); export default { name: 'upload', props: [], mounted () { + this.$store.watch( + function (state) { + return state.Loading.groundnetLoaded; + }, + () => { if(this.$store.state.Loading.groundnetLoaded && + this.$store.state.Loading.pavementLoaded && + this.visible) this.check() } + , + { + deep: false + } + ); + this.$store.watch( + function (state) { + return state.Loading.pavementLoaded; + }, + () => { if(this.$store.state.Loading.groundnetLoaded && + this.$store.state.Loading.pavementLoaded && + this.visible) this.check() } + , + { + deep: false + } + ); + }, data () { return { - gplv2: false, message: null, error: false, progress: 0, max: 0, azure: false + gplv2: false, message: null, error: false, progress: 0, max: 0, azure: false, success: false, uploading: false, buttonText: 'Ok' } }, methods: { reqListener(e) { - if(JSON.parse(e.srcElement.response).status==='OK') { - this.message = null; - this.azure = true; - } else { - this.message = 'Azure down'; - } + try { + if(JSON.parse(e.srcElement.response).status==='OK') { + this.message = null; + this.azure = true; + this.error = false; + } else { + this.message = 'Azure down'; + } + } catch (error) { + console.error(error); + } }, status () { + this.azure = false; var xhr = new XMLHttpRequest(); + var parent = this.$parent; + this.message = 'Checking for Groundweb health' xhr.open('GET', 'http://groundweb.azurewebsites.net/groundnets/status', true); - xhr.addEventListener("load", this.reqListener); - xhr.send(); + xhr.onreadystatechange = function () { + if (xhr.status !== 200){ + parent.$refs.upload.message = 'Azure down'; + parent.$refs.upload.error = true; + console.error(xhr); + } + } + xhr.addEventListener("load", this.reqListener); + try { + xhr.send(); + } catch (err) { + console.error(err); + this.error = true; + } }, - upload () { - var f = path.join(this.$store.state.Settings.settings.airportsDirectory, - this.icao[0], - this.icao[1], - this.icao[2], - this.icao + '.groundnet.new.xml'); + closeClicked () { + Vue.set(this.$parent, 'uploadVisible', false) + return; + }, + handleOkClicked (type) { + this.uploading = true; + var f = path.join(this.$store.state.Settings.settings.airportsDirectory, + this.icao[0], + this.icao[1], + this.icao[2], + this.icao + `.${type}.new.xml`); if (f == null || !fs.existsSync(f)) { this.message = 'File doesn\'t exist'; @@ -72,31 +139,41 @@ var formData = new FormData(); formData.append("gpl", this.gplv2 ) formData.append("user_email", this.$store.state.Settings.settings.email) - formData.append('groundnet', blob, this.icao + '.groundnet.xml'); - + formData.append('groundnet', blob, this.icao + `.${type}.xml`); + var parent = this.$parent; var messageField = this.message; // action after uploading happens + xhr.onreadystatechange = function () { + if (xhr.status !== 200){ + parent.$refs.upload.message = 'Upload Error' + parent.$refs.upload.error = true; + console.error(xhr); + } + } xhr.onload = function(e) { console.log("File uploading completed! "); console.log(e); + parent.$refs.upload.uploading = false if (e.srcElement.status===500) { parent.$refs.upload.message == e.srcElement.statusText } else if(JSON.parse(e.srcElement.response).message.match('[A-Z0-9]* Imported Successfully')) { - Vue.set(parent, 'uploadVisible', false) + parent.$refs.upload.success = true + parent.$refs.upload.message = `${type} Uploaded Successfully` parent.$store.commit('UPLOAD_WIP', parent.$store.state.Airports.currentAirport.icao) - + } else if(JSON.parse(e.srcElement.response).message === 'XML Errors') { var response = JSON.parse(e.srcElement.response); if (response.validationErrors) { + parent.$refs.upload.message = 'XML Errors : \n'; response.validationErrors.forEach(element => { - parent.$refs.upload.message += element.message + '\r\n'; + parent.$refs.upload.message += element.message + '\n'; }); } } else if(JSON.parse(e.srcElement.response) !== undefined) { var response = JSON.parse(e.srcElement.response); parent.$refs.upload.message = response.err; - } else { + } else { parent.$refs.upload.message = response.message; } }; @@ -116,45 +193,22 @@ view.scanning = Boolean(workery.checking) workery.view = view } - }, 1000) - }, - featuresMapper(o) { - if (o instanceof L.ParkingSpot) { - return { 'index': Number(o['id']), - '_leaflet_id': o._leaflet_id, - 'type': 'parking', - 'parkingType': o.options.attributes.type, - 'name': o.options.attributes.name, - 'radius': String(o.options.attributes.radius), - 'lat': o._latlng.lat, - 'lng': o._latlng.lng, - 'box': o.box!==undefined?o.box.getLatLngs():null - }; - } else if (o instanceof L.RunwayNode) { - console.log(o) - return { 'index': Number(o['glueindex']), '_leaflet_id': o._leaflet_id, 'type': 'runway' }; - } else if (o instanceof L.HoldNode) { - console.log(o) - return { 'index': Number(o['glueindex']), '_leaflet_id': o._leaflet_id, 'type': o.holdPointType }; - } else if (o instanceof L.Polyline) { - console.log(o) - var latLngs = o.getLatLngs().map(l => ({lat: l.lat, lng: l.lng, index: l.attributes.index})); - return { 'start': Number(o['begin']), 'end': Number(o['end']), '_leaflet_id': o._leaflet_id, 'type': 'poly', 'isPushBackRoute': o.options.attributes.isPushBackRoute, latLngs: latLngs }; - } else { - console.log('Unknown Type ') - console.log(typeof o) - } + }, 500) }, check () { try { + if(!(this.$store.state.Loading.groundnetLoaded && + this.$store.state.Loading.pavementLoaded)) { + return + } this.scanning = true const winURL = process.env.NODE_ENV === 'development' ? `http://localhost:9080/src/renderer/utils/check.js` : `file://${process.resourcesPath}/workers/check.js` - console.log('make a check worker: ', path.resolve(__dirname, 'check.js')) + console.debug('make a check worker: ', path.resolve(__dirname, 'check.js')) const worker = new Worker(winURL) - console.log(fileUrl('src/renderer/utils/check.js')) + console.debug(fileUrl('src/renderer/utils/check.js')) worker.checking = this.checking worker.max = this.max @@ -163,15 +217,32 @@ worker.progress = 0 // var worker = new Worker(fileUrl('src/renderer/utils/worker.js')) this.worker = worker - var xml = [] - this.$parent.$parent.$parent.$refs.editLayer.groundnetLayerGroup.eachLayer(l => { + var groundnet = [] + + if (!this.editLayer().groundnetLayerGroup) { + this.message = 'Groundnet not visible' + } + if (!this.pavementLayer().pavement) { + this.message = 'Pavement not visible' + } + this.editLayer().groundnetLayerGroup.eachLayer(l => { console.log(l) - xml.push(l) + if (l instanceof L.Polyline) { + l._latlngs[0].glueindex = this.begin; + l._latlngs.slice(-1)[0].glueindex = this.end; + l.extensions(this) + } + groundnet.push(l) }) + var features = groundnet.map(mapper.checkMapper).filter(n => n) + var pavement = [] + this.pavementLayer().pavement.eachLayer(l => { + console.log(l) + pavement.push(l) + }) + var features2 = pavement.map(mapper.checkMapper).filter(n => n) - var features = xml.map(this.featuresMapper).filter(n => n) - - worker.postMessage(['check', features ] ) + worker.postMessage(['check', features.concat(features2) ] ) this.pollData() // the reply var store = this.$store @@ -181,11 +252,10 @@ this.max = 4 } else if (e.data[0] === 'DONE') { console.log('DONE') - store.dispatch('setResults', e.data[1]) worker.terminate() worker.view.max = 0 worker.view.checkDialogVisible = false - clearInterval(this.polling) + clearInterval(this.polling) this.checking = false } else if (e.data.length > 0) { if (e.data[0] === 'max') { @@ -200,6 +270,24 @@ } catch (err) { console.error(err) } + }, + editLayer () { + var parent = this.$parent; + while (!parent.icao||parent.$refs.editLayer==undefined) { + parent = parent.$parent; + if (parent.icao&&parent.$refs.editLayer!==undefined) { + return parent.$refs.editLayer; + } + } + }, + pavementLayer () { + var parent = this.$parent; + while (!parent.icao||parent.$refs.pavementLayer==undefined) { + parent = parent.$parent; + if (parent.icao&&parent.$refs.pavementLayer!==undefined) { + return parent.$refs.pavementLayer; + } + } } }, computed: { @@ -213,28 +301,65 @@ Vue.set(this.$parent, 'uploadVisible', newValue) } }, + textClass: function () { + return !this.error?'centermessage':'error' + }, title: function () { - return `Upload ${this.$parent.$parent.$parent.icao} to groundweb.` + return `Upload ${this.icao} to groundweb.` }, icao: { get: function () { - return this.$parent.$parent.$parent.icao + var parent = this.$parent; + while (!parent.icao) { + parent = parent.$parent; + if (parent.icao) { + return parent.icao; + } + } + return this.$store.state.Airports.currentAirport.icao }, set: function (newValue) { + console.error('ICAO being set ' + newValue); } }, + tower_comittable: function () { + var f = path.join(this.$store.state.Settings.settings.airportsDirectory, + this.icao[0], + this.icao[1], + this.icao[2], + this.icao + '.twr.new.xml'); + return fs.existsSync(f) && this.gplv2 && this.max === 0 && this.azure && !this.uploading; + }, + groundnet_comittable: function () { + var f = path.join(this.$store.state.Settings.settings.airportsDirectory, + this.icao[0], + this.icao[1], + this.icao[2], + this.icao + '.groundnet.new.xml'); + return fs.existsSync(f) && this.$store.state.Check.results.filter(a => a.id>=0).length === 0 && this.gplv2 && this.max === 0 && this.azure && !this.uploading + }, + threshold_comittable: function () { + var f = path.join(this.$store.state.Settings.settings.airportsDirectory, + this.icao[0], + this.icao[1], + this.icao[2], + this.icao + '.threshold.new.xml'); + return fs.existsSync(f) && this.gplv2 && this.max === 0 && this.azure && !this.uploading + }, comittable: function () { - return this.$store.state.Check.results.filter(a => a.id>=0).length === 0 && this.gplv2 && this.max === 0 && this.azure + return this.$store.state.Check.results.filter(a => a.id>=0).length === 0 && this.gplv2 && this.max === 0 && this.azure && !this.uploading }, results: function () { return this.$store.state.Check.results.filter(a => a.id>=0) } - - } + }, } diff --git a/src/renderer/components/event-bus.js b/src/renderer/components/event-bus.js new file mode 100644 index 0000000..cbe0356 --- /dev/null +++ b/src/renderer/components/event-bus.js @@ -0,0 +1,14 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + +import Vue from 'vue' +export const EventBus = new Vue() diff --git a/src/renderer/leaflet/Runway.js b/src/renderer/leaflet/Runway.js new file mode 100644 index 0000000..b13121c --- /dev/null +++ b/src/renderer/leaflet/Runway.js @@ -0,0 +1,41 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + +/* eslint-disable */ + +const turf = require('@turf/turf') + +L.RunwayPolygon = L.Polygon.extend({ + turfyRunway: [], + + setTurfy: function (runwayPoints) { + var latLngs = runwayPoints.map(this.turfToLatLng); + latLngs.push(latLngs[0]); + this.turfyRunway = turf.polygon([latLngs]); + }, + + turfToLatLng: function (turfPoint) { + return [turfPoint.lng, turfPoint.lat]; + } +}); + +var runwayPoly = function (runwayPoints) { + var runwayPoly = new L.RunwayPolygon(runwayPoints); + runwayPoly.setStyle({ color: 'grey', fillColor: 'grey', opacity: 0.5, fillOpacity: 0.5, interactive: false }); + runwayPoly.setTurfy(runwayPoints); + console.debug(runwayPoints); + return runwayPoly; +} + + + +module.exports = runwayPoly; \ No newline at end of file diff --git a/src/renderer/leaflet/TakeoffPad.js b/src/renderer/leaflet/TakeoffPad.js new file mode 100644 index 0000000..5249233 --- /dev/null +++ b/src/renderer/leaflet/TakeoffPad.js @@ -0,0 +1,41 @@ +/* +Copyright 2021 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + +/* eslint-disable */ + +const turf = require('@turf/turf') + +L.TakeoffPolygon = L.Polygon.extend({ + turfyRunway: [], + + setTurfy: function (padPoints) { + var latLngs = padPoints.map(this.turfToLatLng); + latLngs.push(latLngs[0]); + this.turfyRunway = turf.polygon([latLngs]); + }, + + turfToLatLng: function (turfPoint) { + return [turfPoint.lng, turfPoint.lat]; + } +}); + +var takeoffPadPoly = function (padPoints) { + var takeoffPadPoly = new L.TakeoffPolygon(padPoints); + takeoffPadPoly.setStyle({ color: 'black', fillColor: '', opacity: 1.0, fillOpacity: 0.0, interactive: false }); + takeoffPadPoly.setTurfy(padPoints); + console.debug(padPoints); + return takeoffPadPoly; +} + + + +module.exports = takeoffPadPoly; \ No newline at end of file diff --git a/src/renderer/leaflet/Taxiway.js b/src/renderer/leaflet/Taxiway.js new file mode 100644 index 0000000..56e61ea --- /dev/null +++ b/src/renderer/leaflet/Taxiway.js @@ -0,0 +1,25 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + +/* eslint-disable */ + +L.TaxiwayPolygon = L.Polygon.extend({ +}); + +var taxiwayPoly = function (runwayPoints) { + var taxiwayPoly = new L.TaxiwayPolygon(runwayPoints); + taxiwayPoly.setStyle({ color: 'grey', fillColor: 'grey', opacity: 0.3, fillOpacity: 0.3, interactive: false }); + + return taxiwayPoly; +} + +module.exports = taxiwayPoly; \ No newline at end of file diff --git a/src/renderer/loaders/HoldNode.js b/src/renderer/loaders/HoldNode.js index 1e1af5d..86716fe 100644 --- a/src/renderer/loaders/HoldNode.js +++ b/src/renderer/loaders/HoldNode.js @@ -11,7 +11,7 @@ L.HoldNode = L.Marker.extend({ if(this._icon!==null) { this._icon.childNodes[0].style['background-color'] = 'red'; } - }, + }, deselect() { if(this._icon!==null) { this._icon.childNodes[0].style['background-color'] = '#4838cc'; @@ -31,7 +31,7 @@ L.HoldNode = L.Marker.extend({ this.featureLookup[this.glueindex].push(this); }, /** - * + * */ follow(dragIndex, event) { @@ -61,18 +61,18 @@ L.HoldNode = L.Marker.extend({ element.updateEndVertex(event.latlng); element.updateMiddle(); } - } else if (element instanceof L.Editable.VertexMarker) { + } else if (element instanceof L.Editable.VertexMarker) { console.log(element); element.setLatLng(event.latlng); element.latlngs.forEach((latlng, index) => { - console.log(latlng); + console.log(latlng); if(latlng.__vertex === element) { latlng.update(event.latlng); } }); element.editor.feature.setLatLngs(element.latlngs); element.editor.feature.updateMiddle(); - } + } } }) } @@ -80,7 +80,7 @@ L.HoldNode = L.Marker.extend({ var holdNode = function (n, layerGroup) { //console.log(n.attr('lat') + " " + n.attr('lon')); - var latlon = convert(n.attr('lat') + " " + n.attr('lon')); + var latlon = convert(n.attr('lat') + " " + n.attr('lon')); var fa_icon = null; if (n.attr('holdPointType') === 'PushBack') { fa_icon = "
"; @@ -93,8 +93,9 @@ var holdNode = function (n, layerGroup) { iconSize: [30, 42], iconAnchor: [15, 42] }); - const node = new L.HoldNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon }); + const node = new L.HoldNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon }); node.glueindex = n.attr('index'); + node.feature = { properties: { searchTerm: n.attr('index')}}; node.holdPointType = n.attr('holdPointType'); node.addTo(layerGroup); node.addListeners(); diff --git a/src/renderer/loaders/ParkingSpot.js b/src/renderer/loaders/ParkingSpot.js index 2fb6458..bbc02c8 100644 --- a/src/renderer/loaders/ParkingSpot.js +++ b/src/renderer/loaders/ParkingSpot.js @@ -25,10 +25,10 @@ L.ParkingSpot = L.Circle.extend({ if (this.direction === undefined ) { var center = this._latlng; var options = { units: 'kilometers' }; - + var start = turf.destination([center.lng, center.lat], this.options.attributes.radius / 1000, this.normalizeAngle(this.options.attributes.heading+180), options); var end = turf.destination([center.lng, center.lat], this.options.attributes.radius / 1000, this.normalizeAngle(this.options.attributes.heading), options); - // Resize, since leaflet is wrong + // Resize, since leaflet is wrong var rad2 = center.distanceTo(this.turfToLatLng(end), options); console.debug('Dist ', center, [center.lng, center.lat], end.geometry.coordinates, this.options.attributes.radius, rad2); this.setRadius(rad2); @@ -53,7 +53,7 @@ L.ParkingSpot = L.Circle.extend({ try { console.debug("Update Middle ", this.editor.editLayer._layers[0]); var o = this.editor.editLayer._layers; - + console.debug(o); for (var key in o) { if (o.hasOwnProperty(key)) { @@ -63,7 +63,7 @@ L.ParkingSpot = L.Circle.extend({ console.debug(o[key] == this.direction); if (this.editor._resizeLatLng.__vertex!=o[key] && o[key] != this.direction && - o[key] != this.frontWheel && + o[key] != this.frontWheel && o[key] != this.box) { o[key].setLatLng(this.getLatLng()); } @@ -72,9 +72,9 @@ L.ParkingSpot = L.Circle.extend({ //Object.values(o); /* .forEach(vertex => { - console.debug(this.editor._resizeLatLng.__vertex==vertex); + console.debug(this.editor._resizeLatLng.__vertex==vertex); }); - */ + */ } catch (error) { console.error(error); } @@ -85,17 +85,21 @@ L.ParkingSpot = L.Circle.extend({ }, updateHeading(heading) { this.options.attributes.heading = heading; - this.updateVertexFromDirection(); - this.updateWheelPos(); + this.updateVertexFromDirection(); + this.updateWheelPos(); this.updateBox(); }, updateRadius(radius) { this._mRadius = radius; - this.updateDirectionFromVertex(); - this.updateVertexFromDirection(); - this.updateWheelPos(); + this.updateDirectionFromVertex(); + this.updateVertexFromDirection(); + this.updateWheelPos(); this.updateBox(); }, + updateType(type) { + this.options.attributes.type = type; + this.deselect(); + }, // Update the direction vertex from the direction updateVertexFromDirection() { if (this.editEnabled()) { @@ -131,14 +135,15 @@ L.ParkingSpot = L.Circle.extend({ updateWheelPos() { var start = this._latlng; var options = { units: 'kilometers' }; - const parkingSize = validRadii.indexOf(this.options.attributes.radius); + const parkingSize = validRadii.indexOf(this.options.attributes.radius); if (parkingSize>=0) { var frontWheelEnd = turf.destination([start.lng, start.lat], validN2M[parkingSize] / 1000, this.options.attributes.heading, options); if(this.frontWheel!==undefined) { this.frontWheel.setLatLng(this.turfToLatLng(frontWheelEnd)); + return this.turfToLatLng(frontWheelEnd); } - } + } }, updateBox() { var start = [this._latlng.lng, this._latlng.lat]; @@ -176,7 +181,7 @@ L.ParkingSpot = L.Circle.extend({ var latlngs = [leftBack, rightBack, rightMiddle, rightIntermediate, rightFront, leftFront, leftIntermediate, leftMiddle].map(l => this.turfToLatLng(l)); this.box = L.polygon(latlngs); //this.box.addTo(this.editor.editLayer); - this.box._parkingSpot = this; + this.box._parkingSpot = this; this.box.on('click', function (event) { console.debug("Click Parking Box : " + event.target); if (Number(store.default.state.Editable.index) >= 0 && @@ -188,15 +193,18 @@ L.ParkingSpot = L.Circle.extend({ } }); } - event.target._parkingSpot.select(); - }); - + event.target._parkingSpot.select(); + }); + if(this.editor && this.editor.editLayer) { + this.box.addTo(this.editor.editLayer); + } } if(this.box!==undefined) { var latlngs = [leftBack, rightBack, rightMiddle, rightIntermediate, rightFront, leftFront, leftIntermediate, leftMiddle].map(l => this.turfToLatLng(l)); + console.debug(latlngs); this.box.setLatLngs(latlngs); } - } + } }, normalizeAngle( angle ) { if(angle >= 180) { @@ -214,28 +222,61 @@ L.ParkingSpot = L.Circle.extend({ style['color'] = 'red'; this.setStyle(style); if(this.direction) { - this.direction.setStyle(style); + this.direction.setStyle(style); this.frontWheel.setStyle(style); - if(this.box) { - this.box.setStyle(style); - } - } - this.updateWheelPos(); + } + var wheelPos = this.updateWheelPos(); + if(wheelPos) { + store.default.dispatch('setParkingNoseCoords', wheelPos.lat.toFixed(6) + ' ' + wheelPos.lng.toFixed(6)); + } + this.updateBox(); - }, + if(this.box) { + this.box.setStyle(style); + } + }, deselect() { var style = {}; - style['color'] = '#3388ff'; + if(this.options.attributes.type == 'ga') { + style['color'] = 'green'; + } else if(this.options.attributes.type == 'cargo') { + style['color'] = 'yellow'; + } else if(this.options.attributes.type == 'gate') { + style['color'] = '#3388ff'; + } else if(this.options.attributes.type == 'mil-fighter') { + style['color'] = 'red'; + } else if(this.options.attributes.type == 'mil-cargo') { + style['color'] = 'DarkRed'; + } else { + style['color'] = '#3388ff'; + } this.setStyle(style); if(this.direction) { - this.direction.setStyle(style); + this.direction.setStyle(style); this.frontWheel.setStyle(style); - if(this.box) { - this.box.setStyle(style); - } } this.updateWheelPos(); this.updateBox(); + if(this.box) { + this.box.setStyle(style); + } + }, + setInteractive(interactive) { + if (interactive) { + if(this.direction&&this.direction._path) { + L.DomUtil.addClass(this.direction._path, 'leaflet-interactive'); + } + if(this.box&&this.box._path) { + L.DomUtil.addClass(this.box._path, 'leaflet-interactive'); + } + } else { + if(this.direction&&this.direction._path) { + L.DomUtil.removeClass(this.direction._path, 'leaflet-interactive'); + } + if(this.box&&this.box._path) { + L.DomUtil.removeClass(this.box._path, 'leaflet-interactive'); + } + } }, addListeners: function () { this.on('editable:drawing:move', function (event) { @@ -247,36 +288,38 @@ L.ParkingSpot = L.Circle.extend({ event.target.updateVertexFromDirection(); event.target.updateWheelPos(); event.target.updateBox(); - this.follow(event.target.id, event); + this.follow(event.target.id, event); } else if(event.target.editor._resizeLatLng.__vertex._icon === event.sourceTarget._element) { - event.target.updateDirectionFromVertex(); - event.target.updateVertexFromDirection(); + event.target.updateDirectionFromVertex(); + event.target.updateVertexFromDirection(); event.target.updateWheelPos(); event.target.updateBox(); } }); this.on('add', function (event) { - console.log(event); + console.debug(event); event.target.updateBox(); if(event.target.box !== undefined) { event.target.box.addTo(event.target._map); } + event.target.setInteractive(false); }); this.on('remove', function (event) { - console.log(event); + console.debug(event); if(event.target.box !== undefined) { event.target.box.removeFrom(event.target._map); } }); - this.on('editable:vertex:drag', function (event) { + this.on('editable:vertex:drag', function (event) { console.debug("Drag Parking : ", event); }); this.on('editable:vertex:dragend', function (event) { console.debug("DragEnd Parking : ", event); store.default.dispatch('setParking', event.target.options.attributes); store.default.dispatch('setParkingCoords', event.target.getLatLng().lat.toFixed(6) + ' ' + event.target.getLatLng().lng.toFixed(6)); - event.target.updateWheelPos(); + var wheelPos = event.target.updateWheelPos(); + store.default.dispatch('setParkingNoseCoords', wheelPos.lat.toFixed(6) + ' ' + wheelPos.lng.toFixed(6)); event.target.updateBox(); /* store.default.dispatch('setParkingHeading', this.options.attributes.heading) @@ -293,8 +336,8 @@ L.ParkingSpot = L.Circle.extend({ } }); } - event.target.select(); - }); + event.target.select(); + }); this.on('editable:vertex:clicked', function (event) { console.debug(this.featureLookup[event.vertex.glueindex]); if (Number(store.default.state.Editable.index) >= 0 && @@ -309,14 +352,14 @@ L.ParkingSpot = L.Circle.extend({ if(event.target.editor._resizeLatLng.__vertex._icon !== event.sourceTarget._element){ event.vertex._icon.style['background-color'] = 'red'; store.default.dispatch('setParking', event.target.options.attributes); - this.select(); + this.select(); } }); this.on('editable:disable', function (event) { event.target.removeDirection(); - }); + }); }, updateStyle: function () { @@ -330,24 +373,20 @@ L.ParkingSpot = L.Circle.extend({ } }); } - - store.default.dispatch('setParking', this.options.attributes); - store.default.dispatch('setParkingCoords', this.getLatLng().lat.toFixed(6) + ' ' + this.getLatLng().lng.toFixed(6)); - this.select(); }, turfToLatLng: function (turfPoint) { return {lat: turfPoint.geometry.coordinates[1], lng: turfPoint.geometry.coordinates[0]}; }, extensions: function (editLayer) { - this.createDirection(); + this.createDirection(); if (typeof this.featureLookup[this.id] === 'undefined') { this.featureLookup[this.id] = []; } this.featureLookup[this.id].push(this); }, /** - * + * */ follow (dragIndex, event) { @@ -393,7 +432,7 @@ L.ParkingSpot = L.Circle.extend({ }); element.editor.feature.setLatLngs(element.latlngs); element.editor.feature.updateMiddle(); - } + } } }) }, @@ -413,12 +452,14 @@ var parkingSpot = function (n, layerGroup) { var latlon = convert(n.attr('lat') + " " + n.attr('lon')); //console.log(latlon.decimalLatitude); //console.log(convert(n.attr('lat') + " " + n.attr('lon')).decimalLongitude); - const circle = new L.ParkingSpot([latlon.decimalLatitude, latlon.decimalLongitude], { radius: n.attr('radius'), attributes: {} }); - circle.on('editable:enable', function (event) { + const parking = new L.ParkingSpot([latlon.decimalLatitude, latlon.decimalLongitude], { radius: n.attr('radius'), attributes: {} }); + parking.on('editable:enable', function (event) { // event.target.createDirection(); }); - circle.id = n.attr('index'); - circle.glueindex = n.attr('index'); + parking.id = n.attr('index'); + parking.glueindex = n.attr('index'); + parking.feature = { properties: { searchTerm: n.attr('index') + ' ' + n.attr('name')}}; + /* */ //circle.attributes = { type: n.attr('type'), name: n.attr('name'), radius: Number(n.attr('radius')), airlineCodes: n.attr('airlineCodes'), heading: Number(n.attr('heading')) }; $.each( n.attrs, function( key, value ) { - console.debug( '$', circle.id, key , value); - + console.debug( '$', parking.id, key , value); + if(isNaN(value)) - circle.options.attributes[ key ] = value; + parking.options.attributes[ key ] = value; else - circle.options.attributes[ key ] = Number( value); + parking.options.attributes[ key ] = Number( value); }); - circle.addListeners(); - - circle.addTo(layerGroup); - return circle; + parking.addListeners(); + + parking.addTo(layerGroup); + parking.deselect(); + return parking; } module.exports = parkingSpot; \ No newline at end of file diff --git a/src/renderer/loaders/RunwayNode.js b/src/renderer/loaders/RunwayNode.js index ff9c1fd..88b1084 100644 --- a/src/renderer/loaders/RunwayNode.js +++ b/src/renderer/loaders/RunwayNode.js @@ -26,21 +26,35 @@ L.RunwayNode = L.Marker.extend({ store.default.dispatch('setRunway', event.target.options.attributes); } }); + this.on('add', function (event) { + event.target.setInteractive(false); + }); + }, + setInteractive(interactive) { + if (interactive) { + if(this._icon) { + L.DomUtil.addClass(this._icon, 'leaflet-interactive'); + } + } else { + if(this._icon) { + L.DomUtil.removeClass(this._icon, 'leaflet-interactive'); + } + } }, select() { try { - this._icon.style['color'] = 'red'; + this._icon.style['color'] = 'red'; } catch (error) { console.error(error); } - }, + }, deselect() { try { - this._icon.style['color'] = 'black'; + this._icon.style['color'] = 'black'; } catch (error) { console.error(error); } - }, + }, extensions: function (editLayer) { this.options.attributes = {}; if (typeof this.featureLookup[this.glueindex] === 'undefined') { @@ -49,7 +63,7 @@ L.RunwayNode = L.Marker.extend({ this.featureLookup[this.glueindex].push(this); }, /** - * + * */ follow(dragIndex, event) { @@ -79,18 +93,18 @@ L.RunwayNode = L.Marker.extend({ element.updateEndVertex(event.latlng); element.updateMiddle(); } - } else if (element instanceof L.Editable.VertexMarker) { + } else if (element instanceof L.Editable.VertexMarker) { console.log(element); element.setLatLng(event.latlng); element.latlngs.forEach((latlng, index) => { - console.log(latlng); + console.log(latlng); if(latlng.__vertex === element) { latlng.update(event.latlng); } }); element.editor.feature.setLatLngs(element.latlngs); element.editor.feature.updateMiddle(); - } + } } }) } @@ -106,7 +120,9 @@ var runwayNode = function (n, layerGroup) { }); var node = new L.RunwayNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon, attributes: {} }); node.glueindex = n.attr('index'); - $.each( n.attrs, function( key, value ) { + node.feature = n.attr('index'); + + $.each( n.attrs, function( key, value ) { if(isNaN(value)) node.options.attributes[ key ] = value; else diff --git a/src/renderer/loaders/TaxiwaySegmentExtender.js b/src/renderer/loaders/TaxiwaySegmentExtender.js index 05e2d7c..425e810 100644 --- a/src/renderer/loaders/TaxiwaySegmentExtender.js +++ b/src/renderer/loaders/TaxiwaySegmentExtender.js @@ -3,19 +3,25 @@ const Vue = require('vue'); var L = require('leaflet'); const store = require('../store'); +const util = require('util'); +const assign = require('core-js/fn/object/assign'); -exports.extendTaxiSegment = function (taxiwaySegment) { +const extendTaxiSegment = function (taxiwaySegment) { taxiwaySegment.__proto__.begin; taxiwaySegment.__proto__.end; taxiwaySegment.__proto__.bidirectional; + taxiwaySegment.__proto__.updateBeginVertex = function (latlng) { if (this._latlngs[0].__vertex) { this._latlngs[0].__vertex.setLatLng(latlng); + this.selectVertex(Number(this._latlngs[0].glueindex)); } + }; taxiwaySegment.__proto__.updateEndVertex = function (latlng) { if (this._latlngs[1].__vertex) { this._latlngs[1].__vertex.setLatLng(latlng); + this.selectVertex(Number(this._latlngs[1].glueindex)); } }; @@ -33,65 +39,67 @@ exports.extendTaxiSegment = function (taxiwaySegment) { this.editLayer = editLayer; this._latlngs[0].glueindex = this.begin; this._latlngs.slice(-1)[0].glueindex = this.end; - if (typeof this.featureLookup[this.begin] === 'undefined') { - this.featureLookup[this.begin] = new Array(); + if (this.featureLookup) { + if (typeof this.featureLookup[this.begin] === 'undefined') { + this.featureLookup[this.begin] = new Array(); + } + if (typeof this.featureLookup[this.end] === 'undefined') { + this.featureLookup[this.end] = new Array(); + } + this.featureLookup[this.begin].push(this); + this.featureLookup[this.end].push(this); + this.bidirectional = true; } - if (typeof this.featureLookup[this.end] === 'undefined') { - this.featureLookup[this.end] = new Array(); - } - this.featureLookup[this.begin].push(this); - this.featureLookup[this.end].push(this); - this.bidirectional = true; }; taxiwaySegment.__proto__.select = function () { this.options.attributes.selected = true; this.updateStyle(); }; - taxiwaySegment.__proto__.selectVertex = function () { - this.getLatLngs().forEach( element => { - if (Number(element.glueindex) === store.default.state.Editable.index) { - if (element.__vertex._icon != null) { - element.__vertex.__proto__.deselect = function () { - if (this._icon != null) { - this._icon.style.setProperty('background-color','white'); - this._icon.style.setProperty('color','white'); - } else if (this.icon != null) { - if (this.icon.style != null) { - this.icon.style['background-color'] = 'white'; - } else { - this.setStyle({ color: 'white' }) + taxiwaySegment.__proto__.selectVertex = function (index) { + this.getLatLngs().forEach(element => { + if (Number(element.glueindex) === index) { + if (element.__vertex !== undefined && element.__vertex._icon != null) { + element.__vertex.__proto__.deselect = function () { + if (this._icon != null) { + this._icon.style.setProperty('background-color', 'white'); + this._icon.style.setProperty('color', 'white'); + } else if (this.icon != null) { + if (this.icon.style != null) { + this.icon.style['background-color'] = 'white'; + } else { + this.setStyle({ color: 'white' }) + } + } else if (this.options.icon != null) { + if (this.options.icon.style != null) { + this.options.icon.style['background-color'] = 'white'; + } else { + this.options.icon._setIconStyles({ color: 'white' }) + } + } } - } else if (this.options.icon != null) { - if (this.options.icon.style != null) { - this.options.icon.style['background-color'] = 'white'; + element.__vertex._icon.style.setProperty('background-color', 'red'); + element.__vertex._icon.style.setProperty('color', 'red'); + } else if (element.__vertex !== undefined && element.__vertex.icon != null) { + if (element.__vertex.icon.style != null) { + element.__vertex.icon.style['background-color'] = 'red'; } else { - this.options.icon._setIconStyles({ color: 'white' }) + element.__vertex.setStyle({ color: 'red' }) } - } + } else if (element.__vertex.options.icon != null) { + if (element.__vertex.options.icon.style != null) { + element.__vertex.options.icon.style['background-color'] = 'red'; + } else { + element.__vertex.options.icon._setIconStyles({ color: 'red' }) + } + } } - element.__vertex._icon.style.setProperty('background-color','red'); - element.__vertex._icon.style.setProperty('color','red'); - } else if (element.__vertex !== undefined && element.__vertex.icon != null) { - if (element.__vertex.icon.style != null) { - element.__vertex.icon.style['background-color'] = 'red'; - } else { - element.__vertex.setStyle({ color: 'red' }) - } - } else if (element.__vertex.options.icon != null) { - if (element.__vertex.options.icon.style != null) { - element.__vertex.options.icon.style['background-color'] = 'red'; - } else { - element.__vertex.options.icon._setIconStyles({ color: 'red' }) - } - } - } - }); + }); }; taxiwaySegment.__proto__.deselect = function () { this.options.attributes.selected = false; this.updateStyle(); - this.getLatLngs().forEach( element => { - if (element.__vertex!==undefined) { + this.getLatLngs().forEach(element => { + if (element.__vertex !== undefined) { if (element.__vertex._icon != null) { element.__vertex._icon.style['background-color'] = 'white'; } else if (element.__vertex.icon != null) { @@ -106,96 +114,218 @@ exports.extendTaxiSegment = function (taxiwaySegment) { } else { element.__vertex.options.icon._setIconStyles({ color: 'white' }) } - } + } } }); }; taxiwaySegment.__proto__.addListeners = function () { this.on('click', function (event) { - if (Number(store.default.state.Editable.index) >= 0 && - this.featureLookup[store.default.state.Editable.index] !== undefined) { + if (Number(store.default.state.Editable.index) >= 0 && + this.featureLookup[store.default.state.Editable.index] !== undefined) { this.featureLookup[store.default.state.Editable.index].forEach(element => { element.deselect(); }); } event.target.select(); - console.log("Click : " + event.target); - if (store.default.state.Editable.data.arc === undefined || - store.default.state.Editable.data.arc !== event.target.options.attributes) { - if (event.target.options.attributes === undefined) { - event.target.options.attributes = {}; - } - event.target.options.attributes.index = event.target._leaflet_id; + console.debug("Click : " + util.inspect(event.originalEvent)); + if (!event.originalEvent.ctrlKey) { + if (store.default.state.Editable.data.arc === undefined || + store.default.state.Editable.data.arc !== event.target.options.attributes) { + if (event.target.options.attributes === undefined) { + event.target.options.attributes = {}; + } + event.target.options.attributes.index = event.target._leaflet_id; - this.editLayer.featureLookup[event.target._leaflet_id] = []; - this.featureLookup[event.target._leaflet_id].push(this); - event.target.options.attributes.selected = true; - store.default.dispatch('setArc', event.target.options.attributes); + this.editLayer.featureLookup[event.target._leaflet_id] = []; + this.featureLookup[event.target._leaflet_id].push(this); + event.target.options.attributes.selected = true; + store.default.dispatch('setArc', event.target.options.attributes); + } + } else { + var arcs = event.target.expandArc(event.target.options.attributes); + var multiarc = { name: '', index: 900719925474099, ids: [], isPushBackRoute: null, direction: null }; + if (store.default.state.Editable.data.multiarc === undefined || + store.default.state.Editable.data.multiarc !== event.target.options.attributes) { + if (event.target.options.attributes === undefined) { + event.target.options.attributes = {}; + } + event.target.options.attributes.index = event.target._leaflet_id; + + this.editLayer.featureLookup[event.target._leaflet_id] = []; + this.featureLookup[event.target._leaflet_id].push(this); + event.target.options.attributes.selected = true; + + //multiarc.name = JSON.parse(JSON.stringify(event.target.options.attributes.name)); + //multiarc.isPushBackRoute = JSON.parse(JSON.stringify(event.target.options.attributes.isPushBackRoute)); + //multiarc.direction = JSON.parse(JSON.stringify(event.target.options.attributes.direction)); + if (event.target.options.attributes.name !== undefined) { + multiarc.name = assign(event.target.options.attributes.name); + } + if (event.target.options.attributes.isPushBackRoute) { + multiarc.isPushBackRoute = assign(event.target.options.attributes.isPushBackRoute); + } else { + multiarc.isPushBackRoute = false; + } + multiarc.direction = assign(event.target.options.attributes.direction); + + this.editLayer.featureLookup[900719925474099] = []; + + multiarc.ids = []; + + //TODO + store.default.dispatch('setMultiArc', multiarc); + } + var editLayer = this.editLayer; + arcs.forEach(id => { + console.debug(id); + var arc = editLayer.groundnetLayerGroup.getLayer(id); + if (arc && arc instanceof L.Polyline) { + editLayer.featureLookup[900719925474099].push(arc); + arc.select(); + } + }); + store.default.dispatch('setMultiArcIds', arcs); } }); this.on('editable:drawing:move', function (event) { if (dragIndex >= 0) { - console.log('GlueDrag : '+ dragIndex + '\t' + event.target.dragIndex); + this.selectVertex(dragIndex); + console.log('GlueDrag : ' + dragIndex + '\t' + event.target.dragIndex); this.follow(dragIndex, event); } }); + this.on('editable:middlemarker:mousedown', event => { + console.debug('editable:middlemarker:mousedown'); + }); this.on('editable:vertex:new', event => { - console.log(event) + console.debug('editable:vertex:new ' + event.vertex.getIndex() + '\t' + event.vertex.getLastIndex() + '\t'); // Find nearest node + let isOnRunway = this.editLayer.isOnRunway(event.latlng) let closest = this.editLayer.closestLayerSnap(event.latlng, 5) - let taxiwaySegment = event.latlng.__vertex.editor.feature; + let taxiwaySegment = event.vertex.editor.feature; if (taxiwaySegment.options.attributes === undefined) { taxiwaySegment.options.attributes = { direction: 'bi-directional' }; } + var isOnRunwayNum = 0; + if (isOnRunway) { + isOnRunwayNum = 1; + } taxiwaySegment.updateStyle(); - // Glue to another node - if (closest) { - event.latlng['glueindex'] = Number(closest.glueindex); - event.latlng.__vertex.setLatLng(closest.latlng); - event.latlng.attributes = { index: event.latlng.glueindex, isOnRunway: 0 }; - // Push Vertex to lookup - this.editLayer.featureLookup[event.latlng.glueindex].push(event.latlng.__vertex); - if (taxiwaySegment.options.attributes.begin === undefined) { - taxiwaySegment.options.attributes.begin = event.latlng['glueindex'] - } else { - taxiwaySegment.options.attributes.end = event.latlng['glueindex'] + if (event.vertex.getIndex() !== 0 && event.vertex.getIndex() !== event.vertex.getLastIndex()) { + var x = taxiwaySegment.getLatLngs().filter(l => l === event.vertex.latlng); + // Somehow the latlng is not in our Segment!? + if (taxiwaySegment.getLatLngs().length < 3 && x.length === 0) { + var fixed = taxiwaySegment.getLatLngs(); + fixed.splice(1, 0, event.vertex.latlng); + taxiwaySegment.setLatLngs(fixed); } - if (taxiwaySegment.getLatLngs().length === 1) { - taxiwaySegment.begin = closest.glueindex; + var nextIndex = ++taxiwaySegment.editLayer.groundnetLayerGroup.maxId; + var splitOffNodes = taxiwaySegment.getLatLngs().splice(-1); + var remainingNodes = taxiwaySegment.getLatLngs(); + if (remainingNodes.length <= 1 || !remainingNodes[1]) { + console.error('Not enough remaining nodes', remainingNodes); } - taxiwaySegment.end = closest.glueindex; - console.log(`Closest : ${closest}`) - } else { - event.vertex.latlng['glueindex'] = ++this.editLayer.groundnetLayerGroup.maxId; - event.vertex.latlng.attributes = { index: event.vertex.latlng.glueindex, isOnRunway: 0 }; - this.editLayer.featureLookup[event.vertex.latlng.glueindex] = []; - this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(event.vertex); - this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(taxiwaySegment); - // taxiwaySegment.editor.refresh(); + splitOffNodes.unshift(L.latLng(remainingNodes[1].lat, remainingNodes[1].lng, remainingNodes[1].alt)); + remainingNodes[1]['glueindex'] = nextIndex; + remainingNodes[1].attributes = { index: nextIndex, isOnRunway: isOnRunwayNum }; + taxiwaySegment.options.attributes.end = nextIndex; + splitOffNodes[0]['glueindex'] = nextIndex; + splitOffNodes[0].attributes = { index: nextIndex, isOnRunway: isOnRunwayNum }; + taxiwaySegment.setLatLngs(remainingNodes); + //taxiwaySegment.editor.refresh(); //taxiwaySegment.editor.reset(); - if (taxiwaySegment.options.attributes.begin === undefined) { - taxiwaySegment.options.attributes.begin = event.vertex.latlng['glueindex'] - taxiwaySegment.begin = event.vertex.latlng.glueindex; - } else if (taxiwaySegment.options.attributes.end === undefined || - (taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex && - Number(taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex) !== taxiwaySegment.options.attributes.end)) { - taxiwaySegment.options.attributes.end = event.vertex.latlng['glueindex'] - taxiwaySegment.end = Number(event.vertex.latlng.glueindex); + if (splitOffNodes.length > 1) { + var polyline = new L.Polyline(splitOffNodes, { attributes: {} }); + polyline.addTo(taxiwaySegment.editLayer.$parent.$parent.$refs.map.mapObject); + polyline.addTo(taxiwaySegment.editLayer.groundnetLayerGroup); + extendTaxiSegment(polyline); + polyline.addListeners(); + polyline.setEditlayer(taxiwaySegment.editLayer); + polyline.enableEdit(taxiwaySegment.editLayer.$parent.$parent.$refs.map.mapObject); + polyline.editor.refresh(); + //polyline.editor.reset(); + polyline.featureLookup = this.featureLookup; + polyline.feature = { properties: {searchTerm: 'Arc ' + nextIndex + '-' + taxiwaySegment.end}}; + + polyline.options.attributes.name = taxiwaySegment.options.attributes.name; + polyline.options.attributes.direction = taxiwaySegment.options.attributes.direction; + polyline.options.attributes.isPushBackRoute = taxiwaySegment.options.attributes.isPushBackRoute; + polyline.options.attributes.begin = nextIndex; + polyline.options.attributes.end = taxiwaySegment.end; + polyline.updateStyle(); + polyline.begin = nextIndex; + polyline.end = taxiwaySegment.end; + taxiwaySegment.end = nextIndex; + this.editLayer.featureLookup[nextIndex] = []; + this.featureLookup[nextIndex].push(taxiwaySegment); + this.featureLookup[nextIndex].push(polyline); + } else { + console.error('SplitoffNodes Short ', splitOffNodes); + } + } else { + // Glue to another node + if (closest) { + event.latlng['glueindex'] = Number(closest.glueindex); + event.latlng.__vertex.setLatLng(closest.latlng); + event.latlng.attributes = { index: event.latlng.glueindex, isOnRunway: isOnRunwayNum }; + // Push Vertex to lookup + this.editLayer.featureLookup[event.latlng.glueindex].push(event.latlng.__vertex); + if (isOnRunwayNum == 1) { + this.editLayer.addRunwayNode(event.latlng, event.latlng['glueindex']) + } + if (taxiwaySegment.options.attributes.begin === undefined) { + taxiwaySegment.options.attributes.begin = event.latlng['glueindex'] + } else { + taxiwaySegment.options.attributes.end = event.latlng['glueindex'] + } + if (taxiwaySegment.getLatLngs().length === 1) { + taxiwaySegment.begin = closest.glueindex; + } + taxiwaySegment.end = closest.glueindex; + console.debug(`Closest : ${closest}`) + } else { + event.vertex.latlng['glueindex'] = ++this.editLayer.groundnetLayerGroup.maxId; + event.vertex.latlng.attributes = { index: event.vertex.latlng.glueindex, isOnRunway: isOnRunwayNum }; + this.editLayer.featureLookup[event.vertex.latlng.glueindex] = []; + this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(event.vertex); + this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(taxiwaySegment); + if (isOnRunwayNum == 1) { + this.editLayer.addRunwayNode(event.latlng, event.vertex.latlng['glueindex']) + } + // taxiwaySegment.editor.refresh(); + //taxiwaySegment.editor.reset(); + if (taxiwaySegment.options.attributes.begin === undefined) { + taxiwaySegment.options.attributes.begin = event.vertex.latlng['glueindex'] + taxiwaySegment.begin = event.vertex.latlng.glueindex; + } else if (taxiwaySegment.options.attributes.end === undefined || + (taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex && + Number(taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex) !== taxiwaySegment.options.attributes.end)) { + taxiwaySegment.options.attributes.end = event.vertex.latlng['glueindex'] + taxiwaySegment.end = Number(event.vertex.latlng.glueindex); + } } } + //this.splitShape(taxiwaySegment.getLatLngs(), ) }); this.on('editable:vertex:deleted', event => { - console.log('editable:vertex:deleted' + event) + console.debug('editable:vertex:deleted') + }); + this.on('editable:vertex:mousedown', event => { + console.debug('editable:vertex:mousedown') + event.layer.editor.map.fire('mousedown', event); + }); + this.on('editable:vertex:click', event => { + console.debug('editable:vertex:click') }); this.on('editable:vertex:rawclick', event => { + console.debug('editable:vertex:rawclick') event.cancel() - console.log(event) }); this.on('editable:vertex:clicked', function (event) { if (Number(store.default.state.Editable.index) >= 0 && this.featureLookup[store.default.state.Editable.index] !== undefined) { this.featureLookup[store.default.state.Editable.index].forEach(element => { - if(element.deselect !== undefined) { + if (element.deselect !== undefined) { element.deselect(); } }); @@ -211,8 +341,8 @@ exports.extendTaxiSegment = function (taxiwaySegment) { } else { this.editLayer.featureLookup[event.vertex.latlng.glueindex].forEach store.default.dispatch('setNode', event.vertex.latlng) - this.selectVertex() - } + this.selectVertex(store.default.state.Editable.index) + } } }); var dragIndex = -1; @@ -223,45 +353,122 @@ exports.extendTaxiSegment = function (taxiwaySegment) { return; console.log("Drag Start : ", event.vertex.latlng.glueindex); dragIndex = event.vertex.latlng.glueindex; - }); - this.on('editable:vertex:dragend', function (event) { - console.log("Dragend : ", event.vertex); - if (dragIndex > 0) { - event.target.featureLookup[dragIndex].forEach(element => { - if (element instanceof L.ParkingSpot) { - //element.setLatLng(event); - console.log(element); + if (Number(store.default.state.Editable.index) >= 0 && + this.featureLookup[store.default.state.Editable.index] !== undefined) { + this.featureLookup[store.default.state.Editable.index].forEach(element => { + if (element.deselect !== undefined) { + element.deselect(); } }); } - dragIndex = -1; - var parking = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.ParkingSpot); - if (parking.length > 0) { - parking[0].selectParking(); - } else { - if( Number(event.vertex.latlng.glueindex) !== store.default.state.Editable.index) { - if (Number(store.default.state.Editable.index) >= 0 && - this.featureLookup[store.default.state.Editable.index] !== undefined) { - this.featureLookup[store.default.state.Editable.index].forEach(element => { - if(element.deselect !== undefined) { - element.deselect(); - } - }); - } - store.default.dispatch('setNode', event.vertex.latlng) + if (!this.editor.map.editTools.drawing()) { + var hold = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.HoldNode); + if (hold.length > 0) { + hold[0].select(); + } + var parking = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.ParkingSpot); + if (parking.length > 0) { + parking[0].selectParking(); + } else { + this.selectVertex(Number(dragIndex)) } - var lines = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.Polyline); - Vue.default.nextTick(function () { - lines.forEach( line => { - line.selectVertex() - }); - }) } - + }); + this.on('editable:vertex:dragend', function (event) { + console.log("Dragend : ", event.vertex); + try { + if (dragIndex > 0) { + event.target.featureLookup[dragIndex].forEach(element => { + if (element instanceof L.ParkingSpot) { + //element.setLatLng(event); + console.log(element); + } + }); + } + dragIndex = -1; + if (!event.vertex.latlng.glueindex) { + console.error('GlueIndex not found : ', event.vertex); + } + var parking = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.ParkingSpot); + if (parking.length > 0) { + parking[0].selectParking(); + } else { + if (Number(event.vertex.latlng.glueindex) !== store.default.state.Editable.index) { + if (Number(store.default.state.Editable.index) >= 0 && + this.featureLookup[store.default.state.Editable.index] !== undefined) { + this.featureLookup[store.default.state.Editable.index].forEach(element => { + if (element.deselect !== undefined) { + element.deselect(); + } + }); + } + store.default.dispatch('setNode', event.vertex.latlng) + } + var lines = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.Polyline); + Vue.default.nextTick(function () { + lines.forEach(line => { + line.selectVertex(store.default.state.Editable.index) + }); + }) + } + } catch (error) { + console.error(error); + console.error(event.vertex.latlng.glueindex); + } }); }; + + taxiwaySegment.__proto__.expandArc = function (attributes) { + var isPushBackRoute = attributes.isPushBackRoute; + var ids = []; + var walkedNodes = []; + var segmentIds = []; + console.debug('start Walk'); + ids = ids.concat(this.walkPushbackRoute(attributes.begin, walkedNodes, isPushBackRoute)); + ids = ids.concat(this.walkPushbackRoute(attributes.end, walkedNodes, isPushBackRoute)); + return ids; + } + + taxiwaySegment.__proto__.walkPushbackRoute = function (index, walkedNodes, isPushBackRoute) { + console.debug('Walk Level'); + walkedNodes.push(index) + var segmentIds = []; + var polyLines = this.featureLookup[index].filter(n => n instanceof L.Polyline); + if (polyLines === undefined || polyLines.length > 2) { + console.debug('Walk ' + index + '\t' + polyLines.length); + return; + } + + polyLines.forEach(l => { + segmentIds.push(l._leaflet_id); + console.debug('Walk Next ' + index + '\t' + + (walkedNodes.indexOf(index) < 0) + '\t' + + l.begin + '\t' + + (walkedNodes.indexOf(Number(l.begin)) < 0) + '\t' + + l.end + '\t' + + (walkedNodes.indexOf(Number(l.end)) < 0) + '\t' + + l.options.attributes.direction + '\t' + + l.options.attributes.begin + '\t' + + l.options.attributes.end); + console.debug('Walk isPushBackRoute ' + l.options.attributes.isPushBackRoute + '\t' + isPushBackRoute + '\t' + (l.options.attributes.isPushBackRoute === isPushBackRoute)); + if (l.options.attributes.isPushBackRoute === isPushBackRoute) { + console.debug(Number(l.begin) === index && walkedNodes.indexOf(Number(l.end)) < 0); + if (Number(l.begin) === index && walkedNodes.indexOf(Number(l.end)) < 0) { + console.debug('Walk forward ' + l.options.attributes.direction); + segmentIds = segmentIds.concat(this.walkPushbackRoute(Number(l.end), walkedNodes, isPushBackRoute)) + } + console.debug(Number(l.end) === index && walkedNodes.indexOf(Number(l.begin)) < 0); + if (Number(l.end) === index && walkedNodes.indexOf(Number(l.begin)) < 0) { + console.debug('Walk backward ' + l.options.attributes.direction); + segmentIds = segmentIds.concat(this.walkPushbackRoute(Number(l.begin), walkedNodes, isPushBackRoute)) + } + } + }); + return segmentIds; + } + /** - * + * */ taxiwaySegment.__proto__.follow = function (dragIndex, event) { @@ -313,8 +520,58 @@ exports.extendTaxiSegment = function (taxiwaySegment) { }) }; + taxiwaySegment.__proto__.updateArrows = function (zoom) { + if (this._map === null) { + return; + } + if (this.options.attributes.direction === 'forward') { + this.setText(null); + if (zoom <= 16) { + this.setText(' >', { repeat: true, offset: 6, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 15px serif;' } }) + } else if (zoom <= 19) { + this.setText(' > ', { repeat: true, offset: 7, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 20px serif;' } }) + } else { + this.setText(' > ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } }) + } + } else if (this.options.attributes.direction === 'backward') { + this.setText(null); + if (zoom <= 16) { + this.setText(' <', { repeat: true, offset: 6, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 15px serif;' } }) + } else if (zoom <= 19) { + this.setText(' < ', { repeat: true, offset: 7, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 20px serif;' } }) + } else { + this.setText(' < ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } }) + } + } else { + this.setText(null); + } + } + + taxiwaySegment.__proto__.setInteractive = function (interactive) { + if (this.getLayers) { + this.getLayers().forEach(layer => { + layer.setInteractive(interactive); + }); + return; + } + if (!this._path) { + return; + } + + this.options.interactive = interactive; + + if (interactive) { + L.DomUtil.addClass(this._path, 'leaflet-interactive'); + } else { + L.DomUtil.removeClass(this._path, 'leaflet-interactive'); + } + }; + taxiwaySegment.__proto__.updateStyle = function () { var style = {}; + if (!this.options.attributes) { + return; + } if (this.options.attributes.selected) { style.color = 'red'; } else if (this.options.attributes.isPushBackRoute) { @@ -323,18 +580,25 @@ exports.extendTaxiSegment = function (taxiwaySegment) { else { style.color = '#3388ff'; } + if (this.editEnabled()) { + style.interactive = true; + } else { + style.interactive = false; + } this.setStyle(style); - if(this._map !== null) { + if (this._map !== null) { if (this.options.attributes.direction === 'forward') { this.setText(null); this.setText(' > ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } }) } else if (this.options.attributes.direction === 'backward') { this.setText(null); - this.setText(' < ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } }) + this.setText(' < ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } }) } else { this.setText(null); } - - } + + } }; }; + +exports.extendTaxiSegment = extendTaxiSegment; \ No newline at end of file diff --git a/src/renderer/loaders/Threshold.js b/src/renderer/loaders/Threshold.js index 9038342..0f100c3 100644 --- a/src/renderer/loaders/Threshold.js +++ b/src/renderer/loaders/Threshold.js @@ -1,141 +1,164 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ /* eslint-disable */ + const convert = require('geo-coordinates-parser'); -const leaflet = require('leaflet'); -const turf = require('@turf/turf'); -const util = require('util'); +const fs = require('fs'); +const path = require('path'); const store = require('../store'); +const turf = require('@turf/turf'); -var $ = require('jquery'); -L.Threshold = L.Circle.extend({ - select() { - var style = {}; - style['color'] = 'red'; - this.setStyle(style); - }, - addListeners: function () { - this.on('editable:drawing:move', function (event) { - console.log("Move : ", event); - console.log("Move : ", event.latlng); - // Is it the edit vertex (Middle) moving? - if(event.target.editor._resizeLatLng.__vertex._icon !== event.sourceTarget._element){ - event.target.setLatLng(event.latlng); - event.target.updateVertexFromDirection(); - this.follow(event.target.id, event); - } - else if(event.target.editor._resizeLatLng.__vertex._icon === event.sourceTarget._element) { - event.target.updateDirectionFromVertex(); - event.target.updateVertexFromDirection(); - } - }); - /* - this.on('editable:vertex:drag', function (event) { - console.log("Drag : ", event); - }); - */ - this.on('click', function (event) { - console.log("Click : " + event.target); - store.default.dispatch('setParking', event.target.options.attributes); - this.select(); - this.unwatch = store.default.watch( - function (state) { - return state.Editable.data.parking; - }, - () => { - if (event.target instanceof L.Threshold) { - event.target.setStyle({color : '#3388ff'}); - this.unwatch(); - } - } - , - { - deep: true //add this if u need to watch object properties change etc. - } - ); - }); - this.on('editable:vertex:clicked', function (event) { - console.log(this.featureLookup[event.vertex.glueindex]); - if(event.target.editor._resizeLatLng.__vertex._icon !== event.sourceTarget._element){ - event.vertex._icon.style['background-color'] = 'red'; - store.default.dispatch('setParking', event.target.options.attributes); - this.unwatch = store.default.watch( - function (state) { - return state.Editable.data.parking; - }, - () => { - event.target.setStyle({color : '#3388ff'}); - this.unwatch(); - } - , - { - deep: true //add this if u need to watch object properties change etc. - } - ); - - } - }); +/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/ - this.on('editable:disable', function (event) { - event.target.removeDirection(); - }); + +L.Threshold = L.Marker.extend({ + heading: 0, + displacement: 0, + stopw_m: 0, + originLatLng: null, + rwy: '', + interactive: false, + stripSVG: function(fName) { + var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm; + var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8'); + var svg2 = rx.exec(svg); + return svg2[0]; }, - updateStyle: function () { + updateIcon : function(map) { + console.debug(`Lat Lng Threshold ${this.getLatLng()}`); + if(map !== null) { + var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom()); + console.debug('Old Meters per pixel ' + this._metersPP); + console.debug('New Meters per pixel ' + metersPP); + if(this._metersPP != metersPP) { + var pixelSize = (this.iconSize/2) / metersPP; + var scale = pixelSize/this.iconSize; + var offset = 0;//-(this.iconSize/2); + this.setIcon(L.divIcon({ + iconSize: 64, + className: 'threshold-marker-icon', + html: `
${this.svg}
`, + })); + this.setInteractive(this.interactive); + this.update(this.getLatLng()); + this.setLatLng(this.getLatLng()); + this._metersPP = metersPP; + } + } + }, + setInteractive(interactive) { + if (interactive) { + if(this._icon) { + L.DomUtil.addClass(this._icon, 'leaflet-interactive'); + } + } else { + if(this._icon) { + L.DomUtil.removeClass(this._icon, 'leaflet-interactive'); + } + } + this.interactive = interactive; + }, + metersPerPixel: function (latitude, zoomLevel) { + var earthCircumference = 40075017; + var latitudeRadians = latitude * (Math.PI / 180); + return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8); + }, + + pixelValue: function (latitude, meters, zoomLevel) { + return meters / metersPerPixel(latitude, zoomLevel); + }, + setOrigin (originLatLng) { + this.originLatLng = originLatLng; + }, + setHeading (heading) { + this.heading = Number(heading); + }, + setRunway (rwy) { + this.rwy = Number(rwy); + }, + setStopW (stopw_m) { + this.stopw_m = stopw_m; + }, + setDisplacement(displacement) { + const turfOptions = { units: 'kilometers' }; + this.displacement = Number(displacement); + + var newPos = turf.destination([this.originLatLng[1], this.originLatLng[0]], displacement/1000, this.normalizeAngle(this.heading), turfOptions); + var newValue = {lat: newPos.geometry.coordinates[1].toFixed(6), + lng: newPos.geometry.coordinates[0].toFixed(6) }; + console.debug(`Threshold Old : ${this.originLatLng} -> ${this.turfToLatLng(newPos)}`); + this.setLatLng(newValue); + }, + normalizeAngle( angle ) { + if(angle >= 180) { + return angle - 360; + } + if(angle <= -180) { + return angle + 360; + } + return angle; + }, + latToTurf (turfPoint) { + return [turfPoint.lng, turfPoint.lat]; + }, + latLngToTurf (turfPoint) { + return [turfPoint.decimalLongitude, turfPoint.decimalLatitude]; }, turfToLatLng: function (turfPoint) { - return {lat: turfPoint.geometry.coordinates[1], lng: turfPoint.geometry.coordinates[0]}; - }, - extensions: function (editLayer) { - this.createDirection(); - if (typeof this.featureLookup[this.id] === 'undefined') { - this.featureLookup[this.id] = []; - } - this.featureLookup[this.id].push(this); - }, - - _getLatRadius: function () { - return this._mRadius; - }, - - _getLngRadius: function () { - return this._mRadius; - }, - + return '' + turfPoint.geometry.coordinates[1].toFixed(6) + ',' + turfPoint.geometry.coordinates[0].toFixed(6); + } }); -var threshold = function (n, layerGroup) { - //console.log(n.attr('lat') + " " + n.attr('lon')); - var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text()); - //console.log(latlon.decimalLatitude); - //console.log(convert(n.attr('lat') + " " + n.attr('lon')).decimalLongitude); - const circle = new L.Threshold([latlon.decimalLatitude, latlon.decimalLongitude], { radius: 10, attributes: {} }); - circle.on('editable:enable', function (event) { - // event.target.createDirection(); - }); - /* - -*/ - //circle.attributes = { type: n.attr('type'), name: n.attr('name'), radius: Number(n.attr('radius')), airlineCodes: n.attr('airlineCodes'), heading: Number(n.attr('heading')) }; +L.Threshold.addInitHook(function(){ + this.svg = this.stripSVG('FGA_THR.svg'); + this.iconSize = 500; - $.each( n.attrs, function( key, value ) { - console.log( '$', circle.id, key , value); - - if(isNaN(value)) - circle.options.attributes[ key ] = value; - else - circle.options.attributes[ key ] = Number( value); + this.on('click', function (event) { + console.debug("Click Threshold : ", event); + store.default.dispatch('setThreshold', {rwy: event.target.rwy, displacement: event.target.displacement}); }); - circle.addTo(layerGroup); - return circle; + this.on('add', function (event) { + event.target.setInteractive(false); + }); +}); + +//Builds a marker for a threshold +/* + + 13.517142 + 52.380125 + 07L + 68.77 + 0.0 + 160.0 + +*/ +var threshold = function (n, options) { + var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text()); + var rwy = n.find('rwy/text()').text(); + var heading = n.find('hdg-deg/text()').text(); + var displ_m = n.find('displ-m/text()').text(); + var stopw_m = n.find('stopw-m/text()').text(); + + var marker = new L.Threshold([latlon.decimalLatitude, latlon.decimalLongitude], + {pane: 'threshold-pane'}); + marker.setOrigin([latlon.decimalLatitude, latlon.decimalLongitude]); + marker.setHeading(heading); + marker.setDisplacement(displ_m); + marker.setRunway(rwy); + marker.setStopW(stopw_m); + return marker; } -module.exports = threshold; \ No newline at end of file +module.exports = threshold; diff --git a/src/renderer/loaders/Tower.js b/src/renderer/loaders/Tower.js new file mode 100644 index 0000000..057ccc4 --- /dev/null +++ b/src/renderer/loaders/Tower.js @@ -0,0 +1,116 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ +/* eslint-disable */ + +const convert = require('geo-coordinates-parser'); +const fs = require('fs'); +const path = require('path'); +const store = require('../store'); + +/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/ + + +L.TowerMarker = L.Marker.extend({ + options: { + zIndexOffset: 10000, draggable: 'true' + }, + stripSVG: function(fName) { + var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm; + var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8'); + var svg2 = rx.exec(svg); + return svg2[0]; + }, + updateIcon : function(map) { + console.debug(`Lat Lng Tower ${this.getLatLng()}`); + if(map !== null) { + var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom()); + console.debug('Old Meters per pixel ' + this._metersPP); + console.debug('New Meters per pixel ' + metersPP); + if(this._metersPP != metersPP) { + var pixelSize = this.iconSize / metersPP; + var scale = pixelSize/this.iconSize; + var offset = 0;//-(this.iconSize/2); + this.setIcon(L.divIcon({ + iconSize: 32, + className: 'threshold-marker-icon', + html: `
${this.svg}
`, + })); + this.setInteractive(this.interactive); + + this.update(this.getLatLng()); + console.debug(); + this.setLatLng(this.getLatLng()); + this._metersPP = metersPP; + } + } + }, + setInteractive(interactive) { + if (interactive) { + if(this._icon) { + L.DomUtil.addClass(this._icon, 'leaflet-interactive'); + } + } else { + if(this._icon) { + L.DomUtil.removeClass(this._icon, 'leaflet-interactive'); + } + } + this.interactive = interactive; + }, + metersPerPixel: function (latitude, zoomLevel) { + var earthCircumference = 40075017; + var latitudeRadians = latitude * (Math.PI / 180); + return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8); + }, + + pixelValue: function (latitude, meters, zoomLevel) { + return meters / metersPerPixel(latitude, zoomLevel); + }, + setTowerHeight: function (height) { + this.elev_m = height; + } +}); + +L.TowerMarker.addInitHook(function(){ + this.svg = this.stripSVG('tower.svg'); + this.iconSize = 32; + this.on('click', function (event) { + store.default.dispatch('setTowerCoords', + event.target.getLatLng().lat.toFixed(6) + ' ' + + event.target.getLatLng().lng.toFixed(6) + ' ' + + event.target.elev_m); + store.default.dispatch('setTowerHeight', event.target.elev_m ); + }); + this.on('dragstart', function (event) { + console.debug("Drag Tower : ", event); + }); + this.on('dragend', function (event) { + console.debug("DragEnd Tower : ", event); + store.default.dispatch('setTowerCoords', + event.target.getLatLng().lat.toFixed(6) + ' ' + + event.target.getLatLng().lng.toFixed(6) + ' ' + + event.target.elev_m); + store.default.dispatch('setTowerHeight', event.target.elev_m ); + }); + this.on('add', function (event) { + event.target.setInteractive(false); + }); +}); + +//Builds a marker for a ai or multiplayer aircraft +var tower = function (n, options) { + var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text()); + var marker = new L.TowerMarker([latlon.decimalLatitude, latlon.decimalLongitude], {pane: 'tower-pane'}); + marker.elev_m = n.find('elev-m/text()').text(); + return marker; +} + +module.exports = tower; diff --git a/src/renderer/loaders/groundnet_loader.js b/src/renderer/loaders/groundnet_loader.js index 6def3e1..fa3e00d 100644 --- a/src/renderer/loaders/groundnet_loader.js +++ b/src/renderer/loaders/groundnet_loader.js @@ -23,27 +23,44 @@ function addFrequencies (type, value) { value.split(' ').forEach(frequencyValue => { if( value.length > 0) { var frequency = {type: type, value: frequencyValue}; - frequencies.push(frequency); + frequencies.push(frequency); } - }) + }) } exports.addFeature = function (feature) { - featureLookup[feature.id] = new Array(); + featureLookup[feature.id] = []; } -exports.readGroundnetXML = function (fDir, icao, force) { - try { - var layerGroup = L.layerGroup(); - layerGroup.maxId = 0; - var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.xml'); - var fNew = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.new.xml'); - - if (f == null || (!fs.existsSync(f) && force)|| (!fs.existsSync(f) && !fs.existsSync(fNew) )) - return layerGroup; - if (fNew != null && fs.existsSync(fNew) && !force) { - f = fNew; +exports.listSaves = function (fDir, icao) { + var directory = path.join(fDir, icao[0], icao[1], icao[2]); + var files = fs.readdirSync(directory); + var ret = files + .filter(f => f.includes(icao) ) + .filter(f => f.includes('groundnet') ) + .map(f => { + try { + var fileDate = fs.lstatSync(path.join(directory, f)); + return {file: f, mtime: `${fileDate.mtime}`, mtimeMs: `${fileDate.mtimeMs}`}; + } catch (error) { + console.error(error); } + }); + ret.forEach( f => { + console.debug(f); + }); + return ret; +} + +exports.readGroundnetXML = function (fDir, icao, f) { + try { + store.default.dispatch('setGroundnetLoaded', false); + var layerGroup = L.layerGroup(); + layerGroup.minId = 9999999999; + layerGroup.maxId = 0; + + if (f == null || (!fs.existsSync(f) )) + return layerGroup; var features = new Array(); @@ -82,9 +99,9 @@ exports.readGroundnetXML = function (fDir, icao, force) { addFrequencies('UNICOM', unicom); store.default.dispatch('setFrequencies', frequencies); - + var parkingNodes = xml.find('groundnet/parkingList/Parking'); - console.log("Parking Nodes" + parkingNodes.length); + console.debug("Parking Nodes length" + parkingNodes.length); var merged = new Array(); @@ -97,15 +114,16 @@ exports.readGroundnetXML = function (fDir, icao, force) { nodesLookup[n.attr('index')] = n; featureLookup[n.attr('index')] = new Array(); featureLookup[n.attr('index')].push(circle); + layerGroup.minId = Math.min(layerGroup.minId, Number(n.attr('index'))) layerGroup.maxId = Math.max(layerGroup.maxId, Number(n.attr('index'))) features.push(circle); }).sort(); - - store.default.dispatch('setParkings', parkingNodes.map( - p => ({index: Number(p.attrs.index), name: String(p.attrs.name), number: String(p.attrs.number), type: String(p.attrs.type)} + + store.default.dispatch('setParkings', parkingNodes.map( + p => ({index: Number(p.attrs.index), radius: Number(p.attrs.radius), name: String(p.attrs.name), number: String(p.attrs.number), type: String(p.attrs.type)} )).sort((p1, p2) => { if (p1.name === p2.name) { - return p1.number - p2.number + return p1.number?p1.number.localeCompare(p2.number):-1; } else { return p1.name.localeCompare(p2.name) }})); @@ -116,14 +134,16 @@ exports.readGroundnetXML = function (fDir, icao, force) { //attrs.lat //console.log(n.attr('lat') + " " + n.attr('lon')); try { - var latlon = convert(n.attr('lat') + " " + n.attr('lon')); + var latlon = convert(n.attr('lat') + " " + n.attr('lon')); } catch (error) { console.warn(n.attr('lat') + " " + n.attr('lon')); convert(n.attr('lat') + " " + n.attr('lon')); } //console.log(latlon.decimalLatitude); + layerGroup.minId = Math.min(layerGroup.minId, Number(n.attr('index'))) layerGroup.maxId = Math.max(layerGroup.maxId, Number(n.attr('index'))) + console.debug(`Min Id : ${layerGroup.minId} Max Id : ${layerGroup.maxId} `); nodesLookup[n.attr('index')] = n; if (n.attr('isOnRunway') === '1') { @@ -166,7 +186,7 @@ exports.readGroundnetXML = function (fDir, icao, force) { if (element instanceof L.Polyline && element.end === n.attr('begin') && element.begin === n.attr('end')) { element.bidirectional = true; element.options.attributes.direction = 'bi-directional' - bidirectional = true; + bidirectional = true; element.updateStyle(); } }); @@ -174,7 +194,13 @@ exports.readGroundnetXML = function (fDir, icao, force) { if (!bidirectional) { var beginlatlon = convert(beginNode.attr('lat') + " " + beginNode.attr('lon')); var endlatlon = convert(endNode.attr('lat') + " " + endNode.attr('lon')); - var polyline = new L.Polyline([[beginlatlon.decimalLatitude, beginlatlon.decimalLongitude], [endlatlon.decimalLatitude, endlatlon.decimalLongitude]], { attributes: {} }).addTo(layerGroup); + + var pane = 'route-pane'; + if(n.attr('isPushBackRoute') === '1') { + pane = 'pushback-pane'; + } + + var polyline = new L.Polyline([[beginlatlon.decimalLatitude, beginlatlon.decimalLongitude], [endlatlon.decimalLatitude, endlatlon.decimalLongitude]], { pane: pane, attributes: {} }).addTo(layerGroup); extendTaxiSegment(polyline); polyline.addListeners(); polyline._latlngs[0].attributes = {}; @@ -208,6 +234,8 @@ exports.readGroundnetXML = function (fDir, icao, force) { polyline.begin = beginNode.attr('index'); polyline.end = endNode.attr('index'); + polyline.feature = { properties: { searchTerm: 'Arc ' + beginNode.attr('index') + '-' + endNode.attr('index')}}; + // polyline.enableEdit(); // polyline.on('dblclick', function (event) { L.DomEvent.stop; polyline.toggleEdit; }); @@ -224,7 +252,7 @@ exports.readGroundnetXML = function (fDir, icao, force) { } } }).sort(); - + store.default.dispatch('setGroundnetLoaded', true); return layerGroup; }); diff --git a/src/renderer/loaders/groundnet_writer.js b/src/renderer/loaders/groundnet_writer.js index 9dae6cb..1d63bb8 100644 --- a/src/renderer/loaders/groundnet_writer.js +++ b/src/renderer/loaders/groundnet_writer.js @@ -14,10 +14,15 @@ const mathjs = require('mathjs'); var builder = require('xmlbuilder'); -var featureLookup = []; +var featureLookup = []; var parkings = []; var pushBackNodeLookup = []; +/** + * Walk nodes until the pushback node is found. + * @param {*} index + */ + function findRouteToPushback (index) { if (featureLookup===undefined) { return @@ -25,6 +30,7 @@ function findRouteToPushback (index) { var walkedNodes = [index] var pushBackNodes = [] walkPushbackRoute(index, walkedNodes, pushBackNodes) + return pushBackNodes } @@ -51,47 +57,74 @@ function walkPushbackRoute (index, walkedNodes, pushBackNodes) { }); } +/** + * + * @param {*} fDir The directory + * @param {*} icao + * @param {*} featureList + */ exports.writeGroundnetXML = function (fDir, icao, featureList) { try { + try { fs.mkdirSync(path.join(fDir), { recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0]),{ recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0], icao[1]), { recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0], icao[1], icao[2]), { recursive: true })} catch (err) { } + + var fileNames = []; + for (let index = 1; index <= store.default.state.Settings.settings.numberOfSaves; index++) { + fileNames.push(path.join(fDir, icao[0], icao[1], icao[2], icao + `.groundnet.bak.${index}.xml`)); + } var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.new.xml'); - var fBak = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.bak.xml'); if( fs.existsSync(f) ) { - fs.copyFileSync(f, fBak); + var previous = ''; + fileNames.reverse().forEach(fBak => { + if (fs.existsSync(fBak) && previous !== '') { + console.debug( `Copy ${fBak} to ${previous}`); + fs.copyFileSync(fBak, previous); + } + previous = fBak; + }); + fs.copyFileSync(f, previous); } if (f == null) return; + pushBackNodeLookup = []; console.debug(featureList); var parkings = featureList.map(mapParkings).filter(n => n); var runwayNodes = featureList.map(mapRunwayNodes).filter(n => n); var holdNodes = featureList.map(mapHoldPoint).filter(n => n); + + holdNodes.forEach(n => { pushBackNodeLookup[n['@index']] = n; }); - + var nodes = []; var arcList = []; var frequencies = []; - var version = new Date().toUTCString() + ' by FlightgearAirports'; - var name = store.default.state.Settings.settings.name; + var version = new Date().toUTCString() + ' by FlightgearAirports ' + require('electron').remote.app.getVersion(); + var name = store.default.state.Settings.settings.name; - - - featureLookup = []; + featureLookup = []; // Loaded segments featureList.filter(o => o instanceof L.TaxiwaySegment).filter(n => n).forEach(element => { var begin = mapBeginNode(element); + if(begin['@index']==="") + console.warn("Begin missing"); nodes[begin['@index']] = begin; var end = mapEndNode(element); + if(end['@index']==="") + console.warn("End missing"); nodes[end['@index']] = end; }); - // New segments + // New segments featureList.filter(o => o instanceof L.Polyline).filter(n => n).forEach(arcElement => { - // element._latlngs.forEach(latlng => { nodes[latlng.glueindex] = mapVertexNode(latlng) }); + // element._latlngs.forEach(latlng => { nodes[latlng.glueindex] = mapVertexNode(latlng) }); var startIndex = -1; console.debug(arcElement.options.attributes); var currentArc = arcElement.options.attributes; @@ -109,7 +142,7 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) { arc = { '@begin': startIndex, '@end': String(latlng.glueindex) }; styleArc(currentArc, arc); arcList.push(arc); - featureLookup[startIndex][latlng.glueindex] = arc; + featureLookup[startIndex][latlng.glueindex] = arc; } if( currentArc.direction === 'bi-directional' || currentArc.direction === 'backward' ){ arc = { '@begin': String(latlng.glueindex), '@end': startIndex }; @@ -117,19 +150,24 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) { arcList.push(arc); featureLookup[latlng.glueindex][startIndex] = arc; } + if (currentArc.direction === '' || !currentArc.direction) { + console.error( "Arc without direction " + util.inspect(currentArc) ); + } } startIndex = latlng.glueindex; + } else { + console.error( "LatLng without glueindex " + util.inspect(latlng) ); } }); }); runwayNodes.forEach(element => { if (nodes[element['@index']] != undefined) { - nodes[element['@index']]['@isOnRunway'] = "1"; + nodes[element['@index']]['@isOnRunway'] = "1"; } }); - // delete the parkings + // Find the index of the pushback node parkings.forEach(n => { nodes[n['@index']] = null; var pushBackNode = findRouteToPushback(Number(n['@index']))[0]; @@ -142,6 +180,7 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) { arcList = arcList.filter(a => a['@begin'] !== a['@end']); nodes.sort((p, p2) => { return p['@index'] - p2['@index'] }); + //console.debug(util.inspect(nodes)); var uniqueNodes = nodes.filter((v, i, a) => a.indexOf(v) === i); var approachList = store.default.state.Frequencies.items.filter(f => f.type === 'APPROACH').map(mapFrequency); @@ -158,7 +197,54 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) { var unicomList = store.default.state.Frequencies.items.filter(f => f.type === 'UNICOM').map(mapFrequency); - var xmlObj = { groundnet: { version: version, name: name, + + var gapStart = -1; + var gapEnd = -1; + + do { + gapStart = -1; + gapEnd = -1; + var allIds = parkings.map(n => Number(n['@index'])) + .concat(uniqueNodes.map(n => Number(n['@index']))) + .sort((a, b) => a - b); + + allIds.forEach((element, index, array) => { + if (index > 0 && array[index-1] + 1 != element && gapStart == -1 ) { + gapStart = array[index-1]; + gapEnd = element; + } + }); + var gap = gapEnd - gapStart -1; + if ( gap >= 0 ) { + parkings = parkings.map(n => { + if (n['@index']>gapStart) { + n['@index'] = String(n['@index'] - gap); + } + if (n['@pushbackRoute']>gapStart) { + n['@pushbackRoute'] = String(n['@pushbackRoute'] - gap); + } + return n; + }); + uniqueNodes = uniqueNodes.map(n => { + if (n['@index']>gapStart) { + n['@index'] = String(n['@index'] - gap); + } + return n; + }); + arcList = arcList.map(n => { + if (n['@begin']>gapStart) { + n['@begin'] = String(n['@begin'] - gap); + } + if (n['@end']>gapStart) { + n['@end'] = String(n['@end'] - gap); + } + return n; + }); + } + + } while( gapStart > 0 && gapEnd > 0); + + var xmlObj = { groundnet: { version: 1, fgaversion: version, name: name, 'frequencies': { APPROACH: approachList, DEPARTURE: departureList, AWOS: awosList, CLEARANCE: clearanceList, GROUND: groundList, TOWER: towerList, UNICOM: unicomList }, parkingList: { Parking: parkings }, TaxiNodes: { node: uniqueNodes }, TaxiWaySegments: { arc: arcList } } }; @@ -181,12 +267,20 @@ var mapParkings = function (o) { var lat = convertLat(o.getLatLng()); var lon = convertLon(o.getLatLng()); // - var parking = { '@index': String(o['id']), '@type': o.options.attributes.type, '@name': o.options.attributes.name, '@lat': lat, '@lon': lon, '@heading': Number(o.options.attributes.heading%360).toFixed(1), '@radius': String(o.options.attributes.radius) }; + var parking = { '@index': String(o['id']), '@type': o.options.attributes.type, '@lat': lat, '@lon': lon, '@heading': Number(o.options.attributes.heading%360).toFixed(1), '@radius': String(o.options.attributes.radius) }; + if (o.options.attributes.name !== '' && o.options.attributes.name !== 'undefined' && o.options.attributes.name !== undefined) { + parking['@name'] = o.options.attributes.name; + } if( o.options.attributes.airlineCodes) { console.debug(o.options.attributes.airlineCodes); parking['@airlineCodes'] = o.options.attributes.airlineCodes; } - if(o.options.attributes.number) { + if(o.options.attributes.number !== undefined && + typeof o.options.attributes.number === 'number' || ( + typeof o.options.attributes.number === 'string' && + o.options.attributes.number.trim() !== '' + ) + ) { console.debug(o.options.attributes.number); parking['@number'] = o.options.attributes.number; } @@ -198,10 +292,10 @@ var mapParkings = function (o) { var mapRunwayNodes = function (o) { console.debug(o); if (o instanceof L.RunwayNode) { - var runwayNode = { '@index': String(o['glueindex']), - '@lat': convertLat(o._latlng), - '@lon': convertLon(o._latlng), - '@isOnRunway': '1', + var runwayNode = { '@index': String(o['glueindex']), + '@lat': convertLat(o._latlng), + '@lon': convertLon(o._latlng), + '@isOnRunway': '1', '@holdPointType': 'none' }; return runwayNode; } @@ -212,13 +306,17 @@ var mapRunwayNodes = function (o) { var mapHoldPoint = function (o) { if (o instanceof L.HoldNode) { + if( o['holdPointType'] === undefined ) + { + console.error('Oh dear ' + o); + } return { '@index': String(o['glueindex']), '@holdPointType': o['holdPointType'] }; } } var mapBeginNode = function (o) { if (o instanceof L.TaxiwaySegment) { - console.debug(o); + console.debug('Map Begin : ', o['begin']); // return { '@index': String(o['begin']), '@lat': convertLat(o._latlngs[0]), '@lon': convertLon(o._latlngs[0]), '@isOnRunway': '0', '@type': 'begin' }; } @@ -226,7 +324,7 @@ var mapBeginNode = function (o) { var mapEndNode = function (o) { if (o instanceof L.TaxiwaySegment) { - console.debug(o); + console.debug('Map End : ', o['end']); // return { '@index': String(o['end']), '@lat': convertLat(o._latlngs[1]), '@lon': convertLon(o._latlngs[1]), '@isOnRunway': '0', '@type': 'end' }; } @@ -241,31 +339,33 @@ var mapVertexNode = function (l) { } var convertLat = function (latlng) { - console.debug(latlng.lat); + //console.debug(latlng.lat); var NS = latlng.lat > 0 ? 'N' : 'S'; var deg = mathjs.floor(mathjs.abs(latlng.lat)); var min = (mathjs.abs(latlng.lat) - deg) * 60; // console.debug(NS + deg + " " + min); - return NS + String(deg).padStart(2, '0') + " " + mathjs.round(min, 3); + return NS + String(deg).padStart(2, '0') + " " + mathjs.round(min, 6); } var convertLon = function (latlng) { - console.debug(latlng.lng); + //console.debug(latlng.lng); var NS = latlng.lng > 0 ? 'E' : 'W'; var deg = mathjs.floor(mathjs.abs(latlng.lng)); var min = (mathjs.abs(latlng.lng) - deg) * 60; // console.debug(NS + deg + " " + min); - return NS + String(deg).padStart(2, '0') + " " + mathjs.round(min, 3); + return NS + String(deg).padStart(2, '0') + " " + mathjs.round(min, 6); } var styleArc = function (attributes, arc) { - console.debug(attributes); + //console.debug(attributes); if(attributes !== undefined){ if (attributes.isPushBackRoute !== undefined && Number(attributes.isPushBackRoute) === 1 ) { arc['@isPushBackRoute'] = "1"; } else { arc['@isPushBackRoute'] = "0"; } - arc['@name'] = attributes.name; + if ( attributes.name !== '' && attributes.name !== 'undefined') { + arc['@name'] = attributes.name; + } } } \ No newline at end of file diff --git a/src/renderer/loaders/pavement_loader.js b/src/renderer/loaders/pavement_loader.js index fa95db2..3eb9743 100644 --- a/src/renderer/loaders/pavement_loader.js +++ b/src/renderer/loaders/pavement_loader.js @@ -1,10 +1,25 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ /* eslint-disable */ const lineReader = require('readline'); const zlib = require('zlib'); -// const geodesy = require('geodesy'); const LatLonEllipsoidal = require('geodesy/latlon-ellipsoidal-vincenty.js').default; const fs = require('fs'); +const store = require('../store'); + +const buildRunwayPoly = require('../leaflet/Runway.js'); +const buildTaxiwayPoly = require('../leaflet/Taxiway.js'); + /** * * @param {*} line @@ -25,12 +40,12 @@ function bezier(line, icao, layerGroup, currentFeature) { var startPoint = [Number(previous[0]), Number(previous[1])]; var endPoint = [Number(line[1]), Number(line[2])]; - if(module.exports.debug) { - L.polyline([startPoint, endPoint], { color: 'fuchsia' }).addTo(layerGroup); - var marker = new L.marker(endPoint, { title: 'endpoint', color: 'fuchsia' }); - marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, 0] }); - marker.addTo(layerGroup); -} + if (module.exports.debug) { + L.polyline([startPoint, endPoint], { color: 'fuchsia' }).addTo(layerGroup); + var marker = new L.marker(endPoint, { title: 'endpoint', color: 'fuchsia' }); + marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, 0] }); + marker.addTo(layerGroup); + } var control = [Number(line[3]), Number(line[4])]; if (!isNaN(control[0]) && control[0] !== undefined && !isNaN(control[1]) && control[1] !== undefined) { @@ -55,7 +70,7 @@ function bezier(line, icao, layerGroup, currentFeature) { L.polyline([startPoint, controlReflected, endPoint], { color: 'purple' }).addTo(layerGroup); var marker = new L.marker(controlReflected, { title: 'control First' }); - marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), {className: "my-label", offset: [0, 0] }); + marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, 0] }); marker.addTo(layerGroup); } points = deCasteljau([ @@ -66,13 +81,13 @@ function bezier(line, icao, layerGroup, currentFeature) { if (module.exports.debug) { L.polyline([startPoint, exports.bezierPoint, controlReflected, endPoint], { color: 'purple' }).addTo(layerGroup); var marker = new L.marker(exports.bezierPoint, { title: 'exports.bezierPoint' }).addTo(layerGroup); - marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), {className: "my-label", offset: [0, 10] }); + marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, 10] }); marker.addTo(layerGroup); - + var marker1 = new L.marker(controlReflected, { title: 'controlReflected' }).addTo(layerGroup); - marker1.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), {className: "my-label", offset: [0, -10] }); + marker1.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, -10] }); marker1.addTo(layerGroup); - + } points = deCasteljau([ [Number(previous[0]), Number(previous[1])], @@ -253,35 +268,57 @@ function createLineString(currentFeature, layerGroup) { } } -module.exports.readPavement = function (f, icao, cb) { +module.exports.readPavement = function (f, icao, callback) { console.log(f); var pavementLayerGroup = L.layerGroup(); var currentFeature; - lineReader.createInterface({ - input: fs.createReadStream(f).pipe(zlib.createGunzip()) - }).on('line', function (line) { - var fields = line.split(/[ ]+/); - // var fields = line.match('([0-9]+)'); - if (fields == null) - return; - var scanMethod = scanMethods[fields[0]]; - if (scanMethod != null) { - currentFeature = scanMethod(fields, icao, pavementLayerGroup, currentFeature); - } - else { - if (fields[0] == '99') { - lineReader.close(); + store.default.dispatch('setPavementLoaded', false); + + if (!fs.existsSync(f)) { + store.default.dispatch('setPavementLoaded', true); + callback(); + return; + } + try { + fs.accessSync(f, fs.constants.R_OK); + lineReader.createInterface({ + input: fs.createReadStream(f).pipe(zlib.createGunzip()) + }).on('line', function (line) { + try { + var fields = line.split(/[ ]+/); + // var fields = line.match('([0-9]+)'); + if (fields == null) + return; + var scanMethod = scanMethods[fields[0]]; + if (scanMethod != null) { + currentFeature = scanMethod(fields, icao, pavementLayerGroup, currentFeature); + } + else { + if (fields[0] == '99') { + lineReader.close(); + } + // console.log('Ignored:', line); + } + } catch (error) { + console.error('Error reading : ' + line + error); } - // console.log('Ignored:', line); - } - }).on('error', function (err) { - console.error(err); - lr.close(); - }).on('close', function () { - console.log("End"); - cb(pavementLayerGroup); - }); + }).on('error', function (err) { + store.default.dispatch('setPavementLoaded', true); + console.error(err); + lr.close(); + callback(); + }).on('close', function () { + store.default.dispatch('setPavementLoaded', true); + console.log("End"); + callback(pavementLayerGroup); + }); + } catch (err) { + console.error('no access!'); + store.default.dispatch('setPavementLoaded', true); + callback(); + return; + } } module.exports.debug = false; @@ -304,33 +341,24 @@ var scanMethods = { // APTDAT 715 Segment 10: (line, icao, layerGroup) => { if (module.exports.isScanning) { - //var marker = new L.marker([line[1], line[2]], { title: '10 Point', color: 'fuchsia' }); - //marker.bindTooltip(String(line), { className: "my-label", offset: [0, 0] }); - //marker.addTo(layerGroup); - var pointMiddle = new LatLonEllipsoidal(Number(line[1]), Number(line[2])); - var point1 = pointMiddle.destinationPoint(line[5]/6.562, line[4]); - var point2 = pointMiddle.destinationPoint(line[5]/6.562, line[4]-180); + var pointMiddle = new LatLonEllipsoidal(Number(line[1]), Number(line[2])); + var point1 = pointMiddle.destinationPoint(line[5] / 6.562, line[4]); + var point2 = pointMiddle.destinationPoint(line[5] / 6.562, line[4] - 180); - //var runwayPoly2 = new L.Polygon([point1, point2]); - //var marker2 = new L.marker(point2, { title: '10 Point 2', color: 'fuchsia' }); - //marker2.bindTooltip(String(line), { className: "my-label", offset: [0, 0] }); - //marker2.addTo(layerGroup); - //runwayPoly2.setStyle({ color: 'red', interactive: false }); - //runwayPoly2.addTo(layerGroup); - var runwayPoints = []; + var runwayPoints = []; - var bearing = point1.initialBearingTo(point2); - var runwayWidth = Number(line[8])/3.281; + var bearing = point1.initialBearingTo(point2); + // Width in ft + var runwayWidth = Number(line[8]) / 3.281; - runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing + 90))); - runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing + 90))); - runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing - 90))); - runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing - 90))); + runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing + 90))); + runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing + 90))); + runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing - 90))); + runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing - 90))); - var runwayPoly = new L.Polygon(runwayPoints); - runwayPoly.setStyle({ color: 'grey', fillColor: 'grey', opacity: 0.5, fillOpacity: 0.5, interactive: false }); - runwayPoly.addTo(layerGroup); - } + var runwayPoly = buildTaxiwayPoly(runwayPoints); + runwayPoly.addTo(layerGroup); + } }, // Runway 100: (line, icao, layerGroup) => { @@ -348,26 +376,25 @@ var scanMethods = { runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing + 90))); runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing + 90))); runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing - 90))); - runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing - 90))); + runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing - 90))); - var runwayPoly = new L.Polygon(runwayPoints); - runwayPoly.setStyle({ color: 'grey', interactive: false }); + var runwayPoly = buildRunwayPoly(runwayPoints); runwayPoly.addTo(layerGroup); var displacedEnd1 = point1.destinationPoint(Number(line[20]), bearing) - var displacedEnd2 = point2.destinationPoint(Number(line[20]), bearing-180) + var displacedEnd2 = point2.destinationPoint(Number(line[20]), bearing - 180) var runwayLine = new L.Polyline([displacedEnd1, displacedEnd2]); - runwayLine.setStyle({ color: 'yellow', stroke: true, dashArray: [50,50] }); + runwayLine.setStyle({ color: 'yellow', stroke: true, dashArray: [50, 50] }); runwayLine.addTo(layerGroup); - - var t1 = new L.Polyline([displacedEnd1.destinationPoint(runwayWidth / 2, (bearing - 90)), - displacedEnd1.destinationPoint(runwayWidth / 2, (bearing + 90))]); + + var t1 = new L.Polyline([displacedEnd1.destinationPoint(runwayWidth / 2, (bearing - 90)), + displacedEnd1.destinationPoint(runwayWidth / 2, (bearing + 90))]); t1.setStyle({ color: 'yellow' }); t1.addTo(layerGroup); - var t2 = new L.Polyline([displacedEnd2.destinationPoint(runwayWidth / 2, (bearing - 90)), - displacedEnd2.destinationPoint(runwayWidth / 2, (bearing + 90))]); + var t2 = new L.Polyline([displacedEnd2.destinationPoint(runwayWidth / 2, (bearing - 90)), + displacedEnd2.destinationPoint(runwayWidth / 2, (bearing + 90))]); t2.setStyle({ color: 'yellow' }); t2.addTo(layerGroup); @@ -413,8 +440,8 @@ var scanMethods = { console.debug(line); var previous = currentFeature.slice(-1)[0].slice(-1)[0]; if (previous !== undefined && - previous !== null && - previous[0] === line[1] && + previous !== null && + previous[0] === line[1] && previous[1] === line[2]) { module.exports.bezierPoint = null; } else { diff --git a/src/renderer/loaders/threshold_loader.js b/src/renderer/loaders/threshold_loader.js index 9b6b5da..96551fb 100644 --- a/src/renderer/loaders/threshold_loader.js +++ b/src/renderer/loaders/threshold_loader.js @@ -1,19 +1,22 @@ /* eslint-disable */ const fs = require('fs'); const path = require('path'); -var xamel = require('xamel'); +const xamel = require('xamel'); const convert = require('geo-coordinates-parser'); +const LatLonEllipsoidal = require('geodesy/latlon-ellipsoidal-vincenty.js').default; const store = require('../store'); const util = require('util'); +const takeoffPadPoly = require('../leaflet/TakeoffPad.js'); + const threshold = require('./Threshold.js'); var $ = require('jquery'); -exports.readThresholdXML = function (fDir, icao, force) { +exports.readThresholdXML = function (fDir, icao, force, stripes) { try { var layerGroup = L.layerGroup(); layerGroup.maxId = 0; @@ -40,18 +43,39 @@ exports.readThresholdXML = function (fDir, icao, force) { throw err; } - var thresholdNodes = xml.find('PropertyList/runway/threshold'); - console.log("Threshold Nodes" + thresholdNodes.length); + var runwayNodes = xml.find('PropertyList/runway'); + console.log("Threshold Nodes" + runwayNodes.length); - var merged = new Array(); - - var nodesLookup = {}; featureLookup = []; + var index = 0; + runwayNodes.map(r => { + var thresholds = r.find('threshold'); + thresholds.map(n => { + var icon = threshold(n); + icon.index = index; + icon.addTo(layerGroup); + // Width in m + var runwayWidth = 20; + var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text()); + var displ_m = Number(n.find('displ-m/text()').text()); + var pointMiddle = new LatLonEllipsoidal(latlon.decimalLatitude, latlon.decimalLongitude); + var heading = Number(n.find('hdg-deg/text()').text()); + var point1 = pointMiddle.destinationPoint(displ_m, heading); + var point2 = pointMiddle.destinationPoint(displ_m + 80, heading); - thresholdNodes.map(n => { - var circle = threshold(n, layerGroup); - features.push(circle); + var runwayPoints = []; + runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (heading + 90))); + runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (heading + 90))); + runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (heading - 90))); + runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (heading - 90))); + + var runwayPoly = takeoffPadPoly(runwayPoints); + runwayPoly.addTo(layerGroup); + } + ) + + index+=1; }).sort(); return layerGroup; @@ -62,4 +86,4 @@ exports.readThresholdXML = function (fDir, icao, force) { console.error(error); } return layerGroup; -}; \ No newline at end of file +}; diff --git a/src/renderer/loaders/threshold_writer.js b/src/renderer/loaders/threshold_writer.js new file mode 100644 index 0000000..0f6a39f --- /dev/null +++ b/src/renderer/loaders/threshold_writer.js @@ -0,0 +1,120 @@ +/* +Copyright 2021 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + +/* eslint-disable */ +const fs = require('fs'); +const path = require('path'); + +const store = require('../store'); + +const util = require('util'); + +const mathjs = require('mathjs'); + +var builder = require('xmlbuilder'); + + + +var writeThresholdXML = function (fDir, icao, coordinates) { + try { + try { fs.mkdirSync(path.join(fDir), { recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0]),{ recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0], icao[1]), { recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0], icao[1], icao[2]), { recursive: true })} catch (err) { } + + var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.threshold.new.xml'); + var fBak = path.join(fDir, icao[0], icao[1], icao[2], icao + '.threshold.bak.xml'); + + if( fs.existsSync(f) ) { + fs.copyFileSync(f, fBak); + } + if (f == null) + return; + var xmlObj = { PropertyList: { runway: map(coordinates) } }; + + xmlString = builder.create(xmlObj).end({ pretty: true }); + fs.writeFileSync(f, xmlString); + console.debug(xmlString); + } catch (error) { + console.error(error); + } + return; +} + +var map = function (o) { + console.debug(o); + + /** + + + + + 13.485025 + 52.367689 + 07 + 68.75 + 0.0 + 300.0 + + + 13.526097 + 52.377431 + 25 + 248.78 + 0.0 + 300.0 + + + + + 13.517142 + 52.380125 + 07L + 68.77 + 0.0 + 160.0 + + + 13.554253 + 52.388919 + 25R + 248.80 + 0.0 + 300.0 + + + + */ + var ret = []; + Object.keys(o).forEach(key => { + ret.push({ threshold: mapThreshold(o[key])}); + }); + return ret; +} + +/** + * 58.106924 + 6.610419 + 0 + 14 + 131.16 + 273 + 0.0 + + * @param {*} t + */ + +var mapThreshold = function (t) { + return t.map( t => {return {lon: t.longitude, lat: t.latitude, rwy: t.rwy, 'hdg-deg': t.heading, 'displ-m': t.displacement, 'stopw-m': t.stopw_m}}); +} + +export { writeThresholdXML }; \ No newline at end of file diff --git a/src/renderer/loaders/tower_loader.js b/src/renderer/loaders/tower_loader.js new file mode 100644 index 0000000..b44932d --- /dev/null +++ b/src/renderer/loaders/tower_loader.js @@ -0,0 +1,78 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ +/* eslint-disable */ +const fs = require('fs'); +const path = require('path'); +var xamel = require('xamel'); +const convert = require('geo-coordinates-parser'); + +const store = require('../store'); + +const util = require('util'); + +const tower = require('./Tower.js'); + + +var $ = require('jquery'); + +exports.readTowerXML = function (fDir, icao, force) { + try { + var layerGroup = L.layerGroup(); + layerGroup.maxId = 0; + var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.xml'); + var fNew = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.new.xml'); + + if (f == null || !fs.existsSync(f)) + return; + if (fNew != null && fs.existsSync(fNew) && !force) { + f = fNew; + } + + var features = new Array(); + + // map.on("editable:vertex:new", function (event) { + // log.console("Add vertex " + event); + // }); + + var xmlGroundnet = fs.readFileSync(f, 'utf8').toString(); + xamel.parse(xmlGroundnet, function (err, xml) { + console.debug("parsed " + path.basename(f)); + if (err !== null) { + console.error("Error in " + airline); + throw err; + } + + var towerNodes = xml.find('PropertyList/tower/twr'); + console.log("Towers " + towerNodes.length); + + towerNodes.map(n => { + var towerIcon = tower(n, layerGroup); + towerIcon['icao'] = icao + towerIcon.addTo(layerGroup); + /* + //DEBUG Code + var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text()); + var marker = new L.Circle([latlon.decimalLatitude, latlon.decimalLongitude], 5); + marker.addTo(layerGroup); + */ + features.push(towerIcon); + }).sort(); + + return layerGroup; + }); + // var jsonAirports = JSON.parse(geoJSON); + // return jsonAirports; + } catch (error) { + console.error(error); + } + return layerGroup; +}; \ No newline at end of file diff --git a/src/renderer/loaders/tower_writer.js b/src/renderer/loaders/tower_writer.js new file mode 100644 index 0000000..903adf4 --- /dev/null +++ b/src/renderer/loaders/tower_writer.js @@ -0,0 +1,63 @@ +/* +Copyright 2021 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ +/* eslint-disable */ +const fs = require('fs'); +const path = require('path'); + +const store = require('../store'); + +const util = require('util'); + +const mathjs = require('mathjs'); + +var builder = require('xmlbuilder'); + +var featureLookup = []; +var parkings = []; +var pushBackNodeLookup = []; + + +exports.writeTowerXML = function (fDir, icao, coordinates) { + try { + try { fs.mkdirSync(path.join(fDir), { recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0]),{ recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0], icao[1]), { recursive: true })} catch (err) { } + try { fs.mkdirSync(path.join(fDir, icao[0], icao[1], icao[2]), { recursive: true })} catch (err) { } + + var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.new.xml'); + var fBak = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.bak.xml'); + + if( fs.existsSync(f) ) { + fs.copyFileSync(f, fBak); + } + if (f == null) + return; + var xmlObj = { PropertyList: { tower: { twr: map(coordinates)} } }; + + xmlString = builder.create(xmlObj).end({ pretty: true }); + fs.writeFileSync(f, xmlString); + console.debug(xmlString); + } catch (error) { + console.error(error); + } + return; +} + +var map = function (o) { + console.debug(o); + /** + -1.6286902 + 59.53396633 + 3.05 + */ + return { lon: o.longitude, lat: o.latitude, 'elev-m': o.height}; +} \ No newline at end of file diff --git a/src/renderer/loaders/traffic_loader.js b/src/renderer/loaders/traffic_loader.js new file mode 100644 index 0000000..4818896 --- /dev/null +++ b/src/renderer/loaders/traffic_loader.js @@ -0,0 +1,123 @@ +/* +Copyright 2021 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ +/* eslint-disable */ +const fs = require('fs'); +const path = require('path'); +var xamel = require('xamel'); + +const store = require('../store'); + +const util = require('util'); + +exports.readTrafficXML = function (f) { + try { + var ret = []; + var xmlTraffic = fs.readFileSync(f, 'utf8').toString(); + xamel.parse(xmlTraffic, function (err, xml) { + console.debug("parsed " + path.basename(f)); + if (err !== null) { + console.error("Error in " + airline); + throw err; + } + + var requiredAircraft = xml.find('trafficlist/aircraft'); + console.log("Aircraft " + requiredAircraft.length); + + ret.concat(requiredAircraft); + var flights = xml.find('trafficlist/flight'); + console.log("Flights " + flights.length); + ret.concat(flights); + console.log(ret.length); + ret = ret.concat(flights.map(flightMapper)).concat(requiredAircraft.map(aircraftMapper)) + return ret; + }); + return ret; + } catch (error) { + console.error(error); + } +}; + +/* +* + Hebridean_1047 + HBR_BN_2 + VFR + + EGPU + + + 50 + + EGEO + + + WEEK + +*/ + +function flightMapper(params) { + return { + id: `${btoa(buildId(params))}`, + callsign: params.find('callsign').text(), + 'required-aircraft': params.find('required-aircraft').text(), + arrival: { + port: params.find('arrival/port').text(), + time: params.find('arrival/time').text() + }, + departure: { + port: params.find('departure/port').text(), + time: params.find('departure/time').text() + } + }; +} + +function buildId(params) { + return `${params.find('callsign').text()}_`+ + `${params.find('arrival/port').text()}_`+ + `${params.find('arrival/time').text()}_`+ + `${params.find('departure/port').text()}_` + + `${params.find('departure/time').text()}`; +} + +/* + + Aircraft/BN-2/BN-2-Hebridean.xml + HBR + HBR + EGEO + HBR_BN_2 + BN2 + 0 + 8 + gate + turboprop_transport + G-HEBO + false + +*/ + +function aircraftMapper(params) { + return { + model: params.find('model').text(), + livery: params.find('livery').text(), + airline: params.find('airline').text(), + 'home-port': params.find('home-port').text(), + 'required-aircraft': params.find('required-aircraft').text(), + actype: params.find('actype').text(), + offset: params.find('offset').text(), + radius: params.find('radius').text(), + flighttype: params.find('flighttype').text(), + 'performance-class': params.find('performance-class').text(), + 'registration': params.find('registration').text(), + 'heavy': params.find('heavy').text(), + }; +} \ No newline at end of file diff --git a/src/renderer/loaders/traffic_writer.js b/src/renderer/loaders/traffic_writer.js new file mode 100644 index 0000000..08a762e --- /dev/null +++ b/src/renderer/loaders/traffic_writer.js @@ -0,0 +1,180 @@ +/* +Copyright 2021 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + +/* eslint-disable */ +const fs = require('fs'); +const path = require('path'); + +const store = require('../store'); + +const util = require('util'); + +const mathjs = require('mathjs'); + +var builder = require('xmlbuilder'); + +var parkingStats = (acc, cur) => { + if (!acc[cur.radius]) { + acc[cur.radius] = { count: 0, radius: cur.radius } + } + acc[cur.radius].count += 1 + return acc +}; + +/** + + + + Aircraft/BN-2/BN-2-Hebridean.xml + HBR + HBR + EGEO + HBR_BN_2 + BN2 + 0 + 8 + gate + turboprop_transport + G-HEBS + false + + + Hebridean_1047 + HBR_BN_2 + VFR + + EGPU + + + 50 + + EGEO + + + WEEK + + + */ + +var writeTrafficXML = function (fDir, parkings, aircraft) { + try { + var icao = store.default.state.Airports.currentAirport.icao; + var aircraftList = aircraft; + + try { fs.mkdirSync(path.join(fDir), { recursive: true }) } catch (err) { } + try { fs.mkdirSync(path.join(fDir, 'TST'), { recursive: true }) } catch (err) { } + + var f = path.join(fDir, 'TST', icao + '.xml'); + + + var parkingData = parkings.reduce(parkingStats, {}); + + /* + * + + Hebridean_1001 + HBR_BN_2 + VFR + + EGEO + + + 50 + + EGEY + + + WEEK + + */ + + var flightMapper = function (pStat) { + var ret = []; + var blockSize = Math.min( pStat[1].count/6, 6); + for (let index = 0; index < pStat[1].count; index++) { + var aircraft = this[index]; + var minutes = `${Math.floor(index/blockSize)}`.padStart(2, '0'); + var seconds = `${index}`.padStart(2, '0'); + for (let weekday = 0; weekday < 7; weekday++) { + ret.push({ + callsign: `Test_${index}_${weekday}`, + 'required-aircraft': aircraft['required-aircraft'], + fltrules: 'VFR', + departure: { + port: icao, + time: `${weekday}/12:${minutes}:${seconds}` + }, + 'cruise-alt': 50, + arrival: { + port: icao, + time: `${weekday}/13:${minutes}:${seconds}` + }, + repeat: 'WEEK' + }); + } + } + return ret; + } + + /* + + Aircraft/BN-2/BN-2-Hebridean.xml + HBR + HBR + EGEO + HBR_BN_2 + BN2 + 0 + 8 + gate + turboprop_transport + G-HEBO + false + + + */ + var aircraftMapper = function (pStat) { + var ret = []; + if (typeof this === 'undefined') { + return; + } + var possibleAircraft = this.filter(a => a.radius <= pStat[1].radius); + + for (let index = 0; index < pStat[1].count; index++) { + var aircraft = possibleAircraft[Math.floor(Math.random() * possibleAircraft.length)]; + aircraft['required-aircraft'] = `GG-${index}`; + aircraft.registration = `GG-${index}`; + aircraft['home-port'] = icao; + ret.push(aircraft); + } + return ret; + } + + + var aircraftList = Object.entries(parkingData).flatMap(aircraftMapper, aircraft).sort(); + var flightList = Object.entries(parkingData).flatMap(flightMapper, aircraftList).sort(); + + var xmlObj = { trafficList: { aircraft: aircraftList, flight: flightList } }; + + var xmlString = builder.create(xmlObj).end({ pretty: true }); + fs.writeFileSync(f, xmlString); + console.debug(xmlString); + } catch (error) { + console.error(error); + } + return; +} + + +export { writeTrafficXML as writeTrafficXML }; \ No newline at end of file diff --git a/src/renderer/main.js b/src/renderer/main.js index e1b6b03..0c0278a 100644 --- a/src/renderer/main.js +++ b/src/renderer/main.js @@ -14,6 +14,10 @@ Vue.config.productionTip = false Vue.use(ElementUI) +Vue.config.errorHandler = (err, vm, info) => { + console.error(err) +} + /* eslint-disable no-new */ new Vue({ components: { App }, diff --git a/src/renderer/phi/AILayer.js b/src/renderer/phi/AILayer.js index c31c44e..6812678 100644 --- a/src/renderer/phi/AILayer.js +++ b/src/renderer/phi/AILayer.js @@ -264,5 +264,5 @@ function mapSGPropertyNode(node) { })); export function aiLayer(options) { - return new L.AILayer(null, options); + return undefined //new L.AILayer(null, options); } diff --git a/src/renderer/store/modules/Editable.js b/src/renderer/store/modules/Editable.js index c8f1d82..7f5a076 100644 --- a/src/renderer/store/modules/Editable.js +++ b/src/renderer/store/modules/Editable.js @@ -1,15 +1,28 @@ +/** +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + import Vue from 'vue' const state = { type: 'none', index: 'none', editing: false, - data: {airports: {}, parking: {}, arc: {}, node: {}, runway: {}} + data: {airports: {}, parking: {}, arc: {}, multiarc: {}, node: {}, runway: {}, threshold: {}, tower: {}} } const SET_EDIT_AIRPORT = 'SET_EDIT_AIRPORT' const SET_EDIT_PARKING = 'SET_EDIT_PARKING' const SET_EDIT_ARC = 'SET_EDIT_ARC' +const SET_EDIT_MULTI_ARC = 'SET_EDIT_MULTI_ARC' const SET_EDIT_RUNWAY = 'SET_EDIT_RUNWAY' const mutations = { @@ -25,7 +38,6 @@ const mutations = { state.type = 'airport' }, SET_EDIT_PARKING (state, parking) { - Vue.set(state, 'data', {}) var p = Object.assign({}, parking) Vue.set(state.data, 'parking', p) Vue.set(state, 'index', p.index) @@ -35,15 +47,11 @@ const mutations = { if (node === undefined) { return } - if (!state.data || state.type !== 'node') { - Vue.set(state, 'data', {}) - } Vue.set(state.data, 'node', node) Vue.set(state, 'index', node.index) Vue.set(state, 'type', 'node') }, SET_EDIT_RUNWAY (state, runway) { - Vue.set(state, 'data', {}) Vue.set(state.data, 'node', runway) Vue.set(state, 'index', runway.index) Vue.set(state, 'type', 'runway') @@ -52,9 +60,6 @@ const mutations = { if (arc === undefined) { return } - if (!state.data || state.type !== 'arc') { - Vue.set(state, 'data', {}) - } Vue.set(state.data, 'arc', arc) if (state.data.arc.name === undefined) { Vue.set(state.data.arc, 'name', '') @@ -62,6 +67,31 @@ const mutations = { Vue.set(state, 'index', arc.index) Vue.set(state, 'type', 'arc') }, + SET_EDIT_MULTI_ARC (state, arc) { + if (arc === undefined) { + return + } + Vue.set(state.data.multiarc, 'isPushBackRoute', arc.isPushBackRoute) + Vue.set(state.data.multiarc, 'direction', arc.direction) + if (state.data.multiarc.name === undefined) { + Vue.set(state.data.multiarc, 'name', '') + } + Vue.set(state, 'index', arc.index) + + Vue.set(state, 'type', 'multiarc') + }, + 'SET_EDIT_MULTI_ARC_IDS' (state, arcs) { + if (arcs === undefined) { + return + } + if (!state.data || state.type !== 'multiarc') { + return + } + if (state.data.multiarc.ids === undefined) { + state.data.multiarc.ids = [] + } + state.data.multiarc.ids = state.data.multiarc.ids.concat(arcs.filter(n => n).filter((v, i, a) => a.indexOf(v) === i)) + }, 'SET_EDIT_PARKING_NAME' (state, parkingName) { Vue.set(state.data.parking, 'name', parkingName) }, @@ -90,14 +120,29 @@ const mutations = { 'SET_EDIT_PARKING_COORDS' (state, coords) { Vue.set(state.data.parking, 'coords', coords) }, + 'SET_EDIT_PARKING_NOSE_COORDS' (state, coords) { + Vue.set(state.data.parking, 'nosecoords', coords) + }, 'SET_EDIT_ARC_NAME' (state, arcName) { - Vue.set(state.data.arc, 'name', arcName) + if (state.type === 'arc') { + Vue.set(state.data.arc, 'name', arcName) + } else { + Vue.set(state.data.multiarc, 'name', arcName) + } }, 'SET_EDIT_PUSHBACK' (state, isPushBackRoute) { - Vue.set(state.data.arc, 'isPushBackRoute', isPushBackRoute) + if (state.type === 'arc') { + Vue.set(state.data.arc, 'isPushBackRoute', Number(isPushBackRoute)) + } else { + Vue.set(state.data.multiarc, 'isPushBackRoute', Number(isPushBackRoute)) + } }, 'SET_EDIT_DIRECTION' (state, direction) { - Vue.set(state.data.arc, 'direction', direction) + if (state.type === 'arc') { + Vue.set(state.data.arc, 'direction', direction) + } else { + Vue.set(state.data.multiarc, 'direction', direction) + } }, 'SET_EDIT_HOLDPOINTTYPE' (state, holdPointType) { Vue.set(state.data.node, 'holdPointType', holdPointType) @@ -105,6 +150,28 @@ const mutations = { 'SET_EDIT_NODE_COORDS' (state, coords) { Vue.set(state.data.node, 'coords', coords) }, + 'SET_EDIT_TOWER_COORDS' (state, coords) { + state.type = 'tower' + if (!state.data.tower) { + state.data.tower = {} + } + if (!state.data.tower.coords) { + state.data.tower.coords = {} + } + Vue.set(state.data.tower.coords, 'latitude', coords.split(' ')[0]) + Vue.set(state.data.tower.coords, 'longitude', coords.split(' ')[1]) + }, + 'SET_EDIT_TOWER_HEIGHT' (state, height) { + Vue.set(state.data.tower, 'height', height) + }, + 'SET_EDIT_THRESHOLD_COORDS' (state, threshold) { + state.type = 'threshold' + Vue.set(state.data.threshold, 'runway', threshold.rwy) + Vue.set(state.data.threshold, 'displacement', threshold.displacement) + }, + 'SET_EDIT_THRESHOLD_DISPLACEMENT' (state, displacement) { + Vue.set(state.data.threshold, 'displacement', displacement) + }, 'SET_EDIT_ISONRUNWAY' (state, isOnRunway) { Vue.set(state.data.node, 'isOnRunway', isOnRunway) } @@ -129,12 +196,33 @@ const actions = { async setParkingCoords (context, coords) { context.commit('SET_EDIT_PARKING_COORDS', coords) }, + async setParkingNoseCoords (context, coords) { + context.commit('SET_EDIT_PARKING_NOSE_COORDS', coords) + }, async setArc (context, arc) { context.commit(SET_EDIT_ARC, arc) }, + async setMultiArc (context, arc) { + context.commit(SET_EDIT_MULTI_ARC, arc) + }, + async setMultiArcIds (context, arc) { + context.commit('SET_EDIT_MULTI_ARC_IDS', arc) + }, async setNode (context, node) { context.commit('SET_EDIT_NODE', node.attributes) context.commit('SET_EDIT_NODE_COORDS', node.lat.toFixed(6) + ' ' + node.lng.toFixed(6)) + }, + async setTowerCoords (context, node) { + context.commit('SET_EDIT_TOWER_COORDS', node) + }, + async setTowerHeight (context, height) { + context.commit('SET_EDIT_TOWER_HEIGHT', height) + }, + async setThreshold (context, node) { + context.commit('SET_EDIT_THRESHOLD_COORDS', node) + }, + async setDisplacement (context, displacement) { + context.commit('SET_EDIT_THRESHOLD_DISPLACEMENT', displacement) } } diff --git a/src/renderer/store/modules/Loading.js b/src/renderer/store/modules/Loading.js new file mode 100644 index 0000000..d6cc7bf --- /dev/null +++ b/src/renderer/store/modules/Loading.js @@ -0,0 +1,51 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + +import Vue from 'vue' + +const state = { icao: '', groundnetLoaded: false, pavementLoaded: false } + +const mutations = { + SET_ICAO_LOADING (state, icao) { + Vue.set(state, 'icao', icao) + }, + SET_GROUNDNET_LOADED (state, loaded) { + Vue.set(state, 'groundnetLoaded', loaded) + }, + SET_PAVEMENT_LOADED (state, loaded) { + Vue.set(state, 'pavementLoaded', loaded) + } +} + +const actions = { + async setIcaoLoading (context, p) { + context.commit('SET_ICAO_LOADING', p) + }, + async setGroundnetLoaded (context, p) { + if (typeof p !== 'boolean') { + console.error('Not Boolean') + } + context.commit('SET_GROUNDNET_LOADED', p) + }, + async setPavementLoaded (context, p) { + if (typeof p !== 'boolean') { + console.error('Not Boolean') + } + context.commit('SET_PAVEMENT_LOADED', p) + } +} + +export default { + state, + mutations, + actions +} diff --git a/src/renderer/store/modules/Parkings.js b/src/renderer/store/modules/Parkings.js index 299dce9..0f5a3c8 100644 --- a/src/renderer/store/modules/Parkings.js +++ b/src/renderer/store/modules/Parkings.js @@ -1,3 +1,15 @@ +/* +Copyright 2020 Keith Paterson + +This file is part of FG Airports. + +FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/. +*/ + import Vue from 'vue' const state = { items: [] } @@ -31,7 +43,7 @@ const mutations = { const actions = { async addParking (context, p) { - context.commit('ADD_FREADD_PARKINGQUENCY', p) + context.commit('ADD_PARKING', p) }, async updatedParking (context, p) { context.commit('UPDATE_PARKING', p) diff --git a/src/renderer/store/modules/Settings.js b/src/renderer/store/modules/Settings.js index 439130d..83ac9b7 100644 --- a/src/renderer/store/modules/Settings.js +++ b/src/renderer/store/modules/Settings.js @@ -1,6 +1,9 @@ /* eslint-disable */ +const path = require('path'); +const fs = require('fs'); + const state = { - settings: { flightgearDirectory: '.', testDirectory: '.', email: 'flightgearairports@example.org', name: 'unknown', phi_url: 'http://localhost:8080' }, + settings: { numberOfSaves: 1, flightgearDirectory: '.', testDirectory: '.', email: 'flightgearairports@example.org', name: 'unknown', phi_url: 'http://localhost:8080' }, zoom: 14, center: [47.413220, -1.219482], bounds: undefined, @@ -8,41 +11,55 @@ const state = { } const mutations = { - 'DELETE_INDEXED_DB' () { }, - 'FLIGHTGEAR_DIRECTORY' (state, flightgearDirectory) { - state.settings.flightgearDirectory = flightgearDirectory - state.settings.flightgearDirectory_ai = flightgearDirectory + '/data/AI' - state.settings.flightgearDirectory_traffic = flightgearDirectory + '/data/AI/Traffic' - state.settings.flightgearDirectory_apt = flightgearDirectory + '/data/Airports/apt.dat.gz' + 'DELETE_INDEXED_DB'() { }, + 'FLIGHTGEAR_DIRECTORY'(state, flightgearDirectory) { + try { + fs.accessSync(flightgearDirectory) + state.settings.flightgearDirectory = flightgearDirectory + } catch (err) { + try { + fs.accessSync(flightgearDirectory.replace(/\.App/, '')) + state.settings.flightgearDirectory = flightgearDirectory.replace(/\.App/, '') + } catch (error) { + console.warn(error) + } + } + + state.settings.flightgearDirectory_ai = flightgearDirectory + path.sep + 'AI' + state.settings.flightgearDirectory_traffic = path.join(flightgearDirectory, 'AI', 'Traffic'); + state.settings.flightgearDirectory_apt = path.join(flightgearDirectory, 'Airports', 'apt.dat.gz'); }, - 'AIPORTS_DIRECTORY' (state, airportsDirectory) { + 'AIPORTS_DIRECTORY'(state, airportsDirectory) { state.settings.airportsDirectory = airportsDirectory }, - 'TEST_DIRECTORY' (state, testDirectory) { + 'TEST_DIRECTORY'(state, testDirectory) { state.settings.testDirectory = testDirectory }, - 'ZOOM' (state, zoom) { + 'ZOOM'(state, zoom) { state.zoom = zoom }, - 'CENTER' (state, center) { + 'CENTER'(state, center) { state.center = center }, - 'BOUNDS' (state, bounds) { + 'BOUNDS'(state, bounds) { state.bounds = bounds }, - 'SET_EMAIL' (state, email) { + 'SET_EMAIL'(state, email) { state.settings.email = email }, - 'SET_NAME' (state, name) { + 'SET_NAME'(state, name) { state.settings.name = name }, - 'SET_PHI_URL' (state, phi_url) { + 'SET_NUMBER_OF_SAVES'(state, numberOfSaves) { + state.settings.numberOfSaves = numberOfSaves + }, + 'SET_PHI_URL'(state, phi_url) { state.settings.phi_url = phi_url - }, - 'SET_SCAN_LOGGING' (state, scanLogging) { + }, + 'SET_SCAN_LOGGING'(state, scanLogging) { state.settings.scanLogging = scanLogging }, - 'ADD_WIP' (state, airport) { + 'ADD_WIP'(state, airport) { const item = state.wip.find((e) => e.icao === airport.icao) airport.time = Date.now() if (item === null || item === undefined) { @@ -52,12 +69,12 @@ const mutations = { } state.wip.sort((w1, w2) => w1.time - w2.time) }, - 'UPLOAD_WIP' (state, icao) { + 'UPLOAD_WIP'(state, icao) { const item = state.wip.find((e) => e.icao === icao) item.upload = Date.now() state.wip.sort((p, p2) => { return p.time - p2.time }) }, - 'REMOVE_WIP' (state, icao) { + 'REMOVE_WIP'(state, icao) { const item = state.wip.find((e) => e.icao === icao) const index = state.wip.indexOf(item) if (index > -1) { @@ -69,21 +86,21 @@ const mutations = { const plugins = [] const actions = { - async setZoom (context, zoom) { + async setZoom(context, zoom) { context.commit('ZOOM', zoom) }, - async setCenter (context, center) { - if( center.lat !== context.state.center.lat || center.lng !== context.state.center.lng) { + async setCenter(context, center) { + if (center.lat !== context.state.center.lat || center.lng !== context.state.center.lng) { context.commit('CENTER', center) } }, - async setBounds (context, bounds) { + async setBounds(context, bounds) { context.commit('BOUNDS', bounds) }, - async addWip (context, airport) { + async addWip(context, airport) { context.commit('ADD_WIP', airport) }, - async removeWip (context, icao) { + async removeWip(context, icao) { context.commit('REMOVE_WIP', icao) } } diff --git a/src/renderer/utils/check.js b/src/renderer/utils/check.js index 5099a38..2e5862d 100644 --- a/src/renderer/utils/check.js +++ b/src/renderer/utils/check.js @@ -8,9 +8,14 @@ const fs = require('fs'); //debugger; var turf; -if(process.env.NODE_ENV === 'development') { +var check_msg; + +if (process.env.NODE_ENV === 'development') { importScripts('../../../node_modules/dijkstrajs/dijkstra.js'); turf = require('./node_modules/@turf/turf'); +} else if (process.env.NODE_ENV === 'mocha') { + importScripts('../../../node_modules/dijkstrajs/dijkstra.js'); + turf = require('../../../node_modules/@turf/turf') } else { importScripts('dijkstra.js'); turf = require('@turf/turf') @@ -38,89 +43,141 @@ onmessage = function (event) { ).catch(result => { console.error('Crashed'); console.error(result); - postMessage(['DONE', []]); + postMessage(['DONE', [{ id: -1, message: ['Crashed', result] }]]); }); } }; +/** + * Implements the checks of the groundnet + * @param {*} data + */ + async function checkGroundnet(data) { var promise = new Promise(function (resolve, reject) { try { + const fName = process.env.NODE_ENV === 'development' + ? './src/renderer/utils/check_msg.json' + : path.join(`${process.resourcesPath}`, 'workers', 'check_msg.json'); + check_msg = JSON.parse(fs.readFileSync(fName, 'utf8').toString()); //debugger; var parkings = data.map(mapParkings).filter(n => n !== undefined); - var runwayNodes = data.map(mapRunwayNodes).filter(n => n !== undefined); + var runwayNodeIDs = data.map(mapRunwayNodeId).filter(n => n !== undefined); + var runwayNodes = data.map(mapRunwayNode).filter(n => n !== undefined); var pushbackNodes = data.map(mapPushbackNodes).filter(n => n !== undefined); var edges = data.map(mapEdges).filter(n => n !== undefined); - this.max = 4 * parkings.length * runwayNodes.length + - 3 * parkings.length; + var normalNodes = data.map(mapEdges).filter(n => n !== undefined) + .flatMap(m => m.latLngs).filter(n => runwayNodeIDs.indexOf(Number(n.index)) < 0); + + var takeoffPads = data.map(mapTakeoffPads).filter(n => n !== undefined); + + this.max = 30; this.postMessage(['max', this.max]); var boxes = {}; //debugger; data.forEach(element => { //debugger; - if(element.box!==undefined && element.box!==null) { - boxes[element.index] = element.box[0].map(latlng => [latlng.lat, latlng.lng] ); + if (element.box !== undefined && element.box !== null) { + boxes[element.index] = element.box[0].map(latlng => [latlng.lat, latlng.lng]); boxes[element.index].push(boxes[element.index][0]); } }); - var graph = {}; + var directionalGraph = {}; + var bidirectionalGraph = {}; + + console.debug(parkings); parkings.forEach(element => { - graph[element] = {}; + directionalGraph[element] = {}; + bidirectionalGraph[element] = {}; }); - runwayNodes.forEach(element => { - graph[element] = {}; + runwayNodeIDs.forEach(element => { + directionalGraph[element] = {}; + bidirectionalGraph[element] = {}; }); var notOkNodes = []; + //debugger; + console.debug(edges); + if (edges === undefined) { + resolve([{ id: -1, message: check_msg.NO_EDGES }]); + } + this.postMessage(['progress', 1]); + //debugger; + if (takeoffPads.length === 0) { + resolve([{ id: -1, message: check_msg.NO_RUNWAYS }]); + } + this.postMessage(['progress', 1]); edges.forEach(edge => { - graph[edge.start] = {}; - graph[edge.end] = {}; - // Check if there are segments > 2km - edge.latLngs.forEach((latLng, index, arr) => { - if (index>0) { - var d = distance([arr[index-1].lng, arr[index-1].lat], [latLng.lng, latLng.lat]); - if(d>2000) { - notOkNodes.push({ id: Number(arr[index-1].index), message: `Start of long route ${d.toFixed(2)}` }); - notOkNodes.push({ id: Number(arr[index].index), message: `End of long route ${d.toFixed(2)}` }); - } - //console.log(d); - } - }); + directionalGraph[edge.start] = {}; + bidirectionalGraph[edge.start] = {}; + directionalGraph[edge.end] = {}; + bidirectionalGraph[edge.end] = {}; + if (edge.latLngs !== undefined) { + // Check if there are segments > 2km + edge.latLngs.forEach((latLng, index, arr) => { + if (index > 0) { + var d = distance([arr[index - 1].lng, arr[index - 1].lat], [latLng.lng, latLng.lat]); + if (d > 2000) { + notOkNodes.push({ id: Number(arr[index - 1].index), message: check_msg.LONG_ROUTE_START }); + notOkNodes.push({ id: Number(arr[index].index), message: check_msg.LONG_ROUTE_END }); + } + //console.log(d); + } + }); + } }); + this.postMessage(['progress', 1]); + this.postMessage(['progress', 1]); + // Add edges to graphs edges.forEach(element => { - var node1 = graph[element.start]; - node1[Number(element.end)] = 1; - var node2 = graph[element.end]; - node2[Number(element.start)] = 1; + var node1 = directionalGraph[element.start]; + var node2 = directionalGraph[element.end]; + if (element.direction === undefined) { + notOkNodes.push({ id: Number(element._leaflet_id), message: check_msg.EDGE_MISSING_DIRECTION }); + } + if (element.direction === 'bi-directional' || element.direction === 'forward') { + node1[Number(element.end)] = 1; + } + if (element.direction === 'bi-directional' || element.direction === 'backward') { + node2[Number(element.start)] = 1; + } + + var node3 = bidirectionalGraph[element.start]; + var node4 = bidirectionalGraph[element.end]; + node3[Number(element.end)] = 1; + node4[Number(element.start)] = 1; }); - var isLegitEnd = function(v) { - if( Object.keys(graph[v]).length <= 1 ) { + this.postMessage(['progress', 1]); + var isLegitEnd = function (v) { + if (bidirectionalGraph[v] === undefined) { + debugger; + } + if (Object.keys(bidirectionalGraph[v]).length <= 1) { return true; } - return Object.keys(graph[v]).filter( v => runwayNodes[v]).length === 0; + return Object.keys(bidirectionalGraph[v]).filter(v => runwayNodeIDs[v]).length === 0; } - //debugger; - runwayNodes = runwayNodes.filter( + runwayNodeIDs = runwayNodeIDs.filter( (v, i) => isLegitEnd(v) ); - // Check if there is a route from every parking to every runway node + // Check if there is a route from every parking to every runway node var okNodes = []; - logger('info', graph); + logger('info', directionalGraph); parkings.forEach(parkingNode => { - runwayNodes.forEach(runwayNode => { - var ok = checkRoute(graph, parkingNode, runwayNode); + runwayNodeIDs.forEach(runwayNode => { + var ok = checkRoute(directionalGraph, parkingNode, runwayNode); if (ok) { okNodes.push(parkingNode); okNodes.push(runwayNode); } else { console.log(`No route from Parking ${parkingNode} to Runwaynode ${runwayNode}`); } - this.postMessage(['progress', 1]); + }); }); - // Build pushback graph + // Build pushback directionalGraph var noPushbackGraph = {}; parkings.forEach(element => { noPushbackGraph[element] = {}; @@ -144,99 +201,133 @@ async function checkGroundnet(data) { var okPushbacks = []; // Check pushback var multiplePushbackRoutes = {}; - //debugger; parkings.forEach(parkingNode => { pushbackNodes.forEach(pushbackNode => { var numRoutes = checkRoute(noPushbackGraph, parkingNode, pushbackNode); - if (numRoutes===0) { - /* - if(parkingNode===14) { - debugger; - } - */ - if (multiplePushbackRoutes[parkingNode]===undefined && - Object.keys(noPushbackGraph[parkingNode])>0) { - // Only when there is a edge leaving + if (numRoutes === 0) { + if (multiplePushbackRoutes[parkingNode] === undefined && + Object.keys(noPushbackGraph[parkingNode]) > 0) { + // Only when there is a edge leaving multiplePushbackRoutes[parkingNode] = []; - } - } else if (numRoutes===1){ - if (multiplePushbackRoutes[parkingNode]===undefined) { + } + } else if (numRoutes === 1) { + if (multiplePushbackRoutes[parkingNode] === undefined) { multiplePushbackRoutes[parkingNode] = [pushbackNode]; } else { multiplePushbackRoutes[parkingNode].push(pushbackNode); - } - } else if (numRoutes>1){ - if (multiplePushbackRoutes[parkingNode]===undefined) { + } + } else if (numRoutes > 1) { + if (multiplePushbackRoutes[parkingNode] === undefined) { multiplePushbackRoutes[parkingNode] = [pushbackNode]; } else { multiplePushbackRoutes[parkingNode].push(pushbackNode); - } + } } - this.postMessage(['progress', 1]); + }); }); + var notConnectedToPushback = pushbackNodes.map( + id => { + var normalRoutes = bidirectionalGraph[id]; + var pushbackRoutes = noPushbackGraph[id]; + if (Object.keys(pushbackRoutes).length < 1) + return { id: id, message: check_msg.PUSHBACK_NOT_CONNECTED } + }).filter(n => n !== undefined); + this.postMessage(['progress', 1]); + var multipleTaxiRoutes = pushbackNodes.map( + id => { + var normalRoutes = bidirectionalGraph[id]; + var pushbackRoutes = noPushbackGraph[id]; + if (normalRoutes !== undefined) { + var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined); + if (nonPushbackRoutes.length > 1) + return { id: id, message: check_msg.TO_MANY_PUSHBACK_TAXI_ROUTES } + } + }).filter(n => n !== undefined); + this.postMessage(['progress', 1]); + var pushbackExitNotBidirectional = pushbackNodes.map( + id => { + var normalRoutes = bidirectionalGraph[id]; + var pushbackRoutes = noPushbackGraph[id]; + if (normalRoutes !== undefined) { + var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined); + if(nonPushbackRoutes.length > 0) { + var returnRoute = Object.keys(bidirectionalGraph[nonPushbackRoutes[0]]).map(id => Number(id)).filter(retId =>id === retId); + if (returnRoute.length === 0) + return { id: id, message: check_msg.PUSHBACK_EXIT_NOT_BIDRECTIONAL } + } + } + }).filter(n => n !== undefined); + this.postMessage(['progress', 1]); var rogueHoldPoints = pushbackNodes.map( - id => { + id => { var routes = noPushbackGraph[id]; - if(Object.keys(routes).length<1) - return { id: id, message: 'Unconnected Pushbacknode' } + if (Object.keys(routes).length < 1) + return { id: id, message: check_msg.UNCONNECTED_PUSHBACK } /* else if(Object.keys(routes).length>1) return { id: id, message: 'Multiple connected pushback node' } */ } ).filter(n => n !== undefined); + this.postMessage(['progress', 1]); var wrongPushbackRoutes = parkings.filter( function (e) { - //debugger; return this[e] != undefined && this[e].length != 1; } , multiplePushbackRoutes).map( - id => { + id => { var endPoints = multiplePushbackRoutes[id]; - if( endPoints.length<1) - return { id: id, message: 'No way to pushback holdpoint' } - else - return { id: id, message: 'Multiple connected pushback points' } + if (endPoints.length < 1) + return { id: id, message: check_msg.NO_WAY_TO_HOLDPOINT } + else + return { id: id, message: check_msg.MULTIPLE_PUSHBACK } } ); - wrongPushbackRoutes =wrongPushbackRoutes.concat(multiplePushbackRoutes); + + this.postMessage(['progress', 1]); okNodes = okNodes.filter((v, i) => okNodes.indexOf(v) === i); var notOkNodesParkings = parkings.filter( (v, i) => okNodes.indexOf(v) < 0 ).map( - id => { return { id: id, message: 'No way from parking to each runway' } } - ); - var notOkNodesRunways = runwayNodes.filter( - (v, i) => okNodes.indexOf(v) < 0 - ).map( - id => { return { id: id, message: 'No way from runway to each parking' } } + id => { return { id: id, message: check_msg.NO_RUNWAY_ROUTE } } ); - + this.postMessage(['progress', 1]); + + var notOkNodesRunways = runwayNodeIDs.filter( + (v, i) => okNodes.indexOf(v) < 0 + ).map( + id => { return { id: id, message: check_msg.NO_PARKING_ROUTE } } + ); + this.postMessage(['progress', 1]); + if (parkings.length === 0) { - notOkNodes.push({ id: 0, message: 'No parkings' }); + notOkNodes.push({ id: -2, message: check_msg.NO_PARKINGS }); } - if (runwayNodes.length === 0) { - notOkNodes.push({ id: 0, message: 'No Runwaynodes' }); + this.postMessage(['progress', 1]); + if (runwayNodeIDs.length === 0) { + notOkNodes.push({ id: -2, message: check_msg.NO_RUNWAY_NODES }); } - var allEnds = Object.entries(graph).filter( + this.postMessage(['progress', 1]); + var allEnds = Object.entries(bidirectionalGraph).filter( (v, i) => Object.keys(v[1]).length <= 1 ); // Ends that are not on Runway and not a Parking or Pushback - var allLegitimateEndNodes = parkings.concat(runwayNodes).concat(pushbackNodes); + var allLegitimateEndNodes = parkings.concat(runwayNodeIDs).concat(pushbackNodes); var danglingEnds = allEnds.filter( (v, i) => allLegitimateEndNodes.indexOf(Number(v[0])) < 0 ).map( - v => { return { id: Number(v[0]), message: 'Node not a legimate end' } } + v => { return { id: Number(v[0]), message: check_msg.NOT_LEGIT_END } } ); + this.postMessage(['progress', 1]); var parkingNodes = data.map(mapParkingNode).filter(n => n !== undefined); var overlappingParkings = []; parkingNodes.forEach(parkingNode => { if (boxes[parkingNode.index] === undefined) { - overlappingParkings.push({ id: parkingNode.index, message: 'Unknown radius' }); + overlappingParkings.push({ id: parkingNode.index, message: check_msg.UNKNOWN_RADIUS }); } }); // Check for intersecting radii @@ -248,78 +339,106 @@ async function checkGroundnet(data) { [parkingNode1.lng, parkingNode1.lat]); if (d < parkingNode.radius + parkingNode1.radius + 10) { // If bigger circles intersect we should check the boxes - //debugger; - if( boxes[parkingNode.index] !== null && boxes[parkingNode1.index] !== null && + if (boxes[parkingNode.index] !== null && boxes[parkingNode1.index] !== null && boxes[parkingNode.index] !== undefined && boxes[parkingNode1.index] !== undefined) { - var poly1 = turf.polygon([boxes[parkingNode.index]]); - - var poly2 = turf.polygon([boxes[parkingNode1.index]]); - + var poly1 = turf.polygon([boxes[parkingNode.index]]); + + var poly2 = turf.polygon([boxes[parkingNode1.index]]); + var intersection = turf.intersect(poly1, poly2); - if( intersection !== null ) { - overlappingParkings.push({ id: parkingNode.index, message: 'Overlapping parkings' }); - } - } + if (intersection !== null) { + overlappingParkings.push({ id: parkingNode.index, message: check_msg.OVERLAPPING_PARKINGS }); + } + } } } - this.postMessage(['progress', 1]); + }); }); + this.postMessage(['progress', 1]); var invalidParkings = []; // Check for name parkingNodes.forEach(parkingNode => { if (!parkingNode.name || /^\s*$/.test(parkingNode.name)) { - invalidParkings.push({ id: parkingNode.index, message: 'Name empty' }); - this.postMessage(['progress', 1]); + invalidParkings.push({ id: parkingNode.index, message: check_msg.NAME_EMPTY }); + } if (!parkingNode.type) { - invalidParkings.push({ id: parkingNode.index, message: 'Parking type empty' }); - this.postMessage(['progress', 1]); + invalidParkings.push({ id: parkingNode.index, message: check_msg.TYPE_EMPTY }); + } - if (['ga','cargo', 'gate', 'mil-fighter', 'mil-cargo' ].indexOf(parkingNode.parkingType)<0) { - //debugger; - invalidParkings.push({ id: parkingNode.index, message: `Parking type ${parkingNode.parkingType} not valid` }); - this.postMessage(['progress', 1]); + if (['ga', 'cargo', 'gate', 'mil-fighter', 'mil-cargo'].indexOf(parkingNode.parkingType) < 0) { + invalidParkings.push({ id: parkingNode.index, message: check_msg.PARKING_TYPE_INVALID }); } }); - + this.postMessage(['progress', 1]); + this.postMessage(['progress', 1]); + //Check for dual pushback/runway nodes - runwayNodes.forEach(runwayNode => { + runwayNodeIDs.forEach(runwayNode => { if (pushbackNodes.indexOf(runwayNode) >= 0) { - notOkNodes.push({ id: runwayNode, message: 'Dual runway/ pushback node' }); + notOkNodes.push({ id: runwayNode, message: check_msg.DUAL_PUSHBACK }); } }); + this.postMessage(['progress', 1]); + //Check if runwaynodes are on runway + runwayNodes.forEach(runwayNode => { + // debugger; + if (takeoffPads.filter(r => turf.booleanContains(r, latToTurf(runwayNode))).length === 0) { + notOkNodes.push({ id: runwayNode.index, message: check_msg.RUNWAY_NODE_NOT_ON_RUNWAY }); + } + }); + this.postMessage(['progress', 1]); + + //Check if nodes no normal nodes are on runway + normalNodes.forEach(normalNode => { + //debugger; + if (takeoffPads.filter(r => turf.booleanContains(r, latToTurf(normalNode))).length > 0) { + notOkNodes.push({ id: normalNode.index, message: check_msg.NON_RUNWAYNODE_ON_RUNWAY }); + } + }); + this.postMessage(['progress', 1]); + + var doubleEdges = edges.filter((v, i, a) => a.findIndex(t => (t.start === v.start && t.end === v.end) ) !== i); + doubleEdges.forEach(e => { + notOkNodes.push({ id: e.id, message: check_msg.DOUBLE_EDGE }); + }); + + // debugger; notOkNodes = notOkNodes.concat(invalidParkings); - if (invalidParkings.length===0) { - notOkNodes.push({id:-1, message: 'Parkings valid'}); + if (invalidParkings.length === 0) { + notOkNodes.push({ id: -1, message: check_msg.PARKINGS_VALID }); } notOkNodes = notOkNodes.concat(overlappingParkings); - if (overlappingParkings.length===0) { - notOkNodes.push({id:-1, message: 'No parkings overlapping'}); + if (overlappingParkings.length === 0) { + notOkNodes.push({ id: -1, message: check_msg.NO_OVERLAPPING_PARKINGS }); } notOkNodes = notOkNodes.concat(danglingEnds); - if (danglingEnds.length===0) { - notOkNodes.push({id:-1, message: 'No invalid ends'}); + if (danglingEnds.length === 0) { + notOkNodes.push({ id: -1, message: check_msg.NO_INVALID_ENDS }); } notOkNodes = notOkNodes.concat(notOkNodesParkings).concat(rogueHoldPoints); - if (notOkNodesParkings.length===0 && rogueHoldPoints===0) { - notOkNodes.push({id:-1, message: 'Routes from parkings OK'}); + if (notOkNodesParkings.length === 0 && rogueHoldPoints === 0) { + notOkNodes.push({ id: -1, message: check_msg.ROUTES_FROM_PARKINGS_OK }); } - + notOkNodes = notOkNodes.concat(notOkNodesRunways); - if (notOkNodesRunways.length===0) { - notOkNodes.push({id:-1, message: 'Routes from runways OK'}); + if (notOkNodesRunways.length === 0) { + notOkNodes.push({ id: -1, message: check_msg.ROUTES_FROM_RUNWAYS_OK }); } notOkNodes = notOkNodes.concat(wrongPushbackRoutes); - if (wrongPushbackRoutes.length===0) { - notOkNodes.push({id:-1, message: 'Pushback routes OK'}); + notOkNodes = notOkNodes.concat(notConnectedToPushback); + notOkNodes = notOkNodes.concat(multipleTaxiRoutes); + notOkNodes = notOkNodes.concat(pushbackExitNotBidirectional); + if (wrongPushbackRoutes.length === 0 && + notConnectedToPushback.length === 0 && + multipleTaxiRoutes.length === 0 && + pushbackExitNotBidirectional.length === 0 + ) { + notOkNodes.push({ id: -1, message: check_msg.PUSHBACK_ROUTES_OK }); } - // check1(graph); - // check2(); - // this.postMessage(['progress', 1]); resolve(notOkNodes); - } catch (error) { reject(error); } @@ -327,9 +446,9 @@ async function checkGroundnet(data) { return promise; } -function checkRoute(graph, from, to) { +function checkRoute(directionalGraph, from, to) { try { - var pathD = this.dijkstra.find_path(graph, from, to); + var pathD = this.dijkstra.find_path(directionalGraph, from, to); if (pathD.length > 0) { console.log(pathD); return pathD.length; @@ -341,8 +460,8 @@ function checkRoute(graph, from, to) { } } -function check1(graph) { - var graph1 = { +function check1(directionalGraph) { + var directionalGraph1 = { a: { b: 1, d: 1 }, b: { a: 1, c: 1, e: 1 }, c: { b: 1, f: 1 }, @@ -353,7 +472,7 @@ function check1(graph) { h: { e: 1, g: 1, i: 1 }, i: { f: 1, h: 1 } }; - var path = this.dijkstra.find_path(graph, 'a', 'i'); + var path = this.dijkstra.find_path(directionalGraph, 'a', 'i'); console.log(path); } @@ -385,18 +504,44 @@ var mapBoxes = function (o) { return { index: o.index }; } -var mapRunwayNodes = function (o) { +var mapRunwayNodeId = function (o) { if (o.type === 'runway') return o.index; console.debug(o); } +var mapRunwayNode = function (o) { + if (o.type === 'runway') { + return { index: o.index, lat: o.lat, lng: o.lng }; + } +} + +var mapTakeoffPads = function (o) { + if (o.type === 'takeoffpad_poly') { + var pts = o.pavement[0].map(latLngToArray); + pts.push(pts[0]); + return turf.polygon([pts]); + } +} + var mapEdges = function (o) { if (o.type === 'poly') - // debugger; return { - start: o.start, end: o.end, isPushBackRoute: o.isPushBackRoute !== undefined && - o.isPushBackRoute !== 0, latLngs: o.latLngs + id: o._leaflet_id, start: o.start, end: o.end, isPushBackRoute: o.isPushBackRoute !== undefined && + o.isPushBackRoute !== 0, direction: o.direction, latLngs: o.latLngs }; - console.debug(o); } + +var latToTurf = function (turfPoint) { + return turf.point([turfPoint.lng, turfPoint.lat]); +}; + +var latLngToArray = function (turfPoint) { + //debugger; + + return [turfPoint.lng, turfPoint.lat]; +}; + +var turfToLatLng = function (turfPoint) { + return '' + turfPoint.geometry.coordinates[1].toFixed(6) + ',' + turfPoint.geometry.coordinates[0].toFixed(6); +}; diff --git a/src/renderer/utils/check_msg.json b/src/renderer/utils/check_msg.json new file mode 100644 index 0000000..f307dad --- /dev/null +++ b/src/renderer/utils/check_msg.json @@ -0,0 +1,33 @@ +{ + "LONG_ROUTE_START" : ["Start of long route", "Route segments of >2km are Taxidraw artefacts"], + "LONG_ROUTE_END": ["End of long route", "Route segments of >2km are Taxidraw artefacts"], + "EDGE_MISSING_DIRECTION": ["Edge missing direction", "Each edge must have a direction (forward, backward, bi-directional)"], + "NO_RUNWAY_ROUTE": ["No way from parking to each runway", "There must be a route from each parking to each runway."], + "NO_PARKING_ROUTE": ["No way from runway to each parking", "There must be a route from each runway to each parking."], + "NO_PARKINGS": ["No parkings", ""], + "NO_RUNWAY_NODES": ["No Runwaynodes", "Fine for parking only"], + "NOT_LEGIT_END": ["Node not a legimate end", "Taxiroutes must end either at a parking or on a runway"], + "UNKNOWN_RADIUS" :["Unknown radius", "Radii must be one from the list"], + "OVERLAPPING_PARKINGS" :["Overlapping parkings", "Parkings must not overlap"], + "NAME_EMPTY" :["Name empty", "Name of parking must not be empty"], + "TYPE_EMPTY" :["Parking type empty", "The parking type must not be empty"], + "PARKING_TYPE_INVALID" :["Parking type not valid", "The type of parking must be one of ()"], + "DUAL_PUSHBACK": ["Dual runway/ pushback node", "A runway node can not be a hold node at the same time"], + "RUNWAY_NODE_NOT_ON_RUNWAY" : ["Runwaynode not in takeoff pad", ""], + "NON_RUNWAYNODE_ON_RUNWAY": ["Non Runwaynode in takeoff pad", ""], + "PARKINGS_VALID": ["Parkings valid", "All Ok"], + "NO_OVERLAPPING_PARKINGS": ["No parkings overlapping", "Parking positions may not overlap. Reduce the radius or move."], + "NO_INVALID_ENDS": ["No invalid ends", ""], + "ROUTES_FROM_PARKINGS_OK": ["Routes from parkings OK", ""], + "ROUTES_FROM_RUNWAYS_OK": ["Routes from runways OK", ""], + "PUSHBACK_ROUTES_OK": ["Pushback routes OK", ""], + "UNCONNECTED_PUSHBACK": ["Unconnected Pushbacknode", ""], + "NO_WAY_TO_HOLDPOINT":["No way to pushback holdpoint", "There is no route from the parking to the pushback hold point-"], + "MULTIPLE_PUSHBACK": ["Multiple connected pushback points", "There are more than one possible pushback holdpoint routes."], + "PUSHBACK_NOT_CONNECTED": ["Pushback Holding Point not Connected to Pushback Route", ""], + "TO_MANY_PUSHBACK_TAXI_ROUTES": ["Too many Taxi routes from Pushback Holding Point", "There must be only one pushback point reachable from the parking."], + "PUSHBACK_EXIT_NOT_BIDRECTIONAL": ["Pushback Holding Point Exit route is not bidirectional", ""], + "NO_EDGES": ["No Edges", "No checks are run if there are no edges present"], + "NO_RUNWAYS": ["No Runways", "No checks are run if there are no runways present. APT layer visible?"], + "DOUBLE_EDGE": ["No Double Edges", "This edge is doubled"] +} \ No newline at end of file diff --git a/src/renderer/utils/logger.js b/src/renderer/utils/logger.js index 200a07a..8e64a67 100644 --- a/src/renderer/utils/logger.js +++ b/src/renderer/utils/logger.js @@ -1,29 +1,40 @@ -var util = require("util"); +/* eslint-disable no-unused-vars */ +var util = require('util'); const d = new Date(); -const fName = 'scan_' + d.getFullYear() -+ d.getMonth() -+ d.getDay() -+ d.getHours() -+ d.getMinutes() -+ d.getSeconds() -+ d.getMilliseconds() + '.log'; +const fName = 'scan_' + d.getFullYear() + +d.getMonth() + +d.getDay() + +d.getHours() + +d.getMinutes() + +d.getSeconds() + +d.getMilliseconds() + '.log'; var logStream = null; var loggerInit = function (logging) { if (logging) { - logStream = require('fs').createWriteStream( fName, {autoClose: true}); + try { + const homedir = require('os').homedir(); + const logFileName = require('path').join(homedir, fName); + logStream = require('fs').createWriteStream( logFileName, {autoClose: true}); + } catch (error) { + console.error('Logging not possible ' + error); + } } } var logger = function (level, msg, o) { - var d = new Date(); - if(logStream!==null) { + var d = new Date(); + try { + if (logStream !== null) { logStream.write(d.toUTCString() + '|' + level + ' | ' + msg + '\r\n'); } if (o != undefined && logStream!==null) { logStream.write( util.inspect(o,{depth: 2}) + '\r\n'); } + } catch (error) { + console.error('Logging not possible ' + error); + } } \ No newline at end of file diff --git a/src/renderer/utils/scan.js b/src/renderer/utils/scan.js index a3d6cec..303bfc0 100644 --- a/src/renderer/utils/scan.js +++ b/src/renderer/utils/scan.js @@ -16,6 +16,8 @@ You should have received a copy of the GNU General Public License along with FG * @param {*} callback */ +const { Debugger } = require("electron"); + async function asyncForEach(array, callback) { logger('info', "AsyncForEach Len " + array.length); for (let index = 0; index < array.length; index++) { @@ -46,7 +48,7 @@ async function scanGroundnetFiles(p, features) { try { logger('info', 'Start Groundnets ' + p); var files = traverseDir(p); - this.postMessage(['max', files.length]); + this.postMessage(['max', files.length*2]); logger('info', files); asyncForEach(files, async f => { @@ -184,6 +186,9 @@ function scanTrafficIntoDB(p, features) { function traverseDir(dir) { var result = []; + if(!fs.existsSync(dir)) { + return result; + } fs.readdirSync(dir).forEach(file => { let fullPath = path.join(dir, file); if (fs.lstatSync(fullPath).isDirectory()) { @@ -239,26 +244,57 @@ function readAI(f, apts) { resolve(); return; } + const aircraftLookup = {}; + + dat.trafficlist.aircraft.map(n => { + try { + if(aircraftLookup[n['required-aircraft']] === undefined) { + aircraftLookup[n['required-aircraft']] = []; + } + aircraftLookup[n['required-aircraft']].push(n.airline); + aircraftLookup[n['required-aircraft']] = aircraftLookup[n['required-aircraft']].filter((v, i, a) => a.indexOf(v) === i); + } catch (error) { + reject(error); + } + //debugger; + }); + logger('info', 'Traffic', dat.trafficlist.flight); logger('info', "Departure flights " + dat.trafficlist.flight.length); - var merged = new Array(); + // Flat list. Each flight departing or landing counts as one. + var merged = []; + + var airports = {}; + dat.trafficlist.flight.map(n => { - merged.push(n.departure.port); + merged.push(n.departure.port); merged.push(n.arrival.port); + + if(airports[n.departure.port] === undefined) { + airports[n.departure.port] = []; + } + if(airports[n.arrival.port] === undefined) { + airports[n.arrival.port] = []; + } + airports[n.departure.port] = airports[n.departure.port].concat(aircraftLookup[n['required-aircraft']]); + airports[n.departure.port] = airports[n.departure.port].filter((v, i, a) => a.indexOf(v) === i) + airports[n.arrival.port] = airports[n.arrival.port].concat(aircraftLookup[n['required-aircraft']]); + airports[n.arrival.port] = airports[n.arrival.port].filter((v, i, a) => a.indexOf(v) === i) }).sort(); + //debugger; var counts = {}; for (var i = 0; i < merged.length; i++) { counts[merged[i]] = 1 + (counts[merged[i]] || 0); } - asyncForEach(Object.keys(counts), async key => { - logger('info', key); - await store(key, airline[1], counts[key]); + asyncForEach(Object.keys(counts), async icao => { + logger('info', icao); + await store(icao, airports[icao], counts[icao]); }).then(t => { logger('info', "Finished"); resolve(); @@ -290,7 +326,7 @@ function readAI(f, apts) { * @param {*} value */ -function store(icao, airline, value) { +function store(icao, airlines, value) { var promise = new Promise(function (resolve, reject) { logger('info', "Airport " + icao + " has " + value + " new flights"); // Make a request to get a record by key from the object store @@ -300,18 +336,18 @@ function store(icao, airline, value) { var objectStoreRequest = index.get(icao); objectStoreRequest.onsuccess = function (event) { - logger('info', 'Stored ', event); + logger('info', 'Store Request', event); var feature = objectStoreRequest.result; if (!feature) { feature = createFeature(icao); } feature.properties.flights += value; - logger('info', "Airline : ", airline); - if (!feature.properties.airlines.includes(airline)) { - feature.properties.airlines.push(airline); - feature.properties.airlines.sort(); - } logger('info', "ICAO : " + feature.properties.icao + " Flights : " + feature.properties.flights); + logger('info', "Airlines : ", JSON.stringify(airlines)); + //debugger; + feature.properties.airlines = feature.properties.airlines.concat(airlines); + feature.properties.airlines = feature.properties.airlines.filter((v, i, a) => a.indexOf(v) === i) + feature.properties.airlines.sort() // Create another request that inserts the item back into the database var updateAirportRequest = objectStore.put(feature); @@ -320,16 +356,16 @@ function store(icao, airline, value) { // When this new request succeeds, run the displayData() function again to update the display updateAirportRequest.onsuccess = function (event) { - logger('info', "Stored", event); + logger('info', "Updated Success", event); resolve(); }; updateAirportRequest.onerror = function (event) { - logger('info', "Error storing ", event); + logger('info', "Error updating ", event); reject(event); }; }; objectStoreRequest.onerror = function (event) { - logger('info', "Error " + event); + logger('info', "Error reading" + event); reject(event); }; }); @@ -345,6 +381,7 @@ function store(icao, airline, value) { async function readGroundnet(f, features) { var promise = new Promise(function (resolve, reject) { try { + var thisPostMessage = this.postMessage; var filename = path.basename(f).match('^([^.]+)\\.([^.]+)(\\.new)?\\.([^.]+)'); if (filename == null) { resolve("File didn't match"); @@ -439,12 +476,10 @@ async function readGroundnet(f, features) { } if(filename [3] === '.new') { feature['properties']['wipgroundnet'] = nodes && nodes.node ? nodes.node.length : 0; - //debugger; feature['properties']['wipparking'] = parkingnodes && parkingnodes.Parking ? parkingnodes.Parking.length : 0; } else { feature['properties']['groundnet'] = nodes && nodes.node ? nodes.node.length : 0; - //debugger; feature['properties']['parking'] = parkingnodes && parkingnodes.Parking ? parkingnodes.Parking.length : 0; } } @@ -459,6 +494,7 @@ async function readGroundnet(f, features) { // report on the success of the transaction completing, when everything is done transaction.oncomplete = function (event) { logger('info', 'Write Transaction complete ' + event); + thisPostMessage(['progress', 1]); resolve("Stored " + filename[1]); }; @@ -481,7 +517,7 @@ async function readGroundnet(f, features) { }; } objectStoreRequest.onerror = function (event) { - logger('info', "Read Errpr : " + event); + logger('info', "Read Error : " + event); resolve(event); } } diff --git a/static/FGA_ACT_A_GA.svg b/static/FGA_ACT_A_GA.svg new file mode 100644 index 0000000..ea3bfb2 --- /dev/null +++ b/static/FGA_ACT_A_GA.svg @@ -0,0 +1,2 @@ + + diff --git a/static/FGA_ACT_B_PROP.svg b/static/FGA_ACT_B_PROP.svg new file mode 100644 index 0000000..cfb1b14 --- /dev/null +++ b/static/FGA_ACT_B_PROP.svg @@ -0,0 +1,2 @@ + + diff --git a/static/FGA_ACT_B_SHORTEN.svg b/static/FGA_ACT_B_SHORTEN.svg new file mode 100644 index 0000000..9fffc0e --- /dev/null +++ b/static/FGA_ACT_B_SHORTEN.svg @@ -0,0 +1,2 @@ + + diff --git a/static/FGA_ACT_C.svg b/static/FGA_ACT_C.svg new file mode 100644 index 0000000..1353d30 --- /dev/null +++ b/static/FGA_ACT_C.svg @@ -0,0 +1,3 @@ + + +image/svg+xml diff --git a/static/FGA_ACT_D.svg b/static/FGA_ACT_D.svg new file mode 100644 index 0000000..87895c4 --- /dev/null +++ b/static/FGA_ACT_D.svg @@ -0,0 +1,2 @@ + + diff --git a/static/FGA_ACT_E.svg b/static/FGA_ACT_E.svg new file mode 100644 index 0000000..502a9a4 --- /dev/null +++ b/static/FGA_ACT_E.svg @@ -0,0 +1,2 @@ + + diff --git a/static/FGA_ACT_F.svg b/static/FGA_ACT_F.svg new file mode 100644 index 0000000..fee4f5e --- /dev/null +++ b/static/FGA_ACT_F.svg @@ -0,0 +1,17 @@ + + + + + + +image/svg+xml + + + + + + + + + + diff --git a/static/FGA_THR.svg b/static/FGA_THR.svg new file mode 100644 index 0000000..aa41794 --- /dev/null +++ b/static/FGA_THR.svg @@ -0,0 +1,89 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/static/tower.svg b/static/tower.svg new file mode 100644 index 0000000..62da8fa --- /dev/null +++ b/static/tower.svg @@ -0,0 +1,146 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/mocha/index.js b/test/mocha/index.js new file mode 100644 index 0000000..af4b0e7 --- /dev/null +++ b/test/mocha/index.js @@ -0,0 +1,18 @@ +'use strict' + +// Set BABEL_ENV to use proper env config +process.env.BABEL_ENV = 'test' + +// Enable use of ES6+ on required files +require('babel-register')({ + ignore: /node_modules/ +}) + +// Attach Chai APIs to global scope +const { expect, should, assert } = require('chai') +global.expect = expect +global.should = should +global.assert = assert + +// Require all JS files in `./specs` for Mocha to consume +require('require-dir')('./specs') diff --git a/test/mocha/specs/check.spec.js b/test/mocha/specs/check.spec.js new file mode 100644 index 0000000..ff38964 --- /dev/null +++ b/test/mocha/specs/check.spec.js @@ -0,0 +1,228 @@ +var assert = require('chai').assert; +var Worker = require("tiny-worker"); + +process.chdir('src/renderer/utils'); + +describe("Test Check", function () { + describe("Routing Checks", function () { + it("Not legitimate End", function (done) { + var data = [ + { 'start': 1, 'end': 2, '_leaflet_id': 1, 'type': 'poly', 'isPushBackRoute': true } + ]; + var worker = new Worker('check.js'); + worker.onmessage = function (e) { + if (e.data === 'checkStarted') { + } else if (e.data[0] === 'DONE') { + console.log('DONE') + worker.terminate() + if (e.data[1].length === 0) { + done('Crashed') + } else { + console.log(e.data[1]); + console.log(e.data[1].filter(m => m.id === 1)); + assert.lengthOf(e.data[1].filter(m => m.id === 1).filter(m => m.message === 'Node not a legimate end'), 1); + assert.lengthOf(e.data[1].filter(m => m.id === 2).filter(m => m.message === 'Node not a legimate end'), 1); + assert.lengthOf(e.data[1].filter(m => m.message === 'No invalid ends'), 0); + + done() + } + } else if (e.data.length > 0) { + } + }; + worker.postMessage(['check', data]); + }); + it("Legitimate End Runway", function (done) { + var data = [ + { 'start': 1, 'end': 2, '_leaflet_id': 1, 'type': 'poly', 'isPushBackRoute': true, 'direction': 'bi-directional' }, + { 'index': 1, '_leaflet_id': 2, 'type': 'runway' } + ]; + var worker = new Worker('check.js'); + worker.onmessage = function (e) { + if (e.data === 'checkStarted') { + } else if (e.data[0] === 'DONE') { + console.log('DONE') + worker.terminate() + if (e.data[1].length === 0) { + done('Crashed') + } else { + console.log(e.data[1]); + console.log(e.data[1].filter(m => m.id === 1)); + assert.lengthOf(e.data[1].filter(m => m.id === 1).filter(m => m.message === 'No way from runway to each parking'), 1); + assert.lengthOf(e.data[1].filter(m => m.id === 2).filter(m => m.message === 'Node not a legimate end'), 1); + assert.lengthOf(e.data[1].filter(m => m.message === 'No invalid ends'), 0); + done() + } + } else if (e.data.length > 0) { + } + }; + worker.postMessage(['check', data]); + }); + + it("From Parking to Runway bi-directional", function (done) { + var data = [ + { 'start': 1, 'end': 2, '_leaflet_id': 1, 'type': 'poly', 'isPushBackRoute': true, direction: 'bi-directional' }, + { 'index': 1, '_leaflet_id': 2, 'type': 'runway' }, + { 'index': 2, '_leaflet_id': 3, 'name': 'name', parkingType: 'gate', 'type': 'parking' } + ]; + var worker = new Worker('check.js'); + worker.onmessage = function (e) { + if (e.data === 'checkStarted') { + } else if (e.data[0] === 'DONE') { + console.log('DONE') + worker.terminate() + if (e.data[1].length === 0) { + done('Crashed') + } else { + console.log(e.data[1]); + console.log(e.data[1].filter(m => m.id === 1)); + assert.lengthOf(e.data[1].filter(m => m.id === -1).filter(m => m.message === 'Routes from runways OK'), 1); + assert.lengthOf(e.data[1].filter(m => m.message === 'No invalid ends'), 1); + done() + } + } else if (e.data.length > 0) { + } + }; + worker.postMessage(['check', data]); + }); + + it("From Parking to Runway forward OK", function (done) { + var data = [ + { 'start': 1, 'end': 2, '_leaflet_id': 1, 'type': 'poly', 'isPushBackRoute': true, direction: 'forward' }, + { 'index': 1, '_leaflet_id': 3, 'name': 'name', parkingType: 'gate', 'type': 'parking' }, + { 'index': 2, '_leaflet_id': 2, 'type': 'runway' } + ]; + var worker = new Worker('check.js'); + worker.onmessage = function (e) { + if (e.data === 'checkStarted') { + } else if (e.data[0] === 'DONE') { + console.log('DONE') + worker.terminate() + + if (e.data[1].length === 0) { + done('Crashed') + } else { + console.log(e.data[1]); + console.log(e.data[1].filter(m => m.id === 1)); + assert.lengthOf(e.data[1].filter(m => m.id === -1).filter(m => m.message === 'Routes from runways OK'), 1); + assert.lengthOf(e.data[1].filter(m => m.message === 'No invalid ends'), 1); + done() + } + } else if (e.data.length > 0) { + } + }; + worker.postMessage(['check', data]); + }); + + it("From Parking to Runway forward Not Ok", function (done) { + var data = [ + { 'start': 1, 'end': 2, '_leaflet_id': 1, 'type': 'poly', 'isPushBackRoute': true, direction: 'forward' }, + { 'index': 2, '_leaflet_id': 3, 'name': 'name', parkingType: 'gate', 'type': 'parking' }, + { 'index': 1, '_leaflet_id': 2, 'type': 'runway' } + ]; + var worker = new Worker('check.js'); + worker.onmessage = function (e) { + if (e.data === 'checkStarted') { + } else if (e.data[0] === 'DONE') { + console.log('DONE') + worker.terminate() + + if (e.data[1].length === 0) { + done('Crashed') + } else { + console.log(e.data[1]); + console.log(e.data[1].filter(m => m.id === 1)); + assert.lengthOf(e.data[1].filter(m => m.id === -1).filter(m => m.message === 'Routes from runways OK'), 0); + assert.lengthOf(e.data[1].filter(m => m.message === 'No invalid ends'), 1); + done() + } + } else if (e.data.length > 0) { + } + }; + worker.postMessage(['check', data]); + }); + + it("From Parking to Runway reverse OK", function (done) { + var data = [ + { 'start': 1, 'end': 2, '_leaflet_id': 1, 'type': 'poly', 'isPushBackRoute': true, direction: 'backward' }, + { 'index': 2, '_leaflet_id': 3, 'name': 'name', parkingType: 'gate', 'type': 'parking' }, + { 'index': 1, '_leaflet_id': 2, 'type': 'runway' } + ]; + var worker = new Worker('check.js'); + worker.onmessage = function (e) { + if (e.data === 'checkStarted') { + } else if (e.data[0] === 'DONE') { + console.log('DONE') + worker.terminate() + if (e.data[1].length === 0) { + done('Crashed') + } else { + console.log(e.data[1]); + console.log(e.data[1].filter(m => m.id === 1)); + assert.lengthOf(e.data[1].filter(m => m.id === -1).filter(m => m.message === 'Routes from runways OK'), 1); + assert.lengthOf(e.data[1].filter(m => m.message === 'No invalid ends'), 1); + done() + } + } else if (e.data.length > 0) { + } + }; + worker.postMessage(['check', data]); + }); + + it("From Parking to Runway reverse Not OK", function (done) { + var data = [ + { 'start': 1, 'end': 2, '_leaflet_id': 1, 'type': 'poly', 'isPushBackRoute': true, direction: 'backward' }, + { 'index': 1, '_leaflet_id': 3, 'name': 'name', parkingType: 'gate', 'type': 'parking' }, + { 'index': 2, '_leaflet_id': 2, 'type': 'runway' } + ]; + var worker = new Worker('check.js'); + worker.onmessage = function (e) { + if (e.data === 'checkStarted') { + } else if (e.data[0] === 'DONE') { + console.log('DONE') + worker.terminate() + if (e.data[1].length === 0) { + done('Crashed') + } else { + console.log(e.data[1]); + console.log(e.data[1].filter(m => m.id === 1)); + assert.lengthOf(e.data[1].filter(m => m.id === -1).filter(m => m.message === 'Routes from runways OK'), 0, 'No Routes from Runway'); + assert.lengthOf(e.data[1].filter(m => m.message === 'No invalid ends'), 1, 'No invalid ends'); + done() + } + } else if (e.data.length > 0) { + } + }; + worker.postMessage(['check', data]); + }); + }); + describe("Routing Checks", function () { + it("Runway Node not on Runway", function (done) { + var data = [ + { 'index': 2, '_leaflet_id': 2, 'type': 'runway' }, + { 'name': 'R29', 'type': 'runway_area', 'polygon': [] } + ]; + var worker = new Worker('check.js'); + worker.onmessage = function (e) { + if (e.data === 'checkStarted') { + } else if (e.data[0] === 'DONE') { + console.log('DONE') + worker.terminate() + if (e.data[1].length === 0) { + done('Crashed') + } else { + console.log(e.data[1]); + console.log(e.data[1].filter(m => m.id === 1)); + assert.lengthOf(e.data[1].filter(m => m.id === -1).filter(m => m.message === 'Routes from runways OK'), 0, 'No Routes from Runway'); + assert.lengthOf(e.data[1].filter(m => m.message === 'No invalid ends'), 1, 'No invalid ends'); + done() + } + } else if (e.data.length > 0) { + } + }; + worker.postMessage(['check', data]); + }); + }); + describe("", function () { + + }); +}); \ No newline at end of file diff --git a/test/unit/index.js b/test/unit/index.js deleted file mode 100644 index f07be98..0000000 --- a/test/unit/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import Vue from 'vue' -Vue.config.devtools = false -Vue.config.productionTip = false - -// require all test files (files that ends with .spec.js) -const testsContext = require.context('./specs', true, /\.spec$/) -testsContext.keys().forEach(testsContext) - -// require all src files except main.js for coverage. -// you can also change this to match only the subset of files that -// you want coverage for. -const srcContext = require.context('../../src/renderer', true, /^\.\/(?!main(\.js)?$)/) -srcContext.keys().forEach(srcContext) diff --git a/test/unit/karma.conf.js b/test/unit/karma.conf.js deleted file mode 100644 index 6204011..0000000 --- a/test/unit/karma.conf.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict' - -const path = require('path') -const merge = require('webpack-merge') -const webpack = require('webpack') - -const baseConfig = require('../../.electron-vue/webpack.renderer.config') -const projectRoot = path.resolve(__dirname, '../../src/renderer') - -// Set BABEL_ENV to use proper preset config -process.env.BABEL_ENV = 'test' - -let webpackConfig = merge(baseConfig, { - devtool: '#inline-source-map', - plugins: [ - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': '"testing"' - }) - ] -}) - -// don't treat dependencies as externals -delete webpackConfig.entry -delete webpackConfig.externals -delete webpackConfig.output.libraryTarget - -// apply vue option to apply isparta-loader on js -webpackConfig.module.rules - .find(rule => rule.use.loader === 'vue-loader').use.options.loaders.js = 'babel-loader' - -module.exports = config => { - config.set({ - browsers: ['visibleElectron'], - client: { - useIframe: false - }, - coverageReporter: { - dir: './coverage', - reporters: [ - { type: 'lcov', subdir: '.' }, - { type: 'text-summary' } - ] - }, - customLaunchers: { - 'visibleElectron': { - base: 'Electron', - flags: ['--show'] - } - }, - frameworks: ['mocha', 'chai'], - files: ['./index.js'], - preprocessors: { - './index.js': ['webpack', 'sourcemap'] - }, - reporters: ['spec', 'coverage'], - singleRun: true, - webpack: webpackConfig, - webpackMiddleware: { - noInfo: true - } - }) -} diff --git a/test/unit/specs/LandingPage.spec.js b/test/unit/specs/LandingPage.spec.js deleted file mode 100644 index 7cea66f..0000000 --- a/test/unit/specs/LandingPage.spec.js +++ /dev/null @@ -1,13 +0,0 @@ -import Vue from 'vue' -import LandingPage from '@/components/LandingPage' - -describe('LandingPage.vue', () => { - it('should render correct contents', () => { - const vm = new Vue({ - el: document.createElement('div'), - render: h => h(LandingPage) - }).$mount() - - expect(vm.$el.querySelector('.title').textContent).to.contain('Welcome to your new project!') - }) -})