Compare commits

..
Author SHA1 Message Date
DelucseandGitHub 1e95d57139 Update README.md 2020-11-19 17:52:23 +01:00
144 changed files with 1268 additions and 9164 deletions
-7
View File
@@ -1,9 +1,2 @@
REACT_APP_COMPILER_URL=https://compiler.sensebox.de
REACT_APP_BOARD=sensebox-mcu
REACT_APP_BLOCKLY_API=https://api.blockly.sensebox.de
REACT_APP_MYBADGES=https://mybadges.org
REACT_APP_MYBADGES_API=https://mybadges.org/api/v1
# in days
REACT_APP_SHARE_LINK_EXPIRES=30
+4 -4
View File
@@ -2,18 +2,18 @@
# React Ardublockly
This repository contains the source code and documentation of [sensebox-ardublockly](https://sensebox-ardublockly.netlify.app/).
This repository contains the source code and documentation of [sensebox-ardublockly](https://sensebox-ardublockly.netlify.app/) :rocket:.
This project was created with [Create React App](https://github.com/facebook/create-react-app) and represents the continuation or improvement of [blockly.sensebox.de](https://blockly.sensebox.de/ardublockly/?lang=de&board=sensebox-mcu).
## Getting Started
1. [Download](https://github.com/sensebox/React-Ardublockly/archive/master.zip) or clone the GitHub Repository ``git clone https://github.com/sensebox/React-Ardublockly`` and checkout to branch ``master``.
1. [Download](https://github.com/sensebox/React-Ardublockly/archive/bachelor.zip) or clone the GitHub Repository ``git clone https://github.com/sensebox/React-Ardublockly`` and checkout to branch ``bachelor``.
2. install [Node.js v10.xx](https://nodejs.org/en/) on your local machine
3. open shell and navigate inside folder ``React-Ardublockly``
3. open shell and navigate inside folder ``React-Ardublockly`` or rather ``Quellcode``
* run ``npm install``
* run ``npm start``
4. open [localhost:3000](http://localhost:3000)
@@ -22,7 +22,7 @@ This project was created with [Create React App](https://github.com/facebook/cre
Ensure that line 14 in [store.js](https://github.com/sensebox/React-Ardublockly/blob/master/src/store.js#L14) is commented out or otherwise you have installed [Redux DevTools Extension](http://extension.remotedev.io/).
## Demo
A demo of the current status of the master branch can be accessed via [sensebox-ardublockly.netlify.app](https://sensebox-ardublockly.netlify.app/) :rocket:.
A demo of the current status of the bachelor branch can be accessed via [sensebox-ardublockly.netlify.app](https://sensebox-ardublockly.netlify.app/) :rocket:.
* [Home](https://sensebox-ardublockly.netlify.app/)
* [Tutorial Overview](https://sensebox-ardublockly.netlify.app/tutorial)
* [Tutorial-Builder](https://sensebox-ardublockly.netlify.app/tutorial/builder)
+10 -354
View File
@@ -1806,14 +1806,6 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz",
"integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ=="
},
"@types/mdast": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz",
"integrity": "sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==",
"requires": {
"@types/unist": "*"
}
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -1963,11 +1955,6 @@
}
}
},
"@types/unist": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
"integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ=="
},
"@types/yargs": {
"version": "13.0.9",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.9.tgz",
@@ -2581,14 +2568,6 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz",
"integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA=="
},
"axios": {
"version": "0.21.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz",
"integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -3001,11 +2980,6 @@
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
},
"bail": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
"integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ=="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -3597,21 +3571,6 @@
"supports-color": "^5.3.0"
}
},
"character-entities": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
"integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw=="
},
"character-entities-legacy": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
"integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA=="
},
"character-reference-invalid": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
"integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg=="
},
"chardet": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
@@ -6718,63 +6677,6 @@
}
}
},
"html-to-react": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.4.5.tgz",
"integrity": "sha512-KONZUDFPg5OodWaQu2ymfkDmU0JA7zB1iPfvyHehTmMUZnk0DS7/TyCMTzsLH6b4BvxX15g88qZCXFhJWktsmA==",
"requires": {
"domhandler": "^3.3.0",
"htmlparser2": "^5.0",
"lodash.camelcase": "^4.3.0",
"ramda": "^0.27.1"
},
"dependencies": {
"dom-serializer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.1.0.tgz",
"integrity": "sha512-ox7bvGXt2n+uLWtCRLybYx60IrOlWL/aCebWJk1T0d4m3y2tzf4U3ij9wBMUb6YJZpz06HCCYuyCDveE2xXmzQ==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0",
"entities": "^2.0.0"
}
},
"domelementtype": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz",
"integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA=="
},
"domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"requires": {
"domelementtype": "^2.0.1"
}
},
"domutils": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.4.2.tgz",
"integrity": "sha512-NKbgaM8ZJOecTZsIzW5gSuplsX2IWW2mIK7xVr8hTQF2v1CJWTmLZ1HOCh5sH+IzVPAGE5IucooOkvwBRAdowA==",
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.0.1",
"domhandler": "^3.3.0"
}
},
"htmlparser2": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz",
"integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.3.0",
"domutils": "^2.4.2",
"entities": "^2.0.0"
}
}
}
},
"html-webpack-plugin": {
"version": "4.0.0-beta.11",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz",
@@ -7140,20 +7042,6 @@
"kind-of": "^3.0.2"
}
},
"is-alphabetical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
"integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg=="
},
"is-alphanumerical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
"integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
"requires": {
"is-alphabetical": "^1.0.0",
"is-decimal": "^1.0.0"
}
},
"is-arguments": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
@@ -7216,11 +7104,6 @@
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
"integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
},
"is-decimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw=="
},
"is-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
@@ -7276,11 +7159,6 @@
"is-extglob": "^2.1.1"
}
},
"is-hexadecimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="
},
"is-in-browser": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
@@ -8009,11 +7887,6 @@
}
}
},
"js-cookie": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -8408,11 +8281,6 @@
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
},
"lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -8546,30 +8414,6 @@
"safe-buffer": "^5.1.2"
}
},
"mdast-add-list-metadata": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz",
"integrity": "sha512-fB/VP4MJ0LaRsog7hGPxgOrSL3gE/2uEdZyDuSEnKCv/8IkYHiDkIQSbChiJoHyxZZXZ9bzckyRk+vNxFzh8rA==",
"requires": {
"unist-util-visit-parents": "1.1.2"
}
},
"mdast-util-from-markdown": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.1.tgz",
"integrity": "sha512-qJXNcFcuCSPqUF0Tb0uYcFDIq67qwB3sxo9RPdf9vG8T90ViKnksFqdB/Coq2a7sTnxL/Ify2y7aIQXDkQFH0w==",
"requires": {
"@types/mdast": "^3.0.0",
"mdast-util-to-string": "^1.0.0",
"micromark": "~2.10.0",
"parse-entities": "^2.0.0"
}
},
"mdast-util-to-string": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz",
"integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A=="
},
"mdn-data": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
@@ -8658,15 +8502,6 @@
"resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz",
"integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g=="
},
"micromark": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-2.10.1.tgz",
"integrity": "sha512-fUuVF8sC1X7wsCS29SYQ2ZfIZYbTymp0EYr6sab3idFjigFFjGa5UwoniPlV9tAgntjuapW1t9U+S0yDYeGKHQ==",
"requires": {
"debug": "^4.0.0",
"parse-entities": "^2.0.0"
}
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -8885,11 +8720,6 @@
"minimist": "^1.2.5"
}
},
"mnemonic-id": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/mnemonic-id/-/mnemonic-id-3.2.7.tgz",
"integrity": "sha512-kysx9gAGbvrzuFYxKkcRjnsg/NK61ovJOV4F1cHTRl9T5leg+bo6WI0pWIvOFh1Z/yDL0cjA5R3EEGPPLDv/XA=="
},
"moment": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz",
@@ -8998,9 +8828,9 @@
}
},
"node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
"integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ=="
},
"node-int64": {
"version": "0.4.0",
@@ -9564,19 +9394,6 @@
"safe-buffer": "^5.1.1"
}
},
"parse-entities": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
"integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
"requires": {
"character-entities": "^1.0.0",
"character-entities-legacy": "^1.0.0",
"character-reference-invalid": "^1.0.0",
"is-alphanumerical": "^1.0.0",
"is-decimal": "^1.0.0",
"is-hexadecimal": "^1.0.0"
}
},
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
@@ -10903,11 +10720,6 @@
"performance-now": "^2.1.0"
}
},
"ramda": {
"version": "0.27.1",
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
"integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw=="
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -10971,14 +10783,6 @@
"whatwg-fetch": "^3.0.0"
}
},
"react-cookie-consent": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-cookie-consent/-/react-cookie-consent-5.2.0.tgz",
"integrity": "sha512-iRIDynmivejZgLICcpfGbQl94qLn6cjdEHZP0e+ibxzQ7t3zXzdDhsGDSYax8Qu6nGJnlv0bCBd8K0UJUQ5zwQ==",
"requires": {
"js-cookie": "^2.2.1"
}
},
"react-dev-utils": {
"version": "10.2.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.2.1.tgz",
@@ -11201,23 +11005,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-markdown": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-5.0.2.tgz",
"integrity": "sha512-kmkB4JbV7LqkDAjvaKRKtodB3n3Id76/DalaDun1U8FuLB0SenPfvH+jAQ5Pcpo54cACRQc1LB1yXmuuuIVecw==",
"requires": {
"@types/mdast": "^3.0.3",
"@types/unist": "^2.0.3",
"html-to-react": "^1.3.4",
"mdast-add-list-metadata": "1.0.1",
"prop-types": "^15.7.2",
"react-is": "^16.8.6",
"remark-parse": "^9.0.0",
"unified": "^9.0.0",
"unist-util-visit": "^2.0.0",
"xtend": "^4.0.1"
}
},
"react-redux": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz",
@@ -11515,14 +11302,6 @@
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk="
},
"remark-parse": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz",
"integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==",
"requires": {
"mdast-util-from-markdown": "^0.8.0"
}
},
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
@@ -11590,11 +11369,6 @@
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
},
"replace-ext": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
"integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs="
},
"request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
@@ -11620,13 +11394,6 @@
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
"request-promise-core": {
@@ -11971,11 +11738,11 @@
"integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
},
"selfsigned": {
"version": "1.10.8",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz",
"integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==",
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
"integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
"requires": {
"node-forge": "^0.10.0"
"node-forge": "0.9.0"
}
},
"semver": {
@@ -12358,13 +12125,6 @@
"requires": {
"faye-websocket": "^0.10.0",
"uuid": "^3.0.1"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
"sockjs-client": {
@@ -13229,11 +12989,6 @@
"punycode": "^2.1.0"
}
},
"trough": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA=="
},
"ts-pnp": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.6.tgz",
@@ -13326,31 +13081,6 @@
"resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz",
"integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg=="
},
"unified": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz",
"integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==",
"requires": {
"bail": "^1.0.0",
"extend": "^3.0.0",
"is-buffer": "^2.0.0",
"is-plain-obj": "^2.0.0",
"trough": "^1.0.0",
"vfile": "^4.0.0"
},
"dependencies": {
"is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
},
"is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="
}
}
},
"union-value": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
@@ -13388,45 +13118,6 @@
"imurmurhash": "^0.1.4"
}
},
"unist-util-is": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.3.tgz",
"integrity": "sha512-bTofCFVx0iQM8Jqb1TBDVRIQW03YkD3p66JOd/aCWuqzlLyUtx1ZAGw/u+Zw+SttKvSVcvTiKYbfrtLoLefykw=="
},
"unist-util-stringify-position": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
"integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
"requires": {
"@types/unist": "^2.0.2"
}
},
"unist-util-visit": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
"integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0",
"unist-util-visit-parents": "^3.0.0"
},
"dependencies": {
"unist-util-visit-parents": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
"integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0"
}
}
}
},
"unist-util-visit-parents": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz",
"integrity": "sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q=="
},
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@@ -13578,9 +13269,9 @@
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg=="
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"v8-compile-cache": {
"version": "2.1.1",
@@ -13621,34 +13312,6 @@
"extsprintf": "^1.2.0"
}
},
"vfile": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz",
"integrity": "sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw==",
"requires": {
"@types/unist": "^2.0.0",
"is-buffer": "^2.0.0",
"replace-ext": "1.0.0",
"unist-util-stringify-position": "^2.0.0",
"vfile-message": "^2.0.0"
},
"dependencies": {
"is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
}
}
},
"vfile-message": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
"integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-stringify-position": "^2.0.0"
}
},
"vm-browserify": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@@ -14266,13 +13929,6 @@
"requires": {
"ansi-colors": "^3.0.0",
"uuid": "^3.3.2"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
"webpack-manifest-plugin": {
+1 -7
View File
@@ -13,26 +13,20 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"axios": "^0.21.0",
"blockly": "^3.20200924.0",
"file-saver": "^2.0.2",
"mnemonic-id": "^3.2.7",
"moment": "^2.28.0",
"prismjs": "^1.20.0",
"react": "^16.13.1",
"react-cookie-consent": "^5.2.0",
"react-dom": "^16.13.1",
"react-markdown": "^5.0.2",
"react-redux": "^7.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"uuid": "^8.3.1"
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
"dev": "set \"REACT_APP_BLOCKLY_API=http://localhost:8080\" && set \"REACT_APP_MYBADGES_API=http://localhost:3001/api/v1\"&& npm start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 641 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

-28
View File
@@ -5,31 +5,3 @@
position: relative;
padding-bottom: 60px; /* height of your footer + 30px*/
}
.tutorial img{
display: flex;
align-items: center;
max-height: 40vH;
max-width: 100%;
margin: auto;
}
.tutorial blockquote{
background: #f9f9f9;
border-left: 10px solid#4EAF47;
margin: 1.5em 10px;
padding: 0.5em 10px;
quotes: "\201C""\201D""\2018""\2019";
}
blockquote:before {
color:#4EAF47;
content: open-quote;
font-size: 4em;
line-height: 0.1em;
margin-right: 0.25em;
vertical-align: -0.4em;
}
blockquote p {
display: inline;
}
+19 -22
View File
@@ -1,17 +1,18 @@
import React, { Component } from 'react';
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { createBrowserHistory } from "history";
import { Provider } from 'react-redux';
import store from './store';
import { loadUser } from './actions/authActions';
import './App.css';
import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import Content from './components/Content';
import Navbar from './components/Navbar';
import Footer from './components/Footer';
import Routes from './components/Routes';
const theme = createMuiTheme({
palette: {
@@ -21,31 +22,27 @@ const theme = createMuiTheme({
},
secondary: {
main: '#DDDDDD'
},
button: {
compile: '#e27136'
}
}
});
class App extends Component {
const customHistory = createBrowserHistory();
componentDidMount() {
store.dispatch(loadUser());
}
render() {
const customHistory = createBrowserHistory();
return (
<ThemeProvider theme={theme}>
<Provider store={store}>
<Router history={customHistory}>
<Content />
</Router>
</Provider>
</ThemeProvider>
);
}
function App() {
return (
<ThemeProvider theme={theme}>
<Provider store={store}>
<Router history={customHistory}>
<div className="wrapper">
<Navbar />
<Routes />
<Footer />
</div>
</Router>
</Provider>
</ThemeProvider>
);
}
export default App;
-294
View File
@@ -1,294 +0,0 @@
import { MYBADGES_CONNECT, MYBADGES_DISCONNECT, GET_STATUS, USER_LOADED, USER_LOADING, AUTH_ERROR, LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT_SUCCESS, LOGOUT_FAIL, REFRESH_TOKEN_SUCCESS } from '../actions/types';
import axios from 'axios';
import { returnErrors, returnSuccess } from './messageActions';
import { setLanguage } from './generalActions';
// Check token & load user
export const loadUser = () => (dispatch) => {
// user loading
dispatch({
type: USER_LOADING
});
const config = {
success: res => {
dispatch({
type: GET_STATUS,
payload: res.data.user.status
});
dispatch(setLanguage(res.data.user.language));
dispatch({
type: USER_LOADED,
payload: res.data.user
});
},
error: err => {
if(err.response){
dispatch(returnErrors(err.response.data.message, err.response.status));
}
var status = [];
if (window.localStorage.getItem('status')) {
status = JSON.parse(window.localStorage.getItem('status'));
}
dispatch({
type: GET_STATUS,
payload: status
});
dispatch({
type: AUTH_ERROR
});
}
};
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/user`, config, dispatch(authInterceptor()))
.then(res => {
res.config.success(res);
})
.catch(err => {
err.config.error(err);
});
};
var logoutTimerId;
const timeToLogout = 14.9*60*1000; // nearly 15 minutes corresponding to the API
// Login user
export const login = ({ email, password }) => (dispatch) => {
dispatch({
type: USER_LOADING
});
// Headers
const config = {
headers: {
'Content-Type': 'application/json'
}
};
// Request Body
const body = JSON.stringify({ email, password });
axios.post(`${process.env.REACT_APP_BLOCKLY_API}/user`, body, config)
.then(res => {
// Logout automatically if refreshToken "expired"
const logoutTimer = () => setTimeout(
() => dispatch(logout()),
timeToLogout
);
logoutTimerId = logoutTimer();
dispatch(setLanguage(res.data.user.language));
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
dispatch({
type: GET_STATUS,
payload: res.data.user.status
});
dispatch(returnSuccess(res.data.message, res.status, 'LOGIN_SUCCESS'));
})
.catch(err => {
dispatch(returnErrors(err.response.data.message, err.response.status, 'LOGIN_FAIL'));
dispatch({
type: LOGIN_FAIL
});
var status = [];
if (window.localStorage.getItem('status')) {
status = JSON.parse(window.localStorage.getItem('status'));
}
dispatch({
type: GET_STATUS,
payload: status
});
});
};
// Connect to MyBadges-Account
export const connectMyBadges = ({ username, password }) => (dispatch, getState) => {
const config = {
success: res => {
var user = getState().auth.user;
user.badge = res.data.account;
user.badges = res.data.badges;
dispatch({
type: MYBADGES_CONNECT,
payload: user
});
dispatch(returnSuccess(res.data.message, res.status, 'MYBADGES_CONNECT_SUCCESS'));
},
error: err => {
dispatch(returnErrors(err.response.data.message, err.response.status, 'MYBADGES_CONNECT_FAIL'));
}
};
// Request Body
const body = JSON.stringify({ username, password });
axios.post(`${process.env.REACT_APP_BLOCKLY_API}/user/badge`, body, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
if(err.response && err.response.status !== 401){
err.config.error(err);
}
});
};
// Disconnect MyBadges-Account
export const disconnectMyBadges = () => (dispatch, getState) => {
const config = {
success: res => {
var user = getState().auth.user;
user.badge = null;
user.badges = null;
dispatch({
type: MYBADGES_DISCONNECT,
payload: user
});
dispatch(returnSuccess(res.data.message, res.status, 'MYBADGES_DISCONNECT_SUCCESS'));
},
error: err => {
dispatch(returnErrors(err.response.data.message, err.response.status, 'MYBADGES_DISCONNECT_FAIL'));
}
};
axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/badge`, {}, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
if(err.response && err.response.status !== 401){
err.config.error(err);
}
});
};
// Logout User
export const logout = () => (dispatch) => {
const config = {
success: res => {
dispatch({
type: LOGOUT_SUCCESS
});
var status = [];
if (window.localStorage.getItem('status')) {
status = JSON.parse(window.localStorage.getItem('status'));
}
dispatch({
type: GET_STATUS,
payload: status
});
var locale = 'en_US';
if (window.localStorage.getItem('locale')) {
locale = window.localStorage.getItem('locale');
}
else if (navigator.language === 'de-DE'){
locale = 'de_DE';
}
dispatch(setLanguage(locale));
dispatch(returnSuccess(res.data.message, res.status, 'LOGOUT_SUCCESS'));
clearTimeout(logoutTimerId);
},
error: err => {
dispatch(returnErrors(err.response.data.message, err.response.status, 'LOGOUT_FAIL'));
dispatch({
type: LOGOUT_FAIL
});
var status = [];
if (window.localStorage.getItem('status')) {
status = JSON.parse(window.localStorage.getItem('status'));
}
dispatch({
type: GET_STATUS,
payload: status
});
clearTimeout(logoutTimerId);
}
};
axios.post('https://api.opensensemap.org/users/sign-out', {}, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
if(err.response && err.response.status !== 401){
err.config.error(err);
}
});
};
export const authInterceptor = () => (dispatch, getState) => {
// Add a request interceptor
axios.interceptors.request.use(
config => {
config.headers['Content-Type'] = 'application/json';
const token = getState().auth.token;
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
},
error => {
Promise.reject(error);
}
);
// Add a response interceptor
axios.interceptors.response.use(
response => {
// request was successfull
return response;
},
error => {
const originalRequest = error.config;
const refreshToken = getState().auth.refreshToken;
if(refreshToken){
// try to refresh the token failed
if (error.response.status === 401 && originalRequest._retry) {
// router.push('/login');
return Promise.reject(error);
}
// token was not valid and 1st try to refresh the token
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
const refreshToken = getState().auth.refreshToken;
// request to refresh the token, in request-body is the refreshToken
axios.post('https://api.opensensemap.org/users/refresh-auth', {"token": refreshToken})
.then(res => {
if (res.status === 200) {
clearTimeout(logoutTimerId);
const logoutTimer = () => setTimeout(
() => dispatch(logout()),
timeToLogout
);
logoutTimerId = logoutTimer();
dispatch({
type: REFRESH_TOKEN_SUCCESS,
payload: res.data
});
axios.defaults.headers.common['Authorization'] = 'Bearer ' + getState().auth.token;
// request was successfull, new request with the old parameters and the refreshed token
return axios(originalRequest)
.then(res => {
originalRequest.success(res);
})
.catch(err => {
originalRequest.error(err);
});
}
return Promise.reject(error);
})
.catch(err => {
// request failed, token could not be refreshed
if(err.response){
dispatch(returnErrors(err.response.data.message, err.response.status));
}
dispatch({
type: AUTH_ERROR
});
return Promise.reject(error);
});
}
}
// request status was unequal to 401, no possibility to refresh the token
return Promise.reject(error);
}
);
};
+1 -25
View File
@@ -1,4 +1,4 @@
import { VISIT, LANGUAGE, RENDERER, STATISTICS } from './types';
import { VISIT } from './types';
export const visitPage = () => (dispatch) => {
@@ -6,27 +6,3 @@ export const visitPage = () => (dispatch) => {
type: VISIT
});
};
export const setLanguage = (language) => (dispatch, getState) => {
if(!getState().auth.progress && !getState().auth.isAuthenticated){
window.localStorage.setItem('locale', language);
}
dispatch({
type: LANGUAGE,
payload: language
});
};
export const setRenderer = (renderer) => (dispatch) => {
dispatch({
type: RENDERER,
payload: renderer
});
};
export const setStatistics = (showStatistics) => (dispatch) => {
dispatch({
type: STATISTICS,
payload: showStatistics
});
};
-32
View File
@@ -1,32 +0,0 @@
import { GET_ERRORS, CLEAR_MESSAGES, GET_SUCCESS } from './types';
// RETURN Errors
export const returnErrors = (msg, status, id = null) => {
return {
type: GET_ERRORS,
payload: {
msg: msg,
status: status,
id: id
}
};
};
// RETURN Success
export const returnSuccess = (msg, status, id = null) => {
return {
type: GET_SUCCESS,
payload: {
msg: msg,
status: status,
id: id
}
};
};
// CLEAR_MESSAGES
export const clearMessages = () => {
return {
type: CLEAR_MESSAGES
};
};
-205
View File
@@ -1,205 +0,0 @@
import { PROJECT_PROGRESS, GET_PROJECT, GET_PROJECTS, PROJECT_TYPE, PROJECT_DESCRIPTION } from './types';
import axios from 'axios';
import { returnErrors, returnSuccess } from './messageActions';
export const setType = (type) => (dispatch) => {
dispatch({
type: PROJECT_TYPE,
payload: type
});
};
export const setDescription = (description) => (dispatch) => {
dispatch({
type: PROJECT_DESCRIPTION,
payload: description
});
};
export const getProject = (type, id) => (dispatch) => {
dispatch({ type: PROJECT_PROGRESS });
dispatch(setType(type));
const config = {
success: res => {
var data = type === 'share' ? 'content' : type;
var project = res.data[data];
if (project) {
dispatch({
type: GET_PROJECT,
payload: project
});
dispatch({
type: PROJECT_DESCRIPTION,
payload: project.description
});
dispatch({ type: PROJECT_PROGRESS });
dispatch(returnSuccess(res.data.message, res.status, 'GET_PROJECT_SUCCESS'));
}
else {
dispatch({ type: PROJECT_PROGRESS });
dispatch(returnErrors(res.data.message, res.status, 'PROJECT_EMPTY'));
}
},
error: err => {
if(err.response){
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_PROJECT_FAIL'));
}
dispatch({type: PROJECT_PROGRESS});
}
};
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
err.config.error(err);
});
};
export const getProjects = (type) => (dispatch) => {
dispatch({type: PROJECT_PROGRESS});
const config = {
success: res => {
var data = type === 'project' ? 'projects' : 'galleries';
var projects = res.data[data];
dispatch({
type: GET_PROJECTS,
payload: projects
});
dispatch({ type: PROJECT_PROGRESS });
dispatch(returnSuccess(res.data.message, res.status));
},
error: err => {
if(err.response){
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_PROJECTS_FAIL'));
}
dispatch({type: PROJECT_PROGRESS});
}
};
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/${type}`, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
err.config.error(err);
});
};
export const updateProject = (type, id) => (dispatch, getState) => {
var workspace = getState().workspace;
var body = {
xml: workspace.code.xml,
title: workspace.name
};
var project = getState().project;
if (type === 'gallery') {
body.description = project.description;
}
const config = {
success: res => {
var project = res.data[type];
var projects = getState().project.projects;
var index = projects.findIndex(res => res._id === project._id);
projects[index] = project;
dispatch({
type: GET_PROJECTS,
payload: projects
});
if (type === 'project') {
dispatch(returnSuccess(res.data.message, res.status, 'PROJECT_UPDATE_SUCCESS'));
} else {
dispatch(returnSuccess(res.data.message, res.status, 'GALLERY_UPDATE_SUCCESS'));
}
},
error: err => {
if(err.response){
if(type === 'project'){
dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_UPDATE_FAIL'));
} else {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GALLERY_UPDATE_FAIL'));
}
}
}
};
axios.put(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, body, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
err.config.error(err);
});
};
export const deleteProject = (type, id) => (dispatch, getState) => {
var project = getState().project;
const config = {
success: res => {
var projects = getState().project.projects;
var index = projects.findIndex(res => res._id === id);
projects.splice(index, 1)
dispatch({
type: GET_PROJECTS,
payload: projects
});
if (type === 'project') {
dispatch(returnSuccess(res.data.message, res.status, 'PROJECT_DELETE_SUCCESS'));
} else {
dispatch(returnSuccess(res.data.message, res.status, 'GALLERY_DELETE_SUCCESS'));
}
},
error: err => {
dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_DELETE_FAIL'));
}
};
axios.delete(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
if(err.response && err.response.status !== 401){
err.config.error(err);
}
});
};
export const shareProject = (title, type, id) => (dispatch, getState) => {
var body = {
title: title
};
if (type === 'project') {
body.projectId = id;
} else {
body.xml = getState().workspace.code.xml;
}
axios.post(`${process.env.REACT_APP_BLOCKLY_API}/share`, body)
.then(res => {
var shareContent = res.data.content;
if (body.projectId) {
var projects = getState().project.projects;
var index = projects.findIndex(res => res._id === id);
projects[index].shared = shareContent.expiresAt;
dispatch({
type: GET_PROJECTS,
payload: projects
});
}
dispatch(returnSuccess(res.data.message, shareContent._id, 'SHARE_SUCCESS'));
})
.catch(err => {
if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'SHARE_FAIL'));
}
});
};
export const resetProject = () => (dispatch) => {
dispatch({
type: GET_PROJECTS,
payload: []
});
dispatch(setType(''));
dispatch(setDescription(''));
};
+19 -206
View File
@@ -1,152 +1,6 @@
import { MYBADGES_DISCONNECT, TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_STEP } from './types';
import { TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_ID, TUTORIAL_STEP } from './types';
import axios from 'axios';
import { returnErrors, returnSuccess } from './messageActions';
export const tutorialProgress = () => (dispatch) => {
dispatch({type: TUTORIAL_PROGRESS});
};
export const getTutorial = (id) => (dispatch, getState) => {
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`)
.then(res => {
var tutorial = res.data.tutorial;
existingTutorial(tutorial, getState().tutorial.status).then(status => {
dispatch({
type: TUTORIAL_SUCCESS,
payload: status
});
dispatch(updateStatus(status));
dispatch({
type: GET_TUTORIAL,
payload: tutorial
});
dispatch({type: TUTORIAL_PROGRESS});
dispatch(returnSuccess(res.data.message, res.status));
});
})
.catch(err => {
if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_TUTORIAL_FAIL'));
}
dispatch({ type: TUTORIAL_PROGRESS });
});
};
export const getTutorials = () => (dispatch, getState) => {
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial`)
.then(res => {
var tutorials = res.data.tutorials;
console.log(tutorials);
existingTutorials(tutorials, getState().tutorial.status).then(status => {
dispatch({
type: TUTORIAL_SUCCESS,
payload: status
});
console.log('zwei');
dispatch(updateStatus(status));
dispatch({
type: GET_TUTORIALS,
payload: tutorials
});
dispatch({ type: TUTORIAL_PROGRESS });
dispatch(returnSuccess(res.data.message, res.status));
});
})
.catch(err => {
if (err.response) {
dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_TUTORIALS_FAIL'));
}
dispatch({ type: TUTORIAL_PROGRESS });
});
};
export const assigneBadge = (id) => (dispatch, getState) => {
const config = {
success: res => {
var badge = res.data.badge;
var user = getState().auth.user;
user.badges.push(badge._id);
dispatch({
type: MYBADGES_DISCONNECT,
payload: user
});
dispatch(returnSuccess(badge, res.status, 'ASSIGNE_BADGE_SUCCESS'));
},
error: err => {
dispatch(returnErrors(err.response.data.message, err.response.status, 'ASSIGNE_BADGE_FAIL'));
}
};
axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/badge/${id}`, {}, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
if(err.response && err.response.status !== 401){
err.config.error(err);
}
});
};
export const updateStatus = (status) => (dispatch, getState) => {
if(getState().auth.isAuthenticated){
// update user account in database - sync with redux store
axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/status`, {status: status})
.then(res => {
// dispatch(returnSuccess(badge, res.status, 'UPDATE_STATUS_SUCCESS'));
})
.catch(err => {
if(err.response){
// dispatch(returnErrors(err.response.data.message, err.response.status, 'UPDATE_STATUS_FAIL'));
}
});
} else {
// update locale storage - sync with redux store
window.localStorage.setItem('status', JSON.stringify(status));
}
};
export const deleteTutorial = (id) => (dispatch, getState) => {
var tutorial = getState().tutorial;
var id = getState().builder.id;
const config = {
success: res => {
var tutorials = tutorial.tutorials;
var index = tutorials.findIndex(res => res._id === id);
tutorials.splice(index, 1)
dispatch({
type: GET_TUTORIALS,
payload: tutorials
});
dispatch(returnSuccess(res.data.message, res.status, 'TUTORIAL_DELETE_SUCCESS'));
},
error: err => {
dispatch(returnErrors(err.response.data.message, err.response.status, 'TUTORIAL_DELETE_FAIL'));
}
};
axios.delete(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`, config)
.then(res => {
res.config.success(res);
})
.catch(err => {
if(err.response && err.response.status !== 401){
err.config.error(err);
}
});
};
export const resetTutorial = () => (dispatch) => {
dispatch({
type: GET_TUTORIALS,
payload: []
});
dispatch({
type: TUTORIAL_STEP,
payload: 0
});
};
import tutorials from '../data/tutorials';
export const tutorialChange = () => (dispatch) => {
dispatch({
@@ -156,9 +10,9 @@ export const tutorialChange = () => (dispatch) => {
export const tutorialCheck = (status, step) => (dispatch, getState) => {
var tutorialsStatus = getState().tutorial.status;
var id = getState().tutorial.tutorials[0]._id;
var tutorialsStatusIndex = tutorialsStatus.findIndex(tutorialStatus => tutorialStatus._id === id);
var tasksIndex = tutorialsStatus[tutorialsStatusIndex].tasks.findIndex(task => task._id === step._id);
var id = getState().tutorial.currentId;
var tutorialsStatusIndex = tutorialsStatus.findIndex(tutorialStatus => tutorialStatus.id === id);
var tasksIndex = tutorialsStatus[tutorialsStatusIndex].tasks.findIndex(task => task.id === step.id);
tutorialsStatus[tutorialsStatusIndex].tasks[tasksIndex] = {
...tutorialsStatus[tutorialsStatusIndex].tasks[tasksIndex],
type: status
@@ -167,22 +21,18 @@ export const tutorialCheck = (status, step) => (dispatch, getState) => {
type: status === 'success' ? TUTORIAL_SUCCESS : TUTORIAL_ERROR,
payload: tutorialsStatus
});
console.log('drei');
dispatch(updateStatus(tutorialsStatus));
dispatch(tutorialChange());
dispatch(returnSuccess('', '', 'TUTORIAL_CHECK_SUCCESS'));
};
export const storeTutorialXml = (code) => (dispatch, getState) => {
var tutorial = getState().tutorial.tutorials[0];
if (tutorial) {
var id = tutorial._id;
var id = getState().tutorial.currentId;
if (id !== null) {
var activeStep = getState().tutorial.activeStep;
var steps = tutorial.steps;
if (steps && steps[activeStep].type === 'task') {
var steps = tutorials.filter(tutorial => tutorial.id === id)[0].steps;
if (steps[activeStep].type === 'task') {
var tutorialsStatus = getState().tutorial.status;
var tutorialsStatusIndex = tutorialsStatus.findIndex(tutorialStatus => tutorialStatus._id === id);
var tasksIndex = tutorialsStatus[tutorialsStatusIndex].tasks.findIndex(task => task._id === steps[activeStep]._id);
var tutorialsStatusIndex = tutorialsStatus.findIndex(tutorialStatus => tutorialStatus.id === id);
var tasksIndex = tutorialsStatus[tutorialsStatusIndex].tasks.findIndex(task => task.id === steps[activeStep].id);
tutorialsStatus[tutorialsStatusIndex].tasks[tasksIndex] = {
...tutorialsStatus[tutorialsStatusIndex].tasks[tasksIndex],
xml: code
@@ -191,58 +41,21 @@ export const storeTutorialXml = (code) => (dispatch, getState) => {
type: TUTORIAL_XML,
payload: tutorialsStatus
});
dispatch(updateStatus(tutorialsStatus));
}
}
};
export const tutorialId = (id) => (dispatch) => {
dispatch({
type: TUTORIAL_ID,
payload: id
});
};
export const tutorialStep = (step) => (dispatch) => {
dispatch({
type: TUTORIAL_STEP,
payload: step
});
};
const existingTutorials = (tutorials, status) => new Promise(function (resolve, reject) {
var newstatus;
new Promise(function (resolve, reject) {
var existingTutorialIds = tutorials.map((tutorial, i) => {
existingTutorial(tutorial, status).then(status => {
newstatus = status;
});
return tutorial._id;
});
resolve(existingTutorialIds)
}).then(existingTutorialIds => {
// deleting old tutorials which do not longer exist
if (existingTutorialIds.length > 0) {
status = newstatus.filter(status => existingTutorialIds.indexOf(status._id) > -1);
}
resolve(status);
});
});
const existingTutorial = (tutorial, status) => new Promise(function(resolve, reject){
var tutorialsId = tutorial._id;
var statusIndex = status.findIndex(status => status._id === tutorialsId);
if (statusIndex > -1) {
var tasks = tutorial.steps.filter(step => step.type === 'task');
var existingTaskIds = tasks.map((task, j) => {
var tasksId = task._id;
if (status[statusIndex].tasks.findIndex(task => task._id === tasksId) === -1) {
// task does not exist
status[statusIndex].tasks.push({ _id: tasksId });
}
return tasksId;
});
// deleting old tasks which do not longer exist
if (existingTaskIds.length > 0) {
status[statusIndex].tasks = status[statusIndex].tasks.filter(task => existingTaskIds.indexOf(task._id) > -1);
}
}
else {
status.push({ _id: tutorialsId, tasks: tutorial.steps.filter(step => step.type === 'task').map(task => { return { _id: task._id }; }) });
}
resolve(status);
});
+8 -18
View File
@@ -1,4 +1,4 @@
import { PROGRESS, JSON_STRING, BUILDER_CHANGE, BUILDER_ERROR, BUILDER_TITLE, BUILDER_ID, BUILDER_BADGE, BUILDER_ADD_STEP, BUILDER_DELETE_STEP, BUILDER_CHANGE_STEP, BUILDER_CHANGE_ORDER, BUILDER_DELETE_PROPERTY } from './types';
import { PROGRESS, JSON_STRING, BUILDER_CHANGE, BUILDER_ERROR, BUILDER_TITLE, BUILDER_ID, BUILDER_ADD_STEP, BUILDER_DELETE_STEP, BUILDER_CHANGE_STEP, BUILDER_CHANGE_ORDER, BUILDER_DELETE_PROPERTY } from './types';
import data from '../data/hardware.json';
@@ -39,14 +39,6 @@ export const tutorialId = (id) => (dispatch) => {
dispatch(changeTutorialBuilder());
};
export const tutorialBadge = (badge) => (dispatch) => {
dispatch({
type: BUILDER_BADGE,
payload: badge
});
dispatch(changeTutorialBuilder());
};
export const addStep = (index) => (dispatch, getState) => {
var steps = getState().builder.steps;
var step = {
@@ -188,19 +180,16 @@ export const setSubmitError = () => (dispatch, getState) => {
// if(builder.id === undefined || builder.id === ''){
// dispatch(setError(undefined, 'id'));
// }
if (builder.title === '') {
if (builder.id === undefined || builder.title === '') {
dispatch(setError(undefined, 'title'));
}
if (builder.title === null) {
dispatch(setError(undefined, 'badge'));
}
var type = builder.steps.map((step, i) => {
// media and xml are directly checked for errors in their components and
// therefore do not have to be checked again
step.id = i + 1;
if (i === 0) {
if (step.requirements && step.requirements.length > 0) {
var requirements = step.requirements.filter(requirement => /^[0-9a-fA-F]{24}$/.test(requirement));
var requirements = step.requirements.filter(requirement => typeof (requirement) === 'number');
if (requirements.length < step.requirements.length) {
dispatch(changeContent(requirements, i, 'requirements'));
}
@@ -233,7 +222,7 @@ export const setSubmitError = () => (dispatch, getState) => {
export const checkError = () => (dispatch, getState) => {
dispatch(setSubmitError());
var error = getState().builder.error;
if (error.id || error.title || error.badge ||error.type) {
if (error.id || error.title || error.type) {
return true;
}
for (var i = 0; i < error.steps.length; i++) {
@@ -254,9 +243,10 @@ export const progress = (inProgress) => (dispatch) => {
export const resetTutorial = () => (dispatch, getState) => {
dispatch(jsonString(''));
dispatch(tutorialTitle(''));
dispatch(tutorialBadge(undefined));
dispatch(tutorialId(''));
var steps = [
{
id: 1,
type: 'instruction',
headline: '',
text: '',
@@ -284,7 +274,7 @@ export const readJSON = (json) => (dispatch, getState) => {
// accept only valid attributes
var steps = json.steps.map((step, i) => {
var object = {
_id: step._id,
id: step.id,
type: step.type,
headline: step.headline,
text: step.text
@@ -308,7 +298,7 @@ export const readJSON = (json) => (dispatch, getState) => {
return object;
});
dispatch(tutorialTitle(json.title));
dispatch(tutorialBadge(json.badge));
dispatch(tutorialId(json.id));
dispatch(tutorialSteps(steps));
dispatch(setSubmitError());
dispatch(progress(false));
+1 -34
View File
@@ -1,16 +1,3 @@
// authentication
export const USER_LOADING = 'USER_LOADING';
export const USER_LOADED = 'USER_LOADED';
export const AUTH_ERROR = 'AUTH_ERROR';
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
export const LOGIN_FAIL = 'LOGIN_FAIL';
export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
export const LOGOUT_FAIL = 'LOGOUT_FAIL';
export const REFRESH_TOKEN_FAIL = 'REFRESH_TOKEN_FAIL';
export const REFRESH_TOKEN_SUCCESS = 'REFRESH_TOKEN_SUCCESS';
export const MYBADGES_CONNECT = 'MYBADGES_CONNECT';
export const MYBADGES_DISCONNECT = 'MYBADGES_DISCONNECT';
export const NEW_CODE = 'NEW_CODE';
export const CHANGE_WORKSPACE = 'CHANGE_WORKSPACE';
export const CREATE_BLOCK = 'CREATE_BLOCK';
@@ -20,10 +7,7 @@ export const DELETE_BLOCK = 'DELETE_BLOCK';
export const CLEAR_STATS = 'CLEAR_STATS';
export const NAME = 'NAME';
export const TUTORIAL_PROGRESS = 'TUTORIAL_PROGRESS';
export const GET_TUTORIAL = 'GET_TUTORIAL';
export const GET_TUTORIALS = 'GET_TUTORIALS';
export const GET_STATUS = 'GET_STATUS';
export const TUTORIAL_SUCCESS = 'TUTORIAL_SUCCESS';
export const TUTORIAL_ERROR = 'TUTORIAL_ERROR';
export const TUTORIAL_CHANGE = 'TUTORIAL_CHANGE';
@@ -35,7 +19,6 @@ export const JSON_STRING = 'JSON_STRING';
export const BUILDER_CHANGE = 'BUILDER_CHANGE';
export const BUILDER_TITLE = 'BUILDER_TITLE';
export const BUILDER_BADGE = 'BUILDER_BADGE';
export const BUILDER_ID = 'BUILDER_ID';
export const BUILDER_ADD_STEP = 'BUILDER_ADD_STEP';
export const BUILDER_DELETE_STEP = 'BUILDER_DELETE_STEP';
@@ -47,19 +30,3 @@ export const PROGRESS = 'PROGRESS';
export const VISIT = 'VISIT';
export const LANGUAGE = 'LANGUAGE';
export const RENDERER = 'RENDERER';
export const STATISTICS = 'STATISTICS';
// messages
export const GET_ERRORS = 'GET_ERRORS';
export const GET_SUCCESS = 'GET_SUCCESS';
export const CLEAR_MESSAGES = 'CLEAR_MESSAGES';
// projects: share, gallery, project
export const PROJECT_PROGRESS = 'PROJECT_PROGRESS';
export const GET_PROJECT = 'GET_PROJECT';
export const GET_PROJECTS = 'GET_PROJECTS';
export const PROJECT_TYPE = 'PROJECT_TYPE';
export const PROJECT_DESCRIPTION = 'PROJECT_DESCRIPTION';
-34
View File
@@ -1,34 +0,0 @@
import React, { Component } from 'react';
import { withStyles } from '@material-ui/core/styles';
import { fade } from '@material-ui/core/styles/colorManipulator';
import Typography from '@material-ui/core/Typography';
const styles = (theme) => ({
alert: {
marginBottom: '20px',
border: `1px solid ${theme.palette.primary.main}`,
padding: '10px 20px',
borderRadius: '4px',
background: fade(theme.palette.primary.main, 0.3),
color: 'rgb(70,70,70)'
}
});
export class Alert extends Component {
render(){
return(
<div className={this.props.classes.alert}>
<Typography>
{this.props.children}
</Typography>
</div>
);
}
}
export default withStyles(styles, { withTheme: true })(Alert);
+5 -3
View File
@@ -24,12 +24,14 @@
import React from 'react';
import Blockly from 'blockly/core';
import locale from 'blockly/msg/en';
import 'blockly/blocks';
import Toolbox from './toolbox/Toolbox';
import { Card } from '@material-ui/core';
Blockly.setLocale(locale);
class BlocklyComponent extends React.Component {
@@ -37,7 +39,7 @@ class BlocklyComponent extends React.Component {
super(props);
this.blocklyDiv = React.createRef();
this.toolbox = React.createRef();
this.state = { workspace: undefined };
this.state = {workspace: undefined};
}
componentDidMount() {
@@ -49,7 +51,7 @@ class BlocklyComponent extends React.Component {
...rest
},
);
this.setState({ workspace: this.primaryWorkspace })
this.setState({workspace: this.primaryWorkspace})
if (initialXml) {
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(initialXml), this.primaryWorkspace);
@@ -66,7 +68,7 @@ class BlocklyComponent extends React.Component {
render() {
return <React.Fragment>
<Card ref={this.blocklyDiv} id="blocklyDiv" style={this.props.style ? this.props.style : {}} />
<Card ref={this.blocklyDiv} id="blocklyDiv" style={this.props.style ? this.props.style : {}}/>
<Toolbox toolbox={this.toolbox} workspace={this.state.workspace} />
</React.Fragment>;
}
+2 -1
View File
@@ -53,6 +53,7 @@ class BlocklySvg extends Component {
var css = '<defs><style type="text/css" xmlns="http://www.w3.org/1999/xhtml"><![CDATA[' + cssContent + ']]></style></defs>';
var bbox = document.getElementsByClassName("blocklyBlockCanvas")[0].getBBox();
var content = new XMLSerializer().serializeToString(canvas);
var xml = `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="${bbox.width}" height="${bbox.height}" viewBox="${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}">
${css}">${content}</svg>`;
@@ -64,7 +65,7 @@ class BlocklySvg extends Component {
render() {
return (
<div
style={{display: 'inline-flex', justifyContent: 'center', transform: 'scale(0.8) translate(0, calc(100% * -0.2 / 2))'}}
style={{display: 'flex', justifyContent: 'center', transform: 'scale(0.8) translate(0, calc(100% * -0.2 / 2))'}}
dangerouslySetInnerHTML={{ __html: this.state.svg }}
/>
);
+7 -21
View File
@@ -2,22 +2,23 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { onChangeWorkspace, clearStats } from '../../actions/workspaceActions';
// import * as De from 'blockly/msg/de';
import {De} from './msg/de';
import BlocklyComponent from './BlocklyComponent';
import BlocklySvg from './BlocklySvg';
import * as Blockly from 'blockly/core';
import './blocks/index';
import './generator/index';
import { initialXml } from './initialXml.js';
class BlocklyWindow extends Component {
constructor(props) {
super(props);
this.simpleWorkspace = React.createRef();
Blockly.setLocale(De);
}
componentDidMount() {
@@ -45,15 +46,6 @@ class BlocklyWindow extends Component {
if (!xml) xml = initialXml;
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), workspace);
}
if(props.language !== this.props.language){
// change language
if (!xml) xml = initialXml;
var xmlDom = Blockly.Xml.textToDom(xml);
Blockly.Xml.clearWorkspaceAndLoadFromXml(xmlDom, workspace);
// var toolbox = workspace.getToolbox();
// console.log(toolbox);
// workspace.updateToolbox(toolbox.toolboxDef_);
}
Blockly.svgResize(workspace);
}
@@ -64,7 +56,7 @@ class BlocklyWindow extends Component {
style={this.props.svg ? { height: 0 } : this.props.blocklyCSS}
readOnly={this.props.readOnly !== undefined ? this.props.readOnly : false}
trashcan={this.props.trashcan !== undefined ? this.props.trashcan : true}
renderer={this.props.renderer}
renderer='geras'
zoom={{ // https://developers.google.com/blockly/guides/configure/web/zoom
controls: this.props.zoomControls !== undefined ? this.props.zoomControls : true,
wheel: false,
@@ -98,14 +90,8 @@ class BlocklyWindow extends Component {
BlocklyWindow.propTypes = {
onChangeWorkspace: PropTypes.func.isRequired,
clearStats: PropTypes.func.isRequired,
renderer: PropTypes.string.isRequired,
language: PropTypes.string.isRequired
clearStats: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
renderer: state.general.renderer,
language: state.general.language
});
export default connect(mapStateToProps, { onChangeWorkspace, clearStats })(BlocklyWindow);
export default connect(null, { onChangeWorkspace, clearStats })(BlocklyWindow);
-3
View File
@@ -9,7 +9,6 @@ import './sensebox-display';
import './sensebox-lora';
import './sensebox-led';
import './sensebox-sd';
import './mqtt';
import './text';
import './io';
import './audio';
@@ -18,7 +17,5 @@ import './map';
import './procedures';
import './time';
import './variables';
import './lists';
import './webserver';
import '../helpers/types'
-59
View File
@@ -1,59 +0,0 @@
import Blockly, { FieldDropdown } from 'blockly/core'
import * as Types from '../helpers/types'
import { getColour } from '../helpers/colour';
Blockly.Blocks['lists_create_empty'] = {
/**
* Elapsed time in milliseconds block definition
* @this Blockly.Block
*/
init: function () {
this.setHelpUrl('http://arduino.cc/en/Reference/Millis');
this.setColour(getColour().arrays);
this.appendDummyInput()
.appendField("create List with")
this.appendValueInput('NUMBER');
this.appendDummyInput()
.appendField("Items of Type")
.appendField(new FieldDropdown(Types.VARIABLE_TYPES), 'type');
this.setOutput(true, Types.ARRAY.typeId);
this.setTooltip(Blockly.Msg.ARD_TIME_MILLIS_TIP);
},
};
Blockly.Blocks['array_getIndex'] = {
/**
* Elapsed time in milliseconds block definition
* @this Blockly.Block
*/
init: function () {
this.setHelpUrl('http://arduino.cc/en/Reference/Millis');
this.setColour(getColour().arrays);
this.appendDummyInput()
.appendField(new Blockly.FieldVariable(
'X',
null,
['Array'],
'Array'
), 'FIELDNAME');
this.setOutput(true, Types.ARRAY.typeId);
this.setTooltip(Blockly.Msg.ARD_TIME_MILLIS_TIP);
},
};
Blockly.Blocks['lists_length'] = {
/**
* Elapsed time in milliseconds block definition
* @this Blockly.Block
*/
init: function () {
this.setHelpUrl('http://arduino.cc/en/Reference/Millis');
this.setColour(getColour().arrays);
this.appendValueInput('ARRAY')
.appendField('length of')
.setCheck(Types.ARRAY.compatibleTypes);
this.setOutput(true, Types.NUMBER.typeName);
this.setTooltip(Blockly.Msg.ARD_TIME_MILLIS_TIP);
},
};
+58 -237
View File
@@ -4,239 +4,6 @@ import * as Types from '../helpers/types';
import { getCompatibleTypes } from '../helpers/types';
Blockly.Blocks['controls_if'] = {
/**
* Block for if/elseif/else condition.
* @this Blockly.Block
*/
init: function () {
this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL);
this.setColour(getColour().logic);
this.appendValueInput('IF0')
.setCheck(Types.getCompatibleTypes('boolean'))
.appendField(Blockly.Msg.CONTROLS_IF_MSG_IF);
this.appendStatementInput('DO0')
.appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setMutator(new Blockly.Mutator(['controls_if_elseif',
'controls_if_else']));
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function () {
if (!thisBlock.elseifCount_ && !thisBlock.elseCount_) {
return Blockly.Msg.CONTROLS_IF_TOOLTIP_1;
} else if (!thisBlock.elseifCount_ && thisBlock.elseCount_) {
return Blockly.Msg.CONTROLS_IF_TOOLTIP_2;
} else if (thisBlock.elseifCount_ && !thisBlock.elseCount_) {
return Blockly.Msg.CONTROLS_IF_TOOLTIP_3;
} else if (thisBlock.elseifCount_ && thisBlock.elseCount_) {
return Blockly.Msg.CONTROLS_IF_TOOLTIP_4;
}
return '';
});
this.elseifCount_ = 0;
this.elseCount_ = 0;
},
/**
* Create XML to represent the number of else-if and else inputs.
* @return {Element} XML storage element.
* @this Blockly.Block
*/
mutationToDom: function () {
if (!this.elseifCount_ && !this.elseCount_) {
return null;
}
var container = document.createElement('mutation');
if (this.elseifCount_) {
container.setAttribute('elseif', this.elseifCount_);
}
if (this.elseCount_) {
container.setAttribute('else', 1);
}
return container;
},
/**
* Parse XML to restore the else-if and else inputs.
* @param {!Element} xmlElement XML storage element.
* @this Blockly.Block
*/
domToMutation: function (xmlElement) {
this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10) || 0;
this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10) || 0;
this.updateShape_();
},
/**
* Populate the mutator's dialog with this block's components.
* @param {!Blockly.Workspace} workspace Mutator's workspace.
* @return {!Blockly.Block} Root block in mutator.
* @this Blockly.Block
*/
decompose: function (workspace) {
var containerBlock = workspace.newBlock('controls_if_if');
containerBlock.initSvg();
var connection = containerBlock.nextConnection;
for (var i = 1; i <= this.elseifCount_; i++) {
var elseifBlock = workspace.newBlock('controls_if_elseif');
elseifBlock.initSvg();
connection.connect(elseifBlock.previousConnection);
connection = elseifBlock.nextConnection;
}
if (this.elseCount_) {
var elseBlock = workspace.newBlock('controls_if_else');
elseBlock.initSvg();
connection.connect(elseBlock.previousConnection);
}
return containerBlock;
},
/**
* Reconfigure this block based on the mutator dialog's components.
* @param {!Blockly.Block} containerBlock Root block in mutator.
* @this Blockly.Block
*/
compose: function (containerBlock) {
var clauseBlock = containerBlock.nextConnection.targetBlock();
// Count number of inputs.
this.elseifCount_ = 0;
this.elseCount_ = 0;
var valueConnections = [null];
var statementConnections = [null];
var elseStatementConnection = null;
while (clauseBlock) {
switch (clauseBlock.type) {
case 'controls_if_elseif':
this.elseifCount_++;
valueConnections.push(clauseBlock.valueConnection_);
statementConnections.push(clauseBlock.statementConnection_);
break;
case 'controls_if_else':
this.elseCount_++;
elseStatementConnection = clauseBlock.statementConnection_;
break;
default:
throw new Error('Unknown block type.');
}
clauseBlock = clauseBlock.nextConnection &&
clauseBlock.nextConnection.targetBlock();
}
this.updateShape_();
// Reconnect any child blocks.
for (var i = 1; i <= this.elseifCount_; i++) {
Blockly.Mutator.reconnect(valueConnections[i], this, 'IF' + i);
Blockly.Mutator.reconnect(statementConnections[i], this, 'DO' + i);
}
Blockly.Mutator.reconnect(elseStatementConnection, this, 'ELSE');
},
/**
* Store pointers to any connected child blocks.
* @param {!Blockly.Block} containerBlock Root block in mutator.
* @this Blockly.Block
*/
saveConnections: function (containerBlock) {
var clauseBlock = containerBlock.nextConnection.targetBlock();
var i = 1;
while (clauseBlock) {
switch (clauseBlock.type) {
case 'controls_if_elseif':
var inputIf = this.getInput('IF' + i);
var inputDo = this.getInput('DO' + i);
clauseBlock.valueConnection_ =
inputIf && inputIf.connection.targetConnection;
clauseBlock.statementConnection_ =
inputDo && inputDo.connection.targetConnection;
i++;
break;
case 'controls_if_else':
var inputDo = this.getInput('ELSE');
clauseBlock.statementConnection_ =
inputDo && inputDo.connection.targetConnection;
break;
default:
throw new Error('Unknown block type.');
}
clauseBlock = clauseBlock.nextConnection &&
clauseBlock.nextConnection.targetBlock();
}
},
/**
* Modify this block to have the correct number of inputs.
* @private
* @this Blockly.Block
*/
updateShape_: function () {
// Delete everything.
if (this.getInput('ELSE')) {
this.removeInput('ELSE');
}
var i = 1;
while (this.getInput('IF' + i)) {
this.removeInput('IF' + i);
this.removeInput('DO' + i);
i++;
}
// Rebuild block.
for (var i = 1; i <= this.elseifCount_; i++) {
this.appendValueInput('IF' + i)
.setCheck(Types.getCompatibleTypes('boolean'))
.appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF);
this.appendStatementInput('DO' + i)
.appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);
}
if (this.elseCount_) {
this.appendStatementInput('ELSE')
.appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE);
}
}
};
Blockly.Blocks['controls_if_if'] = {
/**
* Mutator block for if container.
* @this Blockly.Block
*/
init: function () {
this.setColour(getColour().logic);
this.appendDummyInput()
.appendField(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['controls_if_elseif'] = {
/**
* Mutator bolck for else-if condition.
* @this Blockly.Block
*/
init: function () {
this.setColour(getColour().logic);
this.appendDummyInput()
.appendField(Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['controls_if_else'] = {
/**
* Mutator block for else condition.
* @this Blockly.Block
*/
init: function () {
this.setColour(getColour().logic);
this.appendDummyInput()
.appendField(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE);
this.setPreviousStatement(true);
this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
// Block for boolean data type: true and false.
{
@@ -257,6 +24,32 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
"tooltip": "%{BKY_LOGIC_BOOLEAN_TOOLTIP}",
"helpUrl": "%{BKY_LOGIC_BOOLEAN_HELPURL}"
},
// Block for if/elseif/else condition.
{
"type": "controls_if",
"message0": "%{BKY_CONTROLS_IF_MSG_IF} %1",
"args0": [
{
"type": "input_value",
"name": "IF0",
"check": Types.getCompatibleTypes('boolean')
}
],
"message1": "%{BKY_CONTROLS_IF_MSG_THEN} %1",
"args1": [
{
"type": "input_statement",
"name": "DO0"
}
],
"previousStatement": null,
"nextStatement": null,
"style": "logic_blocks",
"helpUrl": "%{BKY_CONTROLS_IF_HELPURL}",
"mutator": "controls_if_mutator",
"extensions": ["controls_if_tooltip"]
},
// If/else block that does not use a mutator.
{
"type": "controls_ifelse",
"message0": "%{BKY_CONTROLS_IF_MSG_IF} %1",
@@ -390,16 +183,14 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
"args1": [
{
"type": "input_value",
"name": "THEN",
"check": Types.getCompatibleTypes('boolean'),
"name": "THEN"
}
],
"message2": "%{BKY_LOGIC_TERNARY_IF_FALSE} %1",
"args2": [
{
"type": "input_value",
"name": "ELSE",
"check": Types.getCompatibleTypes('boolean'),
"name": "ELSE"
}
],
"output": null,
@@ -410,6 +201,36 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
}
]); // END JSON EXTRACT (Do not delete this comment.)
Blockly.defineBlocksWithJsonArray([ // Mutator blocks. Do not extract.
// Block representing the if statement in the controls_if mutator.
{
"type": "controls_if_if",
"message0": "%{BKY_CONTROLS_IF_IF_TITLE_IF}",
"nextStatement": null,
"enableContextMenu": false,
"style": "logic_blocks",
"tooltip": "%{BKY_CONTROLS_IF_IF_TOOLTIP}"
},
// Block representing the else-if statement in the controls_if mutator.
{
"type": "controls_if_elseif",
"message0": "%{BKY_CONTROLS_IF_ELSEIF_TITLE_ELSEIF}",
"previousStatement": null,
"nextStatement": null,
"enableContextMenu": false,
"style": "logic_blocks",
"tooltip": "%{BKY_CONTROLS_IF_ELSEIF_TOOLTIP}"
},
// Block representing the else statement in the controls_if mutator.
{
"type": "controls_if_else",
"message0": "%{BKY_CONTROLS_IF_ELSE_TITLE_ELSE}",
"previousStatement": null,
"enableContextMenu": false,
"style": "logic_blocks",
"tooltip": "%{BKY_CONTROLS_IF_ELSE_TOOLTIP}"
}
]);
Blockly.Blocks['logic_compare'] = {
/**
-86
View File
@@ -1,86 +0,0 @@
import * as Blockly from 'blockly/core';
import { getColour } from '../helpers/colour';
/**
* MQTT Blocks
*/
Blockly.Blocks["sensebox_mqtt_setup"] = {
init: function () {
//this.setTooltip(Blockly.Msg.senseBox_wifi_);
this.setHelpUrl('');
this.setColour(getColour().mqtt);
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_mqtt_init)
.appendField(new Blockly.FieldDropdown([["Adafruit IO", 'adafruitio'], ["DIOTY", 'dioty'], ["Other Service", 'custom']]), "service");
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField(Blockly.Msg.senseBox_mqtt_server)
.appendField(new Blockly.FieldTextInput("Server"), "server");
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField(Blockly.Msg.senseBox_mqtt_port)
.appendField(new Blockly.FieldTextInput("Port"), "port");
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField(Blockly.Msg.senseBox_mqtt_username)
.appendField(new Blockly.FieldTextInput("Username"), "username");
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField(Blockly.Msg.senseBox_mqtt_password, "passwordmsg")
.appendField(new Blockly.FieldTextInput("Password"), "password");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
},
onchange: function (e) {
let service = this.getFieldValue('service');
switch (service) {
case 'adafruitio':
this.getField('server').setValue("io.adafruit.com");
this.getField('port').setValue("1883");
this.getField('passwordmsg').setValue("Adafruit IO Key");
break;
case 'dioty':
this.getField('server').setValue("mqtt.dioty.co");
this.getField('port').setValue("1883");
this.getField('passwordmsg').setValue(Blockly.Msg.senseBox_mqtt_password);
break;
case "custom":
this.getField('server').setValue("server");
this.getField('port').setValue("port");
this.getField('passwordmsg').setValue(Blockly.Msg.senseBox_mqtt_password);
break;
default:
break;
}
}
};
Blockly.Blocks["sensebox_mqtt_publish"] = {
init: function () {
this.setColour(getColour().mqtt);
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_mqtt_publish);
this.appendValueInput('value')
.setCheck(null)
.appendField('Feed/Topic')
.appendField(new Blockly.FieldTextInput('Name'), 'publishfeed');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
}
};
Blockly.Blocks["sensebox_mqtt_subscribe"] = {
init: function () {
this.setColour(getColour().mqtt);
this.appendDummyInput()
.appendField(Blockly.Msg.sensebox_mqtt_subscribe);
this.appendDummyInput()
.appendField(new Blockly.FieldTextInput('Feedname'), 'subscribefeed');
this.setOutput(true, null);
}
};
File diff suppressed because it is too large Load Diff
@@ -50,6 +50,8 @@ Blockly.Blocks['sensebox_display_printDisplay'] = {
.setCheck(null);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
let variableName = this.getField('COLOR');
console.log(variableName.getValue());
this.setTooltip(Blockly.Msg.senseBox_display_printDisplay_tip);
this.setHelpUrl('https://sensebox.de/books');
},
@@ -79,54 +81,6 @@ Blockly.Blocks['sensebox_display_printDisplay'] = {
LOOP_TYPES: ['sensebox_display_show'],
};
Blockly.Blocks['sensebox_display_fastPrint'] = {
init: function (block) {
this.setColour(getColour().sensebox);
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_display_fastPrint_show);
this.appendValueInput("Title1", 'Title1')
.appendField(Blockly.Msg.senseBox_display_fastPrint_title);
this.appendValueInput("Value1", 'Value1')
.appendField(Blockly.Msg.senseBox_display_fastPrint_value);
this.appendValueInput("Dimension1", 'Dimension1')
.appendField(Blockly.Msg.senseBox_display_fastPrint_dimension);
this.appendValueInput("Title2", 'Title2')
.appendField(Blockly.Msg.senseBox_display_fastPrint_title);
this.appendValueInput("Value2", 'Value2')
.appendField(Blockly.Msg.senseBox_display_fastPrint_value);
this.appendValueInput("Dimension2", 'Dimension2')
.appendField(Blockly.Msg.senseBox_display_fastPrint_dimension);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setTooltip(Blockly.Msg.sensebox_display_fastPrint_tip);
this.setHelpUrl('https://sensebox.de/books');
},
/**
* Called whenever anything on the workspace changes.
* Add warning if block is not nested inside a the correct loop.
* @param {!Blockly.Events.Abstract} e Change event.
* @this Blockly.Block
*/
onchange: function (e) {
var legal = false;
// Is the block nested in a loop?
var block = this;
do {
if (this.LOOP_TYPES.indexOf(block.type) != -1) {
legal = true;
break;
}
block = block.getSurroundParent();
} while (block);
if (legal) {
this.setWarningText(null);
} else {
this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING);
}
},
LOOP_TYPES: ['sensebox_display_show'],
};
Blockly.Blocks['sensebox_display_plotDisplay'] = {
init: function () {
@@ -42,32 +42,3 @@ Blockly.Blocks['sensebox_rgb_led'] = {
this.setHelpUrl('https://sensebox.de/books');
}
};
Blockly.Blocks['sensebox_ws2818_led'] = {
init: function () {
var dropdownOptions = [[Blockly.Msg.senseBox_ultrasonic_port_A, '1'],
[Blockly.Msg.senseBox_ultrasonic_port_B, '3'], [Blockly.Msg.senseBox_ultrasonic_port_C, '5']];
this.setColour(getColour().sensebox);
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_ws2818_rgb_led)
.appendField("Pin:")
.appendField(new Blockly.FieldDropdown(dropdownOptions), "Port")
this.appendValueInput("BRIGHTNESS", "brightness")
.appendField((Blockly.Msg.senseBox_ws2818_rgb_led_brightness));
this.appendValueInput("POSITION", "position")
.appendField((Blockly.Msg.senseBox_ws2818_rgb_led_position));
this.appendValueInput("RED", 'Number')
.appendField(Blockly.Msg.COLOUR_RGB_RED);//Blockly.Msg.senseBox_basic_red
this.appendValueInput("GREEN", 'Number')
.appendField(Blockly.Msg.COLOUR_RGB_GREEN);//Blockly.Msg.senseBox_basic_green
this.appendValueInput("BLUE", 'Number')
.appendField(Blockly.Msg.COLOUR_RGB_BLUE);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setTooltip(Blockly.Msg.senseBox_rgb_led_tip);
this.setHelpUrl('https://sensebox.de/books');
}
};
@@ -119,38 +119,6 @@ Blockly.Blocks['sensebox_send_lora_sensor_value'] = {
LOOP_TYPES: ['sensebox_lora_message_send'],
};
Blockly.Blocks['sensebox_lora_ttn_mapper'] = {
init: function (block) {
this.setColour(getColour().sensebox);
this.appendDummyInput()
.appendField("TTN Mapper");
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField("Fix Type Limit")
.appendField(new Blockly.FieldDropdown([["0", "0"], ["1", "1"], ["2", "2"], ["3", "3"]].reverse()), "dropdown");
// reverse() because i want 3 be be at first and i'm to lazy to write the array again
this.appendValueInput('Latitude')
.appendField(Blockly.Msg.senseBox_gps_lat)
.setCheck(null);
this.appendValueInput('Longitude')
.appendField(Blockly.Msg.senseBox_gps_lng)
.setCheck(null);
this.appendValueInput('Altitude')
.appendField(Blockly.Msg.senseBox_gps_alt)
.setCheck(null);
this.appendValueInput('pDOP')
.appendField('pDOP')
.setCheck(null);
this.appendValueInput('Fix Type')
.appendField('Fix Type')
.setCheck(null);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setTooltip(Blockly.Msg.senseBox_display_printDisplay_tip);
}
};
Blockly.Blocks['sensebox_lora_cayenne_send'] = {
init: function () {
this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_tip);
+10 -78
View File
@@ -1,14 +1,6 @@
import * as Blockly from 'blockly/core';
import { getColour } from '../helpers/colour';
import store from '../../../store';
var boxes = store.getState().auth.user ? store.getState().auth.user.boxes : null;
store.subscribe(() => {
boxes = store.getState().auth.user ? store.getState().auth.user.boxes : null;
});
var selectedBox = '';
Blockly.Blocks['sensebox_osem_connection'] = {
init: function () {
@@ -24,25 +16,10 @@ Blockly.Blocks['sensebox_osem_connection'] = {
.setAlign(Blockly.ALIGN_LEFT)
.appendField(Blockly.Msg.senseBox_osem_exposure)
.appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_osem_stationary, 'Stationary'], [Blockly.Msg.senseBox_osem_mobile, 'Mobile']]), "type");
if (!boxes) {
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField("senseBox ID")
.appendField(new Blockly.FieldTextInput("senseBox ID"), "BoxID");
} else {
var dropdown = []
for (var i = 0; i < boxes.length; i++) {
dropdown.push([boxes[i].name, boxes[i]._id])
}
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField("senseBox ID")
.appendField(new Blockly.FieldDropdown(dropdown), 'BoxID');
}
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField(Blockly.Msg.senseBox_osem_access_token)
.appendField(new Blockly.FieldTextInput("access_token"), "access_token");
.appendField("senseBox ID")
.appendField(new Blockly.FieldTextInput("senseBox ID"), "BoxID");
this.appendStatementInput('DO')
.appendField(Blockly.Msg.senseBox_sensor)
.setCheck(null);
@@ -50,16 +27,8 @@ Blockly.Blocks['sensebox_osem_connection'] = {
this.setNextStatement(true, null);
},
onchange: function (e) {
selectedBox = this.getFieldValue('BoxID');
console.log(selectedBox)
if (selectedBox !== '' && boxes) {
var accessToken = boxes.find(element => element._id === selectedBox).access_token
if (accessToken !== undefined) {
this.getField('access_token').setValue(accessToken)
} else {
this.getField('access_token').setValue('access_token')
}
}
//Blockly.Blocks.sensebox.getDescendants = blocks;
},
mutationToDom: function () {
@@ -109,52 +78,20 @@ Blockly.Blocks['sensebox_send_to_osem'] = {
this.setColour(getColour().sensebox);
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_send_to_osem);
if (boxes) {
this.appendValueInput('Value')
.appendField('Phänomen')
.appendField(new Blockly.FieldDropdown(
this.generateOptions), 'SensorID');
} else {
this.appendValueInput('Value')
.setAlign(Blockly.ALIGN_LEFT)
.appendField('Phänomen')
.appendField(new Blockly.FieldTextInput(
'sensorID'), 'SensorID')
}
this.appendValueInput('Value')
.setCheck(null)
.appendField('Sensor ID')
.appendField(new Blockly.FieldTextInput('Sensor ID'), 'SensorID');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
},
generateOptions: function () {
var dropdown = [['', '']];
var boxID = selectedBox;
if (boxID !== '' && boxes) {
let box = boxes.find(el => el._id === boxID);
if (box !== undefined) {
for (var i = 0; i < box.sensors.length; i++) {
dropdown.push([box.sensors[i].title, box.sensors[i]._id])
}
console.log(dropdown)
}
if (dropdown.length > 1) {
var options = dropdown.slice(1)
return options
} else {
return dropdown
}
}
return dropdown
},
/**
* Called whenever anything on the workspace changes.
* Add warning if block is not nested inside a the correct loop.
* @param {!Blockly.Events.Abstract} e Change event.
* @this Blockly.Block
*/
onchange: function () {
onchange: function (e) {
var legal = false;
// Is the block nested in a loop?
var block = this;
@@ -171,10 +108,5 @@ Blockly.Blocks['sensebox_send_to_osem'] = {
this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING);
}
},
/**
* List of block types that are loops and thus do not need warnings.
* To add a new loop type add this to your code:
* Blockly.Blocks['controls_flow_statements'].LOOP_TYPES.push('custom_loop');
*/
LOOP_TYPES: ['sensebox_osem_connection']
LOOP_TYPES: ['sensebox_osem_connection'],
};
@@ -309,7 +309,7 @@ Blockly.Blocks['sensebox_button'] = {
Blockly.Blocks['sensebox_scd30'] = {
init: function () {
var dropdownOptions = [[Blockly.Msg.senseBox_scd_co2, "CO2"], [Blockly.Msg.senseBox_temp, "temperature"], [Blockly.Msg.senseBox_hum, "humidity"]];
var dropdownOptions = [[Blockly.Msg.senseBox_temp, "temperature"], [Blockly.Msg.senseBox_hum, "humidity"], [Blockly.Msg.senseBox_bme_co2, "CO2"]];
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_scd30);
this.appendDummyInput()
@@ -318,36 +318,6 @@ Blockly.Blocks['sensebox_scd30'] = {
.appendField(new Blockly.FieldDropdown(dropdownOptions), "dropdown")
this.setOutput(true, Types.NUMBER.typeName);
this.setColour(getColour().sensebox);
this.setTooltip(Blockly.Msg.senseBox_scd_tip);
},
onchange: function (e) {
var dropdown = this.getFieldValue('dropdown');
if (dropdown === 'temperature' || dropdown === 'humidity') {
this.setOutput(true, Types.DECIMAL.typeName);
} else if (dropdown === 'CO2') {
this.setOutput(true, Types.NUMBER.typeName);
}
}
};
/**
* GPS Module
*
*/
Blockly.Blocks['sensebox_gps'] = {
init: function () {
var dropdownOptions = [[Blockly.Msg.senseBox_gps_lat, "latitude"], [Blockly.Msg.senseBox_gps_lng, "longitude"], [Blockly.Msg.senseBox_gps_alt, "altitude"], ["pDOP", "pDOP"], ["Fix Type", "fixType"]];
this.appendDummyInput()
.appendField("GPS Modul");
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(Blockly.Msg.senseBox_value)
.appendField(new Blockly.FieldDropdown(dropdownOptions), "dropdown")
this.setOutput(true, Types.NUMBER.typeName);
this.setColour(getColour().sensebox);
this.setTooltip(Blockly.Msg.senseBox_bme_tip);
}
};
-334
View File
@@ -1,334 +0,0 @@
import Blockly from 'blockly/core';
import { getColour } from '../helpers/colour';
import { getCompatibleTypes } from '../helpers/types'
import * as Types from '../helpers/types';
/**
* Webserver Blocks By Lucas Steinmann
* */
Blockly.Blocks['sensebox_initialize_http_server'] = {
init: function () {
this.setTooltip(Blockly.Msg.senseBox_init_http_server_tip);
this.setHelpUrl('https://sensebox.de/books');
this.setColour(getColour().webserver);
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_init_http_server);
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField("Port")
.appendField(new Blockly.FieldNumber(80), "Port");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
},
onchange: function (e) {
// Is the block nested in a loop?
var block = this;
do {
if (this.LOOP_TYPES.indexOf(block.type) !== -1) {
break;
}
block = block.getSurroundParent();
} while (block);
},
LOOP_TYPES: ['arduino_functions'],
};
Blockly.Blocks['sensebox_http_on_client_connect'] = {
init: function () {
this.setTooltip(Blockly.Msg.senseBox_http_on_client_connect_tip);
this.setColour(getColour().webserver);
this.appendDummyInput().appendField(Blockly.Msg.senseBox_http_on_client_connect);
this.appendStatementInput('ON_CONNECT');
this.setHelpUrl('https://sensebox.de/books');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
}
};
Blockly.Blocks['sensebox_http_method'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_http_method)
this.setOutput(true, Types.TEXT.typeName);
this.setColour(getColour().webserver);
this.setTooltip(Blockly.Msg.senseBox_http_method_tip);
this.setHelpUrl('https://sensebox.de/books');
},
getBlockType: function () {
return Blockly.Types.TEXT;
},
};
Blockly.Blocks['sensebox_http_uri'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_http_uri)
this.setOutput(true, Types.TEXT.typeName);
this.setColour(getColour().webserver);
this.setTooltip(Blockly.Msg.senseBox_http_uri_tip);
this.setHelpUrl('https://sensebox.de/books');
}
};
Blockly.Blocks['sensebox_http_protocol_version'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_http_protocol_version)
this.setOutput(true, Types.TEXT.typeName);
this.setColour(getColour().webserver);
this.setTooltip(Blockly.Msg.senseBox_http_protocol_version_tip);
this.setHelpUrl('https://sensebox.de/books');
}
};
Blockly.Blocks['sensebox_ip_address'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_ip_address);
this.setTooltip(Blockly.Msg.senseBox_ip_address_tip);
this.setHelpUrl('');
this.setOutput(true, Types.TEXT.typeName);
this.setColour(getColour().webserver);
}
};
Blockly.Blocks['sensebox_http_user_agent'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_http_user_agent)
this.setOutput(true, Types.TEXT.typeName);
this.setColour(getColour().webserver);
this.setTooltip(Blockly.Msg.senseBox_http_user_agent_tip);
this.setHelpUrl('https://sensebox.de/books');
}
};
Blockly.Blocks['sensebox_generate_html_doc'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_html_document);
this.appendValueInput('HEADER')
.setAlign(Blockly.ALIGN_LEFT)
.setCheck(getCompatibleTypes('String'))
.appendField(Blockly.Msg.senseBox_html_header);
this.appendValueInput('BODY')
.setAlign(Blockly.ALIGN_LEFT)
.setCheck(getCompatibleTypes('String'))
.appendField(Blockly.Msg.senseBox_html_body);
this.setInputsInline(false);
this.setOutput(true, Types.TEXT.typeName);
this.setColour(getColour().webserver);
this.setTooltip(Blockly.Msg.senseBox_html_document_tip);
this.setHelpUrl('https://sensebox.de/books');
},
};
Blockly.Blocks['sensebox_generate_http_succesful_response'] = {
init: function () {
this.setColour(getColour().webserver);
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_http_success);
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_http_success_l2);
this.appendValueInput('CONTENT')
.appendField(Blockly.Msg.senseBox_http_success_buildhtml)
.setCheck(getCompatibleTypes('String'));
this.setTooltip(Blockly.Msg.senseBox_http_success_tip);
this.setInputsInline(false);
this.setHelpUrl('https://sensebox.de/books');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
}
};
Blockly.Blocks['sensebox_generate_http_not_found_response'] = {
init: function () {
this.setTooltip(Blockly.Msg.senseBox);
this.setColour(getColour().webserver);
this.appendDummyInput().appendField(Blockly.Msg.senseBox_http_not_found);
this.setTooltip(Blockly.Msg.senseBox_http_not_found_tip);
this.setHelpUrl('https://sensebox.de/books');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
}
};
Blockly.Blocks['sensebox_general_html_tag'] = {
init: function () {
this.setTooltip(Blockly.Msg.senseBox_html_general_tag_tip);
this.setColour(getColour().webserver);
this.appendDummyInput()
.appendField("<")
.appendField(new Blockly.FieldTextInput("Tag"), "TAG")
.appendField(">");
this.appendValueInput('DO0')
.setCheck(getCompatibleTypes('String'));
this.setInputsInline(false);
this.setOutput(true, Types.TEXT.typeName);
this.setHelpUrl('https://sensebox.de/books');
this.setPreviousStatement(false);
this.setNextStatement(false);
this.setMutator(new Blockly.Mutator(['additional_child']));
this.additionalChildCount_ = 0;
},
/**
* Create XML to represent the number of else-if and else inputs.
* @return {Element} XML storage element.
* @this Blockly.Block
*/
mutationToDom: function () {
if (!this.additionalChildCount_) {
return null;
}
var container = document.createElement('mutation');
if (this.additionalChildCount_) {
container.setAttribute('add_child', this.additionalChildCount_);
}
return container;
},
/**
* Parse XML to restore the else-if and else inputs.
* @param {!Element} xmlElement XML storage element.
* @this Blockly.Block
*/
domToMutation: function (xmlElement) {
this.additionalChildCount_ = parseInt(xmlElement.getAttribute('add_child'), 10) || 0;
this.updateShape_();
},
/**
* Populate the mutator's dialog with this block's components.
* @param {!Blockly.Workspace} workspace Mutator's workspace.
* @return {!Blockly.Block} Root block in mutator.
* @this Blockly.Block
*/
decompose: function (workspace) {
var containerBlock = workspace.newBlock('first_child');
containerBlock.initSvg();
var connection = containerBlock.nextConnection;
for (var i = 1; i <= this.additionalChildCount_; i++) {
var elseifBlock = workspace.newBlock('additional_child');
elseifBlock.initSvg();
connection.connect(elseifBlock.previousConnection);
connection = elseifBlock.nextConnection;
}
return containerBlock;
},
/**
* Reconfigure this block based on the mutator dialog's components.
* @param {!Blockly.Block} containerBlock Root block in mutator.
* @this Blockly.Block
*/
compose: function (containerBlock) {
var clauseBlock = containerBlock.nextConnection.targetBlock();
// Count number of inputs.
this.additionalChildCount_ = 0;
var statementConnections = [null];
while (clauseBlock) {
switch (clauseBlock.type) {
case 'additional_child':
this.additionalChildCount_++;
statementConnections.push(clauseBlock.statementConnection_);
break;
default:
throw new Error("Unknown block type.");
}
clauseBlock = clauseBlock.nextConnection &&
clauseBlock.nextConnection.targetBlock();
}
this.updateShape_();
// Reconnect any child blocks.
for (var i = 1; i <= this.additionalChildCount_; i++) {
Blockly.Mutator.reconnect(statementConnections[i], this, 'DO' + i);
}
},
/**
* Store pointers to any connected child blocks.
* @param {!Blockly.Block} containerBlock Root block in mutator.
* @this Blockly.Block
*/
saveConnections: function (containerBlock) {
var clauseBlock = containerBlock.nextConnection.targetBlock();
var i = 1;
while (clauseBlock) {
switch (clauseBlock.type) {
case 'additional_child':
var inputDo = this.getInput('DO' + i);
clauseBlock.statementConnection_ =
inputDo && inputDo.connection.targetConnection;
i++;
break;
default:
throw new Error('Unknown block type.');
}
clauseBlock = clauseBlock.nextConnection &&
clauseBlock.nextConnection.targetBlock();
}
},
/**
* Modify this block to have the correct number of inputs.
* @private
* @this Blockly.Block
*/
updateShape_: function () {
// Delete everything.
var i = 1;
while (this.getInput('DO' + i)) {
this.removeInput('DO' + i);
i++;
}
// Rebuild block.
for (i = 1; i <= this.additionalChildCount_; i++) {
this.appendValueInput('DO' + i, Blockly.Arduino.ORDER_NONE);
}
}
};
Blockly.Blocks['first_child'] = {
init: function () {
this.setColour(getColour().webserver);
this.appendDummyInput()
.appendField("<Tag>");
this.setNextStatement(true);
this.setInputsInline(true);
this.setTooltip(Blockly.Msg.senseBox_tag_first_mutator_tip);
this.contextMenu = false;
}
};
Blockly.Blocks['additional_child'] = {
init: function () {
this.setColour(getColour().webserver);
this.appendDummyInput()
.appendField("<Tag>");
this.setPreviousStatement(true);
this.setInputsInline(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.senseBox_tag_optional_mutator_tip);
this.contextMenu = false;
}
};
// Additional Webserver Blocks
Blockly.Blocks['sensebox_web_readHTML'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_sd_web_readHTML)
.setAlign(Blockly.ALIGN_LEFT);
this.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField(Blockly.Msg.sensebox_web_readHTML_filename)
.appendField(new Blockly.FieldTextInput("index.txt"), "FILENAME");
this.setOutput(true, Types.TEXT.typeName);
this.setColour(getColour().webserver);
this.setTooltip(Blockly.Msg.senseBox_output_safetosd_tip);
this.setHelpUrl('https://sensebox.de/books');
}
};
+2 -12
View File
@@ -44,7 +44,7 @@ Blockly['Arduino'].addReservedWords(
'setup,loop,if,else,for,switch,case,while,' +
'do,break,continue,return,goto,define,include,' +
'HIGH,LOW,INPUT,OUTPUT,INPUT_PULLUP,true,false,' +
'interger, constants,floating,point,void,boolean,char,' +
'interger, constants,floating,point,void,bookean,char,' +
'unsigned,byte,int,word,long,float,double,string,String,array,' +
'static, volatile,const,sizeof,pinMode,digitalWrite,digitalRead,' +
'analogReference,analogRead,analogWrite,tone,noTone,shiftOut,shitIn,' +
@@ -106,9 +106,6 @@ Blockly['Arduino'].init = function (workspace) {
// creates a list of code to be setup before the setup block
Blockly['Arduino'].setupCode_ = Object.create(null);
// creates a list of code to be setup before the setup block
Blockly['Arduino'].loraSetupCode_ = Object.create(null);
// creates a list of code for the loop to be runned once
Blockly['Arduino'].loopCodeOnce_ = Object.create(null)
@@ -205,7 +202,6 @@ Blockly['Arduino'].finish = function (code) {
let loopCodeOnce = '';
let setupCode = '';
let preSetupCode = '';
let loraSetupCode = '';
let devVariables = '\n';
for (const key in Blockly['Arduino'].libraries_) {
@@ -237,13 +233,7 @@ Blockly['Arduino'].finish = function (code) {
for (const key in Blockly['Arduino'].setupCode_) {
preSetupCode += Blockly['Arduino'].setupCode_[key] || '';
}
for (const key in Blockly['Arduino'].loraSetupCode_) {
loraSetupCode += Blockly['Arduino'].loraSetupCode_[key] || '';
}
setupCode = '\nvoid setup() { \n' + preSetupCode + '\n' + loraSetupCode + '\n}\n';
setupCode = '\nvoid setup() { \n' + preSetupCode + '\n}\n';
let loopCode = '\nvoid loop() { \n' + loopCodeOnce + code + '\n}\n';
@@ -8,7 +8,6 @@ import './sensebox-display';
import './sensebox-lora';
import './sensebox-led';
import './sensebox-sd';
import './mqtt';
import './logic';
import './text';
import './math';
@@ -18,7 +17,5 @@ import './audio';
import './procedures';
import './time';
import './variables';
import './lists';
import './webserver';
-19
View File
@@ -1,19 +0,0 @@
import * as Blockly from 'blockly/core';
Blockly.Arduino['lists_create_empty'] = function () {
var code = '';
return [code, Blockly.Arduino.ORDER_ATOMIC];
}
Blockly.Arduino['array_getIndex'] = function () {
var code = '';
return [code, Blockly.Arduino.ORDER_ATOMIC];
}
Blockly.Arduino['lists_length'] = function () {
var array = Blockly.Arduino.valueToCode(this, 'ARRAY', Blockly.Arduino.ORDER_ATOMIC);
var code = `${array}.length`;
return [code, Blockly.Arduino.ORDER_ATOMIC];
}
+7 -4
View File
@@ -74,14 +74,14 @@ Blockly.Arduino['controls_if'] = function (Block) {
conditionCode +
') {\n' +
branchCode +
'}\n';
'}';
++n;
} while (Block.getInput('IF' + n));
if (Block.getInput('ELSE')) {
branchCode = Blockly.Arduino.statementToCode(Block, 'ELSE');
code += ' else {\n' + branchCode + '}\n';
code += ' else {\n' + branchCode + '}';
}
return code + '\n';
};
@@ -106,14 +106,14 @@ Blockly.Arduino['controls_ifelse'] = function (Block) {
conditionCode +
') {\n' +
branchCode +
'}\n';
'}';
++n;
} while (Block.getInput('IF' + n));
if (Block.getInput('ELSE')) {
branchCode = Blockly.Arduino.statementToCode(Block, 'ELSE');
code += ' else {\n' + branchCode + '}\n';
code += ' else {\n' + branchCode + '}';
}
return code + '\n';
}
@@ -127,6 +127,9 @@ Blockly.Arduino['logic_negate'] = function (Block) {
};
Blockly.Arduino['switch_case'] = function (block) {
var n = 0;
var argument = Blockly.Arduino.valueToCode(this, 'CONDITION',
-80
View File
@@ -1,80 +0,0 @@
import * as Blockly from 'blockly/core';
/**
* MQTT Blocks
*/
let service;
Blockly.Arduino.sensebox_mqtt_setup = function () {
var server = this.getFieldValue('server');
var port = this.getFieldValue('port');
var username = this.getFieldValue('username');
var pass = this.getFieldValue('password');
service = this.getFieldValue('service');
Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"';
Blockly.Arduino.libraries_['library_adafruitmqtt'] = '#include "Adafruit_MQTT.h"';
Blockly.Arduino.libraries_['library_adafruitmqttclient'] = '#include "Adafruit_MQTT_Client.h"';
Blockly.Arduino.definitions_['mqtt_server'] = '#define SERVER "' + server + '"';
Blockly.Arduino.definitions_['mqtt_port'] = '#define SERVERPORT ' + port + '';
Blockly.Arduino.definitions_['mqtt_username'] = '#define USERNAME "' + username + '"';
Blockly.Arduino.definitions_['mqtt_pass'] = '#define PASS "' + pass + '"';
Blockly.Arduino.definitions_['wifi_client'] = 'WiFiClient client;';
Blockly.Arduino.definitions_['mqtt_client'] = 'Adafruit_MQTT_Client mqtt(&client, SERVER, SERVERPORT, USERNAME, PASS);'
var code = '';
return code;
};
Blockly.Arduino.sensebox_mqtt_publish = function (block) {
var feedname = this.getFieldValue('publishfeed');
var res = feedname.split("/");
var feed_client = res[res.length - 1];
var value = Blockly.Arduino.valueToCode(this, 'value', Blockly.Arduino.ORDER_ATOMIC) || '"No Block connected"';
switch (service) {
case 'adafruitio':
Blockly.Arduino.definitions_['mqtt_' + feed_client + ''] = 'Adafruit_MQTT_Publish ' + feed_client + ' = Adafruit_MQTT_Publish(&mqtt, USERNAME "/feeds/' + feedname + '");'
break;
case 'dioty':
Blockly.Arduino.definitions_['mqtt_' + feed_client + ''] = 'Adafruit_MQTT_Publish ' + feed_client + ' = Adafruit_MQTT_Publish(&mqtt, "/"USERNAME"/' + feedname + '");'
break;
case 'custom':
Blockly.Arduino.definitions_['mqtt_' + feed_client + ''] = 'Adafruit_MQTT_Publish ' + feed_client + ' = Adafruit_MQTT_Publish(&mqtt, ' + feedname + ');'
break;
default:
break;
}
//Blockly.Arduino.definitions_['mqtt_' + feed_client + ''] = 'Adafruit_MQTT_Publish ' + feed_client + ' = Adafruit_MQTT_Publish(&mqtt, USERNAME "/feeds/' + feedname + '");'
Blockly.Arduino.codeFunctions_['mqtt_connect_function'] = `// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
}`;
Blockly.Arduino.loopCodeOnce_['mqtt_connect'] = 'MQTT_connect();';
var code = '' + feed_client + '.publish(' + value + ');';
return code
};
Blockly.Arduino.sensebox_mqtt_subscribe = function (block) {
var feedname = this.getFieldValue('subscribefeed');
var x = 5, feed_client;
feed_client = feedname.substr(feedname.length - x, x);
Blockly.Arduino.definitions_['mqtt_' + feed_client + ''] = 'Adafruit_MQTT_Subscribe ' + feed_client + '= Adafruit_MQTT_Subscribe(&mqtt,' + feedname + ');';
Blockly.Arduino.codeFunctions_['mqtt_' + feed_client + 'callbackFunction'] = `void ` + feed_client + `Callback (double x){
Serial.println(x);
}`;
Blockly.Arduino.setupCode_['mqtt_' + feed_client + '_callback'] = '' + feed_client + '.setCallback(' + feed_client + 'Callback);';
Blockly.Arduino.setupCode_['mqtt_' + feed_client + '_subscribe'] = 'mqtt.subscribe(&' + feed_client + ');';
Blockly.Arduino.loopCodeOnce_['mqtt_processPackages'] = 'mqtt.processPackets(10);';
var code = '';
return code;
};
@@ -28,101 +28,3 @@ Blockly.Arduino['arduino_functions'] = function (block) {
//var loopcode = Blockly.Arduino.scrub_(block, loopBranch); No comment block
return loopBranch;
};
Blockly.Arduino['procedures_defreturn'] = function (block) {
// Define a procedure with a return value.
const funcName = Blockly.Arduino.variableDB_.getName(
block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE
);
const branch = Blockly.Arduino.statementToCode(block, 'STACK');
const returnType = block.getFieldValue('RETURN TYPE') || 'void';
let returnValue =
Blockly.Arduino.valueToCode(block, 'RETURN', Blockly.Arduino.ORDER_NONE) ||
'';
if (returnValue) {
returnValue = Blockly.Arduino.INDENT + 'return ' + returnValue + ';\n';
}
const args = [];
for (let i = 0; i < block.argumentVarModels_.length; i++) {
args[i] =
translateType(block.argumentVarModels_[i].type) +
' ' +
block.argumentVarModels_[i].name;
}
let code =
translateType(returnType) +
' ' +
funcName +
'(' +
args.join(', ') +
') {\n' +
branch +
returnValue +
'}';
code = Blockly.Arduino.scrub_(block, code);
// Add % so as not to collide with helper functions in definitions list.
Blockly.Arduino.functionNames_['%' + funcName] = code;
return null;
};
function translateType(type) {
console.log(type);
switch (type) {
case 'int':
return 'int';
case 'String':
return 'String';
case 'void':
return 'void';
case 'boolean':
return 'boolean';
case 'float':
return 'float'
default:
throw new Error('Invalid Parameter Type');
}
}
Blockly.Arduino['procedures_defnoreturn'] =
Blockly.Arduino['procedures_defreturn'];
Blockly.Arduino['procedures_callreturn'] = function (block) {
// Call a procedure with a return value.
const funcName = Blockly.Arduino.variableDB_.getName(
block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE
);
const args = [];
for (let i = 0; i < block.arguments_.length; i++) {
args[i] =
Blockly.Arduino.valueToCode(
block,
'ARG' + i,
Blockly.Arduino.ORDER_COMMA
) || 'null';
}
const code = funcName + '(' + args.join(', ') + ')';
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino['procedures_callnoreturn'] = function (block) {
// Call a procedure with no return value.
const funcName = Blockly.Arduino.variableDB_.getName(
block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE
);
const args = [];
for (let i = 0; i < block.arguments_.length; i++) {
args[i] =
Blockly.Arduino.valueToCode(
block,
'ARG' + i,
Blockly.Arduino.ORDER_COMMA
) || 'null';
}
return funcName + '(' + args.join(', ') + ');\n';
};
@@ -19,10 +19,10 @@ Blockly.Arduino.sensebox_display_clearDisplay = function () {
};
Blockly.Arduino.sensebox_display_printDisplay = function () {
var x = this.getFieldValue('X');
var y = this.getFieldValue('Y');
var x = Blockly.Arduino.valueToCode(this, 'X', Blockly.Arduino.ORDER_ATOMIC) || '0'
var y = Blockly.Arduino.valueToCode(this, 'Y', Blockly.Arduino.ORDER_ATOMIC) || '0'
var printDisplay = Blockly.Arduino.valueToCode(this, 'printDisplay', Blockly.Arduino.ORDER_ATOMIC) || '"Keine Eingabe"';
var size = this.getFieldValue('SIZE');
var size = Blockly.Arduino.valueToCode(this, 'SIZE', Blockly.Arduino.ORDER_ATOMIC) || '1'
var color = this.getFieldValue('COLOR');
var code = 'display.setCursor(' + x + ',' + y + ');\n';
code += 'display.setTextSize(' + size + ');\n';
@@ -31,42 +31,6 @@ Blockly.Arduino.sensebox_display_printDisplay = function () {
return code;
};
Blockly.Arduino.sensebox_display_fastPrint = function () {
var title1 = Blockly.Arduino.valueToCode(this, 'Title1', Blockly.Arduino.ORDER_ATOMIC) || '0'
var value1 = Blockly.Arduino.valueToCode(this, 'Value1', Blockly.Arduino.ORDER_ATOMIC);
var dimension1 = Blockly.Arduino.valueToCode(this, 'Dimension1', Blockly.Arduino.ORDER_ATOMIC) || '0'
var title2 = Blockly.Arduino.valueToCode(this, 'Title2', Blockly.Arduino.ORDER_ATOMIC) || '0'
var value2 = Blockly.Arduino.valueToCode(this, 'Value2', Blockly.Arduino.ORDER_ATOMIC);
var dimension2 = Blockly.Arduino.valueToCode(this, 'Dimension2', Blockly.Arduino.ORDER_ATOMIC) || '0'
Blockly.Arduino.codeFunctions_['sensebox_fastPrint'] = `
void printOnDisplay(String title1, String measurement1, String unit1, String title2, String measurement2, String unit2) {
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.println(title1);
display.setCursor(0, 10);
display.setTextSize(2);
display.print(measurement1);
display.print(" ");
display.setTextSize(1);
display.println(unit1);
display.setCursor(0, 30);
display.setTextSize(1);
display.println(title2);
display.setCursor(0, 40);
display.setTextSize(2);
display.print(measurement2);
display.print(" ");
display.setTextSize(1);
display.println(unit2);
}
`
var code = ` printOnDisplay(${title1}, String(${value1}), ${dimension1}, ${title2}, String(${value2}), ${dimension2});\n`;
return code;
};
Blockly.Arduino.sensebox_display_show = function (block) {
var show = Blockly.Arduino.statementToCode(block, 'SHOW');
var code = '';
@@ -20,27 +20,3 @@ Blockly.Arduino.sensebox_rgb_led = function () {
code += 'rgb_led_' + dropdown_pin + '.show();';
return code;
};
Blockly.Arduino.sensebox_ws2818_led = function () {
var dropdown_pin = this.getFieldValue('Port');
var blocks = Blockly.mainWorkspace.getAllBlocks();
var count = 0;
for (var i = 0; i < blocks.length; i++) {
if (blocks[i].type === 'sensebox_ws2818_led' && blocks[i].getFieldValue('Port') === dropdown_pin) {
count++;
}
}
var numPixel = count;
var brightness = Blockly.Arduino.valueToCode(this, 'BRIGHTNESS', Blockly.Arduino.ORDER_ATOMIC) || '50'
var position = Blockly.Arduino.valueToCode(this, 'POSITION', Blockly.Arduino.ORDER_ATOMIC) || '0';
var red = Blockly.Arduino.valueToCode(this, 'RED', Blockly.Arduino.ORDER_ATOMIC) || '0'
var green = Blockly.Arduino.valueToCode(this, 'GREEN', Blockly.Arduino.ORDER_ATOMIC) || '0'
var blue = Blockly.Arduino.valueToCode(this, 'BLUE', Blockly.Arduino.ORDER_ATOMIC) || '0'
Blockly.Arduino.definitions_['define_rgb_led' + dropdown_pin] = `#include <Adafruit_NeoPixel.h>\n Adafruit_NeoPixel rgb_led_${dropdown_pin}= Adafruit_NeoPixel(${numPixel}, ${dropdown_pin},NEO_GRB + NEO_KHZ800);\n`;
Blockly.Arduino.setupCode_['setup_rgb_led' + dropdown_pin] = 'rgb_led_' + dropdown_pin + '.begin();\n';
Blockly.Arduino.setupCode_['setup_rgb_led_brightness' + dropdown_pin] = `rgb_led_${dropdown_pin}.setBrightness(${brightness});\n`;
var code = `rgb_led_${dropdown_pin}.setPixelColor(${position},rgb_led_${dropdown_pin}.Color(${red},${green},${blue}));\nrgb_led_${dropdown_pin}.show();\n`;
return code;
};
@@ -120,9 +120,9 @@ Blockly.Arduino.sensebox_lora_initialize_otaa = function (block) {
break;
}
}`;
Blockly.Arduino.loraSetupCode_['initLora'] = 'initLora();\n';
Blockly.Arduino.setupCode_['serial.begin'] = 'Serial.begin(9600);\ndelay(1000);\n';
var code = '';
Blockly.Arduino.setupCode_['initLora'] = 'initLora();';
Blockly.Arduino.setupCode_['serial.begin'] = 'Serial.begin(9600);';
var code = ''
return code;
};
@@ -195,60 +195,6 @@ Blockly.Arduino.sensebox_lora_cayenne_send = function (block) {
return '';
}
Blockly.Arduino.sensebox_lora_ttn_mapper = function (block) {
var latitude = Blockly.Arduino.valueToCode(this, 'Latitude', Blockly.Arduino.ORDER_ATOMIC)
var longitude = Blockly.Arduino.valueToCode(this, 'Longitude', Blockly.Arduino.ORDER_ATOMIC)
var altitude = Blockly.Arduino.valueToCode(this, 'Altitude', Blockly.Arduino.ORDER_ATOMIC)
var pDOP = Blockly.Arduino.valueToCode(this, 'pDOP', Blockly.Arduino.ORDER_ATOMIC)
var fixType = Blockly.Arduino.valueToCode(this, 'Fix Type', Blockly.Arduino.ORDER_ATOMIC)
var fixTypeLimit = this.getFieldValue('dropdown');
Blockly.Arduino.functionNames_['functions_do_send'] = `
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
int fixType = ${fixType};
if (fixType >= ${fixTypeLimit}) { // we have a 3D fix
int32_t latitude = ${latitude}; // in degrees * 10^-7
int32_t longitude = ${longitude}; // in degrees * 10^-7
int32_t altitude = ${altitude} / 100; // in dm above mean sea level
uint16_t pDOP = ${pDOP}; // positional dillution of precision
uint8_t data[12];
data[0] = latitude;
data[1] = latitude >> 8;
data[2] = latitude >> 16;
data[3] = latitude >> 24;
data[4] = longitude;
data[5] = longitude >> 8;
data[6] = longitude >> 16;
data[7] = longitude >> 24;
data[8] = altitude;
data[9] = altitude >> 8;
data[10] = pDOP;
data[11] = pDOP >> 8;
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, data, sizeof(data), 0);
Serial.println(F("Packet queued"));
} else {
// wait for better fix type
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
}
}
// Next TX is scheduled after TX_COMPLETE event.
}`;
Blockly.Arduino.loopCodeOnce_['os_runloop'] = 'os_runloop_once();'
return '';
}
Blockly.Arduino.sensebox_lora_initialize_abp = function (block) {
var nwskey = this.getFieldValue('NWSKEY');
var appskey = this.getFieldValue('APPSKEY');
@@ -426,8 +372,8 @@ Blockly.Arduino.sensebox_lora_initialize_abp = function (block) {
break;
}
}`;
Blockly.Arduino.loraSetupCode_['initLora'] = 'initLora();\n';
Blockly.Arduino.setupCode_['serial.begin'] = 'Serial.begin(9600);\ndelay(1000);\n';
Blockly.Arduino.setupCode_['initLora'] = 'initLora();';
Blockly.Arduino.setupCode_['serial.begin'] = 'Serial.begin(9600);';
return '';
}
@@ -18,20 +18,17 @@ Blockly.Arduino.sensebox_osem_connection = function (Block) {
var box_id = this.getFieldValue('BoxID');
var host = this.getFieldValue('host');
var branch = Blockly.Arduino.statementToCode(Block, 'DO');
var access_token = this.getFieldValue('access_token');
var blocks = this.getDescendants();
//var blocks = Blockly.Block.getDescendants;
var type = this.getFieldValue('type');
var ssl = this.getFieldValue('SSL');
var port = 0;
var count = 0;
if (blocks != undefined) {
for (var i = 0; i < blocks.length; i++) {
if (blocks[i].type === 'sensebox_send_to_osem') {
count++;
// for (var i = 0; i < blocks.length; i++) {
// if (blocks[i].type === 'sensebox_send_to_osem') {
// count++;
}
}
}
// }
// }
var num_sensors = count;
Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"';
Blockly.Arduino.definitions_['num_sensors'] = 'static const uint8_t NUM_SENSORS = ' + num_sensors + ';'
@@ -87,7 +84,7 @@ Blockly.Arduino.sensebox_osem_connection = function (Block) {
if (connected == true) {
// construct the HTTP POST request:
sprintf_P(buffer,
PSTR("POST /boxes/%s/data HTTP/1.1\\nAuthorization: ${access_token}\\nHost: %s\\nContent-Type: "
PSTR("POST /boxes/%s/data HTTP/1.1\\nHost: %s\\nContent-Type: "
"text/csv\\nConnection: close\\nContent-Length: %i\\n\\n"),
SENSEBOX_ID, server, num_measurements * lengthMultiplikator);
// send the HTTP POST request:
@@ -147,7 +144,7 @@ Blockly.Arduino.sensebox_osem_connection = function (Block) {
if (connected == true) {
// construct the HTTP POST request:
sprintf_P(buffer,
PSTR("POST /boxes/%s/data HTTP/1.1\\nAuthorization: ${access_token}\\nHost: %s\\nContent-Type: "
PSTR("POST /boxes/%s/data HTTP/1.1\\nHost: %s\\nContent-Type: "
"text/csv\\nConnection: close\\nContent-Length: %i\\n\\n"),
SENSEBOX_ID, server, num_measurements * lengthMultiplikator);
// send the HTTP POST request:
@@ -263,68 +263,32 @@ Blockly.Arduino.sensebox_scd30 = function () {
Blockly.Arduino.libraries_['scd30_library'] = '#include "SparkFun_SCD30_Arduino_Library.h"'
Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"';
Blockly.Arduino.definitions_['SCD30'] = 'SCD30 airSensor;';
Blockly.Arduino.variables_['scd30_temp'] = 'float scd30_temp;';
Blockly.Arduino.variables_['scd30_humi'] = 'float scd30_humi;';
Blockly.Arduino.variables_['scd30_co2'] = 'float scd30_co2;';
Blockly.Arduino.setupCode_['init_scd30'] = ` Wire.begin();
if (airSensor.begin() == false)
{
Serial.println("Air sensor not detected. Please check wiring. Freezing...");
while (1)
;
}`;
Blockly.Arduino.loopCodeOnce_['scd30_getData'] = `if (airSensor.dataAvailable())
{
scd30_co2 = airSensor.getCO2();
scd30_temp = airSensor.getTemperature();
scd30_humi = airSensor.getHumidity();
}`
var code = '';
switch (dropdown) {
case 'temperature':
code = 'airSensor.getTemperature()';
code = 'scd30_temp';
break;
case 'humidity':
code = 'airSensor.getHumiditiy()';
code = 'scd30_humi';
break;
case 'CO2':
code = 'airSensor.getCO2()';
break;
default:
code = ''
}
return [code, Blockly.Arduino.ORDER_ATOMIC];
}
/**
* GPS Module
*
*/
Blockly.Arduino.sensebox_gps = function () {
var dropdown = this.getFieldValue('dropdown');
Blockly.Arduino.libraries_['gps_library'] = '#include "SparkFun_Ublox_Arduino_Library.h"'
Blockly.Arduino.libraries_['wire'] = '#include <Wire.h>'
Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"';
Blockly.Arduino.definitions_['GPS'] = 'SFE_UBLOX_GPS myGPS;';
Blockly.Arduino.setupCode_['init_gps'] = ` Wire.begin();
if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
{
Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
while (1);
}
myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
myGPS.saveConfiguration(); //Save the current settings to flash and BBR`;
var code = '';
switch (dropdown) {
case 'latitude':
code = 'myGPS.getLatitude()';
break;
case 'longitude':
code = 'myGPS.getLongitude()';
break;
case 'altitude':
code = 'myGPS.getAltitudeMSL()';
break;
case 'pDOP':
code = 'myGPS.getPDOP()';
break;
case 'fixType':
code = 'myGPS.getFixType()';
code = 'scd30_co2';
break;
default:
code = ''
+4 -23
View File
@@ -14,28 +14,9 @@ const setVariableFunction = function (defaultValue) {
const allVars = Blockly.getMainWorkspace().getVariableMap().getAllVariables();
const myVar = allVars.filter(v => v.name === variableName)[0]
var code = ''
switch (myVar.type) {
default:
Blockly.Arduino.variables_[myVar + myVar.type] = myVar.type + " " + myVar.name + ';\n';
code = variableName + ' = ' + (variableValue || defaultValue) + ';\n';
break;
case 'Array':
var arrayType;
var number;
if (this.getChildren().length > 0) {
if (this.getChildren()[0].type === 'lists_create_empty') {
arrayType = this.getChildren()[0].getFieldValue('type');
number = Blockly.Arduino.valueToCode(this.getChildren()[0], 'NUMBER', Blockly['Arduino'].ORDER_ATOMIC);
Blockly.Arduino.variables_[myVar + myVar.type] = `${arrayType} ${myVar.name} [${number}];\n`;
}
}
break;
}
return code;
Blockly.Arduino.variables_[myVar + myVar.type] = myVar.type + " " + myVar.name + ';\n';
return variableName + ' = ' + (variableValue || defaultValue) + ';\n';
};
};
@@ -44,8 +25,8 @@ const getVariableFunction = function (block) {
block.getFieldValue('VAR'),
Blockly.Variables.NAME_TYPE
);
var code = variableName;
return [code, Blockly['Arduino'].ORDER_ATOMIC];
return [variableName, Blockly['Arduino'].ORDER_ATOMIC];
};
Blockly['Arduino']['variables_set_dynamic'] = setVariableFunction()
@@ -1,114 +0,0 @@
import Blockly from 'blockly';
/**
* Webserver Blocks by Lucas Steinmann
*
*/
Blockly.Arduino.sensebox_initialize_http_server = function (block) {
var box_id = this.getFieldValue('Port');
Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"';
Blockly.Arduino.codeFunctions_['define_wifi_server'] = 'WiFiServer server(' + box_id + ');';
Blockly.Arduino.setupCode_['sensebox_wifi_server_beging'] = 'server.begin();';
return '';
};
Blockly.Arduino.sensebox_http_on_client_connect = function (block) {
var onConnect = Blockly.Arduino.statementToCode(block, 'ON_CONNECT');
var code = '';
code += 'WiFiClient client = server.available();\n';
code += 'if (client && client.available()) {\n';
code += ' String request_string = listenClient(client);\n';
code += ' Request request;\n';
code += ' if (parseRequestSafe(request_string, request)) {\n';
code += onConnect;
code += ' }\n';
code += ' delay(1);\n';
code += ' client.stop();\n';
code += ' delay(1);\n';
code += '}\n';
return code;
};
Blockly.Arduino.sensebox_http_method = function (block) {
var code = "request.method";
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.sensebox_http_uri = function (block) {
var code = "request.uri";
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.sensebox_http_protocol_version = function (block) {
var code = "request.protocol_version";
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.sensebox_http_user_agent = function (block) {
var code = "request.user_agent";
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.sensebox_generate_html_doc = function (block) {
var header = Blockly.Arduino.valueToCode(block, 'HEADER', Blockly.Arduino.ORDER_NONE) || '""';
var body = Blockly.Arduino.valueToCode(block, 'BODY', Blockly.Arduino.ORDER_NONE) || '""';
var code = 'buildHTML(' + header + ', ' + body + ')';
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.sensebox_generate_http_succesful_response = function (block) {
var content = Blockly.Arduino.valueToCode(block, 'CONTENT', Blockly.Arduino.ORDER_NONE) || '""';
var code = 'client.println(buildSuccessfulResponse(request, ' + content + '));\n';
return code;
};
Blockly.Arduino.sensebox_generate_http_not_found_response = function (block) {
var code = 'client.println(buildNotFoundResponse(request));\n';
return code;
};
Blockly.Arduino.sensebox_ip_address = function (block) {
var code = "b->getIpAddress()";
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.sensebox_general_html_tag = function (block) {
var tag = this.getFieldValue('TAG');
var code = 'buildTag("' + tag + '",';
var n = 0;
var branch = Blockly.Arduino.valueToCode(block, 'DO' + n, Blockly.Arduino.ORDER_NONE);
if (branch.length > 0) {
code += '\n ' + branch;
} else {
code += '""';
}
for (n = 1; n <= block.additionalChildCount_; n++) {
branch = Blockly.Arduino.valueToCode(block, 'DO' + n, Blockly.Arduino.ORDER_NONE);
code += ' +' + branch;
}
return [code + ')', Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.sensebox_web_readHTML = function (block) {
var filename = this.getFieldValue('FILENAME');
Blockly.Arduino.libraries_['library_spi'] = '#include <SPI.h>';
Blockly.Arduino.libraries_['library_sd'] = '#include <SD.h>';
Blockly.Arduino.codeFunctions_['define_sd' + filename] = 'File webFile;';
Blockly.Arduino.setupCode_['sensebox_sd'] = 'SD.begin(28);';
var func = [
'String generateHTML(){',
' webFile = SD.open("' + filename + '", FILE_READ);',
' String finalString ="";',
' while (webFile.available())',
' {',
' finalString+=(char)webFile.read();',
' }',
' return finalString;',
'}'];
var functionName = Blockly.Arduino.addFunction(
'generateHTML', func.join('\n'));
var code = functionName + '()';
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
-3
View File
@@ -10,9 +10,6 @@ const colours = {
text: 160,
variables: 330,
audio: 250,
arrays: 33,
mqtt: 90,
webserver: 40
}
+3 -5
View File
@@ -60,7 +60,7 @@ export const DECIMAL = {
/** Array/List of items. */
export const ARRAY = {
typeId: 'Array',
typeName: 'Array',
typeName: 'array',
typeMsgName: 'ARD_TYPE_ARRAY',
compatibleTypes: []
}
@@ -87,16 +87,14 @@ export const CHILD_BLOCK_MISSING = {
}
const compatibleTypes = {
Array: ['Array'],
boolean: ['boolean'],
int: ['int', 'long', 'double', 'float'],
int: ['int'],
char: ['char'],
String: ['String'],
void: ['void'],
long: ['int', 'long'],
double: ['int', 'long', 'double'],
float: ['int', 'long', 'double', 'float'],
null: ['null']
float: ['int', 'long', 'double', 'float']
}
+6 -256
View File
@@ -1,3 +1,7 @@
// import * as Blockly from 'blockly/core';
// https://developers.google.com/blockly/guides/configure/web/translations
const Blockly = {};
Blockly.Msg = {};
@@ -272,11 +276,6 @@ Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://de.wikipedia.org/wiki/Pro
Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Rufe einen Funktionsblock ohne Rückgabewert auf.";
Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29";
Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Rufe einen Funktionsblock mit Rückgabewert auf.";
Blockly.Msg.PROCEDURES_CALL = "Rufe";
Blockly.Msg.PROCEDURES_CALL_END = "auf";
Blockly.Msg.PROCEDURES_DEFNORETURN = "Erstelle Funktion";
Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "mit Eingabeparameter:";
Blockly.Msg.PROCEDURES_DEFRETURN_RETURN_TYPE = "Rückgabetype";
Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "mit:";
Blockly.Msg.PROCEDURES_CREATE_DO = "Erzeuge \"Aufruf %1\"";
Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Beschreibe diese Funktion …";
@@ -611,7 +610,6 @@ Blockly.Msg.senseBox_osem_connection = "Verbinde mit openSenseMap";
Blockly.Msg.senseBox_osem_exposure = "Typ";
Blockly.Msg.senseBox_osem_stationary = "Stationär";
Blockly.Msg.senseBox_osem_mobile = "Mobil";
Blockly.Msg.senseBox_osem_access_token = "API Schlüssel";
Blockly.Msg.senseBox_sds011 = "Feinstaubsensor";
Blockly.Msg.senseBox_sds011_dimension = "in µg/m³ an";
Blockly.Msg.senseBox_sds011_pm25 = "PM2.5";
@@ -652,11 +650,7 @@ Blockly.Msg.sensebox_display_fillCircle_radius = "Radius";
Blockly.Msg.sensebox_display_drawRectangle = "Zeichne Rechteck";
Blockly.Msg.sensebox_display_drawRectangle_width = "Breite";
Blockly.Msg.sensebox_display_drawRectangle_height = "Höhe";
Blockly.Msg.senseBox_display_filled = "Ausgefüllt";
Blockly.Msg.senseBox_display_fastPrint_show = "Zeige Messwerte";
Blockly.Msg.senseBox_display_fastPrint_title = "Titel";
Blockly.Msg.senseBox_display_fastPrint_value = "Messwert";
Blockly.Msg.senseBox_display_fastPrint_dimension = "Einheit";
Blockly.Msg.senseBox_display_filled = "Ausgefüllt"
// GPS
Blockly.Msg.senseBox_gps_getValues = "GPS Modul";
Blockly.Msg.senseBox_gps_getValues_tip = "ruft das GPS Signal ab";
@@ -777,251 +771,7 @@ Blockly.Msg.senseBox_telegram_do = "Telegram mache"
Blockly.Msg.senseBox_telegram_do_on_message = "bei Nachricht"
Blockly.Msg.senseBox_telegram_message = "Nachricht"
Blockly.Msg.senseBox_telegram_send = "Sende Nachricht"
//SCD30 CO2 Sensor
Blockly.Msg.senseBox_scd30 = "CO2 Sensor (Sensirion SCD30)";
Blockly.Msg.senseBox_scd_tip = "Gibt den Wert des CO2 Sensors";
Blockly.Msg.senseBox_scd_co2 = "CO2 in ppm";
//WS2818 RGB LED
Blockly.Msg.senseBox_ws2818_rgb_led = "senseBox WS2812 - RGB LED";
Blockly.Msg.senseBox_ws2818_rgb_led_position = "Position";
Blockly.Msg.senseBox_ws2818_rgb_led_brightness = "Helligkeit";
/***
* MQTT
*/
Blockly.Msg.senseBox_mqtt_init = "Verbinde mit MQTT Broker";
Blockly.Msg.senseBox_mqtt_server = "Server";
Blockly.Msg.senseBox_mqtt_port = "Port";
Blockly.Msg.senseBox_mqtt_username = "Benutzername";
Blockly.Msg.senseBox_mqtt_password = "Passwort";
Blockly.Msg.sensebox_mqtt_subscribe = "Subscribe to Feed"
Blockly.Msg.senseBox_mqtt_publish = "Sende an Feed/Topic";
/**
* Typed Variable Modal
*
*/
Blockly.Msg.TYPED_VAR_MODAL_CONFIRM_BUTTON = "Ok";
Blockly.Msg.TYPED_VAR_MODAL_VARIABLE_NAME_LABEL = "Variablen Name: ";
Blockly.Msg.TYPED_VAR_MODAL_TYPES_LABEL = "Variable Typen";
Blockly.Msg.TYPED_VAR_MODAL_CANCEL_BUTTON = "Abbrechen";
Blockly.Msg.TYPED_VAR_MODAL_TITLE = "Erstelle Variable";
Blockly.Msg.TYPED_VAR_MODAL_INVALID_NAME = "Der Name ist ungültig, bitte versuche einen anderen."
/**
* Add Translation for Blocks above
* ---------------------------------------------------------------
* Add Translation for the UI below
*/
/**
* Toolbox
*/
Blockly.Msg.toolbox_sensors = "Sensoren";
Blockly.Msg.toolbox_logic = "Logik";
Blockly.Msg.toolbox_loops = "Schleifen";
Blockly.Msg.toolbox_math = "Mathematik";
Blockly.Msg.toolbox_io = "Eingang/Ausgang";
Blockly.Msg.toolbox_time = "Zeit";
Blockly.Msg.toolbox_functions = "Funktionen";
Blockly.Msg.toolbox_variables = "Variablen";
/**
* Tooltips
*
*/
Blockly.Msg.tooltip_compile_code = "Code kompilieren"
Blockly.Msg.tooltip_save_blocks = "Blöcke speichern";
Blockly.Msg.tooltip_open_blocks = "Blöcke öffnen";
Blockly.Msg.tooltip_screenshot = "Screenshot erstellen";
Blockly.Msg.tooltip_clear_workspace = "Workspace zurücksetzen";
Blockly.Msg.tooltip_share_blocks = "Blöcke teilen";
Blockly.Msg.tooltip_show_code = "Code anzeigen";
Blockly.Msg.tooltip_hide_code = "Code ausblenden"
Blockly.Msg.tooltip_delete_project = "Projekt löschen"
Blockly.Msg.tooltip_project_name = "Name des Projektes"
Blockly.Msg.tooltip_download_project = "Projekt herunterladen"
Blockly.Msg.tooltip_open_project = "Projekt öffnen"
Blockly.Msg.tooltip_update_project = "Projekt aktualisieren"
Blockly.Msg.tooltip_save_project = "Projekt speichern"
Blockly.Msg.tooltip_create_project = "Projekt erstellen"
Blockly.Msg.tooltip_share_project = "Projekt teilen"
Blockly.Msg.tooltip_reset_workspace = "Workspace zurücksetzen"
Blockly.Msg.tooltip_copy_link = "Link kopieren"
Blockly.Msg.tooltip_trashcan_hide = 'gelöschte Blöcke ausblenden'
Blockly.Msg.tooltip_trashcan_delete = 'Blöcke endgültig löschen'
Blockly.Msg.tooltip_project_title = "Titel des Projektes"
Blockly.Msg.tooltip_check_solution = "Lösung kontrollieren"
/**
* Messages
*
*/
Blockly.Msg.messages_delete_project_failed = "Fehler beim Löschen des Projektes. Versuche es noch einmal."
Blockly.Msg.messages_reset_workspace_success = "Das Projekt wurde erfolgreich zurückgesetzt"
Blockly.Msg.messages_PROJECT_UPDATE_SUCCESS = "Das Projekt wurde erfolgreich aktualisiert."
Blockly.Msg.messages_GALLERY_UPDATE_SUCCESS = "Das Galerie-Projekt wurde erfolgreich aktualisiert."
Blockly.Msg.messages_PROJECT_UPDATE_FAIL = "Fehler beim Aktualisieren des Projektes. Versuche es noch einmal."
Blockly.Msg.messages_GALLERY_UPDATE_FAIL = "Fehler beim Aktualisieren des Galerie-Projektes. Versuche es noch einmal."
Blockly.Msg.messages_gallery_save_fail_1 = "Fehler beim Speichern des "
Blockly.Msg.messages_gallery_save_fail_2 = "Projektes. Versuche es noch einmal."
Blockly.Msg.messages_SHARE_SUCCESS = 'Programm teilen'
Blockly.Msg.messages_SHARE_FAIL = "Fehler beim Erstellen eines Links zum Teilen deines Programmes. Versuche es noch einmal."
Blockly.Msg.messages_copylink_success = 'Link erfolgreich in Zwischenablage gespeichert.'
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_GET_TUTORIAL_FAIL = 'Zurück zur Tutorials-Übersicht'
Blockly.Msg.messages_LOGIN_FAIL = 'Der Benutzername oder das Passwort ist nicht korrekt.'
/**
* Share Dialog
*/
Blockly.Msg.sharedialog_headline = "Dein Link wurde erstellt.";
Blockly.Msg.sharedialog_text = "Über den folgenden Link kannst du dein Programm teilen.";
/**
* Project rename Dialog
*/
Blockly.Msg.renamedialog_headline = "Projekt benennen";
Blockly.Msg.renamedialog_text = "Bitte gib einen Namen für das Projekt ein und bestätige diesen mit einem Klick auf 'Bestätigen'."
/**
* Compile Dialog
*
*/
Blockly.Msg.compiledialog_headline = "Fehler"
Blockly.Msg.compiledialog_text = "Beim kompilieren ist ein Fehler aufgetreten. Überprüfe deine Blöcke und versuche es erneut"
/**
* Buttons
*
*/
Blockly.Msg.button_cancel = "Abbrechen";
Blockly.Msg.button_close = "Schließen";
Blockly.Msg.button_accept = "Bestätigen";
Blockly.Msg.button_compile = "Kompilieren";
Blockly.Msg.button_create_variableCreate = "Erstelle Variable";
Blockly.Msg.button_back = "Zurück"
Blockly.Msg.button_next = "nächster Schritt"
Blockly.Msg.button_tutorial_overview = "Tutorial Übersicht"
Blockly.Msg.button_login = "Anmelden"
/**
*
*/
Blockly.Msg.filename = "Dateiname";
Blockly.Msg.projectname = "Projektname";
/**
* Settings
*/
Blockly.Msg.settings_head = "Einstellungen"
Blockly.Msg.settings_language = "Sprache"
Blockly.Msg.settings_language_text = "Auswahl der Sprache gilt für die gesamte Anwendung. Es kann zwischen Deutsch und Englisch unterschieden werden."
Blockly.Msg.settings_language_de = "Deutsch"
Blockly.Msg.settings_language_en = "Englisch"
Blockly.Msg.settings_renderer = "Renderer"
Blockly.Msg.settings_renderer_text = "Der eingestellte Renderer bestimmt das Aussehen der Blöcke. Es kann zwischen 'Geras' und 'Zelos' unterschieden werden, wobei 'Zelos' insbesondere für eine Touch-Anwendung geeignet ist."
Blockly.Msg.settings_statistics = "Statistiken"
Blockly.Msg.settings_statistics_text = "Die Anzeige von Statistiken zur Nutzung der Blöcke oberhalb der Arbeitsfläche kann ein- oder ausgeblendet werden."
Blockly.Msg.settings_statistics_on = "An"
Blockly.Msg.settings_statistics_off = "Aus"
/**
* 404
*/
Blockly.Msg.notfound_head = "Die von Ihnen angeforderte Seite kann nicht gefunden werden."
Blockly.Msg.notfound_text = "Die gesuchte Seite wurde möglicherweise entfernt, ihr Name wurde geändert oder sie ist vorübergehend nicht verfügbar."
/**
* Labels
*/
Blockly.Msg.labels_donotshowagain = 'Dialog nicht mehr anzeigen'
Blockly.Msg.labels_here = "hier"
Blockly.Msg.labels_username = 'E-Mail oder Nutzername'
Blockly.Msg.labels_password = "Passwort"
/**
* Badges
*/
Blockly.Msg.badges_explaination = "Eine Übersicht über alle erhaltenen Badges im Kontext Blockly for senseBox findest du "
Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_01 = "Herzlichen Glückwunsch! Du hast den Badge "
Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_02 = " erhalten."
/**
* Tutorials
*/
Blockly.Msg.tutorials_assessment_task = "Aufgabe"
Blockly.Msg.tutorials_hardware_head = "Für die Umsetzung benötigst du folgende Hardware:"
Blockly.Msg.tutorials_hardware_moreInformation = "Weitere Informationen zur Hardware-Komponente findest du"
Blockly.Msg.tutorials_hardware_here = "hier";
Blockly.Msg.tutorials_requirements = "Bevor du mit diesem Tutorial fortfährst solltest du folgende Tutorials erfolgreich abgeschlossen haben:"
/**
* Tutorial Builder
*/
Blockly.Msg.builder_solution = "Lösung"
Blockly.Msg.builder_solution_submit = "Lösung einreichen"
Blockly.Msg.builder_example_submit = "Beispiel einreichen"
Blockly.Msg.builder_comment = "Anmerkung: Man kann den initialen Setup()- bzw. Endlosschleifen()-Block löschen. Zusätzlich ist es möglich u.a. nur einen beliebigen Block auszuwählen, ohne dass dieser als deaktiviert dargestellt wird."
Blockly.Msg.builder_hardware_order = "Beachte, dass die Reihenfolge des Auswählens maßgebend ist."
Blockly.Msg.builder_hardware_helper = "Wähle mindestens eine Hardware-Komponente aus."
Blockly.Msg.builder_requirements_head = "Voraussetzungen"
Blockly.Msg.builder_requirements_order = "Beachte, dass die Reihenfolge des Anhakens maßgebend ist."
/**
* Login
*/
Blockly.Msg.login_head = "Anmelden"
Blockly.Msg.login_osem_account_01 = "Du benötigst einen "
Blockly.Msg.login_osem_account_02 = "Account um dich einzuloggen"
Blockly.Msg.login_lostpassword = "Du hast dein Passwort vergessen?"
Blockly.Msg.login_createaccount = "Falls du noch keinen Account hast erstellen einen auf "
/**
* Navbar
*/
Blockly.Msg.navbar_tutorials = "Tutorials"
Blockly.Msg.navbar_tutorialbuilder = "Tutorial erstellen"
Blockly.Msg.navbar_gallery = "Gallerie"
Blockly.Msg.navbar_projects = "Projekte"
Blockly.Msg.navbar_menu = "Menü"
Blockly.Msg.navbar_login = "Einloggen"
Blockly.Msg.navbar_mybadges = "myBadges"
Blockly.Msg.navbar_account = "Konto"
Blockly.Msg.navbar_logout = "Abmelden"
Blockly.Msg.navbar_settings = "Einstellungen"
/**
* Codeviewer
*/
Blockly.Msg.codeviewer_arduino = "Arduino Quellcode"
Blockly.Msg.codeviewer_xml = "XML Blöcke"
export const De = Blockly.Msg;
+7 -238
View File
@@ -1,3 +1,7 @@
// import * as Blockly from 'blockly/core';
// https://developers.google.com/blockly/guides/configure/web/translations
const Blockly = {};
Blockly.Msg = {};
@@ -267,24 +271,20 @@ Blockly.Msg.NEW_VARIABLE = "New variable...";
Blockly.Msg.NEW_VARIABLE_TITLE = "New variable name:";
Blockly.Msg.ORDINAL_NUMBER_SUFFIX = "";
Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements";
Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with inputs:";
Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:";
Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29";
Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'.";
Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29";
Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output.";
Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with Inputs:";
Blockly.Msg.PROCEDURES_CALL = "Call";
Blockly.Msg.PROCEDURES_CALL_END = '';
Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with:";
Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'";
Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function...";
Blockly.Msg.PROCEDURES_DEFNORETURN = "Create Function";
Blockly.Msg.PROCEDURES_DEFNORETURN_DO = "";
Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29";
Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something";
Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to";
Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output.";
Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29";
Blockly.Msg.PROCEDURES_DEFRETURN_RETURN_TYPE = "return Type";
Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "return";
Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output.";
Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters.";
@@ -613,11 +613,6 @@ Blockly.Msg.senseBox_display_printDisplay_y = "y-coordinates";
Blockly.Msg.senseBox_display_setSize = "set font size to";
Blockly.Msg.senseBox_display_setSize_tip = "Change the font size. Set a Value between 1-10.";
Blockly.Msg.senseBox_display_white = "White";
Blockly.Msg.senseBox_display_fastPrint_dimension = "Unit";
Blockly.Msg.senseBox_display_fastPrint_show = "Show Measurements";
Blockly.Msg.senseBox_display_fastPrint_tip = "Show two measurements with title and dimension on the display";
Blockly.Msg.senseBox_display_fastPrint_title = "Title";
Blockly.Msg.senseBox_display_fastPrint_value = "Measurement";
Blockly.Msg.senseBox_foto = "Light Dependent Resistor";
Blockly.Msg.senseBox_foto_tip = "simple light depending resistor, gives values between 0 and 1023";
Blockly.Msg.senseBox_gas = "Gas (VOC)";
@@ -681,7 +676,6 @@ Blockly.Msg.senseBox_osem_host = "opensensemap.org";
Blockly.Msg.senseBox_osem_host_workshop = "workshop.opensensemap.org";
Blockly.Msg.senseBox_osem_mobile = "Mobile";
Blockly.Msg.senseBox_osem_stationary = "Stationary";
Blockly.Msg.senseBox_osem_access_token = "API Key";
Blockly.Msg.senseBox_output_filename = "filename";
Blockly.Msg.senseBox_output_format = "format:";
Blockly.Msg.senseBox_output_linebreak = "linebreak";
@@ -759,232 +753,7 @@ Blockly.Msg.sensebox_display_show_tip = "Print on Display";
Blockly.Msg.sensebox_sd_filename = "data";
Blockly.Msg.sensebox_soil_smt50 = "Soil Moisture and Temperature (SMT50)";
Blockly.Msg.sensebox_web_readHTML_filename = "File:";
//SCD30 CO2 Sensor
Blockly.Msg.senseBox_scd30 = "CO2 Sensor (Sensirion SCD30)";
Blockly.Msg.senseBox_scd_co2 = "CO2 in ppm";
Blockly.Msg.senseBox_scd_tip = "Returns value of the CO2 Sensor";
//WS2818 RGB LED
Blockly.Msg.senseBox_ws2818_rgb_led = "senseBox WS2812 - RGB LED";
Blockly.Msg.senseBox_ws2818_rgb_led_brightness = "Helligkeit";
Blockly.Msg.senseBox_ws2818_rgb_led_position = "Position";
/***
* MQTT
*/
Blockly.Msg.senseBox_mqtt_init = "Connect to MQTT Broker";
Blockly.Msg.senseBox_mqtt_server = "Server";
Blockly.Msg.senseBox_mqtt_port = "Port";
Blockly.Msg.senseBox_mqtt_username = "Username";
Blockly.Msg.senseBox_mqtt_password = "Password";
Blockly.Msg.sensebox_mqtt_subscribe = "Subscribe to Feed"
Blockly.Msg.senseBox_mqtt_publish = "Publish to Feed/Topic";
/**
* Add Translation for Blocks above
* ---------------------------------------------------------------
* Add Translation for the UI below
*/
/**
* Toolbox
*/
Blockly.Msg.toolbox_sensors = "Sensors";
Blockly.Msg.toolbox_logic = "Logic";
Blockly.Msg.toolbox_loops = "Loops";
Blockly.Msg.toolbox_math = "Math";
Blockly.Msg.toolbox_io = "Input/Output";
Blockly.Msg.toolbox_time = "Time";
Blockly.Msg.toolbox_functions = "Functions";
Blockly.Msg.toolbox_variables = "Variables";
/**
* Tooltips
*
*/
Blockly.Msg.tooltip_compile_code = "Compile code"
Blockly.Msg.tooltip_save_blocks = "Save blocks";
Blockly.Msg.tooltip_open_blocks = "Open blocks";
Blockly.Msg.tooltip_screenshot = "Download screenshot";
Blockly.Msg.tooltip_clear_workspace = "Reset workspace";
Blockly.Msg.tooltip_share_blocks = "Share blocks";
Blockly.Msg.tooltip_show_code = "Show code";
Blockly.Msg.tooltip_hide_code = "Hide code "
Blockly.Msg.tooltip_delete_project = "Delete project"
Blockly.Msg.tooltip_project_name = "Project name"
Blockly.Msg.tooltip_download_project = "Download project"
Blockly.Msg.tooltip_open_project = "Open project"
Blockly.Msg.tooltip_update_project = "Update project"
Blockly.Msg.tooltip_save_project = "Save project"
Blockly.Msg.tooltip_create_project = "Create project"
Blockly.Msg.tooltip_share_project = "Share project"
Blockly.Msg.tooltip_reset_workspace = "Reset workspace"
Blockly.Msg.tooltip_copy_link = "Cooy link"
Blockly.Msg.tooltip_trashcan_hide = "hide deleted blocks"
Blockly.Msg.tooltip_trashcan_delete = "empty trashcan"
Blockly.Msg.tooltip_project_title = "Project title"
Blockly.Msg.tooltip_check_solution = "Check solution"
/**
* Messages
*
*/
Blockly.Msg.messages_delete_project_failed = "Error deleting the project. Try again."
Blockly.Msg.messages_reset_workspace_success = "The project has been successfully reset."
Blockly.Msg.messages_PROJECT_UPDATE_SUCCESS = "The project was successfully updated."
Blockly.Msg.messages_GALLERY_UPDATE_SUCCESS = "The gallery project was successfully updated."
Blockly.Msg.messages_PROJECT_UPDATE_FAIL = "Error updating the project. Try again."
Blockly.Msg.messages_GALLERY_UPDATE_FAIL = "Error updating the gallery project. Try again."
Blockly.Msg.messages_gallery_save_fail_1 = "Error saving the "
Blockly.Msg.messages_gallery_save_fail_2 = "Project. Try again."
Blockly.Msg.messages_SHARE_SUCCESS = 'Share program'
Blockly.Msg.messages_SHARE_FAIL = "Error creating a link to share your program. Try again."
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_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."
/**
* Share Dialog
*/
Blockly.Msg.sharedialog_headline = "Your link has been created.";
Blockly.Msg.sharedialog_text = "You can share your program using the following link.";
/**
* Project rename Dialog
*/
Blockly.Msg.renamedialog_headline = "Rename project";
Blockly.Msg.renamedialog_text = "Please enter a name for the project and confirm it by clicking 'Confirm'."
/**
* Compile Dialog
*
*/
Blockly.Msg.compiledialog_headline = "Error"
Blockly.Msg.compiledialog_text = "While compiling an error occured. Please check your blocks and try again"
/**
* Buttons
*
*/
Blockly.Msg.button_cancel = "Cancel";
Blockly.Msg.button_close = "Close";
Blockly.Msg.button_accept = "Ok";
Blockly.Msg.button_compile = "Compile";
Blockly.Msg.button_create_variableCreate = "Create Variable";
Blockly.Msg.button_back = "Back"
Blockly.Msg.button_next = "Next step"
Blockly.Msg.button_tutorial_overview = "Tutorial overview"
Blockly.Msg.button_login = "Login"
/**
*
*/
Blockly.Msg.filename = "Filename";
Blockly.Msg.projectname = "Projectname";
/**
* 404
*/
Blockly.Msg.notfound_head = "The page you requested cannot be found."
Blockly.Msg.notfound_text = "The page you are looking for may have been removed, its name changed, or it may be temporarily unavailable."
/**
* Labels
*/
Blockly.Msg.labels_donotshowagain = 'Do not show dialog again'
Blockly.Msg.labels_here = 'here'
Blockly.Msg.labels_username = 'Email or username'
Blockly.Msg.labels_password = "Password"
/**
* Badges
*/
Blockly.Msg.badges_explaination = "An overview of all badges received in the Blockly for senseBox context can be found "
Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_01 = "Congratulations! You have received the badge "
Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_02 = "."
/**
* Tutorials
*/
Blockly.Msg.tutorials_assessment_task = "Task"
Blockly.Msg.tutorials_hardware_head = "For the implementation you need the following hardware:"
Blockly.Msg.tutorials_hardware_moreInformation = "You can find more information about the hardware component."
Blockly.Msg.tutorials_hardware_here = "here";
Blockly.Msg.tutorials_requirements = "Before continuing with this tutorial, you should have successfully completed the following tutorials:"
/**
* Tutorial Builder
*/
Blockly.Msg.builder_solution = "Solution"
Blockly.Msg.builder_solution_submit = "Submit Solution"
Blockly.Msg.builder_example_submit = "Submit example"
Blockly.Msg.builder_comment = "Note: You can delete the initial setup() or infinite loop() block. Additionally, it is possible to select only any block, among others, without displaying it as disabled."
Blockly.Msg.builder_hardware_order = "Note that the order of selection is authoritative."
Blockly.Msg.builder_hardware_helper = "Select at least one hardware component."
Blockly.Msg.builder_requirements_head = "Requirements."
Blockly.Msg.builder_requirements_order = "Note that the order of ticking is authoritative."
/**
* Login
*/
Blockly.Msg.login_head = "Login"
Blockly.Msg.login_osem_account_01 = "You need to have an "
Blockly.Msg.login_osem_account_02 = "Account to login"
Blockly.Msg.login_lostpassword = "Lost your password?"
Blockly.Msg.login_createaccount = "If you don't have an openSenseMap account please register on "
/**
* Settings
*/
Blockly.Msg.settings_head = "Settings"
Blockly.Msg.settings_language = "Language"
Blockly.Msg.settings_language_text = "Selection of the language applies to the entire application. A distinction can be made between German and English."
Blockly.Msg.settings_language_de = "German"
Blockly.Msg.settings_language_en = "English"
Blockly.Msg.settings_renderer = "Renderer"
Blockly.Msg.settings_renderer_text = "The selected renderer determines the appearance of the blocks. A distinction can be made between 'Geras' and 'Zelos', whereby 'Zelos' is particularly suitable for a touch application."
Blockly.Msg.settings_statistics = "Statistics"
Blockly.Msg.settings_statistics_text = "The display of statistics on the usage of the blocks above the workspace can be shown or hidden."
Blockly.Msg.settings_statistics_on = "On"
Blockly.Msg.settings_statistics_off = "Off"
/**
* Navbar
*/
Blockly.Msg.navbar_tutorials = "Tutorials"
Blockly.Msg.navbar_tutorialbuilder = "Create tutorial"
Blockly.Msg.navbar_gallery = "Gallery"
Blockly.Msg.navbar_projects = "Projects"
Blockly.Msg.navbar_menu = "Menu"
Blockly.Msg.navbar_login = "Login"
Blockly.Msg.navbar_mybadges = "myBadges"
Blockly.Msg.navbar_account = "Account"
Blockly.Msg.navbar_logout = "Logout"
Blockly.Msg.navbar_settings = "Settings"
Blockly.Msg.codeviewer_arduino = "Arduino Source Code"
Blockly.Msg.codeviewer_xml = "XML Blocks"
export const En = Blockly.Msg;
+10 -115
View File
@@ -2,6 +2,7 @@ import React from 'react';
import { Block, Value, Field, Shadow, Category } from '../';
import { getColour } from '../helpers/colour'
import '@blockly/block-plus-minus';
import { TypedVariableModal } from '@blockly/plugin-typed-variable-modal';
import * as Blockly from 'blockly/core';
@@ -13,14 +14,12 @@ class Toolbox extends React.Component {
componentDidUpdate() {
this.props.workspace.registerToolboxCategoryCallback('CREATE_TYPED_VARIABLE', this.createFlyout);
const typedVarModal = new TypedVariableModal(this.props.workspace, 'callbackName', [['SHORT_NUMBER', 'char'], ['NUMBER', 'int'], ['DECIMAL', 'float'], ['TEXT', 'String'], ['ARRAY', 'Array'], ['CHARACTER', 'char'], ['BOOLEAN', 'boolean'], ['NULL', 'void'], ['UNDEF', 'undefined']]);
const typedVarModal = new TypedVariableModal(this.props.workspace, 'callbackName', [['SHORT_NUMBER', 'char'], ['NUMBER', 'int'], ['DECIMAL', 'float'], ['TEXT', 'String'], ['CHARACTER', 'char'], ['BOOLEAN', 'boolean'], ['NULL', 'void'], ['UNDEF', 'undefined']]);
typedVarModal.init();
}
createFlyout(workspace) {
let xmlList = [];
// Add your button and give it a callback name.
const button = document.createElement('button');
button.setAttribute('text', 'Create Typed Variable');
@@ -38,7 +37,7 @@ class Toolbox extends React.Component {
render() {
return (
<xml xmlns="https://developers.google.com/blockly/xml" id="blockly" style={{ display: 'none' }} ref={this.props.toolbox}>
<Category name={Blockly.Msg.toolbox_sensors} colour={getColour().sensebox}>
<Category name="Sensoren" colour={getColour().sensebox}>
<Block type="sensebox_sensor_temp_hum" />
<Block type="sensebox_sensor_uv_light" />
<Block type="sensebox_sensor_bmx055_accelerometer" />
@@ -46,7 +45,6 @@ class Toolbox extends React.Component {
<Block type="sensebox_sensor_pressure" />
<Block type="sensebox_sensor_bme680_bsec" />
<Block type="sensebox_scd30" />
<Block type="sensebox_gps" />
<Block type="sensebox_sensor_ultrasonic_ranger" />
<Block type="sensebox_sensor_sound" />
<Block type="sensebox_button" />
@@ -63,33 +61,6 @@ class Toolbox extends React.Component {
<Category name="LED" colour={getColour().sensebox}>
<Block type="sensebox_rgb_led" />
<Block type="sensebox_led" />
<Block type="sensebox_ws2818_led">
<Value name="POSITION">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="BRIGHTNESS">
<Block type="math_number">
<Field name="NUM">30</Field>
</Block>
</Value>
<Value name="RED">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="GREEN">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="BLUE">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
</Block>
</Category>
<Category name="Display" colour={getColour().sensebox}>
<Block type="sensebox_display_beginDisplay" />
@@ -112,28 +83,6 @@ class Toolbox extends React.Component {
</Block>
</Value>
</Block>
<Block type="sensebox_display_fastPrint">
<Value name="Title1">
<Block type="text">
<Field name="TEXT">Title</Field>
</Block>
</Value>
<Value name="Dimension1">
<Block type="text">
<Field name="TEXT">Unit</Field>
</Block>
</Value>
<Value name="Title2">
<Block type="text">
<Field name="TEXT">Title</Field>
</Block>
</Value>
<Value name="Dimension2">
<Block type="text">
<Field name="TEXT">Unit</Field>
</Block>
</Value>
</Block >
<Block type="sensebox_display_plotDisplay">
<Value name="Title">
<Block type="text">
@@ -234,7 +183,7 @@ class Toolbox extends React.Component {
<Block type="sensebox_send_to_osem" />
</Category>
<Category id="catSenseBoxOutput_LoRa" name=" LoRa" colour={getColour().sensebox}>
<Category id="catSenseBoxOutput_LoRa_activation" name=" Aktivierung" colour={getColour().sensebox}>
<Category id="catSenseBoxOutput_LoRa_activation" name=" Aktiviereung" colour={getColour().sensebox}>
<Block type="sensebox_lora_initialize_otaa" />
<Block type="sensebox_lora_initialize_abp" />
</Category>
@@ -242,35 +191,6 @@ class Toolbox extends React.Component {
<Block type="sensebox_lora_message_send" />
<Block type="sensebox_send_lora_sensor_value" />
</Category>
<Category id="catSenseBoxOutput_Map" name=" TTN Mapper" colour={getColour().sensebox}>
<Block type="sensebox_lora_ttn_mapper">
<Value name="Latitude">
<Block type="sensebox_gps">
<Field name="dropdown">latitude</Field>
</Block>
</Value>
<Value name="Longitude">
<Block type="sensebox_gps">
<Field name="dropdown">longitude</Field>
</Block>
</Value>
<Value name="Altitude">
<Block type="sensebox_gps">
<Field name="dropdown">altitude</Field>
</Block>
</Value>
<Value name="pDOP">
<Block type="sensebox_gps">
<Field name="dropdown">pDOP</Field>
</Block>
</Value>
<Value name="Fix Type">
<Block type="sensebox_gps">
<Field name="dropdown">fixType</Field>
</Block>
</Value>
</Block>
</Category>
<Category id="catSenseBoxOutput_LoRa_cayenne" name=" Cayenne LPP" colour={getColour().sensebox}>
<Block type="sensebox_lora_cayenne_send" />
<Block type="sensebox_lora_cayenne_temperature" />
@@ -282,26 +202,7 @@ class Toolbox extends React.Component {
<Block type="sensebox_lora_cayenne_gps" />
</Category>
</Category>
<Category id="webserver" name="Webserver" colour={getColour().webserver}>
<Block type="sensebox_initialize_http_server"></Block>
<Block type="sensebox_http_on_client_connect"></Block>
<Block type="sensebox_ip_address"></Block>
<Block type="sensebox_http_method"></Block>
<Block type="sensebox_http_uri"></Block>
<Block type="sensebox_http_protocol_version"></Block>
<Block type="sensebox_http_user_agent"></Block>
<Block type="sensebox_generate_http_succesful_response"></Block>
<Block type="sensebox_generate_http_not_found_response"></Block>
<Block type="sensebox_generate_html_doc"></Block>
<Block type="sensebox_general_html_tag"></Block>
<Block type="sensebox_web_readHTML"></Block>
</Category>
<Category id="mqtt" name="MQTT" colour={getColour().mqtt}>
<Block type="sensebox_mqtt_setup" />
<Block type="sensebox_mqtt_publish" />
{/* <Block type="sensebox_mqtt_subscribe" /> */}
</Category>
<Category name={Blockly.Msg.toolbox_logic} colour={getColour().logic}>
<Category name="Logik" colour={getColour().logic}>
<Block type="controls_if" />
<Block type="controls_ifelse" />
<Block type="logic_compare" />
@@ -310,7 +211,7 @@ class Toolbox extends React.Component {
<Block type="logic_boolean" />
<Block type="switch_case" />
</Category>
<Category id="loops" name={Blockly.Msg.toolbox_loops} colour={getColour().loops}>
<Category id="loops" name="Schleifen" colour={getColour().loops}>
<Block type="controls_repeat_ext">
<Value name="TIMES">
<Block type="math_number">
@@ -349,7 +250,7 @@ class Toolbox extends React.Component {
<Block type="text_length" />
<Block type="text_isEmpty" />
</Category>
<Category id="time" name={Blockly.Msg.toolbox_time} colour={getColour().time}>
<Category id="time" name="Zeit" colour={getColour().time}>
<Block type="time_delay">
<Value name="DELAY_TIME_MILI">
<Block type="math_number">
@@ -369,7 +270,7 @@ class Toolbox extends React.Component {
<Block type="infinite_loop"></Block>
<Block type="sensebox_interval_timer"></Block>
</Category>
<Category id="math" name={Blockly.Msg.toolbox_math} colour={getColour().math}>
<Category id="catMath" name="Mathematik" colour={getColour().math}>
<Block type="math_number"></Block>
<Block type="math_arithmetic"></Block>
<Block type="math_single"></Block>
@@ -422,15 +323,9 @@ class Toolbox extends React.Component {
</Block>
<Block type="io_notone"></Block>
</Category>
<Category name={Blockly.Msg.toolbox_variables} colour={getColour().variables} custom="CREATE_TYPED_VARIABLE"></Category>
<Category name="Arrays" colour={getColour().arrays} >
<Block type="lists_create_empty" />
<Block type="array_getIndex" />
<Block type="lists_length" />
</Category>
<Category name={Blockly.Msg.toolbox_functions} colour={getColour().procedures} custom="PROCEDURE"></Category>
<Category name="Variablen" colour={getColour().variables} custom="CREATE_TYPED_VARIABLE"></Category>;
<sep></sep>
<Category name={Blockly.Msg.toolbox_io} colour={getColour().io}>
<Category name="Eingang/Ausgang" colour={getColour().io}>
<Block type="io_digitalwrite"></Block>
<Block type="io_digitalread"></Block>
<Block type="io_builtin_led"></Block>
+2 -3
View File
@@ -13,7 +13,6 @@ import MuiAccordion from '@material-ui/core/Accordion';
import MuiAccordionSummary from '@material-ui/core/AccordionSummary';
import MuiAccordionDetails from '@material-ui/core/AccordionDetails';
import { Card } from '@material-ui/core';
import * as Blockly from 'blockly'
const Accordion = withStyles((theme) => ({
@@ -95,7 +94,7 @@ class CodeViewer extends Component {
>
<AccordionSummary>
<b style={{ fontSize: '20px', marginRight: '5px', width: '35px' }}>{curlyBrackets}</b>
<div style={{ margin: 'auto 5px 2px 0px' }}>{Blockly.Msg.codeviewer_arduino}</div>
<div style={{ margin: 'auto 5px 2px 0px' }}>Arduino Quellcode</div>
</AccordionSummary>
<AccordionDetails style={{ padding: 0, height: `calc(${this.state.componentHeight} - 50px - 50px)`, backgroundColor: 'white' }}>
<pre className="line-numbers" style={{ paddingBottom: 0, width: '100%', overflow: 'auto', scrollbarWidth: 'thin', height: 'calc(100% - 30px)', margin: '15px 0', paddingTop: 0, whiteSpace: 'pre-wrap', backgroundColor: 'white' }}>
@@ -113,7 +112,7 @@ class CodeViewer extends Component {
>
<AccordionSummary>
<b style={{ fontSize: '20px', marginRight: '5px', width: '35px' }}>{unequal}</b>
<div style={{ margin: 'auto 5px 2px 0px' }}>{Blockly.Msg.codeviewer_xml}</div>
<div style={{ margin: 'auto 5px 2px 0px' }}>XML Blöcke</div>
</AccordionSummary>
<AccordionDetails style={{ padding: 0, height: `calc(${this.state.componentHeight} - 50px - 50px)`, backgroundColor: 'white' }}>
<pre className="line-numbers" style={{ paddingBottom: 0, width: '100%', overflow: 'auto', scrollbarWidth: 'thin', height: 'calc(100% - 30px)', margin: '15px 0', paddingTop: 0, whiteSpace: 'pre-wrap', backgroundColor: 'white' }}>
@@ -1,11 +1,11 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { workspaceName } from '../../actions/workspaceActions';
import { workspaceName } from '../actions/workspaceActions';
import { detectWhitespacesAndReturnReadableResult } from '../../helpers/whitespace';
import { detectWhitespacesAndReturnReadableResult } from '../helpers/whitespace';
import Dialog from '../Dialog';
import Dialog from './Dialog';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
@@ -15,30 +15,21 @@ import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
import TextField from '@material-ui/core/TextField';
import { faClipboardCheck } from "@fortawesome/free-solid-svg-icons";
import { faCogs } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as Blockly from 'blockly/core';
const styles = (theme) => ({
backdrop: {
zIndex: theme.zIndex.drawer + 1,
color: '#fff',
},
iconButton: {
backgroundColor: theme.palette.button.compile,
button: {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
width: '40px',
height: '40px',
'&:hover': {
backgroundColor: theme.palette.button.compile,
color: theme.palette.primary.contrastText,
}
},
button: {
backgroundColor: theme.palette.button.compile,
color: theme.palette.primary.contrastText,
'&:hover': {
backgroundColor: theme.palette.button.compile,
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
}
}
@@ -86,7 +77,7 @@ class Compile extends Component {
})
.catch(err => {
console.log(err);
this.setState({ progress: false, file: false, open: true, title: Blockly.Msg.compiledialog_headline, content: Blockly.Msg.compiledialog_text });
this.setState({ progress: false, file: false, open: true, title: 'Fehler', content: 'Etwas ist beim Kompilieren schief gelaufen. Versuche es nochmal.' });
});
}
@@ -108,7 +99,7 @@ class Compile extends Component {
this.download();
}
else {
this.setState({ file: true, open: true, title: 'Projekt kompilieren', content: 'Bitte gib einen Namen für die Bennenung des zu kompilierenden Programms ein und bestätige diesen mit einem Klick auf \'Eingabe\'.' });
this.setState({ file: true, open: true, title: 'Blöcke kompilieren', content: 'Bitte gib einen Namen für die Bennenung des zu kompilierenden Programms ein und bestätige diesen mit einem Klick auf \'Eingabe\'.' });
}
}
@@ -120,17 +111,17 @@ class Compile extends Component {
return (
<div style={{}}>
{this.props.iconButton ?
<Tooltip title={Blockly.Msg.tooltip_compile_code} arrow style={{ marginRight: '5px' }}>
<Tooltip title='Blöcke kompilieren' arrow style={{ marginRight: '5px' }}>
<IconButton
className={this.props.classes.iconButton}
className={this.props.classes.button}
onClick={() => this.compile()}
>
<FontAwesomeIcon icon={faClipboardCheck} size="l" />
<FontAwesomeIcon icon={faCogs} size="xs" />
</IconButton>
</Tooltip>
:
<Button style={{ float: 'right', color: 'white' }} variant="contained" className={this.props.classes.button} onClick={() => this.compile()}>
<FontAwesomeIcon icon={faClipboardCheck} style={{ marginRight: '5px' }} /> Kompilieren
<Button style={{ float: 'right', color: 'white' }} variant="contained" color="primary" onClick={() => this.compile()}>
<FontAwesomeIcon icon={faCogs} style={{ marginRight: '5px' }} /> Kompilieren
</Button>
}
<Backdrop className={this.props.classes.backdrop} open={this.state.progress}>
@@ -142,7 +133,7 @@ class Compile extends Component {
content={this.state.content}
onClose={this.toggleDialog}
onClick={this.state.file ? () => { this.toggleDialog(); this.setState({ name: this.props.name }) } : this.toggleDialog}
button={this.state.file ? Blockly.Msg.button_cancel : Blockly.Msg.button_close}
button={this.state.file ? 'Abbrechen' : 'Schließen'}
>
{this.state.file ?
<div style={{ marginTop: '10px' }}>
-54
View File
@@ -1,54 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as Blockly from 'blockly/core';
import { De } from './Blockly/msg/de';
import { En } from './Blockly/msg/en';
import Navbar from './Navbar';
import Footer from './Footer';
import Routes from './Route/Routes';
import Cookies from './Cookies';
class Content extends Component {
componentDidMount() {
if (this.props.language === 'de_DE') {
Blockly.setLocale(De);
} else if (this.props.language === 'en_US') {
Blockly.setLocale(En);
}
}
componentDidUpdate(props){
if(props.language !== this.props.language){
if (this.props.language === 'de_DE') {
Blockly.setLocale(De);
} else if (this.props.language === 'en_US') {
Blockly.setLocale(En);
}
}
}
render() {
return (
<div className="wrapper">
<Navbar />
<Routes />
<Cookies />
<Footer />
</div>
);
}
}
Content.propTypes = {
language: PropTypes.string.isRequired
};
const mapStateToProps = state => ({
language: state.general.language
});
export default connect(mapStateToProps, null)(Content);
-25
View File
@@ -1,25 +0,0 @@
import CookieConsent from "react-cookie-consent";
import React, { Component } from 'react';
class Cookies extends Component {
render() {
return (
<CookieConsent
location="bottom"
buttonText="Okay!!"
cookieName="cookieConsent"
style={{ background: "#2B373B" }}
buttonStyle={{ background: "white", color: "#4EAF47", fontSize: "1rem" }}
expires={150}
>
This website uses cookies to enhance the user experience.{" "}
</CookieConsent>
);
};
}
export default Cookies;
+8 -8
View File
@@ -7,14 +7,14 @@ import Typography from '@material-ui/core/Typography';
class Footer extends Component {
render() {
return (
<footer style={{ position: 'absolute', bottom: '0', width: '100%' }}>
<div style={{ minHeight: '30px', backgroundColor: '#4EAF47', textAlign: 'center', paddingTop: '2px' }}>
<div style={{ color: 'white', height: '100%' }}>
<Link to={"/impressum"} style={{ textDecoration: 'none', color: 'inherit' }}>Impressum</Link>
<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>
<a href="https://sensebox.de" style={{ textDecoration: 'none', color: 'inherit' }}>sensebox.de</a>
<footer style={{position:'absolute', bottom: '0', width: '100%'}}>
<div style={{minHeight:'30px', backgroundColor:'#DDDDDD', textAlign: 'center', paddingTop: '2px'}}>
<div style={{color: 'grey', height: '100%'}}>
<Link to={"/impressum"} style={{textDecoration: 'none', color: 'inherit'}}>Impressum</Link>
<Typography style={{margin: '0px 10px 0px 10px', display: 'initial', fontSize: '1rem'}}>|</Typography>
<Link to={"/ueberuns"} style={{textDecoration: 'none', color: 'inherit'}}>Über uns</Link>
<Typography style={{margin: '0px 10px 0px 10px', display: 'initial', fontSize: '1rem'}}>|</Typography>
<Link to={"/faq"} style={{textDecoration: 'none', color: 'inherit'}}>FAQ</Link>
</div>
</div>
</footer>
+13 -50
View File
@@ -4,15 +4,13 @@ import { connect } from 'react-redux';
import { clearStats, workspaceName } from '../actions/workspaceActions';
import * as Blockly from 'blockly/core';
import { createNameId } from 'mnemonic-id';
import WorkspaceStats from './Workspace/WorkspaceStats';
import WorkspaceFunc from './Workspace/WorkspaceFunc';
import WorkspaceStats from './WorkspaceStats';
import WorkspaceFunc from './WorkspaceFunc';
import BlocklyWindow from './Blockly/BlocklyWindow';
import CodeViewer from './CodeViewer';
import TrashcanButtons from './Workspace/TrashcanButtons';
import TrashcanButtons from './TrashcanButtons';
import HintTutorialExists from './Tutorial/HintTutorialExists';
import Snackbar from './Snackbar';
import Grid from '@material-ui/core/Grid';
import IconButton from '@material-ui/core/IconButton';
@@ -47,24 +45,10 @@ const styles = (theme) => ({
class Home extends Component {
state = {
codeOn: false,
snackbar: false,
type: '',
key: '',
message: ''
codeOn: false
}
componentDidMount() {
this.setState({ stats: window.localStorage.getItem('stats') });
if(!this.props.project){
this.props.workspaceName(createNameId());
}
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' });
}
}
componentDidUpdate(props) {
componentDidUpdate() {
/* Resize and reposition all of the workspace chrome (toolbox, trash,
scrollbars etc.) This should be called when something changes that requires
recalculating dimensions and positions of the trash, zoom, toolbox, etc.
@@ -90,15 +74,10 @@ class Home extends Component {
render() {
return (
<div>
{this.props.statistics ?
<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>
<div style={{ float: 'right', height: '40px', marginBottom: '20px' }}><WorkspaceFunc /></div>
<div style={{ float: 'left', height: '40px', position: 'relative' }}><WorkspaceStats /></div>
<Grid container spacing={2}>
<Grid item xs={12} md={this.state.codeOn ? 8 : 12} style={{ position: 'relative' }}>
<Grid item xs={12} md={this.state.codeOn ? 6 : 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}
@@ -109,24 +88,15 @@ class Home extends Component {
</IconButton>
</Tooltip>
<TrashcanButtons />
{this.props.project ?
< BlocklyWindow blocklyCSS={{ height: '80vH' }} initialXml={this.props.project.xml} />
: < BlocklyWindow blocklyCSS={{ height: '80vH' }} />
}
<BlocklyWindow blocklyCSS={{ height: '80vH' }} blockDisabled />
</Grid>
{this.state.codeOn ?
<Grid item xs={12} md={4}>
<Grid item xs={12} md={6}>
<CodeViewer />
</Grid>
: null}
: null}
</Grid>
<HintTutorialExists />
<Snackbar
open={this.state.snackbar}
message={this.state.message}
type={this.state.type}
key={this.state.key}
/>
</div>
);
};
@@ -134,15 +104,8 @@ class Home extends Component {
Home.propTypes = {
clearStats: PropTypes.func.isRequired,
workspaceName: PropTypes.func.isRequired,
message: PropTypes.object.isRequired,
statistics: PropTypes.bool.isRequired
workspaceName: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
message: state.message,
statistics: state.general.statistics
});
export default connect(mapStateToProps, { clearStats, workspaceName })(withStyles(styles, { withTheme: true })(Home));
export default connect(null, { clearStats, workspaceName })(withStyles(styles, { withTheme: true })(Home));
-47
View File
@@ -1,47 +0,0 @@
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class Impressum extends Component {
render() {
return (
<div style={{ margin: '0px 24px 0px 24px' }}>
<h1>Impressum</h1>
<h2>Angaben gemäß § 5 TMG:</h2>
Institut für Geoinformatik<br />
Heisenbergstraße 2<br />
Geo 1<br />
48149 Münster
<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>
Geschäftsführende Direktorin Prof. Dr. Angela Schwering<br />
Heisenbergstraße 2<br />
Geo 1<br />
48149 Münster
<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>
<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>
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>
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>
);
};
}
export default withRouter(Impressum);
+33 -75
View File
@@ -1,8 +1,5 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { logout } from '../actions/authActions';
import senseboxLogo from './sensebox_logo.svg';
@@ -19,12 +16,9 @@ import IconButton from '@material-ui/core/IconButton';
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 { faBars, faChevronLeft, faBuilding, faIdCard, faEnvelope, faCog, faChalkboardTeacher, faFolderPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as Blockly from 'blockly'
const styles = (theme) => ({
drawerWidth: {
@@ -51,32 +45,32 @@ class Navbar extends Component {
this.setState({ open: !this.state.open });
}
render() {
render(){
return (
<div>
<AppBar
position="relative"
style={{ height: '50px', marginBottom: this.props.tutorialIsLoading || this.props.projectIsLoading ? '0px' : '30px', boxShadow: this.props.tutorialIsLoading || this.props.projectIsLoading ? 'none' : '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)' }}
classes={{ root: this.props.classes.appBarColor }}
style={{height: '50px', marginBottom: '30px'}}
classes={{root: this.props.classes.appBarColor}}
>
<Toolbar style={{ height: '50px', minHeight: '50px', padding: 0, color: 'white' }}>
<Toolbar style={{height: '50px', minHeight: '50px', padding: 0, color: 'white'}}>
<IconButton
color="inherit"
onClick={this.toggleDrawer}
style={{ margin: '0 10px' }}
style={{margin: '0 10px'}}
>
<FontAwesomeIcon icon={faBars} />
</IconButton>
<Link to={"/"} style={{ textDecoration: 'none', color: 'inherit' }}>
<Link to={"/"} style={{textDecoration: 'none', color: 'inherit'}}>
<Typography variant="h6" noWrap>
senseBox Blockly
</Typography>
</Link>
<Link to={"/"} style={{ marginLeft: '10px' }}>
<img src={senseboxLogo} alt="senseBox-Logo" width="30" />
<Link to={"/"} style={{marginLeft: '10px'}}>
<img src={senseboxLogo} alt="senseBox-Logo" width="30"/>
</Link>
{/^\/tutorial(\/.*$|$)/g.test(this.props.location.pathname) ?
<Link to={"/tutorial"} style={{ textDecoration: 'none', color: 'inherit', marginLeft: '10px' }}>
<Link to={"/tutorial"} style={{textDecoration: 'none', color: 'inherit', marginLeft: '10px'}}>
<Typography variant="h6" noWrap>
Tutorial
</Typography>
@@ -88,78 +82,42 @@ class Navbar extends Component {
anchor="left"
onClose={this.toggleDrawer}
open={this.state.open}
classes={{ paper: this.props.classes.drawerWidth }}
ModalProps={{ keepMounted: true }} // Better open performance on mobile.
classes={{paper: this.props.classes.drawerWidth}}
ModalProps={{keepMounted: true}} // Better open performance on mobile.
>
<div style={{ height: '50px', cursor: 'pointer', color: 'white', padding: '0 22px' }} className={this.props.classes.appBarColor} onClick={this.toggleDrawer}>
<div style={{ display: ' table-cell', verticalAlign: 'middle', height: 'inherit', width: '0.1%' }}>
<Typography variant="h6" style={{ display: 'inline' }}>
{Blockly.Msg.navbar_menu}
<div style={{height: '50px', cursor: 'pointer', color: 'white', padding: '0 22px'}} className={this.props.classes.appBarColor} onClick={this.toggleDrawer}>
<div style={{display:' table-cell', verticalAlign: 'middle', height: 'inherit', width: '0.1%'}}>
<Typography variant="h6" style={{display:'inline'}}>
Menü
</Typography>
<div style={{ float: 'right' }}>
<div style={{float: 'right'}}>
<FontAwesomeIcon icon={faChevronLeft} />
</div>
</div>
</div>
<List>
{[{ text: Blockly.Msg.navbar_tutorials, icon: faChalkboardTeacher, link: "/tutorial" },
{ text: Blockly.Msg.navbar_tutorialbuilder, icon: faTools, link: "/tutorial/builder", restriction: this.props.user && this.props.user.blocklyRole !== 'user' && this.props.isAuthenticated },
{ text: Blockly.Msg.navbar_gallery, icon: faLightbulb, link: "/gallery" },
{ text: Blockly.Msg.navbar_projects, icon: faLayerGroup, link: "/project", restriction: this.props.isAuthenticated }].map((item, index) => {
if (item.restriction || Object.keys(item).filter(attribute => attribute === 'restriction').length === 0) {
return (
<Link to={item.link} key={index} style={{ textDecoration: 'none', color: 'inherit' }}>
<ListItem button onClick={this.toggleDrawer}>
<ListItemIcon><FontAwesomeIcon icon={item.icon} /></ListItemIcon>
<ListItemText primary={item.text} />
</ListItem>
</Link>
);
}
}
)}
{[{text: 'Tutorials', icon: faChalkboardTeacher, link: "/tutorial"}, {text: 'Tutorial-Builder', icon: faFolderPlus, link: "/tutorial/builder"}, {text: 'Einstellungen', icon: faCog, link: "/settings"}].map((item, index) => (
<Link to={item.link} key={index} style={{textDecoration: 'none', color: 'inherit'}}>
<ListItem button onClick={this.toggleDrawer}>
<ListItemIcon><FontAwesomeIcon icon={item.icon}/></ListItemIcon>
<ListItemText primary={item.text} />
</ListItem>
</Link>
))}
</List>
<Divider classes={{ root: this.props.classes.appBarColor }} style={{ marginTop: 'auto' }} />
<Divider classes={{root: this.props.classes.appBarColor}} style={{marginTop: 'auto'}}/>
<List>
{[{ text: Blockly.Msg.navbar_login, icon: faSignInAlt, link: '/user/login', restriction: !this.props.isAuthenticated },
{ text: Blockly.Msg.navbar_account, icon: faUserCircle, link: '/user', restriction: this.props.isAuthenticated },
{ text: Blockly.Msg.navbar_mybadges, icon: faCertificate, link: '/user/badge', restriction: this.props.isAuthenticated },
{ text: Blockly.Msg.navbar_logout, icon: faSignOutAlt, function: this.props.logout, restriction: this.props.isAuthenticated },
{ text: Blockly.Msg.navbar_settings, icon: faCog, link: "/settings" }].map((item, index) => {
if (item.restriction || Object.keys(item).filter(attribute => attribute === 'restriction').length === 0) {
return (
<Link to={item.link} key={index} style={{ textDecoration: 'none', color: 'inherit' }}>
<ListItem button onClick={item.function ? () => { item.function(); this.toggleDrawer(); } : this.toggleDrawer}>
<ListItemIcon><FontAwesomeIcon icon={item.icon} /></ListItemIcon>
<ListItemText primary={item.text} />
</ListItem>
</Link>
);
}
}
)}
{[{text: 'Über uns', icon: faBuilding},{text: 'Kontakt', icon: faEnvelope}, {text: 'Impressum', icon: faIdCard}].map((item, index) => (
<ListItem button key={index} onClick={this.toggleDrawer}>
<ListItemIcon><FontAwesomeIcon icon={item.icon}/></ListItemIcon>
<ListItemText primary={item.text} />
</ListItem>
))}
</List>
</Drawer>
{this.props.tutorialIsLoading || this.props.projectIsLoading ?
<LinearProgress style={{ marginBottom: '30px', boxShadow: '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)' }} />
: null}
</div>
);
}
}
Navbar.propTypes = {
tutorialIsLoading: PropTypes.bool.isRequired,
projectIsLoading: PropTypes.bool.isRequired,
isAuthenticated: PropTypes.bool.isRequired,
user: PropTypes.object
};
const mapStateToProps = state => ({
tutorialIsLoading: state.tutorial.progress,
projectIsLoading: state.project.progress,
isAuthenticated: state.auth.isAuthenticated,
user: state.auth.user
});
export default connect(mapStateToProps, { logout })(withStyles(styles, { withTheme: true })(withRouter(Navbar)));
export default withStyles(styles, {withTheme: true})(withRouter(Navbar));
+9 -17
View File
@@ -6,39 +6,31 @@ 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'
class NotFound 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: 'Error' }]} />
<Typography variant='h4' style={{ marginBottom: '5px' }}>{Blockly.Msg.notfound_head}</Typography>
<Typography variant='body1'>{Blockly.Msg.notfound_text}</Typography>
<Breadcrumbs content={[{link: this.props.location.pathname, title: 'Error'}]}/>
<Typography variant='h4' style={{marginBottom: '5px'}}>Die von Ihnen angeforderte Seite kann nicht gefunden werden.</Typography>
<Typography variant='body1'>Die gesuchte Seite wurde möglicherweise entfernt, ihr Name wurde geändert oder sie ist vorübergehend nicht verfügbar.</Typography>
{this.props.button ?
<Button
style={{ marginTop: '20px' }}
style={{marginTop: '20px'}}
variant="contained"
color="primary"
onClick={() => { this.props.history.push(this.props.button.link) }}
onClick={() => {this.props.history.push(this.props.button.link)}}
>
{this.props.button.title}
</Button>
:
:
<Button
style={{ marginTop: '20px' }}
style={{marginTop: '20px'}}
variant="contained"
color="primary"
onClick={() => { this.props.history.push('/') }}
onClick={() => {this.props.history.push('/')}}
>
{Blockly.Msg.button_back}
Zurück zur Startseite
</Button>
}
</div>
-187
View File
@@ -1,187 +0,0 @@
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class Privay extends Component {
render() {
return (
<div style={{ margin: '0px 24px 0px 24px' }}>
<h1>Datenschutzerklärung</h1>
<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>
Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen Kontaktdaten können Sie dem Impressum dieser Website entnehmen.
Wie erfassen wir Ihre Daten?
Ihre Daten werden zum einen dadurch erhoben, dass Sie uns diese mitteilen. Hierbei kann es sich z.B. um Daten handeln, die Sie in ein Kontaktformular eingeben.
Andere Daten werden automatisch beim Besuch der Website durch unsere IT-Systeme erfasst. Das sind vor allem technische Daten (z.B. Internetbrowser, Betriebssystem oder Uhrzeit des Seitenaufrufs). Die Erfassung dieser Daten erfolgt automatisch, sobald Sie unsere Website betreten.
<h4>Wofür nutzen wir Ihre Daten?</h4>
Ein Teil der Daten wird erhoben, um eine fehlerfreie Bereitstellung der Website zu gewährleisten. Andere Daten können zur Analyse Ihres Nutzerverhaltens verwendet werden.
<h4>Welche Rechte haben Sie bezüglich Ihrer Daten?</h4>
Sie haben jederzeit das Recht unentgeltlich Auskunft über Herkunft, Empfänger und Zweck Ihrer gespeicherten personenbezogenen Daten zu erhalten. Sie haben außerdem ein Recht, die Berichtigung, Sperrung oder Löschung dieser Daten zu verlangen. Hierzu sowie zu weiteren Fragen zum Thema Datenschutz können Sie sich jederzeit unter der im Impressum angegebenen Adresse an uns wenden. Des Weiteren steht Ihnen ein Beschwerderecht bei der zuständigen Aufsichtsbehörde zu.
<h4>Analyse-Tools und Tools von Drittanbietern</h4>
Beim Besuch unserer Website kann Ihr Surf-Verhalten statistisch ausgewertet werden. Das geschieht vor allem mit Cookies und mit sogenannten Analyseprogrammen. Die Analyse Ihres Surf-Verhaltens erfolgt in der Regel anonym; das Surf-Verhalten kann nicht zu Ihnen zurückverfolgt werden. Sie können dieser Analyse widersprechen oder sie durch die Nichtbenutzung bestimmter Tools verhindern. Detaillierte Informationen dazu finden Sie in der folgenden Datenschutzerklärung.
Sie können dieser Analyse widersprechen. Über die Widerspruchsmöglichkeiten werden wir Sie in dieser Datenschutzerklärung informieren.
<h2>2. Allgemeine Hinweise und Pflichtinformationen</h2>
<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.
Wir weisen darauf hin, dass die Datenübertragung im Internet(z.B.bei der Kommunikation per E - Mail) Sicherheitslücken aufweisen kann.Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich.
Die verantwortliche Stelle für die Datenverarbeitung auf dieser Website ist:
Institut für Geoinformatik
Heisenbergstraße 2
48149 Münster
Telefon: +49(251) 83 - 33 083
E - Mail: info@sensebox.de
Verantwortliche Stelle ist die natürliche oder juristische Person, die allein oder gemeinsam mit anderen über die Zwecke und Mittel der Verarbeitung von personenbezogenen Daten(z.B.Namen, E - Mail - Adressen o.Ä.) entscheidet.
<h4>Widerruf Ihrer Einwilligung zur Datenverarbeitung</h4>
Viele Datenverarbeitungsvorgänge sind nur mit Ihrer ausdrücklichen Einwilligung möglich.Sie können eine bereits erteilte Einwilligung jederzeit widerrufen.Dazu reicht eine formlose Mitteilung per E - Mail an uns.Die Rechtmäßigkeit der bis zum Widerruf erfolgten Datenverarbeitung bleibt vom Widerruf unberührt.
<h4>Beschwerderecht bei der zuständigen Aufsichtsbehörde</h4>
Im Falle datenschutzrechtlicher Verstöße steht dem Betroffenen ein Beschwerderecht bei der zuständigen Aufsichtsbehörde zu.Zuständige Aufsichtsbehörde in datenschutzrechtlichen Fragen ist der Landesdatenschutzbeauftragte des Bundeslandes, in dem unser Unternehmen seinen Sitz hat.Eine Liste der Datenschutzbeauftragten sowie deren Kontaktdaten können folgendem Link entnommen werden: https://www.bfdi.bund.de/DE/Infothek/Anschriften_Links/anschriften_links-node.html.
<h4>Recht auf Datenübertragbarkeit</h4>
Sie haben das Recht, Daten, die wir auf Grundlage Ihrer Einwilligung oder in Erfüllung eines Vertrags automatisiert verarbeiten, an sich oder an einen Dritten in einem gängigen, maschinenlesbaren Format aushändigen zu lassen.Sofern Sie die direkte Übertragung der Daten an einen anderen Verantwortlichen verlangen, erfolgt dies nur, soweit es technisch machbar ist.
<h4>SSL - bzw.TLS - Verschlüsselung</h4>
Diese Seite nutzt aus Sicherheitsgründen und zum Schutz der Übertragung vertraulicher Inhalte, wie zum Beispiel Bestellungen oder Anfragen, die Sie an uns als Seitenbetreiber senden, eine SSL - bzw.TLS - Verschlüsselung.Eine verschlüsselte Verbindung erkennen Sie daran, dass die Adresszeile des Browsers von “http://” auf “https://” wechselt und an dem Schloss-Symbol in Ihrer Browserzeile.
Wenn die SSL - bzw.TLS - Verschlüsselung aktiviert ist, können die Daten, die Sie an uns übermitteln, nicht von Dritten mitgelesen werden.
<h4>Auskunft, Sperrung, Löschung</h4>
Sie haben im Rahmen der geltenden gesetzlichen Bestimmungen jederzeit das Recht auf unentgeltliche Auskunft über Ihre gespeicherten personenbezogenen Daten, deren Herkunft und Empfänger und den Zweck der Datenverarbeitung und ggf.ein Recht auf Berichtigung, Sperrung oder Löschung dieser Daten.Hierzu sowie zu weiteren Fragen zum Thema personenbezogene Daten können Sie sich jederzeit unter der im Impressum angegebenen Adresse an uns wenden.
<h4>Widerspruch gegen Werbe - Mails</h4>
Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten Kontaktdaten zur Übersendung von nicht ausdrücklich angeforderter Werbung und Informationsmaterialien wird hiermit widersprochen.Die Betreiber der Seiten behalten sich ausdrücklich rechtliche Schritte im Falle der unverlangten Zusendung von Werbeinformationen, etwa durch Spam - E - Mails, vor.
<h2>3. Datenschutzbeauftragter</h2>
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>Telefon: +49(251) 83 - 33 083</p>
<p>E - Mail: info@sensebox.de</p>
<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.
Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren.Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein.
Cookies, die zur Durchführung des elektronischen Kommunikationsvorgangs oder zur Bereitstellung bestimmter, von Ihnen erwünschter Funktionen(z.B.Warenkorbfunktion) erforderlich sind, werden auf Grundlage von Art. 6 Abs. 1 lit.f DSGVO gespeichert.Der Websitebetreiber hat ein berechtigtes Interesse an der Speicherung von Cookies zur technisch fehlerfreien und optimierten Bereitstellung seiner Dienste.Soweit andere Cookies(z.B.Cookies zur Analyse Ihres Surfverhaltens) gespeichert werden, werden diese in dieser Datenschutzerklärung gesondert behandelt.
<h4> Server - Log - Dateien</h4>
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>
Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen.
Grundlage für die Datenverarbeitung ist Art. 6 Abs. 1 lit.b DSGVO, der die Verarbeitung von Daten zur Erfüllung eines Vertrags oder vorvertraglicher Maßnahmen gestattet.
<h4>Kontaktformular</h4>
Wenn Sie uns per Kontaktformular Anfragen zukommen lassen, werden Ihre Angaben aus dem Anfrageformular inklusive der von Ihnen dort angegebenen Kontaktdaten zwecks Bearbeitung der Anfrage und für den Fall von Anschlussfragen bei uns gespeichert.Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.
Die Verarbeitung der in das Kontaktformular eingegebenen Daten erfolgt somit ausschließlich auf Grundlage Ihrer Einwilligung(Art. 6 Abs. 1 lit.a DSGVO).Sie können diese Einwilligung jederzeit widerrufen.Dazu reicht eine formlose Mitteilung per E - Mail an uns.Die Rechtmäßigkeit der bis zum Widerruf erfolgten Datenverarbeitungsvorgänge bleibt vom Widerruf unberührt.
Die von Ihnen im Kontaktformular eingegebenen Daten verbleiben bei uns, bis Sie uns zur Löschung auffordern, Ihre Einwilligung zur Speicherung widerrufen oder der Zweck für die Datenspeicherung entfällt(z.B.nach abgeschlossener Bearbeitung Ihrer Anfrage).Zwingende gesetzliche Bestimmungen – insbesondere Aufbewahrungsfristen – bleiben unberührt.
<h4>Registrierung auf dieser Website</h4>
Sie können sich auf unserer Website registrieren, um zusätzliche Funktionen auf der Seite zu nutzen. Die dazu eingegebenen Daten verwenden wir nur zum Zwecke der Nutzung des jeweiligen Angebotes oder Dienstes, für den Sie sich registriert haben.Die bei der Registrierung abgefragten Pflichtangaben müssen vollständig angegeben werden.Anderenfalls werden wir die Registrierung ablehnen.
Für wichtige Änderungen etwa beim Angebotsumfang oder bei technisch notwendigen Änderungen nutzen wir die bei der Registrierung angegebene E - Mail - Adresse, um Sie auf diesem Wege zu informieren.
Die Verarbeitung der bei der Registrierung eingegebenen Daten erfolgt auf Grundlage Ihrer Einwilligung(Art. 6 Abs. 1 lit.a DSGVO).Sie können eine von Ihnen erteilte Einwilligung jederzeit widerrufen.Dazu reicht eine formlose Mitteilung per E - Mail an uns.Die Rechtmäßigkeit der bereits erfolgten Datenverarbeitung bleibt vom Widerruf unberührt.
Die bei der Registrierung erfassten Daten werden von uns gespeichert, solange Sie auf unserer Website registriert sind und werden anschließend gelöscht.Gesetzliche Aufbewahrungsfristen bleiben unberührt.
<h4>Kommentarfunktion auf dieser Website</h4>
Für die Kommentarfunktion auf dieser Seite werden neben Ihrem Kommentar auch Angaben zum Zeitpunkt der Erstellung des Kommentars, Ihre E - Mail - Adresse und, wenn Sie nicht anonym posten, der von Ihnen gewählte Nutzername gespeichert.
<h4>Speicherung der IP - Adresse</h4>
Unsere Kommentarfunktion speichert die IP - Adressen der Nutzer, die Kommentare verfassen.Da wir Kommentare auf unserer Seite nicht vor der Freischaltung prüfen, benötigen wir diese Daten, um im Falle von Rechtsverletzungen wie Beleidigungen oder Propaganda gegen den Verfasser vorgehen zu können.
<h4>Abonnieren von Kommentaren</h4>
Als Nutzer der Seite können Sie nach einer Anmeldung Kommentare abonnieren.Sie erhalten eine Bestätigungsemail, um zu prüfen, ob Sie der Inhaber der angegebenen E - Mail - Adresse sind.Sie können diese Funktion jederzeit über einen Link in den Info - Mails abbestellen.Die im Rahmen des Abonnierens von Kommentaren eingegebenen Daten werden in diesem Fall gelöscht; wenn Sie diese Daten für andere Zwecke und an anderer Stelle(z.B.Newsletterbestellung) an uns übermittelt haben, verbleiben die jedoch bei uns.
<h4>Speicherdauer der Kommentare</h4>
Die Kommentare und die damit verbundenen Daten(z.B.IP - Adresse) werden gespeichert und verbleiben auf unserer Website, bis der kommentierte Inhalt vollständig gelöscht wurde oder die Kommentare aus rechtlichen Gründen gelöscht werden müssen(z.B.beleidigende Kommentare).
<h4>Rechtsgrundlage</h4>
Die Speicherung der Kommentare erfolgt auf Grundlage Ihrer Einwilligung(Art. 6 Abs. 1 lit.a DSGVO).Sie können eine von Ihnen erteilte Einwilligung jederzeit widerrufen.Dazu reicht eine formlose Mitteilung per E - Mail an uns.Die Rechtmäßigkeit der bereits erfolgten Datenverarbeitungsvorgänge bleibt vom Widerruf unberührt.
<h4>Verarbeiten von Daten(Kunden - und Vertragsdaten)</h4>
Wir erheben, verarbeiten und nutzen personenbezogene Daten nur, soweit sie für die Begründung, inhaltliche Ausgestaltung oder Änderung des Rechtsverhältnisses erforderlich sind(Bestandsdaten).Dies erfolgt auf Grundlage von Art. 6 Abs. 1 lit.b DSGVO, der die Verarbeitung von Daten zur Erfüllung eines Vertrags oder vorvertraglicher Maßnahmen gestattet.Personenbezogene Daten über die Inanspruchnahme unserer Internetseiten(Nutzungsdaten) erheben, verarbeiten und nutzen wir nur, soweit dies erforderlich ist, um dem Nutzer die Inanspruchnahme des Dienstes zu ermöglichen oder abzurechnen.
Die erhobenen Kundendaten werden nach Abschluss des Auftrags oder Beendigung der Geschäftsbeziehung gelöscht.Gesetzliche Aufbewahrungsfristen bleiben unberührt.
{/* 5. Analyse Tools und Werbung
Matomo(ehemals Piwik)
Diese Website benutzt den Open Source Webanalysedienst Matomo.Matomo verwendet so genannte "Cookies".Das sind Textdateien, die auf Ihrem Computer gespeichert werden und die eine Analyse der Benutzung der Website durch Sie ermöglichen.Dazu werden die durch den Cookie erzeugten Informationen über die Benutzung dieser Website auf unserem Server gespeichert.Die IP - Adresse wird vor der Speicherung anonymisiert.
Matomo - Cookies verbleiben auf Ihrem Endgerät, bis Sie sie löschen.
Die Speicherung von Matomo - Cookies erfolgt auf Grundlage von Art. 6 Abs. 1 lit.f DSGVO.Der Websitebetreiber hat ein berechtigtes Interesse an der anonymisierten Analyse des Nutzerverhaltens, um sowohl sein Webangebot als auch seine Werbung zu optimieren.
Die durch den Cookie erzeugten Informationen über die Benutzung dieser Website werden nicht an Dritte weitergegeben.Sie können die Speicherung der Cookies durch eine entsprechende Einstellung Ihrer Browser - Software verhindern; wir weisen Sie jedoch darauf hin, dass Sie in diesem Fall gegebenenfalls nicht sämtliche Funktionen dieser Website vollumfänglich werden nutzen können.
Wenn Sie mit der Speicherung und Nutzung Ihrer Daten nicht einverstanden sind, können Sie die Speicherung und Nutzung hier deaktivieren.In diesem Fall wird in Ihrem Browser ein Opt - Out - Cookie hinterlegt, der verhindert, dass Matomo Nutzungsdaten speichert.Wenn Sie Ihre Cookies löschen, hat dies zur Folge, dass auch das Matomo Opt - Out - Cookie gelöscht wird.Das Opt - Out muss bei einem erneuten Besuch unserer Seite wieder aktiviert werden. */}
<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.
Wenn Sie in Ihrem YouTube - Account eingeloggt sind, ermöglichen Sie YouTube, Ihr Surfverhalten direkt Ihrem persönlichen Profil zuzuordnen.Dies können Sie verhindern, indem Sie sich aus Ihrem YouTube - Account ausloggen.
Die Nutzung von YouTube erfolgt im Interesse einer ansprechenden Darstellung unserer Online - Angebote.Dies stellt ein berechtigtes Interesse im Sinne von Art. 6 Abs. 1 lit.f DSGVO dar.
Weitere Informationen zum Umgang mit Nutzerdaten finden Sie in der Datenschutzerklärung von YouTube unter: https://www.google.de/intl/de/policies/privacy.
</div>
);
};
}
export default withRouter(Privay);
-101
View File
@@ -1,101 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { workspaceName } from '../../actions/workspaceActions';
import { getProject, resetProject } from '../../actions/projectActions';
import { clearMessages, returnErrors } from '../../actions/messageActions';
import { withRouter } from 'react-router-dom';
import Home from '../Home';
import Breadcrumbs from '../Breadcrumbs';
import Backdrop from '@material-ui/core/Backdrop';
import CircularProgress from '@material-ui/core/CircularProgress';
class Project extends Component {
componentDidMount() {
this.props.resetProject();
this.getProject();
}
componentDidUpdate(props) {
if (props.location.pathname !== this.props.location.pathname ||
props.match.params[`${this.props.type}Id`] !== this.props.match.params[`${this.props.type}Id`]) {
if (this.props.message.msg) {
this.props.clearMessages();
}
this.getProject();
}
if (this.props.message !== props.message) {
if (this.props.message.id === 'PROJECT_EMPTY' || this.props.message.id === 'GET_PROJECT_FAIL') {
if (this.props.type !== 'share') {
this.props.returnErrors('', 404, 'GET_PROJECT_FAIL');
this.props.history.push(`/${this.props.type}`);
} else {
this.props.history.push('/');
this.props.returnErrors('', 404, 'GET_SHARE_FAIL');
}
}
else if (this.props.message.id === 'GET_PROJECT_SUCCESS') {
this.props.workspaceName(this.props.project.title);
}
else if (this.props.message.id === 'PROJECT_DELETE_SUCCESS' || this.props.message.id === 'GALLERY_DELETE_SUCCESS') {
this.props.history.push(`/${this.props.type}`);
}
}
}
componentWillUnmount() {
this.props.resetProject();
this.props.workspaceName(null);
}
getProject = () => {
var id = this.props.location.pathname.replace(/\/[a-z]{1,}\//, '');
var param = this.props.location.pathname.replace(`/${id}`, '').replace('/', '');
console.log('param', param);
console.log(id);
this.props.getProject(param, id);
}
render() {
var data = this.props.type === 'project' ? 'Projekte' : 'Galerie';
return (
this.props.progress ?
<Backdrop open invisible>
<CircularProgress color="primary" />
</Backdrop>
: this.props.project ?
<div>
{this.props.type !== 'share' ?
<Breadcrumbs content={[{ link: `/${this.props.type}`, title: data }, { link: this.props.location.pathname, title: this.props.project.title }]} />
: null}
<Home project={this.props.project} projectType={this.props.type} />
</div> : null
);
};
}
Project.propTypes = {
workspaceName: PropTypes.func.isRequired,
getProject: PropTypes.func.isRequired,
resetProject: PropTypes.func.isRequired,
clearMessages: PropTypes.func.isRequired,
returnErrors: PropTypes.func.isRequired,
project: PropTypes.object.isRequired,
type: PropTypes.string.isRequired,
message: PropTypes.object.isRequired,
progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
project: state.project.projects[0],
progress: state.project.progress,
type: state.project.type,
message: state.message
});
export default connect(mapStateToProps, { workspaceName, getProject, resetProject, clearMessages, returnErrors })(withRouter(Project));
-163
View File
@@ -1,163 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { getProjects, resetProject } from '../../actions/projectActions';
import { clearMessages } from '../../actions/messageActions';
import { Link, withRouter } from 'react-router-dom';
import Breadcrumbs from '../Breadcrumbs';
import BlocklyWindow from '../Blockly/BlocklyWindow';
import Snackbar from '../Snackbar';
import WorkspaceFunc from '../Workspace/WorkspaceFunc';
import { withStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
import Divider from '@material-ui/core/Divider';
import Typography from '@material-ui/core/Typography';
import Backdrop from '@material-ui/core/Backdrop';
import CircularProgress from '@material-ui/core/CircularProgress';
const styles = (theme) => ({
link: {
color: theme.palette.primary.main,
textDecoration: 'none',
'&:hover': {
color: theme.palette.primary.main,
textDecoration: 'underline'
}
}
});
class ProjectHome extends Component {
state = {
snackbar: false,
type: '',
key: '',
message: ''
}
componentDidMount() {
var type = this.props.location.pathname.replace('/', '');
this.props.getProjects(type);
if (this.props.message) {
if (this.props.message.id === 'PROJECT_DELETE_SUCCESS') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein Projekt wurde erfolgreich gelöscht.`, type: 'success' });
}
else if (this.props.message.id === 'GALLERY_DELETE_SUCCESS') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein Galerie-Projekt wurde erfolgreich gelöscht.`, type: 'success' });
}
else if (this.props.message.id === 'GET_PROJECT_FAIL') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein angefragtes ${type === 'gallery' ? 'Galerie-' : ''}Projekt konnte nicht gefunden werden.`, type: 'error' });
}
}
}
componentDidUpdate(props) {
if (props.location.pathname !== this.props.location.pathname) {
this.setState({ snackbar: false });
this.props.getProjects(this.props.location.pathname.replace('/', ''));
}
if (props.message !== this.props.message) {
if (this.props.message.id === 'PROJECT_DELETE_SUCCESS') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein Projekt wurde erfolgreich gelöscht.`, type: 'success' });
}
else if (this.props.message.id === 'GALLERY_DELETE_SUCCESS') {
this.setState({ snackbar: true, key: Date.now(), message: `Dein Galerie-Projekt wurde erfolgreich gelöscht.`, type: 'success' });
}
}
}
componentWillUnmount() {
this.props.resetProject();
this.props.clearMessages();
}
render() {
var data = this.props.location.pathname === '/project' ? 'Projekte' : 'Galerie';
return (
<div>
<Breadcrumbs content={[{ link: this.props.location.pathname, title: data }]} />
<h1>{data}</h1>
{this.props.progress ?
<Backdrop open invisible>
<CircularProgress color="primary" />
</Backdrop>
:
<div>
{this.props.projects.length > 0 ?
<Grid container spacing={2}>
{this.props.projects.map((project, i) => {
return (
<Grid item xs={12} sm={6} md={4} xl={3} key={i}>
<Paper style={{ padding: '1rem', position: 'relative', overflow: 'hidden' }}>
<Link to={`/${data === 'Projekte' ? 'project' : 'gallery'}/${project._id}`} style={{ textDecoration: 'none', color: 'inherit' }}>
<h3 style={{ marginTop: 0 }}>{project.title}</h3>
<Divider style={{ marginTop: '1rem', marginBottom: '10px' }} />
<BlocklyWindow
svg
blockDisabled
initialXml={project.xml}
/>
<Typography variant='body2' style={{ fontStyle: 'italic', margin: 0, marginTop: '-10px' }}>{project.description}</Typography>
</Link>
{this.props.user && this.props.user.email === project.creator ?
<div>
<Divider style={{ marginTop: '10px', marginBottom: '10px' }} />
<div style={{ float: 'right' }}>
<WorkspaceFunc
multiple
project={project}
projectType={this.props.location.pathname.replace('/', '')}
/>
</div>
</div>
: null}
</Paper>
</Grid>
)
})}
</Grid>
: <div>
<Typography style={{ marginBottom: '10px' }}>Es sind aktuell keine Projekte vorhanden.</Typography>
{this.props.location.pathname.replace('/', '') === 'project' ?
<Typography>Erstelle jetzt dein <Link to={'/'} className={this.props.classes.link}>eigenes Projekt</Link> oder lasse dich von Projektbeispielen in der <Link to={'/gallery'} className={this.props.classes.link}>Galerie</Link> inspirieren.</Typography>
: null}
</div>
}
</div>
}
<Snackbar
open={this.state.snackbar}
message={this.state.message}
type={this.state.type}
key={this.state.key}
/>
</div>
);
};
}
ProjectHome.propTypes = {
getProjects: PropTypes.func.isRequired,
resetProject: PropTypes.func.isRequired,
clearMessages: PropTypes.func.isRequired,
projects: PropTypes.array.isRequired,
progress: PropTypes.bool.isRequired,
user: PropTypes.object,
message: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
projects: state.project.projects,
progress: state.project.progress,
user: state.auth.user,
message: state.message
});
export default connect(mapStateToProps, { getProjects, resetProject, clearMessages })(withStyles(styles, { withTheme: true })(withRouter(ProjectHome)));
-42
View File
@@ -1,42 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';
class IsLoggedRoute extends Component {
render() {
return (
!this.props.progress ?
<Route
{...this.props.exact}
render={({ location }) =>
!this.props.isAuthenticated ? (
this.props.children
) : (
<Redirect
to={{
pathname: "/",
state: { from: location }
}}
/>
)
}
/> : null
);
}
}
IsLoggedRoute.propTypes = {
isAuthenticated: PropTypes.bool.isRequired,
progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
progress: state.auth.progress
});
export default connect(mapStateToProps, null)(IsLoggedRoute);
-44
View File
@@ -1,44 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Route, Redirect, withRouter } from 'react-router-dom';
class PrivateRoute extends Component {
render() {
return (
!this.props.progress ?
<Route
{...this.props.exact}
render={({ location }) =>
this.props.isAuthenticated ? (
this.props.children
) : (()=>{
return (
<Redirect
to={{
pathname: "/user/login",
state: { from: location }
}}
/>
)
})()
}
/> : null
);
}
}
PrivateRoute.propTypes = {
isAuthenticated: PropTypes.bool.isRequired,
progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
progress: state.auth.progress
});
export default connect(mapStateToProps, null)(withRouter(PrivateRoute));
@@ -1,48 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Route, Redirect, withRouter } from 'react-router-dom';
class PrivateRoute extends Component {
render() {
return (
!this.props.progress ?
<Route
{...this.props.exact}
render={({ location }) =>
this.props.isAuthenticated &&
this.props.user &&
this.props.user.blocklyRole !== 'user' ? (
this.props.children
) : (()=>{
return (
<Redirect
to={{
pathname: "/",
state: { from: location }
}}
/>
)
})()
}
/> : null
);
}
}
PrivateRoute.propTypes = {
isAuthenticated: PropTypes.bool.isRequired,
user: PropTypes.object,
progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
user: state.auth.user,
progress: state.auth.progress
});
export default connect(mapStateToProps, null)(withRouter(PrivateRoute));
-32
View File
@@ -1,32 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Route } from 'react-router-dom';
class PublicRoute extends Component {
render() {
return (
!this.props.progress ?
<Route
{...this.props.exact}
render={({ location }) =>
this.props.children
}
/>
: null
);
}
}
PublicRoute.propTypes = {
progress: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
progress: state.auth.progress
});
export default connect(mapStateToProps, null)(PublicRoute);
-104
View File
@@ -1,104 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { visitPage } from '../../actions/generalActions';
import { Route, Switch, withRouter } from 'react-router-dom';
import PublicRoute from './PublicRoute';
import PrivateRoute from './PrivateRoute';
import PrivateRouteCreator from './PrivateRouteCreator';
import IsLoggedRoute from './IsLoggedRoute';
import Home from '../Home';
import Tutorial from '../Tutorial/Tutorial';
import TutorialHome from '../Tutorial/TutorialHome';
import Builder from '../Tutorial/Builder/Builder';
import NotFound from '../NotFound';
import ProjectHome from '../Project/ProjectHome';
import Project from '../Project/Project';
import Settings from '../Settings/Settings';
import Impressum from '../Impressum';
import Privacy from '../Privacy';
import Login from '../User/Login';
import Account from '../User/Account';
import MyBadges from '../User/MyBadges';
class Routes extends Component {
componentDidUpdate() {
this.props.visitPage();
}
render() {
return (
<div style={{ margin: '0 22px' }}>
<Switch>
<PublicRoute path="/" exact>
<Home/>
</PublicRoute>
{/* Tutorials */}
<PublicRoute path="/tutorial" exact>
<TutorialHome />
</PublicRoute>
<PrivateRouteCreator path="/tutorial/builder" exact>
<Builder />
</PrivateRouteCreator>
<Route path="/tutorial/:tutorialId" exact>
<Tutorial />
</Route>
{/* Sharing */}
<PublicRoute path="/share/:shareId" exact>
<Project />
</PublicRoute>
{/* Gallery-Projects */}
<PublicRoute path="/gallery" exact>
<ProjectHome />
</PublicRoute>
<PublicRoute path="/gallery/:galleryId" exact>
<Project />
</PublicRoute>
{/* User-Projects */}
<PrivateRoute path="/project" exact>
<ProjectHome/>
</PrivateRoute>
<PrivateRoute path="/project/:projectId" exact>
<Project/>
</PrivateRoute>
{/* User */}
<IsLoggedRoute path="/user/login" exact>
<Login />
</IsLoggedRoute>
<PrivateRoute path="/user" exact>
<Account />
</PrivateRoute>
<PrivateRoute path="/user/badge" exact>
<MyBadges />
</PrivateRoute>
{/* settings */}
<PublicRoute path="/settings" exact>
<Settings />
</PublicRoute>
{/* privacy */}
<PublicRoute path="/impressum" exact>
<Impressum />
</PublicRoute>
<PublicRoute path="/privacy" exact>
<Privacy />
</PublicRoute>
{/* Not Found */}
<PublicRoute>
<NotFound />
</PublicRoute>
</Switch>
</div>
);
}
}
Home.propTypes = {
visitPage: PropTypes.func.isRequired
};
export default connect(null, { visitPage })(withRouter(Routes));
+39
View File
@@ -0,0 +1,39 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { visitPage } from '../actions/generalActions';
import { Route, Switch, withRouter } from 'react-router-dom';
import Home from './Home';
import Tutorial from './Tutorial/Tutorial';
import TutorialHome from './Tutorial/TutorialHome';
import Builder from './Tutorial/Builder/Builder';
import NotFound from './NotFound';
class Routes extends Component {
componentDidUpdate(){
this.props.visitPage();
}
render() {
return (
<div style={{ margin: '0 22px' }}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/tutorial" exact component={TutorialHome} />
<Route path="/tutorial/builder" exact component={Builder}/>
<Route path="/tutorial/:tutorialId" exact component={Tutorial} />
<Route component={NotFound} />
</Switch>
</div>
);
}
}
Home.propTypes = {
visitPage: PropTypes.func.isRequired
};
export default connect(null, { visitPage })(withRouter(Routes));
@@ -1,58 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { setLanguage } from '../../actions/generalActions';
import * as Blockly from 'blockly/core';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import Typography from '@material-ui/core/Typography';
import FormHelperText from '@material-ui/core/FormHelperText';
class LanguageSelector 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();
}
handleChange = (event) => {
this.props.setLanguage(event.target.value);
}
render(){
return(
<div>
<Typography style={{fontWeight: 'bold'}}>{Blockly.Msg.settings_language}</Typography>
<FormHelperText style={{color: 'black', lineHeight: 1.3, marginBottom: '8px'}}>{Blockly.Msg.settings_language_text}</FormHelperText>
<FormControl>
<InputLabel id="demo-simple-select-label">{Blockly.Msg.settings_language}</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={this.props.language}
onChange={this.handleChange}
>
<MenuItem value={'de_DE'}>{Blockly.Msg.settings_language_de}</MenuItem>
<MenuItem value={'en_US'}>{Blockly.Msg.settings_language_en}</MenuItem>
</Select>
</FormControl>
</div>
);
}
}
LanguageSelector.propTypes = {
setLanguage: PropTypes.func.isRequired,
language: PropTypes.string.isRequired
};
const mapStateToProps = state => ({
language: state.general.language
});
export default connect(mapStateToProps, { setLanguage })(LanguageSelector);
-57
View File
@@ -1,57 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { setRenderer } from '../../actions/generalActions';
import * as Blockly from 'blockly/core'
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import Typography from '@material-ui/core/Typography';
import FormHelperText from '@material-ui/core/FormHelperText';
class RenderSelector 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>
<Typography style={{fontWeight: 'bold'}}>{Blockly.Msg.settings_renderer}</Typography>
<FormHelperText style={{color: 'black', lineHeight: 1.3, marginBottom: '8px'}}>{Blockly.Msg.settings_renderer_text}</FormHelperText>
<FormControl>
<InputLabel id="demo-simple-select-label">{Blockly.Msg.settings_renderer}</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={this.props.renderer}
onChange={(e) => this.props.setRenderer(e.target.value)}
>
<MenuItem value={'geras'}>Geras</MenuItem>
<MenuItem value={'zelos'}>Zelos</MenuItem>
</Select>
</FormControl>
</div>
);
}
}
RenderSelector.propTypes = {
setRenderer: PropTypes.func.isRequired,
language: PropTypes.string.isRequired,
renderer: PropTypes.string.isRequired
};
const mapStateToProps = state => ({
renderer: state.general.renderer,
language: state.general.language
});
export default connect(mapStateToProps, { setRenderer })(RenderSelector);
-65
View File
@@ -1,65 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import * as Blockly from 'blockly/core';
import Breadcrumbs from '../Breadcrumbs';
import LanguageSelector from './LanguageSelector';
import RenderSelector from './RenderSelector';
import StatsSelector from './StatsSelector';
import Button from '@material-ui/core/Button';
import Paper from '@material-ui/core/Paper';
class Settings 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: Blockly.Msg.settings_head }]} />
<h1>{Blockly.Msg.settings_head}</h1>
<Paper style={{margin: '10px 0px', padding: '10px'}}>
<LanguageSelector />
</Paper>
<Paper style={{margin: '10px 0px', padding: '10px'}}>
<RenderSelector />
</Paper>
<Paper style={{margin: '10px 0px', padding: '10px'}}>
<StatsSelector />
</Paper>
<Button
style={{ marginTop: '10px' }}
variant="contained"
color="primary"
onClick={this.props.pageVisits > 0 ? () => this.props.history.goBack() : () => this.props.history.push('/')}
>
{Blockly.Msg.button_back}
</Button>
</div>
);
};
}
Settings.propTypes = {
language: PropTypes.string.isRequired,
pageVisits: PropTypes.number.isRequired
};
const mapStateToProps = state => ({
language: state.general.language,
pageVisits: state.general.pageVisits
});
export default connect(mapStateToProps, null)(withRouter(Settings));
-56
View File
@@ -1,56 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { setStatistics } from '../../actions/generalActions';
import * as Blockly from 'blockly/core'
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import Typography from '@material-ui/core/Typography';
import FormHelperText from '@material-ui/core/FormHelperText';
class StatsSelector 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>
<Typography style={{fontWeight: 'bold'}}>{Blockly.Msg.settings_statistics}</Typography>
<FormHelperText style={{color: 'black', lineHeight: 1.3, marginBottom: '8px'}}>{Blockly.Msg.settings_statistics_text}</FormHelperText>
<FormControl>
<InputLabel id="demo-simple-select-label">{Blockly.Msg.settings_statistics}</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={this.props.statistics}
onChange={(e) => this.props.setStatistics(e.target.value)}
>
<MenuItem value={true}>{Blockly.Msg.settings_statistics_on}</MenuItem>
<MenuItem value={false}>{Blockly.Msg.settings_statistics_off}</MenuItem>
</Select>
</FormControl>
</div>
);
}
}
StatsSelector.propTypes = {
setStatistics: PropTypes.func.isRequired,
language: PropTypes.string.isRequired,
statistics: PropTypes.bool.isRequired
};
const mapStateToProps = state => ({
statistics: state.general.statistics,
language: state.general.language
});
export default connect(mapStateToProps, { setStatistics })(StatsSelector);
-6
View File
@@ -35,12 +35,6 @@ class Snackbar extends Component {
}
}
componentDidUpdate(){
if(!this.state.open){
clearTimeout(this.timeout);
}
}
componentWillUnmount(){
if(this.state.open){
clearTimeout(this.timeout);
@@ -36,8 +36,8 @@ class TrashcanButtons extends Component {
componentDidUpdate(previousProps, previousState) {
const workspace = Blockly.getMainWorkspace();
const contentsIsOpen = workspace.trashcan.contentsIsOpen();
if (previousState.closeTrashFlyout !== contentsIsOpen) {
this.setState({ closeTrashFlyout: contentsIsOpen });
if(previousState.closeTrashFlyout !== contentsIsOpen){
this.setState({ closeTrashFlyout: contentsIsOpen });
}
}
@@ -59,26 +59,26 @@ class TrashcanButtons extends Component {
return (
this.state.closeTrashFlyout ?
<div>
<Tooltip title={Blockly.Msg.tooltip_trashcan_hide}>
<Tooltip title='gelöschte Blöcke ausblenden'>
<IconButton
className={this.props.classes.closeTrash}
style={{ width: '40px', height: '40px', position: 'absolute', bottom: 10, right: 10, zIndex: 21 }}
style={{width: '40px', height: '40px', position: 'absolute', bottom: 10, right: 10, zIndex: 21 }}
onClick={() => this.closeTrashcan()}
>
<FontAwesomeIcon icon={faTimes} size="xs" />
<FontAwesomeIcon icon={faTimes} size="xs"/>
</IconButton>
</Tooltip>
<Tooltip title={Blockly.Msg.tooltip_trashcan_delete}>
<Tooltip title='Blöcke endgültig löschen'>
<IconButton
className={this.props.classes.deleteTrash}
style={{ width: '40px', height: '40px', position: 'absolute', bottom: 10, right: 50, zIndex: 21 }}
style={{width: '40px', height: '40px', position: 'absolute', bottom: 10, right: 50, zIndex: 21 }}
onClick={() => this.clearTrashcan()}
>
<FontAwesomeIcon icon={faTrash} size="xs" />
<FontAwesomeIcon icon={faTrash} size="xs"/>
</IconButton>
</Tooltip>
</div>
: null
: null
);
};
}
+11 -10
View File
@@ -5,37 +5,38 @@ import { workspaceName } from '../../actions/workspaceActions';
import BlocklyWindow from '../Blockly/BlocklyWindow';
import CodeViewer from '../CodeViewer';
import WorkspaceFunc from '../Workspace/WorkspaceFunc';
import WorkspaceFunc from '../WorkspaceFunc';
import withWidth, { isWidthDown } from '@material-ui/core/withWidth';
import Grid from '@material-ui/core/Grid';
import Card from '@material-ui/core/Card';
import Typography from '@material-ui/core/Typography';
import * as Blockly from 'blockly'
class Assessment extends Component {
componentDidMount() {
// alert(this.props.name);
this.props.workspaceName(this.props.name);
}
componentDidUpdate(props) {
if (props.name !== this.props.name) {
// alert(this.props.name);
this.props.workspaceName(this.props.name);
}
}
render() {
var tutorialId = this.props.tutorial._id;
var tutorialId = this.props.currentTutorialId;
var currentTask = this.props.step;
var status = this.props.status.filter(status => status._id === tutorialId)[0];
var taskIndex = status.tasks.findIndex(task => task._id === currentTask._id);
var status = this.props.status.filter(status => status.id === tutorialId)[0];
var taskIndex = status.tasks.findIndex(task => task.id === currentTask.id);
var statusTask = status.tasks[taskIndex];
return (
<div 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>
<div style={{ float: 'right', height: '40px' }}><WorkspaceFunc solutionCheck /></div>
<Grid container spacing={2} style={{ marginBottom: '5px' }}>
<Grid item xs={12} md={6} lg={8}>
<BlocklyWindow
@@ -46,7 +47,7 @@ class Assessment extends Component {
</Grid>
<Grid item xs={12} md={6} lg={4} style={isWidthDown('sm', this.props.width) ? { height: 'max-content' } : {}}>
<Card style={{ height: 'calc(50% - 30px)', padding: '10px', marginBottom: '10px' }}>
<Typography variant='h5'>{Blockly.Msg.tutorials_assessment_task}</Typography>
<Typography variant='h5'>Arbeitsauftrag</Typography>
<Typography>{currentTask.text}</Typography>
</Card>
<div style={isWidthDown('sm', this.props.width) ? { height: '500px' } : { height: '50%' }}>
@@ -60,16 +61,16 @@ class Assessment extends Component {
}
Assessment.propTypes = {
currentTutorialId: PropTypes.number,
status: PropTypes.array.isRequired,
change: PropTypes.number.isRequired,
workspaceName: PropTypes.func.isRequired,
tutorial: PropTypes.object.isRequired
workspaceName: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
change: state.tutorial.change,
status: state.tutorial.status,
tutorial: state.tutorial.tutorials[0]
currentTutorialId: state.tutorial.currentId
});
export default connect(mapStateToProps, { workspaceName })(withWidth()(Assessment));
-119
View File
@@ -1,119 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { assigneBadge } from '../../actions/tutorialActions';
import Dialog from '../Dialog';
import { Link } from 'react-router-dom';
import { withStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography';
import Avatar from '@material-ui/core/Avatar';
import * as Blockly from 'blockly';
const styles = (theme) => ({
link: {
color: theme.palette.primary.main,
textDecoration: 'none',
'&:hover': {
color: theme.palette.primary.main,
textDecoration: 'underline'
}
}
});
class Badge extends Component {
state = {
open: false,
title: '',
content: ''
};
componentDidUpdate(props) {
if (this.props.message.id === 'TUTORIAL_CHECK_SUCCESS') {
if (this.props.tutorial.badge) {
// is connected to MyBadges?
if (this.props.isAuthenticated && this.props.user && this.props.user.badge) {
if (this.props.user.badges && !this.props.user.badges.includes(this.props.tutorial.badge)) {
if (this.isSuccess()) {
this.props.assigneBadge(this.props.tutorial.badge);
}
}
}
}
}
if (props.message !== this.props.message) {
if (this.props.message.id === 'ASSIGNE_BADGE_SUCCESS') {
this.setState({ title: `Badge: ${this.props.message.msg.name}`, content: `${Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_01} ${this.props.message.msg.name} ${Blockly.Msg.badges_ASSIGNE_BADGE_SUCCESS_02}`, open: true });
}
}
}
isSuccess = () => {
var tutorialId = this.props.tutorial._id;
var status = this.props.status.filter(status => status._id === tutorialId)[0];
var tasks = status.tasks;
var success = tasks.filter(task => task.type === 'success').length / tasks.length;
if (success === 1) {
return true;
}
return false;
}
toggleDialog = () => {
this.setState({ open: !this.state, title: '', content: '' });
}
render() {
return (
<Dialog
style={{ zIndex: 99999999 }}
open={this.state.open}
title={this.state.title}
content={this.state.content}
onClose={() => { this.toggleDialog(); }}
onClick={() => { this.toggleDialog(); }}
button={Blockly.Msg.button_close}
>
<div style={{ marginTop: '10px' }}>
<Paper style={{ textAlign: 'center' }}>
{this.props.message.msg.image && this.props.message.msg.image.path ?
<Avatar src={`${process.env.REACT_APP_MYBADGES}/media/${this.props.message.msg.image.path}`} style={{ width: '200px', height: '200px', marginLeft: 'auto', marginRight: 'auto' }} />
: <Avatar style={{ width: '200px', height: '200px', marginLeft: 'auto', marginRight: 'auto' }}></Avatar>}
<Typography variant='h6' style={{ display: 'flex', cursor: 'default', paddingBottom: '6px' }}>
<div style={{ flexGrow: 1, marginLeft: '10px', marginRight: '10px' }}>{this.props.message.msg.name}</div>
</Typography>
</Paper>
<Typography style={{ marginTop: '10px' }}>
{Blockly.Msg.badges_explaination}<Link to={'/user/badge'} className={this.props.classes.link}>{Blockly.Msg.labels_here}</Link>.
</Typography>
</div>
</Dialog>
);
};
}
Badge.propTypes = {
assigneBadge: PropTypes.func.isRequired,
status: PropTypes.array.isRequired,
change: PropTypes.number.isRequired,
tutorial: PropTypes.object.isRequired,
user: PropTypes.object,
isAuthenticated: PropTypes.bool.isRequired,
message: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
change: state.tutorial.change,
status: state.tutorial.status,
tutorial: state.tutorial.tutorials[0],
user: state.auth.user,
isAuthenticated: state.auth.isAuthenticated,
message: state.message
});
export default connect(mapStateToProps, { assigneBadge })(withStyles(styles, { withTheme: true })(Badge));

Some files were not shown because too many files have changed in this diff Show More