Merged branches

This commit is contained in:
Maximilian Leopold 2019-04-04 15:38:05 +02:00
commit 9153685c33
34 changed files with 1410 additions and 397 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
done.txt
# Generated files
.idea/**/contentModel.xml

View File

@ -35,11 +35,15 @@ dependencies {
//JSON Parser
implementation 'com.google.code.gson:gson:2.8.5'
<<<<<<< HEAD
compile 'org.springframework.boot:spring-boot-starter-tomcat'
compile 'org.springframework.boot:spring-boot-starter-security'
compile 'org.springframework.boot:spring-boot-starter-actuator'
compile 'org.springframework.boot:spring-boot-starter-aop'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '1.2.0.RELEASE'
=======
compile group: 'org.springframework.security', name: 'spring-security-core', version: '5.1.4.RELEASE'
>>>>>>> develop
}

View File

@ -14,7 +14,7 @@ module.exports = {
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
extends: [
'plugin:vue/essential',
'@vue/prettier'
// '@vue/prettier'
],
// required to lint *.vue files

View File

@ -255,9 +255,9 @@
}
},
"@babel/helpers": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.0.tgz",
"integrity": "sha512-2Lfcn74A2WSFUbYJ76ilYE1GnegCKUHTfXxp25EL2zPZHjV7OcDncqNjl295mUH0VnB65mNriXW4J5ROvxsgGg==",
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.2.tgz",
"integrity": "sha512-gQR1eQeroDzFBikhrCccm5Gs2xBjZ57DNjGbqTaHo911IpmSxflOQWMAHPw/TXk8L3isv7s9lYzUkexOeTQUYg==",
"dev": true,
"requires": {
"@babel/template": "^7.4.0",
@ -277,9 +277,9 @@
}
},
"@babel/parser": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.0.tgz",
"integrity": "sha512-ZmMhJfU/+SXXvy9ALjDZopa3T3EixQtQai89JRC48eM9OUwrxJjYjuM/0wmdl2AekytlzMVhPY8cYdLb13kpKQ==",
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.2.tgz",
"integrity": "sha512-9fJTDipQFvlfSVdD/JBtkiY0br9BtfvW2R8wo6CX/Ej2eMuV0gWPk1M67Mt3eggQvBqYW1FCEk8BN7WvGm/g5g==",
"dev": true
},
"@babel/plugin-proposal-async-generator-functions": {
@ -668,9 +668,9 @@
}
},
"@babel/plugin-transform-named-capturing-groups-regex": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz",
"integrity": "sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==",
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.2.tgz",
"integrity": "sha512-NsAuliSwkL3WO2dzWTOL1oZJHm0TM8ZY8ZSxk2ANyKkt5SQlToGA4pzctmq1BEjoacurdwZ3xp2dCQWJkME0gQ==",
"dev": true,
"requires": {
"regexp-tree": "^0.1.0"
@ -907,9 +907,9 @@
"dev": true
},
"@quasar/app": {
"version": "1.0.0-beta.12",
"resolved": "https://registry.npmjs.org/@quasar/app/-/app-1.0.0-beta.12.tgz",
"integrity": "sha512-lQSqW+LuBG9jmglGj82fZ/9J6Dm0nz+dbSna6rOiy4zkt1FjmQ3PCRrImyd+WIsbKUntlTcKJ4+uN6fOlblcvg==",
"version": "1.0.0-beta.13",
"resolved": "https://registry.npmjs.org/@quasar/app/-/app-1.0.0-beta.13.tgz",
"integrity": "sha512-BMF/U/5xE7EntvVWVeQ0ud2k9z5xo4TGast5/Wv/g2+X4/VBIYUFPlDMNJh93okZ6QnRaNycU5xORo+dUiF8Cg==",
"dev": true,
"requires": {
"@quasar/babel-preset-app": "1.0.2",
@ -949,7 +949,7 @@
"minimist": "1.2.0",
"ms": "2.1.1",
"node-loader": "0.6.0",
"opn": "5.4.0",
"opn": "5.5.0",
"optimize-css-assets-webpack-plugin": "5.0.1",
"ouch": "2.0.0",
"postcss-loader": "3.0.0",
@ -962,12 +962,12 @@
"stylus-loader": "3.0.2",
"terser-webpack-plugin": "1.2.3",
"url-loader": "1.1.2",
"vue": "2.6.9",
"vue": "2.6.10",
"vue-loader": "15.7.0",
"vue-router": "3.0.2",
"vue-server-renderer": "2.6.9",
"vue-server-renderer": "2.6.10",
"vue-style-loader": "4.1.2",
"vue-template-compiler": "2.6.9",
"vue-template-compiler": "2.6.10",
"vuex": "3.1.0",
"webpack": "4.29.6",
"webpack-bundle-analyzer": "3.1.0",
@ -1002,9 +1002,9 @@
}
},
"@quasar/extras": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.1.0.tgz",
"integrity": "sha512-594TNuQrQLwzSwhlZMkMn5AIAcNk8zPrsCkdHT021dswMv+IHATGyKJaTH4KuLKLWse+oPRoB0NddLNf9PXiuw=="
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.1.1.tgz",
"integrity": "sha512-n9aQ9N9GBaRF15v3Rm5QDoeLOHFzjQ874f+54TthWmaQvx/8DV6fG/bwLgA6AjLUIZJs3ogm4J1KqWO+4zSg1g=="
},
"@types/q": {
"version": "1.5.2",
@ -1313,7 +1313,6 @@
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz",
"integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
@ -1974,12 +1973,12 @@
}
},
"browserslist": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.1.tgz",
"integrity": "sha512-/pPw5IAUyqaQXGuD5vS8tcbudyPZ241jk1W5pQBsGDfcjNQt7p8qxZhgMNuygDShte1PibLFexecWUPgmVLfrg==",
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.2.tgz",
"integrity": "sha512-zmJVLiKLrzko0iszd/V4SsjTaomFeoVzQGYYOYgRgsbh7WNh95RgDB0CmBdFWYs/3MyFSt69NypjL/h3iaddKQ==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30000949",
"caniuse-lite": "^1.0.30000951",
"electron-to-chromium": "^1.3.116",
"node-releases": "^1.1.11"
}
@ -2123,9 +2122,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30000950",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000950.tgz",
"integrity": "sha512-Cs+4U9T0okW2ftBsCIHuEYXXkki7mjXmjCh4c6PzYShk04qDEr76/iC7KwhLoWoY65wcra1XOsRD+S7BptEb5A==",
"version": "1.0.30000953",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000953.tgz",
"integrity": "sha512-2stdF/q5MZTDhQ6uC65HWbSgI9UMKbc7+HKvlwH5JBIslKoD/J9dvabP4J4Uiifu3NljbHj3iMpfYflLSNt09A==",
"dev": true
},
"chalk": {
@ -2646,15 +2645,14 @@
"dev": true
},
"cosmiconfig": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.1.0.tgz",
"integrity": "sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz",
"integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==",
"dev": true,
"requires": {
"import-fresh": "^2.0.0",
"is-directory": "^0.3.1",
"js-yaml": "^3.9.0",
"lodash.get": "^4.4.2",
"js-yaml": "^3.13.0",
"parse-json": "^4.0.0"
}
},
@ -3253,9 +3251,9 @@
"dev": true
},
"electron-to-chromium": {
"version": "1.3.116",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.116.tgz",
"integrity": "sha512-NKwKAXzur5vFCZYBHpdWjTMO8QptNLNP80nItkSIgUOapPAo9Uia+RvkCaZJtO7fhQaVElSvBPWEc2ku6cKsPA==",
"version": "1.3.119",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.119.tgz",
"integrity": "sha512-3mtqcAWa4HgG+Djh/oNXlPH0cOH6MmtwxN1nHSaReb9P0Vn51qYPqYwLeoSuAX9loU1wrOBhFbiX3CkeIxPfgg==",
"dev": true
},
"elementtree": {
@ -3870,8 +3868,7 @@
"fast-deep-equal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
"dev": true
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
},
"fast-diff": {
"version": "1.2.0",
@ -3913,8 +3910,7 @@
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
"dev": true
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"fast-levenshtein": {
"version": "2.0.6",
@ -5254,9 +5250,9 @@
}
},
"ieee754": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
"integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==",
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
"dev": true
},
"iferr": {
@ -5779,9 +5775,9 @@
"dev": true
},
"js-yaml": {
"version": "3.12.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.2.tgz",
"integrity": "sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==",
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz",
"integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
@ -5803,8 +5799,7 @@
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stable-stringify": {
"version": "1.0.1",
@ -6017,12 +6012,6 @@
"integrity": "sha1-gwWOkDtRy7dZ0JzPVG3qPqOcRxg=",
"dev": true
},
"lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
"dev": true
},
"lodash.kebabcase": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
@ -6434,9 +6423,9 @@
"dev": true
},
"nan": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz",
"integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==",
"version": "2.13.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
"integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==",
"dev": true,
"optional": true
},
@ -6747,9 +6736,9 @@
"dev": true
},
"opn": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz",
"integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==",
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
"integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==",
"dev": true,
"requires": {
"is-wsl": "^1.1.0"
@ -7717,8 +7706,7 @@
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"q": {
"version": "1.5.1",
@ -7733,9 +7721,9 @@
"dev": true
},
"quasar": {
"version": "1.0.0-beta.11",
"resolved": "https://registry.npmjs.org/quasar/-/quasar-1.0.0-beta.11.tgz",
"integrity": "sha512-g6VBCNa9fwNCyrWfxi8GwpXL6qNtyynweVKT+wqMZajjvE6fQ/EwETWF2zsla1Rv9NYsTCnW6o//bQn1vcqJbw=="
"version": "1.0.0-beta.13",
"resolved": "https://registry.npmjs.org/quasar/-/quasar-1.0.0-beta.13.tgz",
"integrity": "sha512-9sDSUYRVzQu2WezUy329K9yBCGaoXFkeVYp9NnvKtzs7b/Wk76GrV4kwkBqVvFZDdOYuI4OFFdjPdKdDDMAILw=="
},
"querystring": {
"version": "0.2.0",
@ -7750,9 +7738,9 @@
"dev": true
},
"querystringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz",
"integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
"integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
"dev": true
},
"randombytes": {
@ -9401,7 +9389,6 @@
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
"dev": true,
"requires": {
"punycode": "^2.1.0"
}
@ -9530,9 +9517,9 @@
}
},
"vue": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.9.tgz",
"integrity": "sha512-t1+tvH8hybPM86oNne3ZozCD02zj/VoZIiojOBPJLjwBn7hxYU5e1gBObFpq8ts1NEn1VhPf/hVXBDAJ3X5ljg==",
"version": "2.6.10",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz",
"integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==",
"dev": true
},
"vue-eslint-parser": {
@ -9588,9 +9575,9 @@
"dev": true
},
"vue-server-renderer": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.9.tgz",
"integrity": "sha512-UAwI9R+H9oh6YIG9xmS4uU1X8MD9bBzDLGIhqB8UHX9tJPrWQTrBijfXfnytDpefIisfz3qLa27qFOKuX4vnsw==",
"version": "2.6.10",
"resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz",
"integrity": "sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug==",
"dev": true,
"requires": {
"chalk": "^1.1.3",
@ -9647,9 +9634,9 @@
}
},
"vue-template-compiler": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.9.tgz",
"integrity": "sha512-QgO0LSCdeH6zUMSgtqel+yDWsZWQPXiWBdFg9qzOhWfQL8vZ+ywinAzE04rm1XrWc+3SU0YAdWISlEgs/i8WWA==",
"version": "2.6.10",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz",
"integrity": "sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg==",
"dev": true,
"requires": {
"de-indent": "^1.0.2",

View File

@ -13,12 +13,13 @@
"build": "quasar build"
},
"dependencies": {
"@quasar/extras": "^1.0.0",
"@quasar/extras": "^1.1.1",
"ajv": "6.8.1",
"axios": "^0.18.0",
"quasar": "^1.0.0-beta.0"
"quasar": "^1.0.0-beta.13"
},
"devDependencies": {
"@quasar/app": "^1.0.0-beta.0",
"@quasar/app": "^1.0.0-beta.13",
"@vue/eslint-config-prettier": "^4.0.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.10.0",

View File

@ -46,11 +46,29 @@ module.exports = function (ctx) {
'QCardSection',
'QCardActions',
'QCheckbox',
'QSeparator'
'QSeparator',
'QImg',
'QTabs',
'QTab',
'QRouteTab',
'QTabPanels',
'QTabPanel',
'QInput',
'QFab',
'QFabAction',
'QDialog',
'QFooter',
'QPageSticky',
'QAvatar',
'QSpinnerPuff',
'QExpansionItem',
'QParallax',
'QEditor',
],
directives: [
'Ripple'
'Ripple',
'ClosePopup'
],
// Quasar plugins
@ -85,8 +103,8 @@ module.exports = function (ctx) {
devServer: {
// https: true,
// port: 8080,
open: true // opens browser window automatically
port: 8081,
open: false // opens browser window automatically
},
// animations: 'all' --- includes all animations

View File

@ -1,7 +1,13 @@
<template>
<q-layout view="hhh Lpr lFf">
<q-header elevated class="">
<q-toolbar class="">
<q-header id="qheader" class="bg-white text-grey-14" elevated>
<q-toolbar class="q-pa-md">
<q-img src="statics/buga_logo.svg" style="max-width: 40px;" class="q-mr-sm"/>
<q-toolbar-title>
BuGa Geocaching
</q-toolbar-title>
<q-btn
flat
dense
@ -9,13 +15,8 @@
@click="leftDrawerOpen = !leftDrawerOpen"
aria-label="Menu"
>
<q-icon name="menu" />
<q-icon name="menu"/>
</q-btn>
<q-toolbar-title>
BuGa Geocaching SPA
</q-toolbar-title>
<!--<div>Quasar v{{ $q.version }}</div>-->
</q-toolbar>
</q-header>
@ -24,107 +25,107 @@
v-model="leftDrawerOpen"
bordered
show-if-above
:mini="miniState"
@mouseover="miniState = false"
@mouseout="miniState = true"
content-class="bg-grey-2">
content-class="">
<q-list>
<q-item-label header>Essential Links</q-item-label>
<q-item-label header>BuGa Geocaching</q-item-label>
<q-item
clickable
class="text-primary"
v-ripple
tag="a"
target="_blank"
href="http://v1.quasar-framework.org"
to="/"
>
<q-item-section avatar>
<q-icon name="school" />
<q-icon name="directions"/>
</q-item-section>
<q-item-section>
<q-item-label>Docs</q-item-label>
<q-item-label caption>v1.quasar-framework.org</q-item-label>
<q-item-label>Startseite</q-item-label>
</q-item-section>
</q-item>
<q-item
clickable
class="text-primary"
v-ripple
tag="a"
target="_blank"
href="https://github.com/quasarframework/"
to="/Overview"
>
<q-item-section avatar>
<q-icon name="code" />
<q-icon name="map"/>
</q-item-section>
<q-item-section>
<q-item-label>Github</q-item-label>
<q-item-label caption>github.com/quasarframework</q-item-label>
<q-item-label>Caches</q-item-label>
</q-item-section>
</q-item>
<q-item
clickable
disable
class="text-primary"
v-ripple
tag="a"
target="_blank"
href="http://chat.quasar-framework.org"
to="/"
>
<q-item-section avatar>
<q-icon name="chat" />
<q-icon name="list"/>
</q-item-section>
<q-item-section>
<q-item-label>Discord Chat Channel</q-item-label>
<q-item-label caption>chat.quasar-framework.org</q-item-label>
<q-item-label>Rangliste</q-item-label>
</q-item-section>
</q-item>
<q-item
clickable
disable
class="text-primary"
v-ripple
tag="a"
target="_blank"
href="https://forum.quasar-framework.org"
to="/Login"
>
<q-item-section avatar>
<q-icon name="record_voice_over" />
<q-icon name="perm_identity"/>
</q-item-section>
<q-item-section>
<q-item-label>Forum</q-item-label>
<q-item-label caption>forum.quasar-framework.org</q-item-label>
<q-item-label>Profil</q-item-label>
</q-item-section>
</q-item>
<q-item
clickable
class="text-primary"
v-ripple
tag="a"
target="_blank"
href="https://twitter.com/quasarframework"
to="/Login"
>
<q-item-section avatar>
<q-icon name="rss_feed" />
<q-icon name="logout"/>
</q-item-section>
<q-item-section>
<q-item-label>Twitter</q-item-label>
<q-item-label caption>@quasarframework</q-item-label>
<q-item-label>Login</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-drawer>
<q-page-container>
<router-view />
<router-view/>
</q-page-container>
</q-layout>
</template>
<script>
import { openURL } from "quasar";
import {openURL} from "quasar";
export default {
name: "MyLayout",
data() {
return {
//leftDrawerOpen: this.$q.platform.is.desktop,
leftDrawerOpen: true,
miniState: true
};
},
methods: {
openURL
}
};
export default {
name: "MyLayout",
data() {
return {
leftDrawerOpen: this.$q.platform.is.desktop,
//menuButtonVisible: !this.$q.platform.is.desktop,
//leftDrawerOpen: true,
//miniState: true
};
},
methods: {
openURL
}
};
</script>
<style></style>

View File

@ -0,0 +1,199 @@
<template>
<div class="q-pa-md">
<div class="q-gutter-y-md" style="max-width: 1200px">
<q-tabs
v-model="tab"
dense
align="justify"
class="bg-white text-green-8 shadow-2"
:breakpoint="0"
>
<q-tab name="table" icon="mail" />
<q-tab name="map" icon="map" />
</q-tabs>
<template>
<div class="q-pa-md">
<q-table
title="Caches"
:data="data"
:columns="columns"
row-key="name"
selection="single"
:selected.sync="selected"
:filter="filter"
grid
hide-header
>
<template v-slot:top-right>
<q-input borderless dense debounce="300" v-model="filter" placeholder="Search">
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</template>
<template v-slot:item="props">
<div
class="q-pa-xs col-xs-12 col-sm-6 col-md-4 col-lg-3 grid-style-transition"
:style="props.selected ? 'transform: scale(0.95);' : ''"
>
<q-card :class="props.selected ? 'bg-grey-2' : ''">
<q-card-section>
<q-checkbox :dense="denseOn" v-model="props.selected" :label="props.row.name" />
</q-card-section>
<q-separator />
<q-list dense>
<q-item v-for="col in props.cols.filter(col => col.name !== 'desc')" :key="col.name">
<q-item-section>
<q-item-label>{{ col.label }}</q-item-label>
</q-item-section>
<q-item-section side>
<q-item-label caption>{{ col.value }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</template>
</q-table>
</div>
</template>
</div>
</div>
</template>
<script>
export default {
data () {
return {
tab: 'mails',
panel: 'mails',
denseOn: true,
filter: '',
selected: [],
columns: [
{
name: 'desc',
required: true,
label: 'Dessert (100g serving)',
align: 'left',
field: row => row.name,
format: val => `${val}`,
sortable: true
},
{ name: 'calories', align: 'center', label: 'Calories', field: 'calories', sortable: true },
{ name: 'fat', label: 'Fat (g)', field: 'fat', sortable: true },
{ name: 'carbs', label: 'Carbs (g)', field: 'carbs' },
{ name: 'protein', label: 'Protein (g)', field: 'protein' },
{ name: 'sodium', label: 'Sodium (mg)', field: 'sodium' },
{ name: 'calcium', label: 'Calcium (%)', field: 'calcium', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) },
{ name: 'iron', label: 'Iron (%)', field: 'iron', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) }
],
data: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
sodium: 87,
calcium: '14%',
iron: '1%'
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
sodium: 129,
calcium: '8%',
iron: '1%'
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
sodium: 337,
calcium: '6%',
iron: '7%'
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
sodium: 413,
calcium: '3%',
iron: '8%'
},
{
name: 'Gingerbread',
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
sodium: 327,
calcium: '7%',
iron: '16%'
},
{
name: 'Jelly bean',
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
sodium: 50,
calcium: '0%',
iron: '0%'
},
{
name: 'Lollipop',
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0,
sodium: 38,
calcium: '0%',
iron: '2%'
},
{
name: 'Honeycomb',
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
sodium: 562,
calcium: '0%',
iron: '45%'
},
{
name: 'Donut',
calories: 452,
fat: 25.0,
carbs: 51,
protein: 4.9,
sodium: 326,
calcium: '2%',
iron: '22%'
},
{
name: 'KitKat',
calories: 518,
fat: 26.0,
carbs: 65,
protein: 7,
sodium: 54,
calcium: '12%',
iron: '6%'
}
]
}
}
}
</script>

