Merge pull request #49 from sensebox/add-tour

Add tour
This commit is contained in:
Mario Pesch 2020-12-18 09:17:54 +01:00 committed by GitHub
commit ad1e5f1b82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 693 additions and 61 deletions

93
NEWS.md Normal file
View File

@ -0,0 +1,93 @@
# Blockly 2020
(aktuelles Preview unter: https://deploy-preview-37--blockly-react.netlify.app/)
In den letzten Wochen haben wir eine komplett neue Lern- und Programmierumgebung für die senseBox geschaffen. Die Basis bildet hierbei weiterhin Google Blockly und das Frontend wird über React realisiert. Fast alle Blöcke wurden bereits aus der alten Version in die neue Version migriert.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_880bb55f28e0dbb0bb9c2160d8e50594.png)
## Blockly Core
Nachdem die bisherige Version, die unter [blockly.sensebox.de](https://blockly.sensebox.de) verfügbar ist, auf einen Google Blockly Core von 2016 aufbaut, wurde es Zeit ein großes Update durchzuführen. Durch den neuen Blockly Core lassen sich auch andere Renderer der Blöcke verwenden. In den Einstellungen kannst du zwischen den zwei Renderern Geras und Zelos auswählen. Geras ist der klassische Blockly Renderer während Zelos vor allem für Touchoberfläche optimiert worden ist.
### Typed Variablen
Neue Variablen werden nun direkt mit einem bestimmten Datentyp angelegt. Ein einfacher Check überprüft ob der zurückgegeben Typ eines Blockes mit dem der Variablen kompatibel ist.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_0d505fc2472178182995732af226e736.png)
### Funktionen (funktioniert aktuell nicht!)
Funktionen mit Rückgabe Wert und Eingabeparametern können angelegt werden. Durch die Verwendung von Funktionen lassen sich auch komplexere Programme übersichtlicher darstellen und bearbeiten. Beim Anlegen einer Funktion kann über das Zahnrad weitere Eingabeparameter hinzuefügt werden.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_bd9544b118a1dbe83d149c00678eb39d.png)
### GPS
Der Code für das GPS Modul wurde neu aufgebaut und ermöglicht es deutlich schneller einen GPS Fix zu bekommen. Zusätzlich lassen sich bald! die Koordinaten in zwei verschiedenen Formaten zurückgebenlassen. Zum einen als Kommazahl zum anderen als Zahl ohne nachkommastellen
### MQTT
Zwei einfache Blöcke ermöglichen es nun die Daten über MQTT an einen Broker zu versenden. Zwei Broker sind bereits "vorprogrammiert" (Adafruit IO und DIOTY). Natürlich können auch eigene Broker verwendet werden. Falls ihr gute freie Broker kennt, die wir hinzufügen sollten meldet euch einfach bei uns.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_a9df4b0b9b1e6f39f09cf3b1743caad2.png)
### TTN Mapper
Bisher war es möglich einen "kleinen" TTN Mapper zu bauen, der die Daten als Cayenne Payload versendet hat. Es gibt nun einen Block der es direkt ermöglicht einen vollständigen TTN Mapper zu Programmieren, der die Daten auch auf [TTNMapper](https://ttnmapper.org/) veröffentlichen kann.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_b59691f2ebcf04d8b67a5f4e7fbe70b6.png)
## Fronted
In der Oberfläche gibt es einige Neuigkeiten. Ziel ist es Blockly für die senseBox zu einer vollständigen Lern- und Programmierumgebung weiterzuentwickeln.
Die Codeanzeige ist standardmäßig ausgeblendet kann aber einfach durch eine Klick auf das `</>` Icon hinzugefügt werden.
### Login mit openSenseMap/senseBox Account
Im Menü unter Login könnt ihr euch mit eurem openSenseMap Account anmelden. Sobald ihr angemeldet seid habt ihr die Möglichkeit Projekte online zu speichern.
Sobald der Login mit dem openSenseMap Account erfolgreich war lassen sich die bereits registrierten senseBox unter Account einsehen.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_c3965edc99021339a30b8d6704471e50.png)
Im Block zum senden an die openSenseMap müssen dann auch keine IDs mehr ausgewählt werden sondern die registrierten senseBox können einfach aus dem Dropdown Menü ausgewählt werden.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_57284cea57bfa5df3d55fe456f9d7cfa.png)
### Speichern von Projekten
Nach dem Login über den openSenseMap Account lassen sich Projekte online speichern und wieder abrufen
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_148146b1206fde184afff6edce26b515.png)
### Tutorials
Es gibt jetzt Tutorials! Eine reihe von verschiedenen Tutorials zeigt dir die ersten Schritte in der Programmierung mit Blockly. (Inhalte werden noch ausgebaut)
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_db0e64df48d4c34a9540ffb089e95769.png)
### Gallery
In der Gallery finden sich Beispiele mit verschiedenen Programmen. Die Beispiele können direkt in Blockly geöffnet werden, um Änderungen vorzunehmen oder das Programm direkt auf deine senseBox zu übertragen.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_c61e1fa98f9d840507a8a53b00605484.png)
### Teilen von Programmen
Über den Share Button kann ein Link zum Teilen der aktuellen Blöcke erstellt werden. Wann immer du dein Projekt mit anderen Teilen willst musst du nicht mehr eine XML Datei erstellen und verschicken sondern kannst einen Link erstellen, der direkt zu deinem Programm führt. Beachte, dass vor dem Teilen von Blöcken sämtliche sensiblen Daten, wie zum Beispiel Passwörter, Netzwerknamen, Lora oder openSenseMap Keys entfernt werden sollten. Die Links zum teilen von Programmen laufen nach 30 Tagen ab.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_a8dba6720fe2fb39cadf129d9bb04a62.png)
## Fehler
Falls ihr Fehler findet legt bitte ein Issue in folgendem Repository an: https://github.com/sensebox/React-Ardublockly/issues

205
package-lock.json generated
View File

