mirror of
https://github.com/thomasnordquist/MQTT-Explorer.git
synced 2026-09-12 01:23:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
322c8e67aa | ||
|
|
906eadf08b | ||
|
|
225f536cd1 | ||
|
|
87f0f06a07 | ||
|
|
e294d9700f | ||
|
|
fdece7ae91 | ||
|
|
d2bb098772 | ||
|
|
490678d7b4 | ||
|
|
2d649b3f51 | ||
|
|
0de67a48a6 | ||
|
|
1267bb27f7 | ||
|
|
31b3077743 | ||
|
|
7015c31a91 | ||
|
|
f486f5888c | ||
|
|
33bd2b7340 | ||
|
|
241a99207d | ||
|
|
fa9f321d88 |
@@ -0,0 +1,24 @@
|
||||
# MQTT-Explorer
|
||||
|
||||
See the whole picture of your message queue.
|
||||
The perfect tool to integrate new services, IoT devices in your network.
|
||||
This application subscribes to all topics on your MQTT-Server and displays your message queue hierarchy, allowing you to drill-down to the topics that are of interest.
|
||||
|
||||
## Download
|
||||
The app is prebuilt for Windows, Linux and Mac. [Downloads](https://github.com/thomasnordquist/MQTT-Explorer/releases)
|
||||
|
||||

|
||||
|
||||
|
||||
## Develop
|
||||
PRs and issues are welcome
|
||||
|
||||
Install with `npm run install`, build with `npm run build`
|
||||
|
||||
Start with `npm run start`
|
||||
|
||||
The `app` directory contains all the rendering logic, the `backend` directory currently contains the models, tests, connection management.
|
||||
|
||||
## License
|
||||
Not yet decided which licens exactly, but the basic idea is: "You may do whatever you want with this tool, except sell it."
|
||||
|
||||
@@ -32,9 +32,42 @@
|
||||
#-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.8);
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
#splash {
|
||||
z-index: 1000000;
|
||||
background-color: #303030;
|
||||
display: block;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
opacity: 1;
|
||||
}
|
||||
#splash1 {
|
||||
margin: 37vh auto 0 auto;
|
||||
height: 25vh;
|
||||
width: 25vh;
|
||||
background-image:url('./rings.svg');
|
||||
background-size: cover;
|
||||
}
|
||||
#splash2 {
|
||||
margin: 0 auto;
|
||||
}
|
||||
@keyframes unsplash {
|
||||
0% {opacity: 1;}
|
||||
100% {opacity: 0;}
|
||||
}
|
||||
</style>
|
||||
<script src="http://localhost:35729/livereload.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="splash"><div id="splash1"></div>
|
||||
<!-- <div id="splash1">
|
||||
<div id="splash2" style="color: #ddd" class="la-square-jelly-box la-3x">
|
||||
<div>a</div>
|
||||
<div>ads</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="app" style="font:-webkit-control"></div>
|
||||
<script src="./build/bundle.js"></script>
|
||||
</body>
|
||||
|
||||
Generated
+433
@@ -483,6 +483,15 @@
|
||||
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"asn1.js": {
|
||||
"version": "4.10.1",
|
||||
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
|
||||
@@ -516,6 +525,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
},
|
||||
"assign-symbols": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
|
||||
@@ -536,6 +551,12 @@
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -569,6 +590,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
|
||||
"dev": true
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"backo2": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
|
||||
@@ -649,6 +682,15 @@
|
||||
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
|
||||
"integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"better-assert": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
|
||||
@@ -946,6 +988,12 @@
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
|
||||
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA=="
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
|
||||
@@ -1071,6 +1119,15 @@
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
|
||||
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
|
||||
@@ -1134,6 +1191,19 @@
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"conf": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz",
|
||||
"integrity": "sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dot-prop": "^4.1.0",
|
||||
"env-paths": "^1.0.0",
|
||||
"make-dir": "^1.0.0",
|
||||
"pkg-up": "^2.0.0",
|
||||
"write-file-atomic": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"connect-history-api-fallback": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz",
|
||||
@@ -1306,6 +1376,15 @@
|
||||
"es5-ext": "^0.10.9"
|
||||
}
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"date-now": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
|
||||
@@ -1432,6 +1511,12 @@
|
||||
"rimraf": "^2.2.8"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
@@ -1506,6 +1591,15 @@
|
||||
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
|
||||
"integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
|
||||
"integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-obj": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"duplexify": {
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz",
|
||||
@@ -1517,11 +1611,53 @@
|
||||
"stream-shift": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"electron-nucleus": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-nucleus/-/electron-nucleus-1.11.0.tgz",
|
||||
"integrity": "sha512-n8Nz4D0z0SrBg5Y8JEIDdbNtradG2tozrSnpxB/PK9arJo5YujA4+4OAWiA5ggDi/UJs+zjlU/1iTVnPFgxtgw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"electron-store": "^1.3.0",
|
||||
"node-machine-id": "^1.1.10",
|
||||
"request": "^2.85.0",
|
||||
"ws": "^5.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
||||
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron-store": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-store/-/electron-store-1.3.0.tgz",
|
||||
"integrity": "sha512-r1Pdl5MwpiCxgbsl0qnwv/GABO5+J/JTO16+KyqL+bOITIk9o3cq3Sw69uO9NgPkpfcKeEwxtJFbtbiBlGTiDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"conf": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
|
||||
@@ -1612,6 +1748,12 @@
|
||||
"tapable": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"env-paths": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz",
|
||||
"integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=",
|
||||
"dev": true
|
||||
},
|
||||
"errno": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
|
||||
@@ -1813,6 +1955,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"dev": true
|
||||
},
|
||||
"extend-shallow": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
|
||||
@@ -1891,6 +2039,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
@@ -2030,6 +2184,23 @@
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
|
||||
"dev": true
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"forwarded": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||
@@ -2624,6 +2795,15 @@
|
||||
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
|
||||
"integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
|
||||
@@ -2690,6 +2870,22 @@
|
||||
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
|
||||
"integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ=="
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
|
||||
"dev": true
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.5.5",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"has-binary2": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
|
||||
@@ -2843,6 +3039,17 @@
|
||||
"micromatch": "^3.1.9"
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"https-browserify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
|
||||
@@ -3067,6 +3274,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||
"dev": true
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
|
||||
@@ -3101,6 +3314,12 @@
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
|
||||
"dev": true
|
||||
},
|
||||
"is-windows": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
|
||||
@@ -3135,6 +3354,12 @@
|
||||
"whatwg-fetch": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||
"dev": true
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
|
||||
@@ -3145,16 +3370,34 @@
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"dev": true
|
||||
},
|
||||
"json-parse-better-errors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
|
||||
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
|
||||
"dev": true
|
||||
},
|
||||
"json3": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
|
||||
@@ -3168,6 +3411,18 @@
|
||||
"minimist": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"jss": {
|
||||
"version": "9.8.7",
|
||||
"resolved": "https://registry.npmjs.org/jss/-/jss-9.8.7.tgz",
|
||||
@@ -3699,6 +3954,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-machine-id": {
|
||||
"version": "1.1.10",
|
||||
"resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.10.tgz",
|
||||
"integrity": "sha512-6SVxo3Ic2Qc09z1rCJh3No7ubizPLszImsMQnZZWfzeOC6SYU4orN214++c3ikB8uaP/A6dwSlO88A3ohI5oNA==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
|
||||
@@ -3725,6 +3986,12 @@
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@@ -3993,6 +4260,12 @@
|
||||
"sha.js": "^2.4.8"
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"dev": true
|
||||
},
|
||||
"pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
@@ -4019,6 +4292,60 @@
|
||||
"find-up": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"pkg-up": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
|
||||
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"find-up": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
|
||||
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
||||
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-locate": "^2.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
|
||||
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-try": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
|
||||
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-limit": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
|
||||
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"popper.js": {
|
||||
"version": "1.14.6",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz",
|
||||
@@ -4085,6 +4412,12 @@
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.1.31",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
|
||||
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==",
|
||||
"dev": true
|
||||
},
|
||||
"public-encrypt": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
|
||||
@@ -4385,6 +4718,34 @@
|
||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.0",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.4.3",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
@@ -4964,6 +5325,23 @@
|
||||
"extend-shallow": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz",
|
||||
"integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
"ssri": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
|
||||
@@ -5235,6 +5613,24 @@
|
||||
"repeat-string": "^1.6.1"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
||||
@@ -5245,6 +5641,21 @@
|
||||
"resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
||||
"integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"dev": true
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.16",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
|
||||
@@ -5439,6 +5850,17 @@
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"vm-browserify": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
|
||||
@@ -5776,6 +6198,17 @@
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"write-file-atomic": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
|
||||
"integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.11",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"@types/react": "^16.7.18",
|
||||
"@types/react-dom": "^16.0.11",
|
||||
"@types/react-redux": "^6.0.12",
|
||||
"electron-nucleus": "^1.11.0",
|
||||
"react": "^16.7.0",
|
||||
"react-dom": "^16.7.0",
|
||||
"react-redux": "^6.0.0",
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||
<svg width="45" height="45" viewBox="0 0 45 45" xmlns="http://www.w3.org/2000/svg" stroke="#fff">
|
||||
<g fill="none" fill-rule="evenodd" transform="translate(1 1)" stroke-width="2">
|
||||
<circle cx="22" cy="22" r="6" stroke-opacity="0">
|
||||
<animate attributeName="r"
|
||||
begin="1.5s" dur="3s"
|
||||
values="6;22"
|
||||
calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
<animate attributeName="stroke-opacity"
|
||||
begin="1.5s" dur="3s"
|
||||
values="1;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
<animate attributeName="stroke-width"
|
||||
begin="1.5s" dur="3s"
|
||||
values="2;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="22" cy="22" r="6" stroke-opacity="0">
|
||||
<animate attributeName="r"
|
||||
begin="3s" dur="3s"
|
||||
values="6;22"
|
||||
calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
<animate attributeName="stroke-opacity"
|
||||
begin="3s" dur="3s"
|
||||
values="1;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
<animate attributeName="stroke-width"
|
||||
begin="3s" dur="3s"
|
||||
values="2;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="22" cy="22" r="8">
|
||||
<animate attributeName="r"
|
||||
begin="0s" dur="1.5s"
|
||||
values="6;1;2;3;4;5;6"
|
||||
calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
+31
-25
@@ -1,14 +1,17 @@
|
||||
import * as React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import * as q from '../../backend/src/Model'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import { withStyles, Theme } from '@material-ui/core/styles'
|
||||
import Tree from './components/Tree/Tree'
|
||||
import TitleBar from './components/TitleBar'
|
||||
import Sidebar from './components/Sidebar/Sidebar'
|
||||
import Connection from './components/ConnectionSetup/Connection'
|
||||
import Settings from './components/Settings'
|
||||
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import { AppState } from './reducers'
|
||||
import Connection from './components/ConnectionSetup/Connection'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import Settings from './components/Settings'
|
||||
import Sidebar from './components/Sidebar/Sidebar'
|
||||
import TitleBar from './components/TitleBar'
|
||||
import Tree from './components/Tree/Tree'
|
||||
import UpdateNotifier from './UpdateNotifier'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
interface State {
|
||||
selectedNode?: q.TreeNode,
|
||||
@@ -79,24 +82,27 @@ class App extends React.Component<Props, State> {
|
||||
public render() {
|
||||
const { settingsVisible } = this.props
|
||||
const { content, contentShift, centerContent } = this.getStyles()
|
||||
return <div style={centerContent}>
|
||||
<CssBaseline />
|
||||
<Settings />
|
||||
<div style={settingsVisible ? contentShift : content}>
|
||||
<TitleBar />
|
||||
<div style={centerContent}>
|
||||
<div style={this.getStyles().left}>
|
||||
<Tree connectionId={this.state.connectionId} didSelectNode={(node: q.TreeNode) => {
|
||||
this.setState({ selectedNode: node })
|
||||
}} />
|
||||
return (
|
||||
<div style={centerContent}>
|
||||
<CssBaseline />
|
||||
<Settings />
|
||||
<div style={settingsVisible ? contentShift : content}>
|
||||
<TitleBar />
|
||||
<div style={centerContent}>
|
||||
<div style={this.getStyles().left}>
|
||||
<Tree connectionId={this.state.connectionId} didSelectNode={(node: q.TreeNode) => {
|
||||
this.setState({ selectedNode: node })
|
||||
}} />
|
||||
</div>
|
||||
<div style={this.getStyles().right}>
|
||||
<Sidebar connectionId={this.state.connectionId} />
|
||||
</div>
|
||||
</div>
|
||||
<div style={this.getStyles().right}>
|
||||
<Sidebar connectionId={this.state.connectionId} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Connection onConnection={(connectionId: string) => this.setState({ connectionId })}/>
|
||||
</div >
|
||||
</div>
|
||||
<UpdateNotifier />
|
||||
<Connection onConnection={(connectionId: string) => this.setState({ connectionId })}/>
|
||||
</div >
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
Modal,
|
||||
Paper,
|
||||
Snackbar,
|
||||
SnackbarContent,
|
||||
Typography,
|
||||
} from '@material-ui/core'
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
import { UpdateInfo, checkForUpdates, rendererEvents, updateAvailable } from '../../events'
|
||||
import { green, red } from '@material-ui/core/colors'
|
||||
|
||||
import { AppState } from './reducers'
|
||||
import Close from '@material-ui/icons/Close'
|
||||
import CloudDownload from '@material-ui/icons/CloudDownload'
|
||||
import { UpdateFileInfo } from 'builder-util-runtime'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { updateNotifierActions } from './actions'
|
||||
|
||||
interface Props {
|
||||
showUpdateNotification: boolean
|
||||
showUpdateDetails: boolean
|
||||
classes: any
|
||||
actions: any
|
||||
}
|
||||
|
||||
class UpdateNotifier extends React.Component<Props, {}> {
|
||||
private updateInfo?: UpdateInfo
|
||||
constructor(props: any) {
|
||||
super(props)
|
||||
this.state = {
|
||||
selectedNode: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
rendererEvents.emit(checkForUpdates, undefined)
|
||||
rendererEvents.subscribe(updateAvailable, this.handleUpdate)
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
rendererEvents.unsubscribeAll(updateAvailable)
|
||||
}
|
||||
|
||||
private handleUpdate = (updateInfo: UpdateInfo) => {
|
||||
this.updateInfo = updateInfo
|
||||
this.props.actions.showUpdateNotification(true)
|
||||
}
|
||||
|
||||
private onCloseNotification = (event: React.SyntheticEvent<any>, reason: string) => {
|
||||
if (reason === 'clickaway') {
|
||||
return
|
||||
}
|
||||
this.props.actions.showUpdateNotification(false)
|
||||
}
|
||||
|
||||
private closeNotification = () => {
|
||||
this.props.actions.showUpdateNotification(false)
|
||||
}
|
||||
|
||||
private showDetails = () => {
|
||||
this.props.actions.showUpdateNotification(false)
|
||||
this.props.actions.showUpdateDetails(true)
|
||||
}
|
||||
|
||||
private hideDetails = () => {
|
||||
this.props.actions.showUpdateDetails(false)
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div>
|
||||
{this.renderUpdateNotification()}
|
||||
{this.renderUpdateDetails()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private renderUpdateNotification() {
|
||||
const snackbarAnchor: any = {
|
||||
vertical: 'top',
|
||||
horizontal: 'right',
|
||||
}
|
||||
|
||||
return (
|
||||
<Snackbar
|
||||
anchorOrigin={snackbarAnchor}
|
||||
open={this.props.showUpdateNotification}
|
||||
autoHideDuration={7000}
|
||||
onClose={this.onCloseNotification}
|
||||
>
|
||||
<SnackbarContent
|
||||
className={this.props.classes.success}
|
||||
message="Update available"
|
||||
action={this.notificationActions()}
|
||||
/>
|
||||
</Snackbar>
|
||||
)
|
||||
}
|
||||
|
||||
private notificationActions() {
|
||||
return [(
|
||||
<Button key="undo" size="small" onClick={this.showDetails}>
|
||||
Download
|
||||
</Button>
|
||||
), (
|
||||
<IconButton
|
||||
key="close"
|
||||
aria-label="Close"
|
||||
color="inherit"
|
||||
className={this.props.classes.close}
|
||||
onClick={this.closeNotification}
|
||||
>
|
||||
<Close />
|
||||
</IconButton>
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
private renderUpdateDetails() {
|
||||
if (!this.updateInfo) {
|
||||
return null
|
||||
}
|
||||
const releaseNotes = (this.updateInfo.releaseNotes as string) || ''
|
||||
return (
|
||||
<Modal
|
||||
open={this.props.showUpdateDetails}
|
||||
disableAutoFocus={true}
|
||||
onClose={this.hideDetails}
|
||||
>
|
||||
<Paper className={this.props.classes.root}>
|
||||
<Typography variant="h6" className={this.props.classes.title}>Version {this.updateInfo.version}</Typography>
|
||||
<Typography className={this.props.classes.title}>Changelog</Typography>
|
||||
<div className={this.props.classes.releaseNotes} dangerouslySetInnerHTML={{ __html: releaseNotes }} />
|
||||
{this.renderDownloads(this.updateInfo)}
|
||||
<Button className={this.props.classes.closeButton} color="secondary" onClick={this.hideDetails}>Close</Button>
|
||||
</Paper>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
private urlToFilename(url: string) {
|
||||
const parts = url.split('/')
|
||||
|
||||
return parts[parts.length - 1]
|
||||
}
|
||||
|
||||
private renderDownloads(updateInfo: UpdateInfo) {
|
||||
console.log(updateInfo)
|
||||
return updateInfo.files
|
||||
.map((file: UpdateFileInfo, index: number) => (
|
||||
<div key={index}>
|
||||
<Button
|
||||
className={this.props.classes.download}
|
||||
href={file.url}
|
||||
>
|
||||
<IconButton><CloudDownload /></IconButton>{this.urlToFilename(file.url)}
|
||||
</Button>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) => ({
|
||||
success: {
|
||||
backgroundColor: green[600],
|
||||
color: theme.typography.button.color,
|
||||
},
|
||||
close: {
|
||||
padding: theme.spacing.unit / 2,
|
||||
},
|
||||
root: {
|
||||
minWidth: '350px',
|
||||
maxWidth: '500px',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
margin: '20vh auto auto auto',
|
||||
padding: `${2 * theme.spacing.unit}px`,
|
||||
outline: 'none',
|
||||
},
|
||||
title: {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
releaseNotes: {
|
||||
overflow: 'auto scroll',
|
||||
color: theme.palette.text.secondary,
|
||||
backgroundColor: 'rgba(60, 60, 60, 0.6)',
|
||||
maxHeight: '28vh',
|
||||
},
|
||||
paper: {
|
||||
padding: `${theme.spacing.unit * 2}px`,
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
download: {
|
||||
width: '100%',
|
||||
},
|
||||
closeButton: {
|
||||
display: 'block',
|
||||
margin: '0 0 0 auto',
|
||||
},
|
||||
})
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
showUpdateNotification: state.showUpdateNotification,
|
||||
showUpdateDetails: state.showUpdateDetails,
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: any) => {
|
||||
return {
|
||||
actions: bindActionCreators(updateNotifierActions, dispatch),
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles, { withTheme: true })(connect(mapStateToProps, mapDispatchToProps)(UpdateNotifier))
|
||||
@@ -0,0 +1,15 @@
|
||||
import { ActionTypes, CustomAction } from '../reducers'
|
||||
|
||||
export const showUpdateNotification = (show: boolean): CustomAction => {
|
||||
return {
|
||||
type: ActionTypes.showUpdateNotification,
|
||||
showUpdateNotification: show,
|
||||
}
|
||||
}
|
||||
|
||||
export const showUpdateDetails = (show: boolean): CustomAction => {
|
||||
return {
|
||||
type: ActionTypes.showUpdateDetails,
|
||||
showUpdateDetails: show,
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as settingsActions from './Settings'
|
||||
import * as treeActions from './Tree'
|
||||
import * as sidebarActions from './Sidebar'
|
||||
import * as treeActions from './Tree'
|
||||
import * as updateNotifierActions from './UpdateNotifier'
|
||||
|
||||
export { settingsActions, treeActions, sidebarActions }
|
||||
export { settingsActions, treeActions, sidebarActions, updateNotifierActions }
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import {
|
||||
Typography, Toolbar, Modal,
|
||||
MenuItem, Button, Grid, Paper,
|
||||
TextField, Switch, FormControlLabel,
|
||||
Button,
|
||||
CircularProgress,
|
||||
FormControlLabel,
|
||||
Grid,
|
||||
MenuItem,
|
||||
Modal,
|
||||
Paper,
|
||||
Switch,
|
||||
TextField,
|
||||
Toolbar,
|
||||
Typography,
|
||||
} from '@material-ui/core'
|
||||
import { withStyles, Theme, StyleRulesCallback } from '@material-ui/core/styles'
|
||||
import Notification from './Notification'
|
||||
import { MqttOptions, DataSourceState } from '../../../../backend/src/DataSource'
|
||||
import { DataSourceState, MqttOptions } from '../../../../backend/src/DataSource'
|
||||
import { StyleRulesCallback, Theme, withStyles } from '@material-ui/core/styles'
|
||||
import { addMqttConnectionEvent, makeConnectionStateEvent, removeConnection, rendererEvents } from '../../../../events'
|
||||
|
||||
import sha1 = require('sha1')
|
||||
|
||||
interface Props {
|
||||
@@ -53,7 +61,7 @@ class Connection extends React.Component<Props, State> {
|
||||
|
||||
const defaultState = {
|
||||
visible: true,
|
||||
host: 'nodered',
|
||||
host: 'iot.eclipse.org',
|
||||
protocol: protocols[0],
|
||||
port: 1883,
|
||||
tls: false,
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import * as React from 'react'
|
||||
import { Snackbar, SnackbarContent } from '@material-ui/core'
|
||||
import { red, green } from '@material-ui/core/colors'
|
||||
import { withStyles, Theme } from '@material-ui/core/styles'
|
||||
|
||||
enum MessageType {
|
||||
success = 'success',
|
||||
error = 'error',
|
||||
}
|
||||
|
||||
interface Props {
|
||||
message: string
|
||||
type: MessageType
|
||||
onClose: () => void
|
||||
classes: any
|
||||
}
|
||||
|
||||
interface State {
|
||||
snackBarOpen: boolean
|
||||
}
|
||||
|
||||
class Notification extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = { snackBarOpen: false }
|
||||
}
|
||||
|
||||
public static styles = (theme: Theme) => ({
|
||||
success: {
|
||||
backgroundColor: green[600],
|
||||
color: theme.typography.button.color,
|
||||
},
|
||||
error: {
|
||||
backgroundColor: red[600],
|
||||
color: theme.typography.button.color,
|
||||
},
|
||||
})
|
||||
|
||||
public render() {
|
||||
return <Snackbar
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
open={this.state.snackBarOpen}
|
||||
autoHideDuration={6000}
|
||||
onClose={() => { this.setState({ snackBarOpen: false }) }}
|
||||
>
|
||||
<SnackbarContent
|
||||
className={this.props.classes[this.props.type]}
|
||||
message={this.props.message}
|
||||
/>
|
||||
</Snackbar>
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(Notification.styles)(Notification)
|
||||
@@ -1,23 +1,23 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
|
||||
import Drawer from '@material-ui/core/Drawer'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Divider from '@material-ui/core/Divider'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import Select from '@material-ui/core/Select'
|
||||
import { AppState, NodeOrder } from '../reducers'
|
||||
import {
|
||||
Divider,
|
||||
Drawer,
|
||||
IconButton,
|
||||
Input,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
Typography,
|
||||
} from '@material-ui/core'
|
||||
import { StyleRulesCallback, withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import ChevronRight from '@material-ui/icons/ChevronRight'
|
||||
|
||||
import { Typography, InputBase, Input, InputLabel } from '@material-ui/core'
|
||||
import { withStyles, StyleRulesCallback } from '@material-ui/core/styles'
|
||||
|
||||
import { settingsActions } from '../actions'
|
||||
import { AppState, NodeOrder } from '../reducers'
|
||||
|
||||
import { connect } from 'react-redux'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { settingsActions } from '../actions'
|
||||
|
||||
const styles: StyleRulesCallback = theme => ({
|
||||
drawer: {
|
||||
@@ -85,7 +85,6 @@ class Settings extends React.Component<Props, {}> {
|
||||
|
||||
private renderAutoExpand() {
|
||||
const { classes, autoExpandLimit } = this.props
|
||||
|
||||
return (
|
||||
<div style={{ padding: '8px' }}>
|
||||
<InputLabel htmlFor="auto-expand">Auto Expand</InputLabel>
|
||||
@@ -93,11 +92,10 @@ class Settings extends React.Component<Props, {}> {
|
||||
value={autoExpandLimit}
|
||||
onChange={this.onChangeAutoExpand}
|
||||
input={<Input name="auto-expand" id="auto-expand-label-placeholder" />}
|
||||
displayEmpty={true}
|
||||
name="auto-expand"
|
||||
className={classes.input}
|
||||
>
|
||||
<MenuItem value={0}><em>Disabled</em></MenuItem>
|
||||
<MenuItem value={0}><em>Collapsed</em></MenuItem>
|
||||
<MenuItem value={2}>Few</MenuItem>
|
||||
<MenuItem value={3}>Some</MenuItem>
|
||||
<MenuItem value={10}>Most</MenuItem>
|
||||
|
||||
@@ -124,9 +124,6 @@ class Publish extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
private editorOptions = {
|
||||
enableBasicAutocompletion: true,
|
||||
enableLiveAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
showLineNumbers: false,
|
||||
tabSize: 2,
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import * as React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
|
||||
import { AppBar, IconButton, InputBase, Toolbar, Typography } from '@material-ui/core'
|
||||
import Search from '@material-ui/icons/Search'
|
||||
import Menu from '@material-ui/icons/Menu'
|
||||
import { withStyles, StyleRulesCallback } from '@material-ui/core/styles'
|
||||
import { fade } from '@material-ui/core/styles/colorManipulator'
|
||||
import { StyleRulesCallback, withStyles } from '@material-ui/core/styles'
|
||||
|
||||
import Menu from '@material-ui/icons/Menu'
|
||||
import Search from '@material-ui/icons/Search'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { fade } from '@material-ui/core/styles/colorManipulator'
|
||||
import { settingsActions } from '../actions'
|
||||
|
||||
const styles: StyleRulesCallback = theme => ({
|
||||
@@ -92,7 +92,7 @@ class TitleBar extends React.Component<Props, State> {
|
||||
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.props.actions.toggleSettingsVisibility}>
|
||||
<Menu />
|
||||
</IconButton>
|
||||
<Typography className={classes.title} variant="h6" color="inherit">MQTT-Xplorer</Typography>
|
||||
<Typography className={classes.title} variant="h6" color="inherit">MQTT-Explorer</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import * as React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import { Typography } from '@material-ui/core'
|
||||
import TreeNode from './TreeNode'
|
||||
|
||||
import { makeConnectionMessageEvent, rendererEvents } from '../../../../events'
|
||||
|
||||
import { AppState } from '../../reducers'
|
||||
import TreeNode from './TreeNode'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
const MovingAverage = require('moving-average')
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import * as React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import { withTheme, Theme } from '@material-ui/core/styles'
|
||||
|
||||
import { AppState, NodeOrder } from '../../reducers'
|
||||
import { Theme, withTheme } from '@material-ui/core/styles'
|
||||
|
||||
import TreeNode from './TreeNode'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
export interface Props {
|
||||
lastUpdate: number
|
||||
@@ -63,7 +64,7 @@ class TreeNodeSubnodes extends React.Component<Props, {}> {
|
||||
|
||||
return (
|
||||
<span style={{ display: 'block', clear: 'both' }} >
|
||||
{this.props.collapsed ? null : listItems}
|
||||
{listItems}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
+14
-3
@@ -1,10 +1,14 @@
|
||||
import './tracking'
|
||||
|
||||
import * as React from 'react'
|
||||
import * as ReactDOM from 'react-dom'
|
||||
|
||||
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'
|
||||
import reducers, { AppState, NodeOrder } from './reducers'
|
||||
|
||||
import App from './App'
|
||||
import { Provider } from 'react-redux'
|
||||
import { createStore } from 'redux'
|
||||
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'
|
||||
import reducers, { NodeOrder, AppState } from './reducers'
|
||||
import App from './App'
|
||||
|
||||
const initialAppState: AppState = {
|
||||
settings: {
|
||||
@@ -14,6 +18,7 @@ const initialAppState: AppState = {
|
||||
},
|
||||
sidebar: {},
|
||||
selectedTopic: undefined,
|
||||
showUpdateDetails: false,
|
||||
}
|
||||
const store = createStore(reducers, initialAppState)
|
||||
|
||||
@@ -24,6 +29,12 @@ const theme = createMuiTheme({
|
||||
typography: { useNextVariants: true },
|
||||
})
|
||||
|
||||
const splash = document.getElementById('splash')
|
||||
if (splash) {
|
||||
splash.style.animation = 'unsplash 1s ease-out 0s 1 normal forwards'
|
||||
setTimeout(() => splash.remove(), 1100)
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<MuiThemeProvider theme={theme}>
|
||||
<Provider store={store}>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Reducer, Action } from 'redux'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
|
||||
import { Action, Reducer } from 'redux'
|
||||
|
||||
import { trackEvent } from '../tracking'
|
||||
|
||||
export enum ActionTypes {
|
||||
setAutoExpandLimit = 'SET_AUTO_EXPAND_LIMIT',
|
||||
toggleSettingsVisibility = 'TOGGLE_SETTINGS_VISIBILITY',
|
||||
@@ -8,6 +11,8 @@ export enum ActionTypes {
|
||||
selectTopic = 'SELECT_TOPIC',
|
||||
setPublishTopic = 'SET_PUBLISH_TOPIC',
|
||||
setPublishPayload = 'SET_PUBLISH_PAYLOAD',
|
||||
showUpdateNotification = 'SHOW_UPDATE_NOTIFICATION',
|
||||
showUpdateDetails = 'SHOW_UPDATE_DETAILS',
|
||||
}
|
||||
|
||||
export interface CustomAction extends Action {
|
||||
@@ -17,6 +22,8 @@ export interface CustomAction extends Action {
|
||||
selectedTopic?: q.TreeNode
|
||||
publishTopic?: string
|
||||
publishPayload?: string
|
||||
showUpdateNotification?: boolean
|
||||
showUpdateDetails?: boolean
|
||||
}
|
||||
|
||||
export interface SidebarState {
|
||||
@@ -28,6 +35,8 @@ export interface AppState {
|
||||
settings: SettingsState,
|
||||
selectedTopic?: q.TreeNode
|
||||
sidebar: SidebarState
|
||||
showUpdateNotification?: boolean
|
||||
showUpdateDetails: boolean
|
||||
}
|
||||
|
||||
export interface SettingsState {
|
||||
@@ -47,11 +56,11 @@ const reducer: Reducer<AppState | undefined, CustomAction> = (state, action) =>
|
||||
if (!state) {
|
||||
throw Error('No initial state')
|
||||
}
|
||||
console.log(action)
|
||||
|
||||
trackEvent(action.type)
|
||||
console.log(action, state)
|
||||
switch (action.type) {
|
||||
case ActionTypes.setAutoExpandLimit:
|
||||
if (!action.autoExpandLimit) {
|
||||
if (action.autoExpandLimit === undefined) {
|
||||
return state
|
||||
}
|
||||
return {
|
||||
@@ -62,7 +71,6 @@ const reducer: Reducer<AppState | undefined, CustomAction> = (state, action) =>
|
||||
},
|
||||
}
|
||||
case ActionTypes.setPublishTopic:
|
||||
console.log(state)
|
||||
return {
|
||||
...state,
|
||||
sidebar: { ...state.sidebar, publishTopic: action.publishTopic },
|
||||
@@ -94,7 +102,20 @@ const reducer: Reducer<AppState | undefined, CustomAction> = (state, action) =>
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
settings: { ...state.settings, autoExpandLimit: state.settings.autoExpandLimit },
|
||||
settings: { ...state.settings, nodeOrder: action.nodeOrder },
|
||||
}
|
||||
case ActionTypes.showUpdateNotification:
|
||||
return {
|
||||
...state,
|
||||
showUpdateNotification: action.showUpdateNotification,
|
||||
}
|
||||
case ActionTypes.showUpdateDetails:
|
||||
if (action.showUpdateDetails === undefined) {
|
||||
return state
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
showUpdateDetails: action.showUpdateDetails,
|
||||
}
|
||||
default:
|
||||
return state
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
let userId = window.localStorage.getItem('userId')
|
||||
const sha1 = require('sha1')
|
||||
|
||||
if (!userId) {
|
||||
userId = sha1(sha1(Math.random()) + sha1(performance.now()) + sha1(Date.now())).slice(0, 8) as string
|
||||
window.localStorage.setItem('userId', userId)
|
||||
}
|
||||
|
||||
const Nucleus = require('electron-nucleus')('5c3b3e0443b7cc00eec3782b', {
|
||||
userId,
|
||||
disableInDev: true,
|
||||
})
|
||||
|
||||
export default Nucleus
|
||||
|
||||
export function trackEvent(name: string) {
|
||||
if (name.match(/^@@redux/)) {
|
||||
return
|
||||
}
|
||||
Nucleus.track(name)
|
||||
}
|
||||
+28
-7
@@ -1,11 +1,21 @@
|
||||
import {
|
||||
addMqttConnectionEvent, backendEvents,
|
||||
makeConnectionStateEvent, removeConnection,
|
||||
makeConnectionMessageEvent, makePublishEvent, AddMqttConnection, Message,
|
||||
AddMqttConnection,
|
||||
EventDispatcher,
|
||||
Message,
|
||||
addMqttConnectionEvent,
|
||||
backendEvents,
|
||||
checkForUpdates,
|
||||
makeConnectionMessageEvent,
|
||||
makeConnectionStateEvent,
|
||||
makePublishEvent,
|
||||
removeConnection,
|
||||
updateAvailable,
|
||||
} from '../../events'
|
||||
import { MqttSource, DataSource } from './DataSource'
|
||||
import { DataSource, MqttSource } from './DataSource'
|
||||
|
||||
class ConnectionManager {
|
||||
import { UpdateInfo } from 'builder-util-runtime'
|
||||
|
||||
export class ConnectionManager {
|
||||
private connections: {[s: string]: DataSource<any>} = {}
|
||||
|
||||
public manageConnections() {
|
||||
@@ -49,5 +59,16 @@ class ConnectionManager {
|
||||
}
|
||||
}
|
||||
|
||||
const connectionManager = new ConnectionManager()
|
||||
connectionManager.manageConnections()
|
||||
class UpdateNotifier {
|
||||
public onCheckUpdateRequest = new EventDispatcher<void, UpdateNotifier>(this)
|
||||
constructor() {
|
||||
backendEvents.subscribe(checkForUpdates, () => {
|
||||
this.onCheckUpdateRequest.dispatch()
|
||||
})
|
||||
}
|
||||
public notify(updateInfo: UpdateInfo) {
|
||||
backendEvents.emit(updateAvailable, updateInfo)
|
||||
}
|
||||
}
|
||||
|
||||
export const updateNotifier = new UpdateNotifier()
|
||||
|
||||
+24
-12
@@ -1,17 +1,15 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const { autoUpdater } = require("electron-updater")
|
||||
const log = require('electron-log');
|
||||
const { ConnectionManager, updateNotifier } = require('./backend/build/backend/src/index.js')
|
||||
|
||||
autoUpdater.logger = log;
|
||||
autoUpdater.logger.transports.file.level = 'info';
|
||||
log.info('App starting...');
|
||||
|
||||
// Modules to control application life and create native browser window
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
try {
|
||||
require('./backend/build/backend/src/index.js')
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
const connectionManager = new ConnectionManager()
|
||||
connectionManager.manageConnections()
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
@@ -47,11 +45,25 @@ function createWindow () {
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.on('ready', () => {
|
||||
createWindow()
|
||||
try {
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
let updateInfo
|
||||
autoUpdater.on('update-available', (info) => {
|
||||
updateInfo = info
|
||||
})
|
||||
|
||||
autoUpdater.on('error', () => {
|
||||
if (updateInfo) {
|
||||
updateNotifier.notify(updateInfo)
|
||||
}
|
||||
})
|
||||
|
||||
updateNotifier.onCheckUpdateRequest.subscribe(() => {
|
||||
try {
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed.
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
import { IpcMain, IpcRenderer, ipcMain, ipcRenderer } from 'electron'
|
||||
|
||||
import { Event } from './Events'
|
||||
import { ipcMain, ipcRenderer, IpcRenderer, IpcMain } from 'electron'
|
||||
|
||||
interface EventBusInterface {
|
||||
subscribe<MessageType>(event: Event<MessageType>, callback:(msg: MessageType) => void): void
|
||||
|
||||
+13
-1
@@ -1,4 +1,8 @@
|
||||
import { MqttOptions, DataSourceState } from '../backend/src/DataSource'
|
||||
import { DataSourceState, MqttOptions } from '../backend/src/DataSource'
|
||||
|
||||
import { UpdateInfo } from 'builder-util-runtime'
|
||||
|
||||
export { UpdateInfo } from 'builder-util-runtime'
|
||||
|
||||
export interface Event<MessageType> {
|
||||
topic: string
|
||||
@@ -23,6 +27,14 @@ export function makeConnectionStateEvent(connectionId: string): Event<DataSource
|
||||
}
|
||||
}
|
||||
|
||||
export const checkForUpdates: Event<void> = {
|
||||
topic: 'app/update/check',
|
||||
}
|
||||
|
||||
export const updateAvailable: Event<UpdateInfo> = {
|
||||
topic: 'app/update/available',
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
topic: string,
|
||||
payload: any
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "MQTT-Explorer",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"description": "Explore your message queues",
|
||||
"main": "electron.js",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user