View File

@ -1,14 +0,0 @@
<template>
<div class="q-pa-md">
<q-table
title="Treats"
:data="data"
:columns="columns"
row-key="name"
selection="single"
:selected.sync="selected"
/>
<div class="q-mt-md">Selected: {{ JSON.stringify(selected) }}</div>
</div>
</template>

View File

@ -1,185 +1,49 @@
<template>
<div class="q-pa-md">
<q-table
title="Treats"
:data="data"
:columns="columns"
row-key="name"
selection="single"
:selected.sync="selected"
:filter="filter"
grid
hide-header
>
<template v-slot:top-right>
<q-input borderless dense debounce="300" v-model="filter" placeholder="Search">
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</template>
<template v-slot:item="props">
<div
class="q-pa-xs col-xs-12 col-sm-6 col-md-4 col-lg-3 grid-style-transition"
:style="props.selected ? 'transform: scale(0.95);' : ''"
<q-card class="my-card q-mb-md" style="max-width: 600px">
<q-parallax
src="https://www.buga2019.de/we-bilder/2.Aktuelles/BUGA-Zwerg/zwerg-im-gras-buga-heilbronn-2019.jpg?m=1550501506"
:height="200"
/>
<q-card-section>
<div class="text-h6">GeoCaching</div>
<div class="text-body2">Willkommen</div>
<q-expansion-item
expand-separator
rounded-borders
class="bg-green-3 text-black shadow-2 full-width q-mt-md"
label="Was ist GeoCaching?"
>
<q-card :class="props.selected ? 'bg-grey-2' : ''">
<q-card>
<q-card-section>
<q-checkbox :dense="denseOn" v-model="props.selected" :label="props.row.name" />
GeoCaching ist eine spielerische Führung, eine Schnitzeljagd, über die Bundesgartenschau.
Es gibt mehrere Routen (Caches), von denen man wählen kann. Auf jedem Cache gibt es mehrere Stationen, bei denen Rätsel und Aufgaben gelöst werden müssen, um die nächste zu finden.
Eine Station ist eine QR-Code, bei dessen einscannen das nächste Rätsel freigeschaltet wird.
Findet ein Cacher alle Stationen eines Caches erhält er eine kleine Belohnung und sammelt Punkte für eine Rangliste.
</q-card-section>
<q-separator />
<q-list dense>
<q-item v-for="col in props.cols.filter(col => col.name !== 'desc')" :key="col.name">
<q-item-section>
<q-item-label>{{ col.label }}</q-item-label>
</q-item-section>
<q-item-section side>
<q-item-label caption>{{ col.value }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</template>
</q-expansion-item>
</q-card-section>
</q-card>
<q-card class="my-card" style="max-width: 600px">
<q-parallax
src="https://www.buga2019.de/we-bilder/1.Bundesgartenschau/171205_BUGA-2019_Sommerinsel_LOMA_430px.jpg?m=1550501561"
:height="200"
/>
</q-table>
<q-card-section>
<div class="text-h6">Loslegen</div>
<q-btn color="green-3" text-color="black" class="full-width q-mt-md" label="Zu den Caches" to="/Overview"/>
</q-card-section>
</q-card>
</div>
</template>
<style lang="stylus">
.grid-style-transition
transition transform .3s
</style>
<script>
export default {
data () {
return {
denseOn: true,
filter: '',
selected: [],
columns: [
{
name: 'desc',
required: true,
label: 'Dessert (100g serving)',
align: 'left',
field: row => row.name,
format: val => `${val}`,
sortable: true
},
{ name: 'calories', align: 'center', label: 'Calories', field: 'calories', sortable: true },
{ name: 'fat', label: 'Fat (g)', field: 'fat', sortable: true },
{ name: 'carbs', label: 'Carbs (g)', field: 'carbs' },
{ name: 'protein', label: 'Protein (g)', field: 'protein' },
{ name: 'sodium', label: 'Sodium (mg)', field: 'sodium' },
{ name: 'calcium', label: 'Calcium (%)', field: 'calcium', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) },
{ name: 'iron', label: 'Iron (%)', field: 'iron', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) }
],
data: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
sodium: 87,
calcium: '14%',
iron: '1%'
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
sodium: 129,
calcium: '8%',
iron: '1%'
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
sodium: 337,
calcium: '6%',
iron: '7%'
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
sodium: 413,
calcium: '3%',
iron: '8%'
},
{
name: 'Gingerbread',
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
sodium: 327,
calcium: '7%',
iron: '16%'
},
{
name: 'Jelly bean',
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
sodium: 50,
calcium: '0%',
iron: '0%'
},
{
name: 'Lollipop',
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0,
sodium: 38,
calcium: '0%',
iron: '2%'
},
{
name: 'Honeycomb',
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
sodium: 562,
calcium: '0%',
iron: '45%'
},
{
name: 'Donut',
calories: 452,
fat: 25.0,
carbs: 51,
protein: 4.9,
sodium: 326,
calcium: '2%',
iron: '22%'
},
{
name: 'KitKat',
calories: 518,
fat: 26.0,
carbs: 65,
protein: 7,
sodium: 54,
calcium: '12%',
iron: '6%'
}
]
export default {
data () {
return {
}
}
}
}
</script>