@ -1143,6 +1143,24 @@
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
},
"@emotion/is-prop-valid": {
"version": "0.8.8",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
"integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
"requires": {
"@emotion/memoize": "0.7.4"
}
},
"@emotion/memoize": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
},
"@emotion/unitless": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
},
"@fortawesome/fontawesome-common-types": {
"version": "0.2.30",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.30.tgz",
@ -1479,6 +1497,11 @@
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw=="
},
"@rooks/use-mutation-observer": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/@rooks/use-mutation-observer/-/use-mutation-observer-3.4.0.tgz",
"integrity": "sha512-q10+v3WbvSt5fj55VMikTPaUZ9Yl+IYDsymodWr2+cKx0PD97VBeWYjk3xHJPqJgejBHwnrwiNkJKGFY5iW+WQ=="
},
"@sheerun/mutationobserver-shim": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
@ -2786,6 +2809,22 @@
"resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz",
"integrity": "sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA=="
},
"babel-plugin-styled-components": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz",
"integrity": "sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA==",
"requires": {
"@babel/helper-annotate-as-pure": "^7.0.0",
"@babel/helper-module-imports": "^7.0.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"lodash": "^4.17.11"
}
},
"babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
},
"babel-plugin-syntax-object-rest-spread": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
@ -3553,6 +3592,11 @@
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"camelize": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
},
"caniuse-api": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
@ -3725,6 +3769,11 @@
}
}
},
"classnames": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
},
"clean-css": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
@ -4216,6 +4265,11 @@
"postcss": "^7.0.5"
}
},
"css-color-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
"integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
},
"css-color-names": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
@ -4306,6 +4360,23 @@
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
},
"css-to-react-native": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz",
"integrity": "sha512-VOFaeZA053BqvvvqIA8c9n0+9vFppVBAHCp6JgFTtTMU3Mzi+XnelJ9XC9ul3BqFzZyQ5N+H0SnwsWT2Ebchxw==",
"requires": {
"camelize": "^1.0.0",
"css-color-keywords": "^1.0.0",
"postcss-value-parser": "^3.3.0"
},
"dependencies": {
"postcss-value-parser": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
}
}
},
"css-tree": {
"version": "1.0.0-alpha.37",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
@ -4698,6 +4769,11 @@
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw=="
},
"detect-node-es": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.0.0.tgz",
"integrity": "sha512-S4AHriUkTX9FoFvL4G8hXDcx6t3gp2HpfCza3Q0v6S78gul2hKWifLQbeW+ZF89+hSm2ZIc/uF3J97ZgytgTRg=="
},
"detect-port-alt": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz",
@ -6138,6 +6214,16 @@
}
}
},
"focus-lock": {
"version": "0.6.8",
"resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.6.8.tgz",
"integrity": "sha512-vkHTluRCoq9FcsrldC0ulQHiyBYgVJB2CX53I8r0nTC6KnEij7Of0jpBspjt3/CuNb6fyoj3aOh9J2HgQUM0og=="
},
"focus-outline-manager": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/focus-outline-manager/-/focus-outline-manager-1.0.2.tgz",
"integrity": "sha1-e/NliGU0H7awjQQqA3udKGixGbU="
},
"follow-redirects": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.12.1.tgz",
@ -7387,6 +7473,11 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"is-what": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-3.12.0.tgz",
"integrity": "sha512-2ilQz5/f/o9V7WRWJQmpFYNmQFZ9iM+OXRonZKcYgTkCzjb949Vi4h282PD1UfmgHk666rcWonbRJ++KI41VGw=="
},
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@ -8413,11 +8504,21 @@
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
},
"lodash.pick": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
"integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM="
},
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@ -8590,6 +8691,11 @@
"p-is-promise": "^2.0.0"
}
},
"memoize-one": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
"integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
},
"memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@ -8623,6 +8729,14 @@
}
}
},
"merge-anything": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-2.4.4.tgz",
"integrity": "sha512-l5XlriUDJKQT12bH+rVhAHjwIuXWdAIecGwsYjv2LJo+dA1AeRTmeQS+3QBpO6lEthBMDi2IUMpLC1yyRvGlwQ==",
"requires": {
"is-what": "^3.3.1"
}
},
"merge-deep": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.2.tgz",
@ -10971,6 +11085,14 @@
"whatwg-fetch": "^3.0.0"
}
},
"react-clientside-effect": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz",
"integrity": "sha512-nRmoyxeok5PBO6ytPvSjKp9xwXg9xagoTK1mMjwnQxqM9Hd7MNPl+LS1bOSOe+CV2+4fnEquc7H/S8QD3q697A==",
"requires": {
"@babel/runtime": "^7.0.0"
}
},
"react-cookie-consent": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-cookie-consent/-/react-cookie-consent-5.2.0.tgz",
@ -11196,6 +11318,19 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.7.tgz",
"integrity": "sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA=="
},
"react-focus-lock": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.2.1.tgz",
"integrity": "sha512-47g0xYcCTZccdzKRGufepY8oZ3W1Qg+2hn6u9SHZ0zUB6uz/4K4xJe7yYFNZ1qT6m+2JDm82F6QgKeBTbjW4PQ==",
"requires": {
"@babel/runtime": "^7.0.0",
"focus-lock": "^0.6.6",
"prop-types": "^15.6.2",
"react-clientside-effect": "^1.2.2",
"use-callback-ref": "^1.2.1",
"use-sidecar": "^1.0.1"
}
},
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@ -11347,6 +11482,22 @@
"prop-types": "^15.6.2"
}
},
"reactour": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/reactour/-/reactour-1.18.0.tgz",
"integrity": "sha512-de0Pa5NkDU6I8IyGl+7+rWdDcx3AskmJYK/yIKU11D9EPIN79qzn852gjJgvH/jXZqeEfa+rmMWg72vA0UkmgA==",
"requires": {
"@rooks/use-mutation-observer": "3.4.0",
"classnames": "2.2.6",
"focus-outline-manager": "^1.0.2",
"lodash.debounce": "4.0.8",
"lodash.pick": "4.4.0",
"prop-types": "15.7.2",
"react-focus-lock": "2.2.1",
"scroll-smooth": "1.1.0",
"scrollparent": "2.0.1"
}
},
"read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@ -11959,6 +12110,16 @@
"ajv-keywords": "^3.4.1"
}
},
"scroll-smooth": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/scroll-smooth/-/scroll-smooth-1.1.0.tgz",
"integrity": "sha512-68OUOXKN/ykM/Dbp4Lhza3O9QQUuW/c01WTsZzDOUyVgb1I5QjT/awOHCCbuYTSV1QnExUQ9w+KcxmVxlXIiAg=="
},
"scrollparent": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.0.1.tgz",
"integrity": "sha1-cV1bnMV3YPsivczDvvtb/gaxoxc="
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
@ -12842,6 +13003,26 @@
}
}
},
"styled-components": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz",
"integrity": "sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g==",
"requires": {
"@babel/helper-module-imports": "^7.0.0",
"@babel/traverse": "^7.0.0",
"@emotion/is-prop-valid": "^0.8.1",
"@emotion/unitless": "^0.7.0",
"babel-plugin-styled-components": ">= 1",
"css-to-react-native": "^2.2.2",
"memoize-one": "^5.0.0",
"merge-anything": "^2.2.4",
"prop-types": "^15.5.4",
"react-is": "^16.6.0",
"stylis": "^3.5.0",
"stylis-rule-sheet": "^0.0.10",
"supports-color": "^5.5.0"
}
},
"stylehacks": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",
@ -12864,6 +13045,16 @@
}
}
},
"stylis": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
"integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
},
"stylis-rule-sheet": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz",
"integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@ -13536,6 +13727,20 @@
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
},
"use-callback-ref": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.4.tgz",
"integrity": "sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ=="
},
"use-sidecar": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.3.tgz",
"integrity": "sha512-ygJwGUBeQfWgDls7uTrlEDzJUUR67L8Rm14v/KfFtYCdHhtjHZx1Krb3DIQl3/Q5dJGfXLEQ02RY8BdNBv87SQ==",
"requires": {
"detect-node-es": "^1.0.0",
"tslib": "^1.9.3"
}
},
"util": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",