View File

@ -0,0 +1,139 @@
<template>
<div class="q-pa-md">
<form class="login" @submit.prevent="login">
<div class="q-pa-md">
<div class="column q-gutter-lg" style="">
<div class="col">
<div class="">
<div class="" style="max-width: 440px">
<q-input outlined filled stack-label v-model="user.username" type="text" label="Benutzername" autocomplete="username"/>
</div>
</div>
</div>
<div class="col">
<div class="">
<div class="" style="max-width: 440px">
<q-input outlined filled stack-label v-model="user.password" type="password" label="Passwort" autocomplete="current-password"/>
</div>
</div>
</div>
<div class="col">
<div class="">
<div class="" style="max-width: 440px">
<q-btn
:outline="this.user.isAuthenticated"
:disabled="this.user.isAuthenticated"
label="Login"
color="primary"
class="full-width"
type="submit"
unelevated
/>
<q-btn
:outline="!this.user.isAuthenticated"
:disabled="!this.user.isAuthenticated"
label="Logout"
color="red"
class="full-width q-mt-md"
unelevated
@click="logout"
/>
</div>
</div>
</div>
</div>
</div>
</form>
<q-dialog v-model="credentialsDialog" persistent transition-show="scale" transition-hide="scale">
<q-card class="bg-red-9 text-white" style="">
<q-card-section>
<div class="text-h6">Fehler</div>
</q-card-section>
<q-card-section>
Es konnten keine übereinstimmenden Zugangsdaten in der Datenbank gefunden werden.
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat label="OK" color="red-9" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog> </div>
</template>
<script>
export default {
data() {
return {
user: {
username: "moximoti",
password: "1234",
//token: "",
isAuthenticated: false
},
credentialsDialog: false,
};
},
// beforeMount: {
// init: function () {
// this.isAuthenticated();
// console.log("initiated");
// }
// },
mounted () {
this.isAuthenticated();
console.log("mounted: initiated");
},
methods: {
login: function () {
// const { username, password } = this;
// this.$store.dispatch(AUTH_REQUEST, { username, password }).then(() => {
// this.$router.push('/')
// })
const data = {
username: this.user.username,
password: this.user.password
} //JSON.stringify(this.user);
console.log("GET http://localhost:8080/api/login/ - json: " + JSON.stringify(data));
this.$axios.post('http://localhost:8080/api/login', data) // TODO muss GET mit AUTH Header werden
.then((response) => {
console.log("GET/POST http://localhost:8080/api/login/ - response: " + response.data);
//this.user.token = response.data;
localStorage.setItem('userToken', JSON.stringify(response.data));
//localStorage.setItem('userToken', response.data);
this.isAuthenticated();
})
.catch((error) => {
console.log("error: " + error);
this.credentialsDialog=true;
})
},
isAuthenticated: function () {
console.log("isAuthenticated()");
console.log("content of localstorage: ");
console.log(JSON.parse(localStorage.getItem('userToken')));
if (localStorage.getItem('userToken')) {
this.user.isAuthenticated = true;
} else {
this.user.isAuthenticated = false;
}
},
logout: function () {
console.log("logout()");
console.log(JSON.parse(localStorage.getItem('userToken')));
this.$axios.get('http://localhost:8080/api/logout', {
params: {
token: JSON.parse(localStorage.getItem('userToken'))
}
})
.then((response) => {
console.log("GET/POST http://localhost:8080/api/logout/ - response: " + response.data);
localStorage.removeItem('userToken');
this.isAuthenticated();
})
.catch((error) => {
});
},
},
};
</script>

View File

@ -0,0 +1,136 @@
<template>
<q-page class="column">
<div class="bg-red col col-shrink" style="">
<q-tabs
v-model="tab"
class="bg-grey-2"
inline-label
align="justify"
active-bg-color="bg-grey-1"
active-color="cyan-14"
indicator-color="cyan-14"
switch-indicator
>
<q-tab name="list" label="Liste" icon="list"/>
<q-tab name="map" label="Karte" icon="map"/>
</q-tabs>
<q-separator color="grey-4"/>
</div>
<div class="col flex column">
<q-tab-panels v-model="tab" animated swipeable class="col">
<q-tab-panel name="list" class=" fit">
<q-list>
<q-card class="q-mb-md" v-for="cache in caches" :key="cache.id">
<q-expansion-item
class=""
expand-icon-toggle
expand-separator
icon="location_on"
:label="cache.name"
:caption="cache.rankingPoints+' Punkte / Size '+cache.stationen.length"
>
<q-item
class="q-pr-sm "
>
<q-item-section top avatar class="self-center">
<!--<q-icon rounded color="cyan-14" name="location_on" size="3rem"/>-->
</q-item-section>
<q-item-section>
<q-item-label caption>{{ cache.description }}</q-item-label>
</q-item-section>
<q-item-section side top class="self-center" >
</q-item-section>
</q-item>
<q-item class="q-pr-sm reverse">
<q-btn @click="startCache(cache.id)" flat unelevated stack color="positive" icon="arrow_forward" label="Starten" size="sm"/>
</q-item>
</q-expansion-item>
</q-card>
</q-list>
</q-tab-panel>
<q-tab-panel name="map" class="q-pa-none fit">
<!--<div class="full-width full-height absolute-full" style="background: url('statics/osm_mock.png'); background-size: cover">-->
<!--</div>-->
<q-img src="https://www.buga2019.de/we-bilder/3.Gartenausstellung/Gelaendeplan/190320_Gelaendeplan-quadratisch.jpg" transition="fade" class="absolute-full">
<template v-slot:loading>
<q-spinner-puff color="cyan-14" size="4em"/>
</template>
</q-img>
</q-tab-panel>
</q-tab-panels>
</div>
</q-page>
</template>
<style>
/*
.my-list-card-item
padding-left: 8px
*/
</style>
<script>
//import {dom} from 'quasar'
//const {height, width} = dom
export default {
data() {
return {
tab: 'list',
// hheight: 71.0,
// fheight: 36.0, //37
//header: {h: '0px', w: 0}
caches: [],
}
},
mounted: function () {
//this.header.h = style(this.$refs.layout.$refs.header, 'height')
// this.hheight = height(document.getElementById('qheader'));
// this.fheight = height(document.getElementById('qfooter'));
},
computed: {
// mapHeight() {
// let header = this.hheight
// let footer = this.fheight
// let offset = header + footer + 1;
// console.log(offset)
// return {minHeight: offset ? `calc(100vh - ${offset}px)` : '100vh'};
// },
// computedMainStyle() {
// return { height: `calc( 100vh - ${this.header.h} )` };
// }
},
created: function() {
console.log("created(): " + this.caches);
this.fetchAllCaches();
},
methods: {
fetchAllCaches() {
this.$axios.get('http://localhost:8080/api/allCaches')
.then((response) => {
console.log("Caches: " + this.caches);
this.caches = response.data;
})
},
startCache(cacheID) {
const userToken = JSON.parse(localStorage.getItem('userToken'));
let params = { cacheID: cacheID };
if (userToken != null) {
params.token = userToken;
}
console.log(params);
this.$axios.get('http://localhost:8080/api/startCache', { params })
.then((response) => {
console.log("Angefangen: " + response.data);
})
}
}
}
</script>

View File