View File

@ -26,8 +26,10 @@
"react-redux": "^7.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1",
"reactour": "^1.18.0",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"styled-components": "^4.4.1",
"uuid": "^8.3.1"
},
"scripts": {

View File

@ -15,6 +15,14 @@
margin: auto;
}
.news img{
display: flex;
align-items: center;
max-height: 40vH;
max-width: 100%;
margin: auto;
}
.tutorial blockquote{
background: #f9f9f9;
border-left: 10px solid#4EAF47;

View File

@ -880,7 +880,7 @@ Blockly.Msg.messages_copylink_success = 'Link erfolgreich in Zwischenablage gesp
Blockly.Msg.messages_rename_success_01 = 'Das Projekt wurde erfolgreich in '
Blockly.Msg.messages_rename_success_02 = 'umbenannt.'
Blockly.Msg.messages_newblockly_head = "Willkommen zur neuen Version Blockly für die senseBox"
Blockly.Msg.messages_newblockly_text = "Die neue Blockly Version befindet sich zurzeit in der Testphase. Alle Neuigkeiten findet ihr hier:"
Blockly.Msg.messages_newblockly_text = "Die neue Blockly Version befindet sich zurzeit in der Testphase. Alle Neuigkeiten findet ihr hier: "
Blockly.Msg.messages_GET_TUTORIAL_FAIL = 'Zurück zur Tutorials-Übersicht'
Blockly.Msg.messages_LOGIN_FAIL = 'Der Benutzername oder das Passwort ist nicht korrekt.'
/**
@ -1024,4 +1024,27 @@ Blockly.Msg.codeviewer_arduino = "Arduino Quellcode"
Blockly.Msg.codeviewer_xml = "XML Blöcke"
/**
* Home Tour
*/
Blockly.Msg.hometour_wrapper = "Willkommen zu Blockly für die senseBox. In dieser Tour werde ich dir alle wichtigen Funktionen der Oberfläche zeigen"
Blockly.Msg.hometour_workspaceFunc = "Hier findest du alle Buttons um dein Programm zu übertragen, zu speichern oder zu teilen"
Blockly.Msg.hometour_blocklyWindow = "Dies ist deine Arbeitsfläche. Hier kannst du mithilfe der Blöcke deinen Programmcode erstellen"
Blockly.Msg.hometour_blocklyToolboxDiv = "In der Toolbox befinden sich alle Blöcke. Verbinde diese in der Arbeitsfläche und erstelle dein Programmcode"
Blockly.Msg.hometour_compileBlocks = "Wenn du fertig mit dem Programmieren bist und deinen Programmcode auf die senseBox übertragen möchtest klicke hier um deinen Programmcode zu kompilieren."
Blockly.Msg.hometour_menuButton = "Im Menü findest du Tutorials und eine Gallery mit verschiedenen Beispiel Programmen. Logge dich über deinen openSenseMap Account ein und du erhälst noch mehr Funktionen"
Blockly.Msg.hometour_showCode = "Über diesen Button kannst du dir den generierten Programmcode anzeigen lassen"
Blockly.Msg.hometour_shareBlocks = "Erstelle über diesen Button einen Kurzlink und teile deine Blöcke mit anderen Nutzer:innen"
/**
* Assessment Tour
*/
Blockly.Msg.assessmenttour_solutionCheck = "Wenn deine Lösung fertig ist klicke hier um diese zu überprüfen"
Blockly.Msg.assessmenttour_assessmentDiv = "Los gehts! Löse die folgende Aufgabe, um das Tutorial abzuschließen. "
Blockly.Msg.assessmenttour_injectionDiv = "Erstelle hier deine Lösung. Du kannst alle Blöcke aus der Toolbox verwenden."
export const De = Blockly.Msg;

View File

@ -847,7 +847,7 @@ Blockly.Msg.messages_copylink_success = 'Link successfully saved to clipboard.'
Blockly.Msg.messages_rename_success_01 = 'The project was successfully saved to '
Blockly.Msg.messages_rename_success_02 = 'renamed.'
Blockly.Msg.messages_newblockly_head = 'Welcome to the new version Blockly for the senseBox'
Blockly.Msg.messages_newblockly_text = "The new Blockly version is currently in testing. You can find all the news here:"
Blockly.Msg.messages_newblockly_text = "The new Blockly version is currently in testing. You can find all the news here: "
Blockly.Msg.messages_GET_TUTORIAL_FAIL = 'Back to tutorials overview'
Blockly.Msg.messages_LOGIN_FAIL = 'The username or password is incorrect.'
Blockly.Msg.messages_login_error = "Enter both a username and a password."
@ -987,4 +987,27 @@ Blockly.Msg.navbar_settings = "Settings"
Blockly.Msg.codeviewer_arduino = "Arduino Source Code"
Blockly.Msg.codeviewer_xml = "XML Blocks"
/**
* Home Tour
*/
Blockly.Msg.hometour_wrapper = "Welcome to the new Learn- and Programmingapp for the senseBox. In this tour I will show you all the important features of the interface"
Blockly.Msg.hometour_workspaceFunc = "Here you will find all the buttons to compile, save or share your program"
Blockly.Msg.hometour_blocklyWindow = "This is your workspace. Here you can use the blocks to create your program code"
Blockly.Msg.hometour_blocklyToolboxDiv = "The toolbox contains all the blocks. Connect them in the workspace and create your program code."
Blockly.Msg.hometour_compileBlocks = "When you are done programming and want to transfer your program code to the senseBox click here to compile your program code."
Blockly.Msg.hometour_menuButton = "In the menu you will find tutorials and a gallery with different example programs. Log in with your openSenseMap account and you will get even more features."
Blockly.Msg.hometour_showCode = "With this button you can show the generated program code"
Blockly.Msg.hometour_shareBlocks = "Use this button to create a short link and share your blocks with other users"
/**
* Assessment Tour
*/
Blockly.Msg.assessmenttour_solutionCheck = "When your solution is ready click here to check it"
Blockly.Msg.assessmenttour_assessmentDiv = "Let's go! Solve the following task to complete the tutorial. "
Blockly.Msg.assessmenttour_injectionDiv = "Create your solution here. You can use any blocks from the toolbox."
export const En = Blockly.Msg;

View File

@ -14,6 +14,8 @@ class Footer extends Component {
<Typography style={{ margin: '0px 10px 0px 10px', display: 'initial', fontSize: '1rem' }}>|</Typography>
<Link to={"/privacy"} style={{ textDecoration: 'none', color: 'inherit' }}>Privacy</Link>
<Typography style={{ margin: '0px 10px 0px 10px', display: 'initial', fontSize: '1rem' }}>|</Typography>
<Link to={"/news"} style={{ textDecoration: 'none', color: 'inherit' }}>News</Link>
<Typography style={{ margin: '0px 10px 0px 10px', display: 'initial', fontSize: '1rem' }}>|</Typography>
<a href="https://sensebox.de" style={{ textDecoration: 'none', color: 'inherit' }}>sensebox.de</a>
</div>
</div>

View File

@ -56,10 +56,10 @@ class Home extends Component {
componentDidMount() {
this.setState({ stats: window.localStorage.getItem('stats') });
if(!this.props.project){
if (!this.props.project) {
this.props.workspaceName(createNameId());
}
if(this.props.message && this.props.message.id === 'GET_SHARE_FAIL'){
if (this.props.message && this.props.message.id === 'GET_SHARE_FAIL') {
this.setState({ snackbar: true, key: Date.now(), message: `Das angefragte geteilte Projekt konnte nicht gefunden werden.`, type: 'error' });
}
}
@ -94,14 +94,14 @@ class Home extends Component {
<div style={{ float: 'left', height: '40px', position: 'relative' }}><WorkspaceStats /></div>
: null
}
<div style={{ float: 'right', height: '40px', marginBottom: '20px' }}>
<WorkspaceFunc project={this.props.project} projectType={this.props.projectType}/>
<div className='workspaceFunc' style={{ float: 'right', height: '40px', marginBottom: '20px' }}>
<WorkspaceFunc project={this.props.project} projectType={this.props.projectType} />
</div>
<Grid container spacing={2}>
<Grid item xs={12} md={this.state.codeOn ? 8 : 12} style={{ position: 'relative' }}>
<Tooltip title={this.state.codeOn ? 'Code ausblenden' : 'Code anzeigen'} >
<IconButton
className={this.state.codeOn ? this.props.classes.codeOn : this.props.classes.codeOff}
className={`showCode ${this.state.codeOn ? this.props.classes.codeOn : this.props.classes.codeOff}`}
style={{ width: '40px', height: '40px', position: 'absolute', top: -12, right: 8, zIndex: 21 }}
onClick={() => this.onChange()}
>
@ -109,16 +109,18 @@ class Home extends Component {
</IconButton>
</Tooltip>
<TrashcanButtons />
{this.props.project ?
< BlocklyWindow blocklyCSS={{ height: '80vH' }} initialXml={this.props.project.xml} />
: < BlocklyWindow blocklyCSS={{ height: '80vH' }} />
}
<div className='blocklyWindow'>
{this.props.project ?
< BlocklyWindow blocklyCSS={{ height: '80vH' }} initialXml={this.props.project.xml} />
: < BlocklyWindow blocklyCSS={{ height: '80vH' }} />
}
</div>
</Grid>
{this.state.codeOn ?
<Grid item xs={12} md={4}>
<CodeViewer />
</Grid>
: null}
: null}
</Grid>
<HintTutorialExists />
<Snackbar

View File

@ -1,13 +1,14 @@
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import Container from '@material-ui/core/Container';
class Impressum extends Component {
render() {
return (
<div style={{ margin: '0px 24px 0px 24px' }}>
<h1>Impressum</h1>
<Container fixed>
<div style={{ margin: '0px 24px 0px 24px' }}>
<h1>Impressum</h1>
<h2>Angaben gemäß § 5 TMG:</h2>
<h2>Angaben gemäß § 5 TMG:</h2>
Institut für Geoinformatik<br />
Heisenbergstraße 2<br />
Geo 1<br />
@ -16,7 +17,7 @@ class Impressum extends Component {
<h2>Kontakt:</h2>
E-Mail: <a href="mailto:info@mybadges.org!">info@mybadges.org</a>
<h2>Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV:</h2>
<h2>Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV:</h2>
Geschäftsführende Direktorin Prof. Dr. Angela Schwering<br />
Heisenbergstraße 2<br />
Geo 1<br />
@ -25,21 +26,22 @@ class Impressum extends Component {
<h2>Streitschlichtung</h2>
Die Europäische Kommission stellt eine Plattform zur Online-Streitbeilegung (OS) bereit: <a href="https://ec.europa.eu/consumers/odr" target="_blank" rel="noopener noreferrer">https://ec.europa.eu/consumers/odr</a>.<br />
Unsere E-Mail-Adresse finden Sie oben im Impressum.<br />
<p>Wir sind nicht bereit oder verpflichtet, an Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle teilzunehmen.</p>
<p>Wir sind nicht bereit oder verpflichtet, an Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle teilzunehmen.</p>
<h3>Haftung für Inhalte</h3>
<h3>Haftung für Inhalte</h3>
Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.
<p>Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.</p>
<h3>Haftung für Links</h3>
<h3>Haftung für Links</h3>
Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar.
<p>Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.</p>
<h3>Urheberrecht</h3>
<h3>Urheberrecht</h3>
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet.
<p>Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.</p>
</div>
</div>
</Container>
);
};
}

View File

@ -20,10 +20,12 @@ import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import LinearProgress from '@material-ui/core/LinearProgress';
import { faBars, faChevronLeft, faLayerGroup, faSignInAlt, faSignOutAlt, faCertificate, faUserCircle, faCog, faChalkboardTeacher, faTools, faLightbulb } from "@fortawesome/free-solid-svg-icons";
import Tour from 'reactour'
import { home, assessment } from './Tour';
import { faBars, faChevronLeft, faLayerGroup, faSignInAlt, faSignOutAlt, faCertificate, faUserCircle, faQuestionCircle, faCog, faChalkboardTeacher, faTools, faLightbulb } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as Blockly from 'blockly'
import Tooltip from '@material-ui/core/Tooltip';
const styles = (theme) => ({
@ -34,6 +36,10 @@ const styles = (theme) => ({
},
appBarColor: {
backgroundColor: theme.palette.primary.main
},
tourButton: {
marginleft: 'auto',
marginright: '30px',
}
});
@ -43,7 +49,8 @@ class Navbar extends Component {
constructor(props) {
super(props);
this.state = {
open: false
open: false,
isTourOpen: false
};
}
@ -51,7 +58,21 @@ class Navbar extends Component {
this.setState({ open: !this.state.open });
}
openTour = () => {
this.setState({ isTourOpen: true });
}
closeTour = () => {
this.setState({ isTourOpen: false });
}
render() {
var isHome = /^\/(\/.*$|$)/g.test(this.props.location.pathname);
var isTutorial = /^\/tutorial(\/.*$|$)/g.test(this.props.location.pathname);
var isAssessment = /^\/tutorial\/.{1,}$/g.test(this.props.location.pathname) &&
!this.props.tutorialIsLoading && this.props.tutorial &&
this.props.tutorial.steps[this.props.activeStep].type === 'task';
return (
<div>
<AppBar
@ -64,6 +85,7 @@ class Navbar extends Component {
color="inherit"
onClick={this.toggleDrawer}
style={{ margin: '0 10px' }}
className="MenuButton"
>
<FontAwesomeIcon icon={faBars} />
</IconButton>
@ -75,12 +97,41 @@ class Navbar extends Component {
<Link to={"/"} style={{ marginLeft: '10px' }}>
<img src={senseboxLogo} alt="senseBox-Logo" width="30" />
</Link>
{/^\/tutorial(\/.*$|$)/g.test(this.props.location.pathname) ?
{isTutorial ?
<Link to={"/tutorial"} style={{ textDecoration: 'none', color: 'inherit', marginLeft: '10px' }}>
<Typography variant="h6" noWrap>
Tutorial
</Typography>
</Link> : null}
{isHome ?
<Tooltip title='Hilfe starten' arrow>
<IconButton
color="inherit"
className={`openTour ${this.props.classes.button}`}
onClick={() => { this.openTour(); }}
style={{ margin: '0 30px 0 auto' }}
>
<FontAwesomeIcon icon={faQuestionCircle} />
</IconButton>
</Tooltip>
: null}
{isAssessment ?
<Tooltip title='Hilfe starten' arrow>
<IconButton
color="inherit"
className={`openTour ${this.props.classes.button}`}
onClick={() => { this.openTour(); }}
style={{ margin: '0 30px 0 auto' }}
>
<FontAwesomeIcon icon={faQuestionCircle} />
</IconButton>
</Tooltip>
: null}
<Tour
steps={isHome ? home() : assessment()}
isOpen={this.state.isTourOpen}
onRequestClose={() => { this.closeTour(); }}
/>
</Toolbar>
</AppBar>
<Drawer
@ -152,14 +203,18 @@ Navbar.propTypes = {
tutorialIsLoading: PropTypes.bool.isRequired,
projectIsLoading: PropTypes.bool.isRequired,
isAuthenticated: PropTypes.bool.isRequired,
user: PropTypes.object
user: PropTypes.object,
tutorial: PropTypes.object.isRequired,
activeStep: PropTypes.number.isRequired
};
const mapStateToProps = state => ({
tutorialIsLoading: state.tutorial.progress,
projectIsLoading: state.project.progress,
isAuthenticated: state.auth.isAuthenticated,
user: state.auth.user
user: state.auth.user,
tutorial: state.tutorial.tutorials[0],
activeStep: state.tutorial.activeStep,
});
export default connect(mapStateToProps, { logout })(withStyles(styles, { withTheme: true })(withRouter(Navbar)));

154
src/components/News.js Normal file
View File

@ -0,0 +1,154 @@
import React, { Component } from 'react';
import Breadcrumbs from './Breadcrumbs';
import { withRouter } from 'react-router-dom';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import * as Blockly from 'blockly'
import ReactMarkdown from 'react-markdown';
import Container from '@material-ui/core/Container';
const news = `
# *17.12.2020* - Erstes Beta Release der neuen Lern- und Programmierumgebung für die senseBox
In den letzten Wochen haben wir eine komplett neue Lern- und Programmierumgebung für die senseBox geschaffen. Die Basis bildet hierbei weiterhin Google Blockly und das Frontend wird über React realisiert. Fast alle Blöcke wurden bereits aus der alten Version in die neue Version migriert.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_880bb55f28e0dbb0bb9c2160d8e50594.png)
## Blockly Core
Nachdem die bisherige Version, die unter [blockly.sensebox.de](https://blockly.sensebox.de) weiterhin verfügbar ist, auf einen Google Blockly Core von 2016 aufbaut, wurde es Zeit ein großes Update durchzuführen. Durch den neuen Blockly Core lassen sich auch andere Renderer der Blöcke verwenden. In den Einstellungen kannst du zwischen den zwei Renderern Geras und Zelos auswählen. Geras ist der klassische Blockly Renderer während Zelos vor allem für Touchoberfläche optimiert worden ist.
### Typed Variablen
Neue Variablen werden nun direkt mit einem bestimmten Datentyp angelegt. Ein einfacher Check überprüft ob der zurückgegeben Typ eines Blockes mit dem der Variablen kompatibel ist.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_0d505fc2472178182995732af226e736.png)
### Funktionen (funktioniert aktuell nicht!)
Funktionen mit Rückgabe Wert und Eingabeparametern können angelegt werden. Durch die Verwendung von Funktionen lassen sich auch komplexere Programme übersichtlicher darstellen und bearbeiten. Beim Anlegen einer Funktion kann über das Zahnrad weitere Eingabeparameter hinzuefügt werden.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_bd9544b118a1dbe83d149c00678eb39d.png)
### GPS
Der Code für das GPS Modul wurde neu aufgebaut und ermöglicht es deutlich schneller einen GPS Fix zu bekommen. Zusätzlich lassen sich bald! die Koordinaten in zwei verschiedenen Formaten zurückgebenlassen. Zum einen als Kommazahl zum anderen als Zahl ohne nachkommastellen
### MQTT
Zwei einfache Blöcke ermöglichen es nun die Daten über MQTT an einen Broker zu versenden. Zwei Broker sind bereits "vorprogrammiert" (Adafruit IO und DIOTY). Natürlich können auch eigene Broker verwendet werden. Falls ihr gute freie Broker kennt, die wir hinzufügen sollten meldet euch einfach bei uns.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_a9df4b0b9b1e6f39f09cf3b1743caad2.png)
### TTN Mapper
Bisher war es möglich einen "kleinen" TTN Mapper zu bauen, der die Daten als Cayenne Payload versendet hat. Es gibt nun einen Block der es direkt ermöglicht einen vollständigen TTN Mapper zu Programmieren, der die Daten auch auf [TTNMapper](https://ttnmapper.org/) veröffentlichen kann.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_b59691f2ebcf04d8b67a5f4e7fbe70b6.png)
## Fronted
In der Oberfläche gibt es einige Neuigkeiten. Ziel ist es Blockly für die senseBox zu einer vollständigen Lern- und Programmierumgebung weiterzuentwickeln.
Die Codeanzeige ist standardmäßig ausgeblendet kann aber einfach durch eine Klick auf das \`</>\` Icon hinzugefügt werden.
### Login mit openSenseMap/senseBox Account
Im Menü unter Login könnt ihr euch mit eurem openSenseMap Account anmelden. Sobald ihr angemeldet seid habt ihr die Möglichkeit Projekte online zu speichern.
Sobald der Login mit dem openSenseMap Account erfolgreich war lassen sich die bereits registrierten senseBox unter Account einsehen.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_c3965edc99021339a30b8d6704471e50.png)
Im Block zum senden an die openSenseMap müssen dann auch keine IDs mehr ausgewählt werden sondern die registrierten senseBox können einfach aus dem Dropdown Menü ausgewählt werden.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_57284cea57bfa5df3d55fe456f9d7cfa.png)
### Speichern von Projekten
Nach dem Login über den openSenseMap Account lassen sich Projekte online speichern und wieder abrufen
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_148146b1206fde184afff6edce26b515.png)
### Tutorials
Es gibt jetzt Tutorials! Eine reihe von verschiedenen Tutorials zeigt dir die ersten Schritte in der Programmierung mit Blockly. (Inhalte werden noch ausgebaut)
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_db0e64df48d4c34a9540ffb089e95769.png)
### Gallery
In der Gallery finden sich Beispiele mit verschiedenen Programmen. Die Beispiele können direkt in Blockly geöffnet werden, um Änderungen vorzunehmen oder das Programm direkt auf deine senseBox zu übertragen.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_c61e1fa98f9d840507a8a53b00605484.png)
### Teilen von Programmen
Über den Share Button kann ein Link zum Teilen der aktuellen Blöcke erstellt werden. Wann immer du dein Projekt mit anderen Teilen willst musst du nicht mehr eine XML Datei erstellen und verschicken sondern kannst einen Link erstellen, der direkt zu deinem Programm führt. Beachte, dass vor dem Teilen von Blöcken sämtliche sensiblen Daten, wie zum Beispiel Passwörter, Netzwerknamen, Lora oder openSenseMap Keys entfernt werden sollten. Die Links zum teilen von Programmen laufen nach 30 Tagen ab.
![](https://radosgw.public.os.wwu.de/pad/uploads/upload_a8dba6720fe2fb39cadf129d9bb04a62.png)
## Fehler
Falls ihr Fehler findet legt bitte ein Issue in folgendem Repository an: [React-Ardublockly](https://github.com/sensebox/React-Ardublockly/issues)
`
class News extends Component {
componentDidMount() {
// Ensure that Blockly.setLocale is adopted in the component.
// Otherwise, the text will not be displayed until the next update of the component.
this.forceUpdate();
}
render() {
return (
<div>
<Breadcrumbs content={[{ link: this.props.location.pathname, title: 'News' }]} />
<Container fixed>
<Typography variant='body1'><ReactMarkdown className="news" children={news}>
</ReactMarkdown></Typography>
</Container>
{
this.props.button ?
<Button
style={{ marginTop: '20px' }}
variant="contained"
color="primary"
onClick={() => { this.props.history.push(this.props.button.link) }}
>
{this.props.button.title}
</Button>
:
<Button
style={{ marginTop: '20px' }}
variant="contained"
color="primary"
onClick={() => { this.props.history.push('/') }}
>
{Blockly.Msg.button_back}
</Button>
}
</div >
);
};
}
export default withRouter(News);

View File

@ -1,18 +1,19 @@
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import Container from '@material-ui/core/Container';
class Privay extends Component {
render() {
return (
<div style={{ margin: '0px 24px 0px 24px' }}>
<h1>Datenschutzerklärung</h1>
<Container fixed>
<div style={{ margin: '0px 24px 0px 24px' }}>
<h1>Datenschutzerklärung</h1>
<h2>1. Datenschutz auf einen Blick</h2>
<h3>Allgemeine Hinweise</h3>
<h2>1. Datenschutz auf einen Blick</h2>
<h3>Allgemeine Hinweise</h3>
Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren personenbezogenen Daten passiert, wenn Sie unsere Website besuchen. Personenbezogene Daten sind alle Daten, mit denen Sie persönlich identifiziert werden können. Ausführliche Informationen zum Thema Datenschutz entnehmen Sie unserer unter diesem Text aufgeführten Datenschutzerklärung.
<h3>Datenerfassung auf unserer Website</h3>
<h4>Wer ist verantwortlich für die Datenerfassung auf dieser Website?</h4>
<h4>Wer ist verantwortlich für die Datenerfassung auf dieser Website?</h4>
Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen Kontaktdaten können Sie dem Impressum dieser Website entnehmen.
@ -38,7 +39,7 @@ Sie können dieser Analyse widersprechen. Über die Widerspruchsmöglichkeiten w
<h2>2. Allgemeine Hinweise und Pflichtinformationen</h2>
<h3>Datenschutz</h3>
<h3>Datenschutz</h3>
Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst.Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung.
Wenn Sie diese Website benutzen, werden verschiedene personenbezogene Daten erhoben.Personenbezogene Daten sind Daten, mit denen Sie persönlich identifiziert werden können.Die vorliegende Datenschutzerklärung erläutert, welche Daten wir erheben und wofür wir sie nutzen.Sie erläutert auch, wie und zu welchem Zweck das geschieht.
@ -81,14 +82,14 @@ Gesetzlich vorgeschriebener Datenschutzbeauftragter
Wir haben für unser Unternehmen einen Datenschutzbeauftragten bestellt.
<p>Institut für Geoinformatik</p>
<p>Heisenbergstraße 2</p>
<p>48149 Münster</p>
<p>Heisenbergstraße 2</p>
<p>48149 Münster</p>
<p>Telefon: +49(251) 83 - 33 083</p>
<p>E - Mail: info@sensebox.de</p>
<p>Telefon: +49(251) 83 - 33 083</p>
<p>E - Mail: info@sensebox.de</p>
<h2>4. Datenerfassung auf unserer Website</h2>
<h3>Cookies</h3>
<h2>4. Datenerfassung auf unserer Website</h2>
<h3>Cookies</h3>
Die Internetseiten verwenden teilweise so genannte Cookies.Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren.Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen.Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert.
Die meisten der von uns verwendeten Cookies sind so genannte Session - Cookies.Sie werden nach Ende Ihres Besuchs automatisch gelöscht.Andere Cookies bleiben auf Ihrem Endgerät gespeichert bis Sie diese löschen.Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen.
@ -101,14 +102,14 @@ Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies i
Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server - Log - Dateien, die Ihr Browser automatisch an uns übermittelt.Dies sind:
<ul>
<li>Browsertyp und Browserversion</li>
<li>verwendetes Betriebssystem</li>
<li>Referrer URL</li>
<li>Hostname des zugreifenden Rechners</li>
<li>Uhrzeit der Serveranfrage</li>
<li>
IP - Adresse</li>
</ul>
<li>Browsertyp und Browserversion</li>
<li>verwendetes Betriebssystem</li>
<li>Referrer URL</li>
<li>Hostname des zugreifenden Rechners</li>
<li>Uhrzeit der Serveranfrage</li>
<li>
IP - Adresse</li>
</ul>
Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen.
@ -164,8 +165,8 @@ Wenn Sie mit der Speicherung und Nutzung Ihrer Daten nicht einverstanden sind, k
<h2>Plugins und Tools</h2>
<h3>YouTube</h3>
<h2>Plugins und Tools</h2>
<h3>YouTube</h3>
Unsere Website nutzt Plugins der von Google betriebenen Seite YouTube.Betreiber der Seiten ist die YouTube, LLC, 901 Cherry Ave., San Bruno, CA 94066, USA.
Wenn Sie eine unserer mit einem YouTube - Plugin ausgestatteten Seiten besuchen, wird eine Verbindung zu den Servern von YouTube hergestellt.Dabei wird dem YouTube - Server mitgeteilt, welche unserer Seiten Sie besucht haben.
@ -177,6 +178,7 @@ Die Nutzung von YouTube erfolgt im Interesse einer ansprechenden Darstellung uns
Weitere Informationen zum Umgang mit Nutzerdaten finden Sie in der Datenschutzerklärung von YouTube unter: https://www.google.de/intl/de/policies/privacy.
</div>
</Container>
);
};
}

View File

@ -23,7 +23,7 @@ import Privacy from '../Privacy';
import Login from '../User/Login';
import Account from '../User/Account';
import MyBadges from '../User/MyBadges';
import News from '../News'
class Routes extends Component {
@ -36,7 +36,7 @@ class Routes extends Component {
<div style={{ margin: '0 22px' }}>
<Switch>
<PublicRoute path="/" exact>
<Home/>
<Home />
</PublicRoute>
{/* Tutorials */}
<PublicRoute path="/tutorial" exact>
@ -61,10 +61,10 @@ class Routes extends Component {
</PublicRoute>
{/* User-Projects */}
<PrivateRoute path="/project" exact>
<ProjectHome/>
<ProjectHome />
</PrivateRoute>
<PrivateRoute path="/project/:projectId" exact>
<Project/>
<Project />
</PrivateRoute>
{/* User */}
<IsLoggedRoute path="/user/login" exact>
@ -87,10 +87,14 @@ class Routes extends Component {
<PublicRoute path="/privacy" exact>
<Privacy />
</PublicRoute>
<PublicRoute path="/news" exact>
<News />
</PublicRoute>
{/* Not Found */}
<PublicRoute>
<NotFound />
</PublicRoute>
</Switch>
</div>
);

57
src/components/Tour.js Normal file
View File

@ -0,0 +1,57 @@
import * as Blockly from 'blockly/core';
export const home = () => {
return [
{
selector: ".wrapper",
content: `${Blockly.Msg.hometour_wrapper}`,
},
{
selector: ".blocklyWindow",
content: `${Blockly.Msg.hometour_blocklyWindow}`,
},
{
selector: ".blocklyToolboxDiv",
content: `${Blockly.Msg.hometour_blocklyToolboxDiv}`,
},
{
selector: '.workspaceFunc',
content: `${Blockly.Msg.hometour_workspaceFunc}`,
},
{
selector: ".compileBlocks",
content: `${Blockly.Msg.hometour_compileBlocks}`,
},
{
selector: ".shareBlocks",
content: `${Blockly.Msg.hometour_shareBlocks}`,
},
{
selector: ".showCode",
content: `${Blockly.Msg.hometour_showCode}`,
},
{
selector: ".MenuButton",
content: `${Blockly.Msg.hometour_menuButton}`,
}
];
};
export const assessment = () => {
return [
// to be continued...
{
selector: '.assessmentDiv',
content: `${Blockly.Msg.assessmenttour_assessmentDiv}`
},
{
selector: '.injectionDiv',
content: `${Blockly.Msg.assessmenttour_injectionDiv}`
},
{
selector: '.solutionCheck',
content: `${Blockly.Msg.assessmenttour_solutionCheck}`
}
];
};

View File

@ -33,7 +33,7 @@ class Assessment extends Component {
var statusTask = status.tasks[taskIndex];
return (
<div style={{ width: '100%' }}>
<div className="assessmentDiv" style={{ width: '100%' }}>
<Typography variant='h4' style={{ float: 'left', marginBottom: '5px', height: '40px', display: 'table' }}>{currentTask.headline}</Typography>
<div style={{ float: 'right', height: '40px' }}><WorkspaceFunc assessment /></div>
<Grid container spacing={2} style={{ marginBottom: '5px' }}>

View File

@ -64,7 +64,7 @@ class HintTutorialExists extends Component {
button={Blockly.Msg.button_close}
>
<div>
{Blockly.Msg.messages_newblockly_text}<Link to="/tutorial" className={this.props.classes.link}>test</Link>
{Blockly.Msg.messages_newblockly_text}<Link to="/news" className={this.props.classes.link}>Blockly News</Link>
</div>
<FormControlLabel
style={{ marginTop: '20px' }}

View File

@ -61,7 +61,7 @@ class SolutionCheck extends Component {
<div>
<Tooltip title={Blockly.Msg.tooltip_check_solution} arrow>
<IconButton
className={this.props.classes.compile}
className={`solutionCheck ${this.props.classes.compile}`}
style={{ width: '40px', height: '40px', marginRight: '5px' }}
onClick={() => this.check()}
>

View File

@ -122,7 +122,7 @@ class Compile extends Component {
{this.props.iconButton ?
<Tooltip title={Blockly.Msg.tooltip_compile_code} arrow style={{ marginRight: '5px' }}>
<IconButton
className={this.props.classes.iconButton}
className={`compileBlocks ${this.props.classes.iconButton}`}
onClick={() => this.compile()}
>
<FontAwesomeIcon icon={faClipboardCheck} size="l" />

View File

@ -44,7 +44,7 @@ class DownloadProject extends Component {
<div style={this.props.style}>
<Tooltip title={Blockly.Msg.tooltip_download_project} arrow>
<IconButton
className={this.props.classes.button}
className={`saveBlocks ${this.props.classes.button}`}
onClick={() => this.downloadXmlFile()}
>
<FontAwesomeIcon icon={faFileDownload} size="xs" />

View File

@ -95,7 +95,7 @@ class WorkspaceFunc extends Component {
<div style={this.props.style}>
<Tooltip title={Blockly.Msg.tooltip_share_project} arrow>
<IconButton
className={this.props.classes.button}
className={`shareBlocks ${this.props.classes.button}`}
onClick={() => this.shareBlocks()}
>
<FontAwesomeIcon icon={faShareAlt} size="xs" />