@ -0,0 +1,59 @@
<template>
<q-page class="q-ma-md">
<h4 class="text-h4">Neue Station</h4>
<q-editor
:toolbar="[
['bold', 'italic', 'strike', 'underline'],
['undo', 'redo']
]"
v-model="description" min-height="10rem" />
<!--<q-input-->
<!--v-model="description"-->
<!--filled-->
<!--type="textarea"-->
<!--/>-->
<p class="text-h5 q-mt-md">Location</p>
<q-img transition="fade"
class="q-mb-md "
:ratio="16/9"
src="https://www.buga2019.de/we-bilder/3.Gartenausstellung/Gelaendeplan/190320_Gelaendeplan-quadratisch.jpg"
></q-img>
<div class="row q-col-gutter-md">
<q-input class="col" dense stack-label filled v-model="text" label="Längengrad/Breitengrad" />
<div class="col-shrink">
<q-btn unelevated color="primary" class="full-height" icon="my_location"/>
</div>
</div>
<p class="text-h5 q-mt-md">Lösung</p>
<q-input class="col" dense stack-label filled v-model="text" label="Lösung" />
<q-input class="col q-mt-md" dense stack-label filled v-model="text" label="Code" readonly/>
</q-page>
</template>
<script>
export default {
name: "Station",
data() {
return {
description: "Rätsel, Aufgabe und Informationen zur Station.",
text:"v-model !!"
}
},
created: function() {
},
beforeMount: function() {
},
mounted: function() {
console.log("'id' from url: "+this.$route.params.id)
},
computed: {
},
methods: {
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,84 @@
<template>
<div class="q-pa-md row items-start q-col-gutter-md">
<div class="col col-sm-6" v-for="cache in caches" :key="cache.id">
<q-card flat bordered class="my-card bg-grey-1">
<q-img :ratio="16/9" src="https://cdn.quasar-framework.org/img/parallax2.jpg">
<div class="absolute-bottom">
<div class="text-h6">
<span>{{ cache.name }}</span>
<!--<span v-if="cache.stationen.length > 2"> (Multicache)</span>-->
<!--<span v-else> (Singlecache)</span>-->
</div>
</div>
</q-img>
<q-card-section>
{{ cache.description }}
</q-card-section>
<q-separator inset />
<q-card-actions align="around">
<q-btn flat color="green" class="btn-fixed-width" >Cache starten</q-btn>
<q-btn flat outline class="btn-fixed-width">Ansehen</q-btn>
</q-card-actions>
</q-card>
</div>
</div>
</template>
<style lang="stylus">
.grid-style-transition
transition transform .3s
.btn-fixed-width
width: 48%
</style>
<script>
export default {
data () {
return {
denseOn: true,
filter: '',
selected: [],
caches: [],
columns: [
{
name: 'desc',
required: true,
label: 'Dessert (100g serving)',
align: 'left',
field: row => row.title,
format: val => `${val}`,
sortable: true
},
{ name: 'userId', align: 'center', label: 'ID', field: 'userId', sortable: true },
{ name: 'id', label: 'fID', field: 'id', sortable: true },
{ name: 'title', label: 'Titel', field: 'title' },
{ name: 'completed', label: 'Komplett', field: 'completed' },
],
// data: [
// {
// "userId": 1,
// "id": 1,
// "title": "delectus aut autem",
// "completed": false
// }
// ]
}
},
created: function() {
console.log("created(): " + this.caches);
this.fetchTodos();
},
methods: {
fetchTodos () {
this.$axios.get('http://localhost:8080/api/allCaches')
.then((response) => {
console.log("Caches: " + this.caches);
this.caches = response.data;
})
}
}
}
</script>

View File

@ -5,9 +5,34 @@ const routes = [
children: [{ path: "", component: () => import("pages/Index.vue") }]
},
{
path: "/dashboard/",
path: "/overview/",
component: () => import("layouts/MyLayout.vue"),
children: [{ path: "", component: () => import("pages/Dashboard.vue") }]
children: [{ path: "", component: () => import("pages/Overview.vue") }]
},
{
path: "/testcaches/",
component: () => import("layouts/MyLayout.vue"),
children: [{path: "", component: () => import("pages/TestCaches.vue")}]
},
{
path: "/cacheview/",
component: () => import("layouts/MyLayout.vue"),
children: [{ path: "", component: () => import("pages/CacheView.vue") }]
},
{
path: "/station/",
component: () => import("layouts/MyLayout.vue"),
children: [{ path: "", component: () => import("pages/Station.vue") }]
},
{
path: "/station/:id",
component: () => import("layouts/MyLayout.vue"),
children: [{ path: "", component: () => import("pages/Station.vue") }]
},
{
path: "/login/",
component: () => import("layouts/MyLayout.vue"),
children: [{ path: "", component: () => import("pages/Login.vue") }]
}
];

View File

@ -0,0 +1,35 @@
<svg xmlns="http://www.w3.org/2000/svg" width="103.187mm" height="99.871mm" viewBox="0 0 292.5 283.1">
<defs>
<style>
.a, .e {
fill: #58c5c7;
}
.a, .b, .c, .g {
opacity: 0.65;
isolation: isolate;
}
.b, .f {
fill: #ec0090;
}
.c, .d {
fill: #5ca038;
}
.g, .h {
fill: #accd6b;
}
</style>
</defs>
<title>buga_logo</title>
<path class="a" d="M272.4,1H256.8V83.4c-.3,6.2-.4,11.7-1.8,17.8-2.2,11.1-10.2,32.9-31.5,33.2h0c30.2-.2,43.3-22.1,46.4-33.2,1.9-6.1,2.1-11.5,2.5-17.8ZM165.6,1V83.4c.4,6.3.6,11.7,2.5,17.8,3,11.1,16.3,33,46.5,33.2-21.4-.2-29.4-22.1-31.6-33.2-1.4-6.1-1.5-11.5-1.8-17.8V1Zm49,133.4Z"/>
<path class="b" d="M29.7,1H15.8V133.5H29.6V1ZM75.1,1H71.8c1.6,0,7.3.3,11.7,2.6C91.9,7.9,97.9,20,97.9,33.1c0,4.1-.7,14.2-6.7,21.9a36.431,36.431,0,0,1-5.1,5.3,20.877,20.877,0,0,1,7.8,3.4c8.2,5.7,12.7,18.1,12.7,31,0,4.5-.7,14.6-6,24-4.7,8.5-10.7,12.8-17.9,14.2-2.2.4-4.6.4-6.9.6h5.1c3.2-.2,6.6-.2,9.8-.6,10.2-1.3,18.7-5.7,25.3-14.2a39.435,39.435,0,0,0,8.5-24c0-12.9-6.4-25.4-17.9-31a38.989,38.989,0,0,0-11-3.4c3.6-2.4,5.7-3.8,7.2-5.3a29.422,29.422,0,0,0,9.4-21.9A31.582,31.582,0,0,0,91.8,3.6C85.5,1.2,76.8,1,75.1,1"/>
<path class="c" d="M223.4,157.9v.5L271.2,282H291Zm-8.6,0L147.2,282H167l47.8-123.5Z"/>
<path class="d" d="M271.2,282,223.4,158V282ZM167,282h47.8V158Z"/>
<path class="e" d="M256.7,83.4V1H223.5V134.4c21.3-.3,29.3-22.1,31.5-33.2,1.3-6.1,1.4-11.6,1.7-17.8m-42.1,51V1H181.2V83.4c.3,6.2.4,11.7,1.8,17.8,2.1,11.1,10.2,33,31.6,33.2"/>
<path class="f" d="M91.3,55c6-7.8,6.7-17.8,6.7-21.9C98,20,92,7.9,83.6,3.6,79,1.2,72.8,1,71.6,1H68V133.5h7.8c2.3-.2,4.7-.2,6.9-.6,7.2-1.3,13.2-5.7,17.9-14.2a50.913,50.913,0,0,0,6-24c0-12.9-4.5-25.3-12.7-31a22.143,22.143,0,0,0-7.7-3.4A31.991,31.991,0,0,0,91.3,55m-39,78.5h6.9V1H29.7V133.5Z"/>
<path class="g" d="M59.1,283.2h0c-8.3-1.1-16-5.5-22.4-12.2l-.1-.1c-1-1.1-2-2.2-3-3.4a3.039,3.039,0,0,1-.5-.7,37.117,37.117,0,0,1-2.3-3.2,14,14,0,0,0-1-1.6c-.5-.9-1.1-1.8-1.6-2.7-.4-.7-.7-1.5-1.1-2.2s-.8-1.6-1.2-2.4a4.875,4.875,0,0,1-.4-1.1c-.6-1.3-1.1-2.5-1.6-3.9,0-.1-.1-.2-.1-.3a73.839,73.839,0,0,1-2.9-10.2,89.8,89.8,0,0,1-1.5-10.4c-.2-2.5-.3-4.9-.3-7.5,0-7.2.8-25.1,10.3-40.5,7.6-12.4,18.5-21.1,29.9-22.6h0c-18.5,1.2-33.8,10.2-44.5,22.6C1.2,196.1,0,214,0,221.2c0,33,25.5,60,59.1,62m68-61.8H108.3c0,2.5-.1,4.9-.3,7.3a89.8,89.8,0,0,1-1.5,10.4,70.079,70.079,0,0,1-2.9,10.2c0,.1-.1.2-.1.3-.5,1.3-1,2.6-1.6,3.9-.1.4-.3.7-.4,1.1l-1.2,2.4c-.4.8-.7,1.5-1.1,2.2-.5.9-1.1,1.8-1.6,2.7a14,14,0,0,1-1,1.6,37.117,37.117,0,0,1-2.3,3.2,3.039,3.039,0,0,0-.5.7c-1,1.2-2,2.3-3,3.4l-.1.1c-6.4,6.7-14.1,11.1-22.4,12.2h0c33.3-1.9,58.7-28.7,58.8-61.7"/>
<path class="h" d="M59.1,283.2V158.1c-11.4,1.5-22.4,10.2-29.9,22.6-9.5,15.5-10.3,33.3-10.3,40.5-.1,33,18,59,40.2,62m49.2-61.8H68v61.7c22.1-2.9,40.2-28.7,40.3-61.7"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

View File

@ -0,0 +1,4 @@
/*
export function someAction (context) {
}
*/

View File

@ -0,0 +1,4 @@
/*
export function someGetter (state) {
}
*/

View File

@ -0,0 +1,12 @@
import state from './state'
import * as getters from './getters'
import * as mutations from './mutations'
import * as actions from './actions'
export default {
namespaced: true,
state,
getters,
mutations,
actions
}

View File

@ -0,0 +1,38 @@
import axios from 'axios'
/*
export function someMutation (state) {
}
*/
export const evalAuth = (state) => {
console.log("isAuthenticated()");
console.log(localStorage.getItem('userToken'));
if (localStorage.getItem('userToken')) { // TODO hier muss Abfrage mit API, z.B. /api/user?token="ME" stattfinden.
state.user.isAuthenticated = true;
} else {
state.user.isAuthenticated = false;
}
};
export const logout = (state) => {
console.log("logout()");
console.log(localStorage.getItem('userToken'));
localStorage.removeItem('userToken');
console.log(localStorage.getItem('userToken'));
state.commit(evalAuth(state));
};
export const login = (state) => {
const data = {
username: state.user.username,
password: state.user.password
};
console.log("GET http://localhost:8080/api/login/ - json: " + JSON.stringify(data));
this.state.$axios.post('http://localhost:8080/api/login', data) // TODO muss GET mit AUTH Header werden
.then((response) => {
console.log("GET/POST http://localhost:8080/api/login/ - response: " + response.data);
localStorage.setItem('userToken', JSON.stringify(response));
state.commit(evalAuth(state));
})
.catch((error) => {
console.log("error: " + error);
//errorDialog = true;
})
};

View File

@ -0,0 +1,7 @@
export default {
user: {
username: "moximoti",
password: "1234",
isAuthenticated: false
},
}

View File

@ -1,25 +1,54 @@
import Vue from "vue";
import Vuex from "vuex";
import Axios from "axios";
import auth from "./auth"
// import example from './module-example'
Vue.use(Vuex);
Vue.use(Vuex, Axios);
/*
* If not building with SSR mode, you can
* directly export the Store instantiation
*/
export default function(/* { ssrContext } */) {
// export default function(/* { ssrContext } */) {
// const Store = new Vuex.Store({
// modules: {
// // example
// },
//
// // enable strict mode (adds overhead!)
// // for dev mode only
// strict: process.env.DEV
// });
//
// return Store;
// }
export default function (/* { ssrContext } */) {
const Store = new Vuex.Store({
modules: {
// example
auth
},
// enable strict mode (adds overhead!)
// for dev mode only
strict: process.env.DEV
});
})
return Store;
}
/*
if we want some HMR magic for it, we handle
the hot update like below. Notice we guard this
code with "process.env.DEV" -- so this doesn't
get into our production build (and it shouldn't).
*/
if (process.env.DEV && module.hot) {
module.hot.accept(['./auth'], () => {
const newShowcase = require('./auth').default;
store.hotUpdate({ modules: { showcase: newShowcase } })
})
}
return Store
};

View File

@ -745,10 +745,10 @@
resolved "https://registry.yarnpkg.com/@positron/stack-trace/-/stack-trace-1.0.0.tgz#14fcc712a530038ef9be1ce6952315a839f466a8"
integrity sha1-FPzHEqUwA475vhzmlSMVqDn0Zqg=
"@quasar/app@^1.0.0-beta.0":
version "1.0.0-beta.12"
resolved "https://registry.yarnpkg.com/@quasar/app/-/app-1.0.0-beta.12.tgz#fa5e4a0ea662e969d1306dd8d50345d136051212"
integrity sha512-lQSqW+LuBG9jmglGj82fZ/9J6Dm0nz+dbSna6rOiy4zkt1FjmQ3PCRrImyd+WIsbKUntlTcKJ4+uN6fOlblcvg==
"@quasar/app@^1.0.0-beta.13":
version "1.0.0-beta.13"
resolved "https://registry.yarnpkg.com/@quasar/app/-/app-1.0.0-beta.13.tgz#55127104ed2fc3b7bbed2882ecbaf8412a00a3e2"
integrity sha512-BMF/U/5xE7EntvVWVeQ0ud2k9z5xo4TGast5/Wv/g2+X4/VBIYUFPlDMNJh93okZ6QnRaNycU5xORo+dUiF8Cg==
dependencies:
"@quasar/babel-preset-app" "1.0.2"
"@vue/preload-webpack-plugin" "1.1.0"
@ -787,7 +787,7 @@
minimist "1.2.0"
ms "2.1.1"
node-loader "0.6.0"
opn "5.4.0"
opn "5.5.0"
optimize-css-assets-webpack-plugin "5.0.1"
ouch "2.0.0"
postcss-loader "3.0.0"
@ -800,12 +800,12 @@
stylus-loader "3.0.2"
terser-webpack-plugin "1.2.3"
url-loader "1.1.2"
vue "2.6.9"
vue "2.6.10"
vue-loader "15.7.0"
vue-router "3.0.2"
vue-server-renderer "2.6.9"
vue-server-renderer "2.6.10"
vue-style-loader "4.1.2"
vue-template-compiler "2.6.9"
vue-template-compiler "2.6.10"
vuex "3.1.0"
webpack "4.29.6"
webpack-bundle-analyzer "3.1.0"
@ -836,10 +836,10 @@
babel-plugin-dynamic-import-node "2.2.0"
core-js "2.6.5"
"@quasar/extras@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.1.0.tgz#acb43f7b2bb8e65851b5ba30bc05147c48854168"
integrity sha512-594TNuQrQLwzSwhlZMkMn5AIAcNk8zPrsCkdHT021dswMv+IHATGyKJaTH4KuLKLWse+oPRoB0NddLNf9PXiuw==
"@quasar/extras@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.1.1.tgz#f514bf5108c5de964949aaa336ba65266a25fd88"
integrity sha512-n9aQ9N9GBaRF15v3Rm5QDoeLOHFzjQ874f+54TthWmaQvx/8DV6fG/bwLgA6AjLUIZJs3ogm4J1KqWO+4zSg1g==
"@types/q@^1.5.1":
version "1.5.2"
@ -4925,14 +4925,7 @@ opener@^1.5.1:
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
opn@5.4.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035"
integrity sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==
dependencies:
is-wsl "^1.1.0"
opn@^5.1.0:
opn@5.5.0, opn@^5.1.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==
@ -5727,10 +5720,10 @@ qs@6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
quasar@^1.0.0-beta.0:
version "1.0.0-beta.11"
resolved "https://registry.yarnpkg.com/quasar/-/quasar-1.0.0-beta.11.tgz#cbccd35e2a41f333492dad2cd15b8ccf5225e918"
integrity sha512-g6VBCNa9fwNCyrWfxi8GwpXL6qNtyynweVKT+wqMZajjvE6fQ/EwETWF2zsla1Rv9NYsTCnW6o//bQn1vcqJbw==
quasar@^1.0.0-beta.13:
version "1.0.0-beta.13"
resolved "https://registry.yarnpkg.com/quasar/-/quasar-1.0.0-beta.13.tgz#81622ece941b93a0186c646f1b343f400c16ebe6"
integrity sha512-9sDSUYRVzQu2WezUy329K9yBCGaoXFkeVYp9NnvKtzs7b/Wk76GrV4kwkBqVvFZDdOYuI4OFFdjPdKdDDMAILw==
querystring-es3@^0.2.0:
version "0.2.1"
@ -7012,10 +7005,10 @@ vue-router@3.0.2:
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be"
integrity sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg==
vue-server-renderer@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.9.tgz#74b970be513887ad255b2132daa1720a16af69ed"
integrity sha512-UAwI9R+H9oh6YIG9xmS4uU1X8MD9bBzDLGIhqB8UHX9tJPrWQTrBijfXfnytDpefIisfz3qLa27qFOKuX4vnsw==
vue-server-renderer@2.6.10:
version "2.6.10"
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz#cb2558842ead360ae2ec1f3719b75564a805b375"
integrity sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug==
dependencies:
chalk "^1.1.3"
hash-sum "^1.0.2"
@ -7034,10 +7027,10 @@ vue-style-loader@4.1.2, vue-style-loader@^4.1.0:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
vue-template-compiler@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.9.tgz#26600415ff81a7a241aebc2d4e0abaa0f1a07915"
integrity sha512-QgO0LSCdeH6zUMSgtqel+yDWsZWQPXiWBdFg9qzOhWfQL8vZ+ywinAzE04rm1XrWc+3SU0YAdWISlEgs/i8WWA==
vue-template-compiler@2.6.10:
version "2.6.10"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz#323b4f3495f04faa3503337a82f5d6507799c9cc"
integrity sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg==
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
@ -7047,10 +7040,10 @@ vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.9.tgz#415c1cc1a5ed00c8f0acdd0a948139d12b7ea6b3"
integrity sha512-t1+tvH8hybPM86oNne3ZozCD02zj/VoZIiojOBPJLjwBn7hxYU5e1gBObFpq8ts1NEn1VhPf/hVXBDAJ3X5ljg==
vue@2.6.10:
version "2.6.10"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
vuex@3.1.0:
version "3.1.0"

View File

@ -4,17 +4,17 @@ import com.google.gson.Gson;
import hhn.labsw.bugageocaching.entities.*;
import hhn.labsw.bugageocaching.exceptions.IllegalParameterException;
import hhn.labsw.bugageocaching.repositories.*;
import hhn.labsw.bugageocaching.service.SecurityService;
import hhn.labsw.bugageocaching.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
@RestController
public class Controller {
@ -41,50 +41,72 @@ public class Controller {
UserRepository userRepository;
@Autowired
private UserService userService;
StationReihenfolgeRepository stationReihenfolgeRepository;
@Autowired
private SecurityService securityService;
private AtomicLong counter = new AtomicLong();
@RequestMapping("/allCaches")
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/allCaches")
@ResponseBody
public String getAllCaches() {
return new Gson().toJson(cacheRepository.findAll());
}
@RequestMapping("/startCache")
public @ResponseBody
String startCache(@RequestParam(value = "userID", defaultValue = "-1") String userID,
@RequestParam String cacheID) throws IllegalParameterException {
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/login")
@ResponseBody
public ResponseEntity<Object> login(@RequestBody User user) {
if (user.getUsername() == null || user.getPassword() == null) {
System.out.println(user.getUsername());
System.out.println(user.getPassword());
return ResponseEntity.status(401).body(null);
}
if (userRepository.findByUsername(user.getUsername()) == null) {
return ResponseEntity.status(401).body(null);
}
if (!userID.equals("-1")) { // ein angemeldeter user startet den cache(es werden zwei parameter übergeben)
if (BCrypt.checkpw(user.getPassword(), userRepository.findByUsername(user.getUsername()).getPassword())) {
String token = user.getUsername() + BCrypt.hashpw(String.valueOf(System.currentTimeMillis() + counter.incrementAndGet()), BCrypt.gensalt());
String hashedToken = BCrypt.hashpw(token, BCrypt.gensalt());
userRepository.findByUsername(user.getUsername()).setToken(hashedToken);
userRepository.save(userRepository.findByUsername(user.getUsername()));
//return ResponseEntity.ok(new Gson().toJson(token));
return ResponseEntity.ok(token);
}
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body(null);
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/startCache")
@ResponseBody
public String startCache(@RequestParam(value = "token", defaultValue = "-1") String token,
@RequestParam String cacheID) throws IllegalParameterException {
if (!token.equals("-1")) { // ein angemeldeter user startet den cache(es werden zwei parameter übergeben)
Bearbeitet bearbeitet = new Bearbeitet();
Optional<User> userOptional = userRepository.findById(Integer.valueOf(userID));
if (userOptional.isPresent()) {
User user = userOptional.get();
bearbeitet.setUser(user);
} else {
throw new IllegalParameterException("There is no user with the ID " + userID);
}
User user = userRepository.findByUsername(token.substring(0, token.indexOf("$")));
bearbeitet.setUser(user);
Optional<Cache> cacheOptional = cacheRepository.findById(Integer.valueOf(cacheID));
if (cacheOptional.isPresent()) {
Cache cache = cacheOptional.get();
bearbeitet.setCache(cache);
Station startStation = cache.getStartStation();
bearbeitet.setAktuelleStation(startStation);
} else {
throw new IllegalParameterException( "There is no cache with the ID " + cacheID);
throw new IllegalParameterException("There is no cache with the ID " + cacheID);
}
Optional<CacheAccesDefinition> cacheAccesDefinitionOptional =
cacheAccesDefinitionRepository.findById(1); // bearbeitet
cacheAccesDefinitionRepository.findById(0); // angefangen
if (cacheAccesDefinitionOptional.isPresent()) {
CacheAccesDefinition cacheAccesDefinition = cacheAccesDefinitionOptional.get();
bearbeitet.setCacheAccesDefinition(cacheAccesDefinition);
} else {
throw new IllegalParameterException("There is no cacheAccesDefinition with the ID " + 1);
throw new IllegalParameterException("There is no cacheAccesDefinition with the ID " + 0);
}
bearbeitetRepository.save(bearbeitet);
@ -97,15 +119,222 @@ public class Controller {
Cache cache = cacheOptional.get();
return new Gson().toJson(cache);
} else {
throw new IllegalParameterException( "There is no cache with the ID " + cacheID);
throw new IllegalParameterException("There is no cache with the ID " + cacheID);
}
}
}
@RequestMapping("/securityCheck")
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/logout")
@ResponseBody
public String securityCheck(){
return "Angemeldet";
boolean logout(@RequestParam String token) {
// System.out.println("logout");
User user = userRepository.findByUsername(token.substring(0, token.indexOf("$")));
// System.out.println(token);
// System.out.println(user.getToken());
if (user == null || user.getToken().isEmpty() )
return false;
user.setToken(null);
userRepository.save(user);
return true;
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/createStation")
@ResponseBody
String createStation(@RequestParam String description,
@RequestParam String lattitude,
@RequestParam String longitude,
@RequestParam String solution) throws IllegalParameterException {
if (description.length() == 0 || lattitude.length() == 0 || longitude.length() == 0 || solution.length() == 0) {
throw new IllegalParameterException("Fields can´t be empty");
}
double latti;
double longi;
try {
latti = Double.valueOf(lattitude);
if (latti < -90 || latti > 90) {
throw new IllegalParameterException("Lattitude has to be in the range of -90 to 90 degrees");
}
} catch (NumberFormatException e) {
throw new NumberFormatException("Lattitude has to be a decimal number");
}
try {
longi = Double.valueOf(longitude);
if (longi < -180 || longi > 180) {
throw new IllegalParameterException("Longitude has to be in the range of -180 to 180 degrees");
}
} catch (NumberFormatException e) {
throw new NumberFormatException("Longitude has to be a decimal number");
}
Station station = new Station();
station.setDescription(description);
station.setLattitude(latti);
station.setLongitude(longi);
station.setSolution(solution);
Random r = new Random();
int low = 100000;
int high = 1000000;
int code = r.nextInt(high - low) + low;
station.setCode(code);
stationRepository.save(station);
return new Gson().toJson(station);
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/checkAdmin")
@ResponseBody
boolean checkAdmin(@RequestParam String token) {
User user = userRepository.findByUsername(token.substring(0, token.indexOf("$")));
for (Role role : user.getRoles()) {
if (role.getId() == 0) { // is admin
return true;
}
}
return false;
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/getAllStations")
@ResponseBody
ResponseEntity getAllStations() {
return ResponseEntity.status(200).body(new Gson().toJson(stationRepository.findAll()));
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/createCache")
@ResponseBody
ResponseEntity createCache(@RequestParam String description,
@RequestParam String name,
@RequestParam String rankingPoints,
@RequestParam(value = "rewardID", defaultValue = "-1") String rewardID,
@RequestParam List<Station> stationen) throws IllegalParameterException {
if (description.length() == 0 || name.length() == 0 || rankingPoints.length() == 0 || stationen.size() == 0) {
return ResponseEntity.status(400).body("Fields can´t be empty");
}
for (Cache cache : cacheRepository.findAll()) {
if (cache.getName().equals(name)) {
return ResponseEntity.status(400).body("name is already taken");
}
}
int points;
try {
points = Integer.valueOf(rankingPoints);
if (points < 0) {
return ResponseEntity.status(400).body("Ranking points has to be a positive number");
}
} catch (NumberFormatException e) {
return ResponseEntity.status(400).body("Ranking points has to be an integer");
}
Optional<Reward> rewardOptional = rewardRepository.findById(Integer.valueOf(rewardID));
Reward reward = rewardOptional.orElse(null);
Cache cache = new Cache();
cache.setDescription(description);
cache.setName(name);
cache.setRankingPoints(Integer.valueOf(rankingPoints));
cache.setReward(reward);
cache.setStartStation(stationen.get(0));
cache.setStationen(stationen);
cacheRepository.save(cache);
for (int i = 0; i + 1 < stationen.size(); i++) {
StationReihenfolge stationReihenfolge = new StationReihenfolge();
stationReihenfolge.setCache(cache);
stationReihenfolge.setStation(stationen.get(i));
stationReihenfolge.setNachfolgeStation(stationen.get(i + 1));
stationReihenfolgeRepository.save(stationReihenfolge);
}
return ResponseEntity.status(200).body(new Gson().toJson(cache));
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/deleteCache")
@ResponseBody
ResponseEntity deleteCache(@RequestParam String cacheID) {
Optional<Cache> optionalCache = cacheRepository.findById(Integer.valueOf(cacheID));
if (!optionalCache.isPresent()) {
return ResponseEntity.status(404).body(new Gson().toJson("There is no cache with the ID " + cacheID));
}
Cache cache = optionalCache.get();
for (StationReihenfolge stationReihenfolge : stationReihenfolgeRepository.findAll()) {
if (stationReihenfolge.getCache().getId() == cache.getId()) {
stationReihenfolgeRepository.delete(stationReihenfolge);
}
}
for (Bearbeitet bearbeitet : bearbeitetRepository.findAll()) {
if (bearbeitet.getCache().getId() == cache.getId()) {
bearbeitetRepository.delete(bearbeitet);
}
}
cacheRepository.delete(cache);
return ResponseEntity.status(200).body(new Gson().toJson(true));
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/getMyCaches")
@ResponseBody
ResponseEntity getMyCaches(@RequestParam String token) {
try {
User user = userRepository.findByUsername(token.substring(0, token.indexOf("$")));
if (user != null) {
ArrayList<Bearbeitet> bearbeitetList = new ArrayList<>();
for (Bearbeitet bearbeitet : bearbeitetRepository.findAll()) {
if (bearbeitet.getUser().getId() == user.getId()) {
bearbeitetList.add(bearbeitet);
}
}
return ResponseEntity.status(200).body(new Gson().toJson(bearbeitetList));
} else {
return ResponseEntity.status(404).body("User was not found in the database");
}
} catch (StringIndexOutOfBoundsException e) {
return ResponseEntity.status(400).body("Invalid token");
}
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/getRankingList")
@ResponseBody
ResponseEntity getRankingList() {
return ResponseEntity.status(200).body(new Gson().toJson(userRepository.getRankingList()));
}
@CrossOrigin(origins = "http://localhost:8081") // only for dev purpose
@RequestMapping("/api/getUser")
@ResponseBody
ResponseEntity getUser(@RequestParam String token) {
try {
User user = userRepository.findByUsername(token.substring(0, token.indexOf("$")));
if (user != null) {
return ResponseEntity.status(200).body(new Gson().toJson(user));
} else {
return ResponseEntity.status(404).body("User was not found in the database");
}
} catch (StringIndexOutOfBoundsException e) {
return ResponseEntity.status(400).body("Invalid token");
}
}
}

View File

@ -20,6 +20,9 @@ public class Bearbeitet {
@OneToOne
private CacheAccesDefinition cacheAccesDefinition;
@OneToOne
private Station aktuelleStation;
public int getId() {
return id;
}
@ -51,4 +54,12 @@ public class Bearbeitet {
public void setCacheAccesDefinition(CacheAccesDefinition cacheAccesDefinition) {
this.cacheAccesDefinition = cacheAccesDefinition;
}
public Station getAktuelleStation() {
return aktuelleStation;
}
public void setAktuelleStation(Station aktuelleStation) {
this.aktuelleStation = aktuelleStation;
}
}

View File

@ -23,6 +23,9 @@ public class Cache {
@ManyToOne
private Reward reward;
@ManyToOne
private Station startStation;
public Cache() {
}
@ -73,4 +76,12 @@ public class Cache {
public void setReward(Reward reward) {
this.reward = reward;
}
public Station getStartStation() {
return startStation;
}
public void setStartStation(Station startStation) {
this.startStation = startStation;
}
}

View File

@ -3,20 +3,32 @@ package hhn.labsw.bugageocaching.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
<<<<<<< HEAD
import javax.persistence.ManyToMany;
import java.util.Set;
=======
>>>>>>> develop
@Entity
public class Role {
@Id
@GeneratedValue
<<<<<<< HEAD
int id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users;
=======
private int id;
private String name;
public Role() {
}
>>>>>>> develop
public int getId() {
return id;
@ -33,6 +45,7 @@ public class Role {
public void setName(String name) {
this.name = name;
}
<<<<<<< HEAD
public Set<User> getUsers() {
return users;
@ -41,4 +54,6 @@ public class Role {
public void setUsers(Set<User> users) {
this.users = users;
}
=======
>>>>>>> develop
}

View File

@ -14,6 +14,8 @@ public class Station {
private String description;
private double longitude;
private double lattitude;
private int code;
private String solution;
public Station() {
}
@ -50,4 +52,19 @@ public class Station {
this.lattitude = lattitude;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getSolution() {
return solution;
}
public void setSolution(String solution) {
this.solution = solution;
}
}

View File

@ -0,0 +1,53 @@
package hhn.labsw.bugageocaching.entities;
import javax.persistence.*;
@Entity
@Table
public class StationReihenfolge {
@Id
@GeneratedValue
private int id;
@OneToOne
private Cache cache;
@OneToOne
private Station station;
@OneToOne
private Station nachfolgeStation;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Cache getCache() {
return cache;
}
public void setCache(Cache cache) {
this.cache = cache;
}
public Station getStation() {
return station;
}
public void setStation(Station station) {
this.station = station;
}
public Station getNachfolgeStation() {
return nachfolgeStation;
}
public void setNachfolgeStation(Station nachfolgeStation) {
this.nachfolgeStation = nachfolgeStation;
}
}

View File

@ -1,7 +1,11 @@
package hhn.labsw.bugageocaching.entities;
import javax.persistence.*;
<<<<<<< HEAD
import java.util.Set;
=======
import java.util.List;
>>>>>>> develop
@Entity
@Table
@ -17,6 +21,14 @@ public class User {
private int rankingPointsSum;
private String email;
private String password;
<<<<<<< HEAD
=======
@ManyToMany
private List<Role> roles;
private String token;
>>>>>>> develop
@ManyToOne
private Team team;
@ -91,6 +103,7 @@ public class User {
this.team = team;
}
<<<<<<< HEAD
public Set<Role> getRoles() {
return roles;
}
@ -105,5 +118,21 @@ public class User {
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
=======
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
>>>>>>> develop
}
}

View File

@ -0,0 +1,7 @@
package hhn.labsw.bugageocaching.repositories;
import hhn.labsw.bugageocaching.entities.StationReihenfolge;
import org.springframework.data.repository.CrudRepository;
public interface StationReihenfolgeRepository extends CrudRepository<StationReihenfolge, Integer> {
}

View File

@ -1,9 +1,23 @@
package hhn.labsw.bugageocaching.repositories;
import hhn.labsw.bugageocaching.entities.User;
<<<<<<< HEAD
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
User findByUsername(String username);
=======
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.Collection;
import java.util.List;
public interface UserRepository extends CrudRepository<User, Integer> {
User findByUsername(String username);
@Query(value = "SELECT u.username, u.ranking_points_sum from user u order by ranking_points_sum DESC", nativeQuery = true)
List<Object[]> getRankingList();
>>>>>>> develop
}

View File

@ -2,4 +2,5 @@ spring.datasource.url=jdbc:mariadb://seserver.se.hs-heilbronn.de:3406/buga19Geoc
spring.datasource.username=BuGa19GeocachingUser
spring.datasource.password=GeocachingPw
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true