Running Version with indexDB

This commit is contained in:
Thomas Mack 2022-03-28 08:31:59 +02:00
parent 1c42a5d608
commit 8a6e300c47
23 changed files with 1461 additions and 138 deletions

206
package-lock.json generated
View File

@ -5,19 +5,23 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "billibox-vue",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@dsb-norge/vue-keycloak-js": "*",
"@fortawesome/fontawesome-pro": "^6.1.1", "@fortawesome/fontawesome-pro": "^6.1.1",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"bootstrap": "^5.1.3", "bootstrap": "^5.1.3",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"fs": "^0.0.1-security", "fs": "^0.0.1-security",
"keycloak-js": "^17.0.1", "keycloak-js": "^17.0.1",
"uuid": "^8.3.2",
"vee-validate": "^4.5.10",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-class-component": "^8.0.0-0", "vue-class-component": "^8.0.0-0",
"vue-router": "^4.0.14", "vue-router": "^4.0.14",
"vuex": "^4.0.2" "vue-validate": "^1.0.1",
"vuex": "^4.0.2",
"yup": "^0.32.11"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.16", "@babel/core": "^7.12.16",
@ -1642,7 +1646,6 @@
"version": "7.17.8", "version": "7.17.8",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.8.tgz", "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.8.tgz",
"integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==", "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==",
"dev": true,
"dependencies": { "dependencies": {
"regenerator-runtime": "^0.13.4" "regenerator-runtime": "^0.13.4"
}, },
@ -1698,6 +1701,31 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@dsb-norge/vue-keycloak-js": {
"version": "2.1.3-beta",
"resolved": "https://registry.npmjs.org/@dsb-norge/vue-keycloak-js/-/vue-keycloak-js-2.1.3-beta.tgz",
"integrity": "sha512-RXnX/qwuUzNblxgQ8maxIKofhyQndpcIm8+egKonzSiTMAMUhyV8poSBoGEA3RCgcaxwOZhEw6rF0F39fc4BAg==",
"dependencies": {
"keycloak-js": "^15.0.2"
},
"peerDependencies": {
"vue": "^2.6.0 || >=3.0.0-rc.0"
}
},
"node_modules/@dsb-norge/vue-keycloak-js/node_modules/base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
},
"node_modules/@dsb-norge/vue-keycloak-js/node_modules/keycloak-js": {
"version": "15.1.1",
"resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-15.1.1.tgz",
"integrity": "sha512-PPu70WfSI2CWX7GoF5AQ4HkqYJLTAOV/25wDG//9S5SUOhqIDxKjAv6P54hy8nKt2+rIZF2kqpv7FNEmBN2W4g==",
"dependencies": {
"base64-js": "1.3.1",
"js-sha256": "0.9.0"
}
},
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "0.4.3", "version": "0.4.3",
"resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
@ -2095,6 +2123,11 @@
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true "dev": true
}, },
"node_modules/@types/lodash": {
"version": "4.14.180",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.180.tgz",
"integrity": "sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g=="
},
"node_modules/@types/mime": { "node_modules/@types/mime": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.2.tgz", "resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.2.tgz",
@ -3430,6 +3463,8 @@
"resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz",
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
"dev": true, "dev": true,
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0", "json-schema-traverse": "^1.0.0",
@ -3441,7 +3476,9 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true "dev": true,
"optional": true,
"peer": true
}, },
"node_modules/ajv-keywords": { "node_modules/ajv-keywords": {
"version": "3.5.2", "version": "3.5.2",
@ -7302,8 +7339,12 @@
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"dev": true },
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
}, },
"node_modules/lodash.debounce": { "node_modules/lodash.debounce": {
"version": "4.0.8", "version": "4.0.8",
@ -7876,6 +7917,11 @@
"thenify-all": "^1.0.0" "thenify-all": "^1.0.0"
} }
}, },
"node_modules/nanoclone": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.1.tgz", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.1.tgz",
@ -9079,6 +9125,11 @@
"webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0"
} }
}, },
"node_modules/property-expr": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
},
"node_modules/proxy-addr": { "node_modules/proxy-addr": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz",
@ -9268,8 +9319,7 @@
"node_modules/regenerator-runtime": { "node_modules/regenerator-runtime": {
"version": "0.13.9", "version": "0.13.9",
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
"dev": true
}, },
"node_modules/regenerator-transform": { "node_modules/regenerator-transform": {
"version": "0.14.5", "version": "0.14.5",
@ -10316,6 +10366,11 @@
"node": ">=0.6" "node": ">=0.6"
} }
}, },
"node_modules/toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
},
"node_modules/totalist": { "node_modules/totalist": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/totalist/-/totalist-1.1.0.tgz", "resolved": "https://registry.npmmirror.com/totalist/-/totalist-1.1.0.tgz",
@ -10595,7 +10650,6 @@
"version": "8.3.2", "version": "8.3.2",
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": { "bin": {
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
} }
@ -10625,6 +10679,17 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/vee-validate": {
"version": "4.5.10",
"resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.5.10.tgz",
"integrity": "sha512-7dZE0PZTNY3Ztp6Gz8iw+QS7Fz59vU1qkD0rBJkldkf9Faw2lFjWgE0tiCist5RQkLgt7/HaVbojzb/SCdutfA==",
"dependencies": {
"@vue/devtools-api": "^6.0.0-beta.15"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue": { "node_modules/vue": {
"version": "3.2.31", "version": "3.2.31",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.31.tgz", "resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.31.tgz",
@ -10860,6 +10925,11 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true "dev": true
}, },
"node_modules/vue-validate": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/vue-validate/-/vue-validate-1.0.1.tgz",
"integrity": "sha1-M7YT7lmM2y8uNbQ9f59HxYbbILc="
},
"node_modules/vuex": { "node_modules/vuex": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
@ -11571,6 +11641,23 @@
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz", "resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
"dev": true "dev": true
},
"node_modules/yup": {
"version": "0.32.11",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
"integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
"dependencies": {
"@babel/runtime": "^7.15.4",
"@types/lodash": "^4.14.175",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nanoclone": "^0.2.1",
"property-expr": "^2.0.4",
"toposort": "^2.0.2"
},
"engines": {
"node": ">=10"
}
} }
}, },
"dependencies": { "dependencies": {
@ -12686,7 +12773,6 @@
"version": "7.17.8", "version": "7.17.8",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.8.tgz", "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.17.8.tgz",
"integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==", "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==",
"dev": true,
"requires": { "requires": {
"regenerator-runtime": "^0.13.4" "regenerator-runtime": "^0.13.4"
} }
@ -12730,6 +12816,30 @@
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
"@dsb-norge/vue-keycloak-js": {
"version": "2.1.3-beta",
"resolved": "https://registry.npmjs.org/@dsb-norge/vue-keycloak-js/-/vue-keycloak-js-2.1.3-beta.tgz",
"integrity": "sha512-RXnX/qwuUzNblxgQ8maxIKofhyQndpcIm8+egKonzSiTMAMUhyV8poSBoGEA3RCgcaxwOZhEw6rF0F39fc4BAg==",
"requires": {
"keycloak-js": "^15.0.2"
},
"dependencies": {
"base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
},
"keycloak-js": {
"version": "15.1.1",
"resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-15.1.1.tgz",
"integrity": "sha512-PPu70WfSI2CWX7GoF5AQ4HkqYJLTAOV/25wDG//9S5SUOhqIDxKjAv6P54hy8nKt2+rIZF2kqpv7FNEmBN2W4g==",
"requires": {
"base64-js": "1.3.1",
"js-sha256": "0.9.0"
}
}
}
},
"@eslint/eslintrc": { "@eslint/eslintrc": {
"version": "0.4.3", "version": "0.4.3",
"resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
@ -13074,6 +13184,11 @@
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true "dev": true
}, },
"@types/lodash": {
"version": "4.14.180",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.180.tgz",
"integrity": "sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g=="
},
"@types/mime": { "@types/mime": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.2.tgz", "resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.2.tgz",
@ -13358,7 +13473,6 @@
"integrity": "sha512-vf4KqrmuOSnoEYGUiHPeMoxhh6wpiucLWXISn7xYFU80pK1lqcuhbl6tpurAanUIyRO/ENDUQBH7RAdbLNq1bA==", "integrity": "sha512-vf4KqrmuOSnoEYGUiHPeMoxhh6wpiucLWXISn7xYFU80pK1lqcuhbl6tpurAanUIyRO/ENDUQBH7RAdbLNq1bA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/core": "^7.12.16",
"@babel/helper-compilation-targets": "^7.12.16", "@babel/helper-compilation-targets": "^7.12.16",
"@babel/helper-module-imports": "^7.12.13", "@babel/helper-module-imports": "^7.12.13",
"@babel/plugin-proposal-class-properties": "^7.12.13", "@babel/plugin-proposal-class-properties": "^7.12.13",
@ -13371,7 +13485,6 @@
"@vue/babel-plugin-jsx": "^1.0.3", "@vue/babel-plugin-jsx": "^1.0.3",
"@vue/babel-preset-jsx": "^1.1.2", "@vue/babel-preset-jsx": "^1.1.2",
"babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-dynamic-import-node": "^2.3.3",
"core-js": "^3.8.3",
"core-js-compat": "^3.8.3", "core-js-compat": "^3.8.3",
"semver": "^7.3.4" "semver": "^7.3.4"
}, },
@ -14140,15 +14253,14 @@
"resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz", "resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dev": true, "dev": true,
"requires": { "requires": {},
"ajv": "^8.0.0"
},
"dependencies": { "dependencies": {
"ajv": { "ajv": {
"version": "8.11.0", "version": "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz",
"resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz",
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
"dev": true, "dev": true,
"optional": true,
"peer": true,
"requires": { "requires": {
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0", "json-schema-traverse": "^1.0.0",
@ -14160,7 +14272,9 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true "dev": true,
"optional": true,
"peer": true
} }
} }
}, },
@ -17229,8 +17343,12 @@
"lodash": { "lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"dev": true },
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
}, },
"lodash.debounce": { "lodash.debounce": {
"version": "4.0.8", "version": "4.0.8",
@ -17697,6 +17815,11 @@
"thenify-all": "^1.0.0" "thenify-all": "^1.0.0"
} }
}, },
"nanoclone": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
},
"nanoid": { "nanoid": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.1.tgz", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.1.tgz",
@ -18562,6 +18685,11 @@
"log-update": "^2.1.0" "log-update": "^2.1.0"
} }
}, },
"property-expr": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
},
"proxy-addr": { "proxy-addr": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz",
@ -18718,8 +18846,7 @@
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.13.9", "version": "0.13.9",
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
"dev": true
}, },
"regenerator-transform": { "regenerator-transform": {
"version": "0.14.5", "version": "0.14.5",
@ -19583,6 +19710,11 @@
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"dev": true "dev": true
}, },
"toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
},
"totalist": { "totalist": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/totalist/-/totalist-1.1.0.tgz", "resolved": "https://registry.npmmirror.com/totalist/-/totalist-1.1.0.tgz",
@ -19791,8 +19923,7 @@
"uuid": { "uuid": {
"version": "8.3.2", "version": "8.3.2",
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
"dev": true
}, },
"v8-compile-cache": { "v8-compile-cache": {
"version": "2.3.0", "version": "2.3.0",
@ -19816,6 +19947,14 @@
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"dev": true "dev": true
}, },
"vee-validate": {
"version": "4.5.10",
"resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.5.10.tgz",
"integrity": "sha512-7dZE0PZTNY3Ztp6Gz8iw+QS7Fz59vU1qkD0rBJkldkf9Faw2lFjWgE0tiCist5RQkLgt7/HaVbojzb/SCdutfA==",
"requires": {
"@vue/devtools-api": "^6.0.0-beta.15"
}
},
"vue": { "vue": {
"version": "3.2.31", "version": "3.2.31",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.31.tgz", "resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.31.tgz",
@ -20004,6 +20143,11 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true "dev": true
}, },
"vue-validate": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/vue-validate/-/vue-validate-1.0.1.tgz",
"integrity": "sha1-M7YT7lmM2y8uNbQ9f59HxYbbILc="
},
"vuex": { "vuex": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
@ -20562,6 +20706,20 @@
"dev": true "dev": true
} }
} }
},
"yup": {
"version": "0.32.11",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
"integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
"requires": {
"@babel/runtime": "^7.15.4",
"@types/lodash": "^4.14.175",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nanoclone": "^0.2.1",
"property-expr": "^2.0.4",
"toposort": "^2.0.2"
}
} }
} }
} }

View File

@ -8,16 +8,21 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@dsb-norge/vue-keycloak-js": "*",
"@fortawesome/fontawesome-pro": "^6.1.1", "@fortawesome/fontawesome-pro": "^6.1.1",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"bootstrap": "^5.1.3", "bootstrap": "^5.1.3",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"fs": "^0.0.1-security", "fs": "^0.0.1-security",
"keycloak-js": "^17.0.1", "keycloak-js": "^17.0.1",
"uuid": "^8.3.2",
"vee-validate": "^4.5.10",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-class-component": "^8.0.0-0", "vue-class-component": "^8.0.0-0",
"vue-router": "^4.0.14", "vue-router": "^4.0.14",
"vuex": "^4.0.2" "vue-validate": "^1.0.1",
"vuex": "^4.0.2",
"yup": "^0.32.11"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.16", "@babel/core": "^7.12.16",

View File

@ -0,0 +1,51 @@
<template>
<nav class="navbar navbar-expand-lg bg-vue navbar-dark">
<div class="container">
<ul class="navbar-nav me-auto">
<li class="nav-item active">
<router-link to="/list" class="nav-link">Startseite</router-link>
</li>
<li class="nav-item">
<router-link to="/shop/item/create" class="nav-link">Neue Kamera</router-link>
</li>
<li class="nav-item">
<router-link to="/auth" class="nav-link">Auth</router-link>
</li>
</ul>
<div class="text-white" v-if="user && user.id"> angemeldet als: {{user.firstName}} {{user.lastName}} </div>
<button class="btn bg-vue2" @click="$keycloak.logoutFn" v-if="$keycloak.authenticated">
<i class="fas fa-sign-out-alt"></i> Logout
</button>
</div>
</nav>
</template>
<script>
import { mapGetters} from "vuex";
export default {
name: "TheNavbar",
computed: {
// ...mapGetters(["cartTotal"]),
...mapGetters({
user: "userProfile"
})
},
methods: {
async signOut() {
try {
await this.$store.dispatch("signout");
await this.$router.push("/");
} catch(e) {
console.log(e);
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,35 @@
<template>
<div>AuthRedirect</div>
<div class="container">
<p class=" row alert alert-info">{{queryInfo}}</p>
<p class="row alert alert-info">{{pathInfo}}</p>
</div>
</template>
<script>
export default {
name: "AuthRedirect",
beforeMount() {
console.log("Auth.beforeMount");
this.$keycloak.loadUserProfile().then( (res) => {
console.log("res", res);
});
},
computed: {
queryInfo() {
return this.$route.query
},
pathInfo() {
return this.$route.fullPath
},
}
}
</script>
<style scoped>
</style>

View File

@ -1,13 +1,146 @@
<template> <template>
<div>Login User</div> <div>
<div class="my-5 text-center offset-2 col-8">
<img src="~@fortawesome/fontawesome-pro/svgs/solid/user-lock.svg" class="img-fluid" />
</div>
<div class="text-center">
<h2>Jetzt anmelden</h2>
<p>
oder
<a class="text-vue2" role="button" @click="changeComponent('RegisterUser')"
>erstellen Sie ein Konto.</a
>
</p>
</div>
<div class="alert alert-danger col-md-8 offset-2" v-if="error"> {{ errorDisplayText }}</div>
<Form @submit="submitData" :validation-schema="schema" v-slot="{ errors }">
<div class="form-row">
<div class="form-group col-md-8 offset-2">
<label for="email"><strong>E-Mail-Adresse</strong></label>
<Field
as="input"
name="email"
type="email"
class="form-control"
id="email"
/>
<small class="text-danger" v-if="errors.email">{{
errors.email
}}</small>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-8 offset-2">
<label for="password"><strong>Passwort</strong></label>
<Field
as="input"
name="password"
type="password"
class="form-control"
id="password"
/>
<small class="text-danger" v-if="errors.password">{{
errors.password
}}</small>
</div>
</div>
<div class="form-row mt-3">
<div class="form-group col-md-8 offset-2">
<div class="d-grid">
<button class="btn bg-vue">
<span v-if="!isLoading">Einloggen</span>
<span v-else class="spinner-border spinner-border-sm"></span>
</button>
</div>
</div>
</div>
</Form>
<button class="btn bg-vue"
@click="keyCloakLogin"
>
<span v-if="!isLoading">Keycloak Login</span>
<span v-else class="spinner-border spinner-border-sm"></span>
</button>
</div>
</template> </template>
<script> <script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";
export default { export default {
name: "LoginUser" name: "LoginUser",
components: {
Form,
Field,
},
emits: {
"change-component": (payload) => {
if (payload.componentName !== "RegisterUser") {
return false;
}
return true;
},
},
data() {
const schema = yup.object().shape({
email: yup
.string()
.required("E-Mail Adresse wird benötigt.")
.trim()
.email("Das ist keine gültige E-Mail Adresse"),
password: yup
.string()
.required("Ein Passwort wird benötigt.")
.min(6, "Das Passwort muss mindestens sechs Zeichen lang sein."),
});
return {
schema,
error: "",
isLoading: false
};
},
computed: {
errorDisplayText() {
return "Es ist ein Fehler aufgetreten"
}
},
methods: {
keyCloakLogin() {
this.$store.dispatch("login", {
})
},
submitData(values) {
console.log(values);
this.isLoading = true;
this.error = "";
this.$store.dispatch("signin", {
email: values.email,
password: values.password
})
.then(()=> {
this.isLoading = false;
this.$router.push({path: "/shop"});
})
.catch((error) => {
this.error = error.message;
this.isLoading = false;
}
)
},
changeComponent(componentName) {
this.$emit("change-component", { componentName });
},
}
} }
</script> </script>
<style scoped> <style scoped>
</style> </style>

View File

@ -1,10 +1,143 @@
<template> <template>
<div>RegisterUser</div> <div>
<div class="my-5 text-center offset-2 col-8">
<img src="~@fortawesome/fontawesome-pro/svgs/solid/door-open.svg" class="img-fluid" />
</div>
<div class="text-center">
<h2>Jetzt registrieren</h2>
<p>
oder
<a class="text-vue2" role="button" @click="changeComponent('LoginUser')"
>melden Sie sich mit Ihrem Konto an</a
>
</p>
</div>
<div class="alert alert-danger col-md-8 offset-2" v-if="error"> {{ errorDisplayText }}</div>
<Form @submit="submitData" :validation-schema="schema" v-slot="{ errors }">
<div class="form-row">
<div class="form-group col-md-8 offset-2">
<label for="email"><strong>E-Mail-Adresse</strong></label>
<Field as="input" name="email" type="email" class="form-control" id="email" />
<small class="text-danger" v-if="errors.email">{{errors.email}}</small>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-8 offset-2">
<label for="password"><strong>Passwort</strong></label>
<Field type="password" name="password" class="form-control" id="password" />
<small class="text-danger" v-if="errors.password">{{errors.password}}</small>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-8 offset-2">
<label for="confirmPassword"
><strong>Passwort wiederholen</strong></label
>
<Field type="password" name="confirmPassword" class="form-control" id="confirmPassword" />
<small class="text-danger" v-if="errors.confirmPassword">{{errors.confirmPassword}}</small>
</div>
</div>
<div class="form-row mt-3">
<div class="form-group col-md-8 offset-2">
<div class="d-grid">
<button class="btn bg-vue">
<span v-if="!isLoading">Registrieren</span>
<span v-else class="spinner-border spinner-border-sm"></span>
</button>
<button class="btn bg-vue"
@click="keyCloakLogin"
>
<span v-if="!isLoading">Keycloak Login</span>
<span v-else class="spinner-border spinner-border-sm"></span>
</button>
</div>
</div>
</div>
</Form>
</div>
</template> </template>
<script> <script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";
export default { export default {
name: "RegiterUser" name: "RegiterUser",
components: {
Form,
Field
},
emits: {
'change-component': (componentName) => {
if(componentName.componentName !== "LoginUser") {
return false;
}
return true;
}
}, data() {
const schema = yup.object().shape({
email: yup.string()
.required("E-Mail Adresse wird benötigt")
.trim()
.email("Das ist keine gültige E-Mail-Adresse"),
password: yup.string()
.required("Ein Passwort wird benötigt")
.trim()
.min(6, "Das Passwort muss mindestens 6 Zeichen lang sein"),
confirmPassword: yup.string().required("Bitte wiederholen Sie Ihr Passwort")
.oneOf([yup.ref("password")], "Passwörter stimmen nicht überein")
});
return {
schema,
error: "",
isLoading: false
};
},
computed: {
errorDisplayText() {
if(this.error) {
if(this.error.includes("EMAIL_EXISTS")) {
return "Die E-Mail Adresse existiert bereits."
}
}
return "Es ist ein Fehler aufgetreten"
}
},
methods: {
keyCloakLogin() {
this.$store.dispatch("login", {
})
},
submitData(values) {
console.log(values);
this.isLoading = true;
this.error = "";
this.$store.dispatch("signup", {
email: values.email,
password: values.password
}) .then(()=> {
this.isLoading = false;
console.log(this.$store.state);
this.changeComponent("LoginUser")
})
.catch((error) => {
this.error = error.message;
this.isLoading = false;
}
)
},
changeComponent(componentName) {
this.$emit("change-component", {componentName})
;
},
}
} }
</script> </script>

View File

@ -0,0 +1,124 @@
<template>
<transition
enter-active-class="animate__animated animate__lightSpeedInRight"
mode="out-in"
appear
>
<div class="row" :key="activeCamera.id">
<div class="col-12">
<h1 class="mt-4">
Bearbeiten
<button class="btn btn-lg bg-vue float-end"
@click="leaveEditmode"
>Verwerfen</button>
</h1>
<Form @submit="submitData" :validation-schema="schema" v-slot="{ errors }">
<div class="card mt-4">
<div class="row no-gutters">
<div class="col-md-4">
<img
src="https://dummyimage.com/600x400/34495e/fff"
class="card-img"
/>
</div>
<div class="col-md-8">
<div class="card-body">
<div class="row">
<div class="col-9">
<label for="name">Name der Kamera</label>
<Field as="input" name="name" :value="activeCamera.name" type="text" class="form-control" id="name"></Field>
<small class="text-danger" v-if="errors.name">{{errors.name}}</small>
</div>
<div class="col-3">
<div class="d-grid">
<button class="btn bg-vue2"
> </button>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
Lorem
</div>
</div>
</div>
</div>
</div>
</div>
<button class="btn btn-lg bg-vue float-end mx-3"
>Speichern</button>
</Form>
</div>
</div>
</transition>
</template>
<script>
import { mapGetters} from "vuex";
import { Form, Field } from "vee-validate";
import * as yup from "yup";
export default {
name: "CameraReadDetail",
components: {
Form,
Field
},
data() {
const schema = yup.object().shape({
name: yup.string()
.required("Name wird benötigt")
.trim()
});
return {
schema,
error: "",
isLoading: false
}
},
computed: {
...mapGetters(["activeCamera"]),
errorDisplayText() {
if(this.error) {
return "Es ist ein Fehler aufgetreten"
}
return "Es ist ein irgendein Fehler aufgetreten"
}
},
methods: {
submitData(values) {
console.log("SubmitData", values);
this.$store.dispatch("storeCamera", {
active:false,
brand_key:"pentax",
buildtype:"slr",
description:"Langer Text",
edit:false,
name: values.name,
shape_key:"neuwertig",
year_of_production:2000,
year_of_purchase:2022,
});
},
leaveEditmode() {
this.$store.dispatch("setCameraEditState", {cameraId:this.activeCamera.id, edit:false})
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,27 +1,26 @@
<template> <template>
<div class="container"> <div class="container ">
<div class=""> <div class="">
Wir haben {{cameras.length}} in der Liste Wir haben {{ cameras.length }} in der Liste
<input type="text" name="searchstring" v-model="searchText"> <input type="text" name="searchstring" v-model="searchText">
</div> </div>
</div> <section>
<div v-for="camera in filteredCameras" :key="camera.id"> <div v-for="camera in filteredCameras" :key="camera.id">
<transition-group
enter-active-class="animate__animated animate__bounceInRight"
leave-active-class="animate__animated animate__bounceOutRight"
mode="out-in"
>
<component <component
:is="componentName" :is="componentName"
:camera=camera :camera=camera
:key="camera.id" :key="camera.id"
></component> ></component>
</transition-group>
</div>
</section>
</div> </div>
</template> </template>
<script> <script>
import CameraListItem from "@/components/camera/CameraListItem"; import CameraListItem from "@/components/camera/CameraListItem";
export default { export default {
name: "CameraList", name: "CameraList",
components: { components: {
@ -29,24 +28,29 @@ export default {
}, },
props: { props: {
cameras: { cameras: {
type:Object, type: Object,
required: true required: true
} }
}, },
data() { data() {
return { return {
searchText: "" searchText: "",
orderBy: "name",
orderDirection: "acs"
} }
}, },
computed:{ computed: {
componentName() { componentName() {
return "CameraListItem"; return "CameraListItem";
}, },
filteredCameras() { filteredCameras() {
if(this.searchText ==="") return this.cameras ; if (this.searchText === "") return this.cameras;
else return this.cameras.filter( (camera) => camera.name.toLowerCase().includes(this.searchText.toLowerCase())); else {
return this.cameras.filter((camera) => camera.name.toLowerCase().includes(this.searchText.toLowerCase()));
} }
} }
}
} }
</script> </script>

View File

@ -1,13 +1,29 @@
<template> <template>
<div class="card mt-3" <transition
@click="toggleActive">
<div class="card-header" enter-active-class="animate__animated animate__fadeIn"
leave-active-class="animate__animated animate__fadeOut"
mode="out-in"
appear
>
<div class="card mt-3"
@click="toggleActive"
:key="camera.id"
>
<div class="card-header col-md-12"
:class="getActiveStyle" :class="getActiveStyle"
>{{ camera.name }}</div> >
<div class="card-body"> <div class="row">
<div class="col-md-8">{{ camera.name }}</div>
<div class="col-md-4 text-end">{{ camera.year_of_purchase }}</div>
</div>
</div>
<div class="card-body" :class="`${getActiveStyle}`">
{{camera.year_of_production}} {{camera.year_of_production}}
</div> </div>
</div> </div>
</transition>
</template> </template>
<script> <script>

View File

@ -0,0 +1,72 @@
<template>
<transition
enter-active-class="animate__animated animate__lightSpeedInRight"
mode="out-in"
appear
>
<div class="row" :key="activeCamera.id">
<div class="col-12">
<h1 class="mt-4">
Neuer Artikel
<button class="btn btn-lg bg-vue float-end"
@click="editCamera"
>Bearbeiten</button>
</h1>
<div class="card mt-4">
<div class="row no-gutters">
<div class="col-md-4">
<img
src="https://dummyimage.com/600x400/34495e/fff"
class="card-img"
/>
</div>
<div class="col-md-8">
<div class="card-body">
<div class="row">
<div class="col-9">
<h5 class="card-title mb-4">{{ activeCamera.name }}</h5>
</div>
<div class="col-3">
<div class="d-grid">
<button class="btn bg-vue2"
> </button>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
Lorem
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
import { mapGetters} from "vuex";
export default {
name: "CameraReadDetail",
computed: {
...mapGetters(["activeCamera"]),
},
methods: {
editCamera() {
this.$store.dispatch("setCameraEditState", {cameraId:this.activeCamera.id, edit:true})
}
}
}
</script>
<style scoped>
</style>

154
src/indexdDB/index.ts Normal file
View File

@ -0,0 +1,154 @@
export default class BilliDB {
private DB_VERSION: number;
private DB_NAME: string;
constructor(dbName:string, dbVersion:number) {
this.DB_NAME = dbName;
this.DB_VERSION = dbVersion;
}
async getDb():Promise<IDBOpenDBRequest> {
return new Promise((resolve, reject) => {
const request = window.indexedDB.open(this.DB_NAME, this.DB_VERSION);
request.onerror = e => {
console.log("Error opening db", e);
reject("Error");
}
request.onsuccess =e => {
console.log("connect erfolgreich");
// @ts-ignore
resolve(e.target.result)
}
request.onupgradeneeded = e => {
console.log("onupgradeneeded");
// @ts-ignore
const db = e.target.result;
db.createObjectStore("cameras", {autoIncrement: false, keyPath: 'id'});
db.createObjectStore("brands", {autoIncrement: false, keyPath: 'schluessel'});
db.createObjectStore("conditions", {autoIncrement: false, keyPath: 'schluessel'});
db.createObjectStore("buildtypes", {autoIncrement: false, keyPath: 'schluessel'});
}
})
}
async saveItem(item, storeId:string) {
const db = await this.getDb();
return new Promise((resolve, reject) => {
console.log("Starting Add Transaction");
// @ts-ignore
const trans = db.transaction([storeId], 'readwrite');
trans.oncomplete = (e) => {
resolve(e);
};
trans.onerror = (e) => {
console.log("on Error", e)
reject(e);
};
const store = trans.objectStore(storeId);
store.add(item);
store.onerror = (e) => {
console.log("Error on Store", e)
}
store.oncomplete = (e) => {
console.log("oncomplete on Store", e)
}
store.onsuccess = (e) => {
console.log("onsuccess on Store", e)
}
})
}
async saveItems(items, storeId:string) {
const db = await this.getDb();
return new Promise((resolve, reject) => {
console.log("Starting Add Transaction");
// @ts-ignore
const trans = db.transaction([storeId], 'readwrite');
trans.oncomplete = (e) => {
resolve(e);
};
trans.onerror = (e) => {
console.log("on Error", e)
reject(e);
};
const store = trans.objectStore(storeId);
items.forEach((item) => {
store.add(item);
})
store.onerror = (e) => {
console.log("Error on Store", e)
}
store.oncomplete = (e) => {
console.log("oncomplete on Store", e)
}
store.onsuccess = (e) => {
console.log("onsuccess on Store", e)
}
})
}
async getItems(storeId:string) {
console.log("DB-getItems", storeId)
const db = await this.getDb();
return new Promise((resolve, reject) => {
console.log("DB-getItems: Starting Get Transaction");
const items = [];
// @ts-ignore
const trans = db.transaction([storeId], 'readonly');
trans.oncomplete = (e) => {
resolve(items);
};
trans.onerror = (e) => {
console.log("on Error", e)
reject(e);
};
const store = trans.objectStore(storeId);
console.log("--> We have try to get a cursor");
store.openCursor().onsuccess = (e) => {
console.log("--> We have a cursor", e.target.result);
const cursor = e.target.result;
if(cursor) {
items.push(cursor.value);
cursor.continue();
}
console.log("onsuccess on getAll", items)
// resolve(e.target.result);
}
store.onerror = (e) => {
console.log("Error on getAll", e)
}
store.oncomplete = (e) => {
console.log("oncomplete on getAll", e)
}
})
}
}

View File

@ -0,0 +1,61 @@
<template>
<div>
<TheNavbar></TheNavbar>
<main>
<div class="container-fluid" :class="containerClasses">
<div class="row" :class="rowClasses">
<div :class="leftColumnClasses">
<slot name="leftCol">
<h1>Linke Spalte</h1>
</slot>
</div>
<div :class="rightColumnClasses">
<slot name="rightCol"><h1>Rechte Spalte</h1></slot>
</div>
</div>
</div>
</main>
</div>
</template>
<script>
import TheNavbar from "@/components/TheNavbar";
export default {
name: "TheShopLayout",
components: {
TheNavbar
},
props: {
leftColumnClass: {
type:String,
default: 'col-md-8'
},
rightColumnClass: {
type:String,
default: 'col-md-4'
},
fullsize: {
type: Boolean,
default: false,
}
},
computed: {
leftColumnClasses() {
return [this.leftColumnClass, this.fullsize ? "h-100": ""];
},
rightColumnClasses() {
return [this.rightColumnClass, this.fullsize ? "h-100": ""];
},
rowClasses(){
return [this.fullsize ? "h-100": ""];
},
containerClasses(){
return [this.fullsize ? "vh-100": ""];
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,9 +1,37 @@
import { createApp } from 'vue'; import Vue from 'vue';
import App from './App.vue'; import App from './App.vue';
import store from './store'; import Keycloak from "keycloak-js";
import router from './router'; const initOptions = {
createApp(App) url: 'http://auth.toking.de/', realm: 'toking', clientId: 'billibox', onLoad: 'login-required',
.use(store) redirectUri: 'http://127.0.0.1:8080/'
.use(router) };
.mount('#app'); //const app = createApp(App);
//# sourceMappingURL=main.js.map const keycloak = Keycloak(initOptions);
keycloak.init({ onLoad: initOptions.onLoad }).then((auth) => {
if (!auth) {
window.location.reload();
}
else {
Vue.$log.info("Authenticated");
new Vue({
el: '#app',
render: h => h(App, { props: { keycloak: keycloak } })
});
}
//Token Refresh
setInterval(() => {
keycloak.updateToken(70).then((refreshed) => {
if (refreshed) {
Vue.$log.info('Token refreshed' + refreshed);
}
else {
Vue.$log.warn('Token not refreshed, valid for '
+ Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds');
}
}).catch(() => {
Vue.$log.error('Failed to refresh token');
});
}, 6000);
}).catch(() => {
Vue.$log.error("Authenticated Failed");
});

View File

@ -2,9 +2,97 @@ import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import store from './store'; import store from './store';
import router from './router' import router from './router'
import VueKeyCloak from '@dsb-norge/vue-keycloak-js'
import { KeycloakInstance } from "keycloak-js";
import { VueKeycloakInstance } from "@dsb-norge/vue-keycloak-js/dist/types";
const app =
createApp(App);
createApp(App)
.use(store) app.use(store)
.use(router) app.use(router)
.mount('#app') app.use(VueKeyCloak, {
config: {
url: 'https://auth.toking.de/',
realm: 'toking',
clientId: 'billibox',
redirectUri: 'http://127.0.0.1:8080/',
onLoad: 'login-required',
enableLogging: true,
scope: 'open-id'
},
init: {
onLoad: 'login-required'
},
onReady (keycloak: KeycloakInstance) {
store.dispatch("storeKeycloak", keycloak).then( (res) => {
keycloak.loadUserProfile().then( (res) => {
store.dispatch("storeUserProfile", res);
console.log("res", res);
});
}
)
}
})
app.mount('#app')
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$keycloak: VueKeycloakInstance
}
}
// import Vue from 'vue';
// import App from './App.vue';
// import Keycloak from "keycloak-js";
// const initOptions = {
// url: 'https://auth.toking.de/', realm: 'toking', clientId: 'billibox', onLoad: 'login-required',
// redirectUri: 'http://127.0.0.1:8080/'
// };
// //const app = createApp(App);
// const keycloak = Keycloak(initOptions);
// keycloak.init({ onLoad: 'login-required', redirectUri: 'http://127.0.0.1:8080/' }).then((auth) => {
// if (!auth) {
// window.location.reload();
// }
// else {
// // @ts-ignore
// console.info("Authenticated", auth);
// // @ts-ignore
//
// new Vue({
// el: '#app',
// render: h => h(App, { props: { keycloak: keycloak } })
// });
// }
// //Token Refresh
// // setInterval(() => {
// // keycloak.updateToken(70).then((refreshed) => {
// // if (refreshed) {
// // // @ts-ignore
// //
// // console.info('Token refreshed' + refreshed);
// // }
// // else {
// // // @ts-ignore
// //
// // console.warn('Token not refreshed, valid for '
// // + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds');
// // }
// // }).catch(() => {
// // // @ts-ignore
// //
// // console.error('Failed to refresh token');
// // });
// // }, 6000);
// }).catch(() => {
// // @ts-ignore
//
// console.error("Authenticated Failed");
// });

View File

@ -1,4 +1,5 @@
<template> <template>
<TheNavbar></TheNavbar>
<TheTwoColumnsLayout <TheTwoColumnsLayout
:left-column-class="'col-md-8 bg-vue'" :left-column-class="'col-md-8 bg-vue'"
:right-column-class="'col-md-4'" :right-column-class="'col-md-4'"
@ -37,10 +38,12 @@
import TheTwoColumnsLayout from "@/layouts/TheTwoColumnsLayout"; import TheTwoColumnsLayout from "@/layouts/TheTwoColumnsLayout";
import RegisterUser from "@/components/auth/RegisterUser"; import RegisterUser from "@/components/auth/RegisterUser";
import LoginUser from "@/components/auth/LoginUser"; import LoginUser from "@/components/auth/LoginUser";
import TheNavbar from "@/components/TheNavbar";
export default { export default {
name: "HomePage", name: "HomePage",
components: { components: {
TheNavbar,
TheTwoColumnsLayout, TheTwoColumnsLayout,
RegisterUser, RegisterUser,
LoginUser LoginUser
@ -59,5 +62,5 @@ export default {
</script> </script>
<style scoped> <style scoped>
svg { color: white}; svg { color: white}
</style> </style>

View File

@ -1,59 +1,70 @@
<template> <template>
<TheTwoColumnsLayout> <TheCameraLayout
:left-column-class="'col-md-8 '"
:right-column-class="'col-md-4 bg-vue'"
:fullsize="true"
>
<template #leftCol> <template #leftCol>
<div class="mt-5 text-center"> <div v-if="activeCamera && activeCamera.edit">
<div class="display-1 my-5">Billibox</div> <CameraEditDetail></CameraEditDetail>
<div class="display-4 my-5">Die kleine Welt alter Fotoapparate</div>
<div class="my-5 offset-4 col-4">
<img src="~@fortawesome/fontawesome-pro/svgs/duotone/camera.svg" class="img-fluid">
</div> </div>
<div v-else-if="activeCamera">
<CameraReadDetail></CameraReadDetail>
</div>
<div v-else>
<h2>Bitte wählen sie eine Kamera aus der Liste</h2>
</div> </div>
</template> </template>
<template #rightCol> <template #rightCol>
<transition
enter-active-class="animate__animated animate__bounceInRight"
leave-active-class="animate__animated animate__bounceOutRight"
mode="out-in"
>
<CameraList :cameras="cameras"></CameraList> <CameraList :cameras="cameras"></CameraList>
</transition>
</template> </template>
</TheTwoColumnsLayout> </TheCameraLayout>
</template> </template>
<script> <script>
import TheTwoColumnsLayout from "@/layouts/TheTwoColumnsLayout"; import TheCameraLayout from "@/layouts/TheCameraLayout";
import CameraList from "@/components/camera/CameraList"; import CameraList from "@/components/camera/CameraList";
import CameraReadDetail from "@/components/camera/CameraReadDetail";
import CameraEditDetail from "@/components/camera/CameraEditDetail";
import {mapGetters} from "vuex";
export default { export default {
name: "ReadListPage", name: "ReadListPage",
components: {
CameraList,
TheCameraLayout,
CameraReadDetail,
CameraEditDetail
},
computed: { computed: {
...mapGetters(["activeCamera"]),
storeIsInitialized( ) { storeIsInitialized( ) {
return this.$store.getters.isInitialized; return this.$store.getters.isInitialized;
}, },
cameras() { cameras() {
return this.$store.getters.cameras; return this.$store.getters.cameras;
}
}, },
components: {
CameraList,
TheTwoColumnsLayout
}, },
beforeCreate() { beforeCreate() {
console.log("beforeCreate", this.$store.getters.isInitialized); console.log("beforeCreate", this.$store.getters.isInitialized);
if(!this.$store.getters.isInitialized) { if(!this.$store.getters.isInitialized) {
console.log("Not yet initialized") console.log("Not yet initialized")
this.$store.dispatch("initialize"); this.$store.dispatch("initialize", {seed: true});
} }
}, },
data() { data() {
return { return {
} }
} },
} }
</script> </script>

View File

@ -21,9 +21,26 @@ const router = createRouter( {
}); });
router.beforeEach((to, from, next) => { function sleep(ms) {
if(to.meta.requiresAuth && !store.getters.isAuthenticated) { return new Promise(resolve => setTimeout(resolve, ms))
next("/") }
router.beforeEach(async(to, from, next) => {
if(to.meta.requiresAuth) {
// @ts-ignore
const kc = store.getters.keycloak;
console.log(kc);
while(typeof kc == "undefined" || kc.createLoginUrl === null) {
await sleep(100);
}
if(kc.authenticated) {
next()
}
else {
const loginUrl = kc.createLoginUrl()
window.location.replace(loginUrl)
}
} else { } else {
next(); next();
} }

View File

@ -1,6 +1,7 @@
import store from "@/store"; import store from "@/store";
import ReadCameraPage from "@/pages/ReadCameraPage.vue"; import ReadCameraPage from "@/pages/ReadCameraPage.vue";
import ReadListPage from "@/pages/ReadListPage.vue"; import ReadListPage from "@/pages/ReadListPage.vue";
import AuthRedirect from '@/components/auth/AuthRedirect.vue'
const appRoutes = [ const appRoutes = [
@ -9,13 +10,13 @@ const appRoutes = [
alias: "/home", alias: "/home",
name: "home", name: "home",
component: () => import('@/pages/HomePage.vue'), component: () => import('@/pages/HomePage.vue'),
beforeEnter: (to:any, from:any, next:any) => { // beforeEnter: (to:any, from:any, next:any) => {
if (store.getters.isAuthenticated) { // if (store.getters.isAuthenticated) {
next("/shop"); // next("/list");
} else { // } else {
next(); // next();
} // }
} // }
}, },
{ {
path: "/read/cameara/:id", path: "/read/cameara/:id",
@ -37,7 +38,24 @@ const appRoutes = [
requiresAuth: false, requiresAuth: false,
// enterTransition: "rubberBand" // enterTransition: "rubberBand"
} }
},
{
path: "/auth",
component: AuthRedirect,
props: true,
meta: {
requiresAuth: true,
// enterTransition: "rubberBand"
}
},
{
path: "/profile",
component: AuthRedirect,
props: true,
meta: {
requiresAuth: true,
// enterTransition: "rubberBand"
}
}, },
] ]

View File

@ -1,3 +1,4 @@
export const shape = [ export const shape = [
{ schluessel: "neu", name: "neu", beschreibung: '' }, { schluessel: "neu", name: "neu", beschreibung: '' },
{ schluessel: "neuwertig", name: "neuwertig", beschreibung: '' }, { schluessel: "neuwertig", name: "neuwertig", beschreibung: '' },
@ -209,6 +210,36 @@ export const cameras = [
description: "Langer Text", description: "Langer Text",
year_of_production: 2000, year_of_production: 2000,
year_of_purchase: 2022, year_of_purchase: 2022,
},
{
id: "agfa_01",
brand_key: "agfa",
shape_key: "neuwertig",
name: "Agfa Click",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 2000,
},
{
id: "agfa_02",
brand_key: "agfa",
shape_key: "neuwertig",
name: "Agfa Box",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 1980,
},
{
id: "cancon_02",
brand_key: "canon",
shape_key: "neuwertig",
name: "Canon EOS",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 1980,
} }
]; ];
//# sourceMappingURL=seed.js.map //# sourceMappingURL=seed.js.map

View File

@ -1,6 +1,7 @@
export const SEED_VERSION = 1;
export const shape = [ export const conditions = [
{schluessel: "neu", name: "neu", beschreibung: ''}, {schluessel: "neu", name: "neu", beschreibung: ''},
{schluessel: "neuwertig", name: "neuwertig", beschreibung: ''}, {schluessel: "neuwertig", name: "neuwertig", beschreibung: ''},
{schluessel: "lg", name: "leichte Gebrauchsspuren", beschreibung: ''}, {schluessel: "lg", name: "leichte Gebrauchsspuren", beschreibung: ''},
@ -215,6 +216,66 @@ export const cameras = [
description: "Langer Text", description: "Langer Text",
year_of_production: 2000, year_of_production: 2000,
year_of_purchase: 2022, year_of_purchase: 2022,
},
{
id: "agfa_01",
brand_key: "agfa",
shape_key: "neuwertig",
name: "Agfa Click",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 2000,
},
{
id: "agfa_02",
brand_key: "agfa",
shape_key: "neuwertig",
name: "Agfa Box",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 1980,
},
{
id: "cancon_02",
brand_key: "canon",
shape_key: "neuwertig",
name: "Canon EOS",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 1980,
},
{
id: "agfa_03",
brand_key: "agfa",
shape_key: "neuwertig",
name: "Agfa Click",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 2000,
},
{
id: "agfa_05",
brand_key: "agfa",
shape_key: "neuwertig",
name: "Agfa Box",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 1980,
},
{
id: "cancon_07",
brand_key: "canon",
shape_key: "neuwertig",
name: "Canon EOS",
buildtype: "slr",
description: "Langer Text",
year_of_production: 2000,
year_of_purchase: 1980,
} }
] ]

View File

@ -1,28 +1,64 @@
import {ActionContext} from "vuex"; import {ActionContext} from "vuex";
import Keycloak from "keycloak-js";
const keyInitOptions = {
url: 'https://auth.toking.de/',
realm: 'toking',
clientId: 'billibox',
redirectUri: 'http://127.0.0.1:8080/',
onLoad: 'login-required',
enableLogging: true,
scope: 'open-id'
}
const state = { const state = {
userId: null, keycloak: null,
token: null userProfile: null,
}; };
const getters = { const getters = {
isAuthenticated(state:any ) { isAuthenticated(state:any ) {
return state.token return state.keycloak.authenticated
}, },
token: (state:any) => state.token token: (state:any) => state.token,
keycloak: (state:any) => state.keycloak,
userProfile: (state:any) => state.userProfile
}; };
const mutations = { const mutations = {
setUser(context:ActionContext<any, any>, payload:any) {
console.log("mutations.setUser", payload); storeKeycloak(context:ActionContext<any, any>, payload:any) {
state.userId = payload.userId; console.log("mutations.storeKeycloak");
state.token = payload.token; state.keycloak = payload;
}, },
storeUserProfile(context:ActionContext<any, any>, payload:any) {
state.userProfile = payload
}
}; };
const actions = {}; const actions = {
storeKeycloak(context:ActionContext<any, any>, payload:any) {
console.log("action.storeKeycloak");
context.commit("storeKeycloak", payload);
},
getToken(context:any, payload:any) {
console.log("actions.getToken")
console.log("Authenticated", context.state.keycloak)
context.state.keycloak.updateToken(70).then((refreshed) => {
console.log("Refresehd Token", refreshed);
}).catch((err)=> {
console.log("Error", err);
})
},
storeUserProfile(context:ActionContext<any, any>, payload:any) {
context.commit("storeUserProfile", payload)
}
};
const modules = {}; const modules = {};
const authModule = { const authModule = {

View File

@ -1,24 +1,34 @@
import {ActionContext} from "vuex"; import {ActionContext} from "vuex";
import * as seed from "@/seed"; import * as seed from "@/seed";
import BilliDB from "@/indexdDB";
import { v4 as uuidv4 } from 'uuid';
import {SEED_VERSION} from "@/seed";
const db = new BilliDB("billibox", 3);
const state = { const state = {
isInitialized: false, isInitialized: false,
cameras: [], cameras: [],
brands: [], brands: [],
shapes: [], conditions: [],
buildtypes: [] buildtypes: []
}; };
const getters = { const getters = {
cameras: (state: any) => state.cameras, cameras: (state: any) => {
return state.cameras.sort();
},
camera: (state: any) => (id: any) => state.cameras.find((camera: any) => camera.id === id), camera: (state: any) => (id: any) => state.cameras.find((camera: any) => camera.id === id),
activeCamera: (state: any) => state.cameras.find((camera:any) => camera.active ), activeCamera: (state: any) => state.cameras.find((camera:any) => camera.active ),
brands: (state: any) => state.brands, brands: (state: any) => state.brands,
brand: (state: any) => (id: any) => state.brands.find((brand: any) => brand.schluessel === id), brand: (state: any) => (id: any) => state.brands.find((brand: any) => brand.schluessel === id),
shapes: (state: any) => state.shapes, conditions: (state: any) => state.conditions,
shape: (state: any) => (id: any) => state.shapes.find((shape: any) => shape.schluessel === id), condition: (state: any) => (id: any) => state.conditions.find((condition: any) => condition.schluessel === id),
buildtypes: (state: any) => state.buildtypes, buildtypes: (state: any) => state.buildtypes,
buildtype: (state: any) => (id: any) => state.buildtypes.find((buildtype: any) => buildtype.schluessel === id), buildtype: (state: any) => (id: any) => state.buildtypes.find((buildtype: any) => buildtype.schluessel === id),
@ -39,25 +49,47 @@ const mutations = {
}) })
console.log("STORE", state.cameras); console.log("STORE", state.cameras);
}, },
storeCamera(sate:any, payload:any) {
// console.log("mutation.storeCamera", payload)
const objCamera = state.cameras.find((camera:any) => camera.id === payload.id);
if(objCamera) {
// console.log("found existing Camera", objCamera.id);
payload.edit =false;
objCamera.name = payload.name;
} else {
// console.log("creating new Camera");
payload.edit = false;
state.cameras.push(payload);
}
return payload.id;
},
setCameraActiveState(state:any, payload:any) { setCameraActiveState(state:any, payload:any) {
// console.log("setCameraActiveState", payload);
state.cameras.map((camera:any) => camera.active= false); state.cameras.map((camera:any) => camera.active= false);
const objCamera = state.cameras.find((camera:any) => camera.id === payload.id); const objCamera = state.cameras.find((camera:any) => camera.id === payload.id);
objCamera.active = payload.active; objCamera.active = payload.active;
}, },
setBrands(state:any, payload:any) { setCameraEditState(state:any, payload:any) {
console.log("mutation.setBrands"); state.cameras.map((camera:any) => camera.edit= false);
state.brands = payload; const objCamera = state.cameras.find((camera:any) => camera.id === payload.id);
console.log("STORE", state.brands); objCamera.edit = payload.edit;
}, },
setShapes(state:any, payload:any) { setBrands(state:any, payload:any) {
console.log("mutation.setShapes"); // console.log("mutation.setBrands");
state.shapes = payload; state.brands = payload;
console.log("STORE", state.shapes); // console.log("STORE", state.brands);
},
setConditions(state:any, payload:any) {
//console.log("mutation.setConditions");
state.conditions = payload;
//console.log("STORE", state.conditions);
}, },
setBuildtypes(state:any, payload:any) { setBuildtypes(state:any, payload:any) {
console.log("mutation.setBuildtypes"); //console.log("mutation.setBuildtypes");
state.buildtypes = payload; state.buildtypes = payload;
console.log("STORE", state.buildtypes); //console.log("STORE", state.buildtypes);
}, },
setInitialized(state:any, payload:boolean) { setInitialized(state:any, payload:boolean) {
state.isInitialized = payload; state.isInitialized = payload;
@ -65,7 +97,12 @@ const mutations = {
}; };
const actions = { const actions = {
fetchCameras(context:ActionContext<any, any>) { fetchCameras(context:ActionContext<any, any>) {
context.commit("setCameras", seed.cameras); console.log("action.fetchCameras")
db.getItems("cameras").then((cameras) => {
console.log("From DB", cameras);
context.commit("setCameras", cameras);
})
}, },
fetchBrands(context:ActionContext<any, any>) { fetchBrands(context:ActionContext<any, any>) {
context.commit("setBrands", seed.brands); context.commit("setBrands", seed.brands);
@ -73,8 +110,8 @@ const actions = {
fetchBuildTypes(context:ActionContext<any, any>) { fetchBuildTypes(context:ActionContext<any, any>) {
context.commit("setBuildtypes", seed.buildtype); context.commit("setBuildtypes", seed.buildtype);
}, },
fetchShape(context:ActionContext<any, any>) { fetchCondition(context:ActionContext<any, any>) {
context.commit("setShapes", seed.shape); context.commit("setConditions", seed.conditions);
}, },
setCameraActiveState(context:ActionContext<any, any>, payload:any) { setCameraActiveState(context:ActionContext<any, any>, payload:any) {
console.log("action.setCameraActiveState", payload) console.log("action.setCameraActiveState", payload)
@ -82,12 +119,58 @@ const actions = {
context.commit("setCameraActiveState", {id: payload.cameraId, active:payload.active}); context.commit("setCameraActiveState", {id: payload.cameraId, active:payload.active});
}, },
initialize(context:ActionContext<any, any>) {
setCameraEditState(context:ActionContext<any, any>, payload:any) {
console.log("action.setCameraEditState", payload)
const cameraObj = state.cameras.find( (camera:any) => camera.id === payload.cameraId);
context.commit("setCameraEditState", {id: payload.cameraId, edit:payload.edit});
},
storeCamera(context:ActionContext<any, any>, payload:any) {
// console.log("action.storeCamera", payload)
if(!payload.id) payload.id = uuidv4();
//console.log(" ... with id ", payload.id);
//console.log("Try to save to indexDB");
db.saveItem(payload , "cameras").then( (res) => {
console.log("DB-Save resolved", res )}
)
context.commit("storeCamera", payload);
context.commit("setCameraActiveState", {cameraId:payload.id, active:true})
},
initialize(context:ActionContext<any, any>, payload) {
db.getDb();
const promises = [];
const seedVersion = localStorage.getItem("SEED_VERSION") || 0;
if(payload.seed && seedVersion < SEED_VERSION ) {
console.log("SEEDING database");
promises.push(db.saveItems(seed.brands, "brands"));
promises.push(db.saveItems(seed.conditions, "conditions"));
promises.push(db.saveItems(seed.buildtype, "buildtypes"));
promises.push(db.saveItems(seed.cameras, "cameras"));
localStorage.setItem("SEED_VERSION", seed.SEED_VERSION.toString())
} else {
console.log("SEEDING skipped");
}
Promise.all(promises).then( (e) => {
console.log("All written to store")
}
)
context.dispatch("fetchCameras"); context.dispatch("fetchCameras");
context.dispatch("fetchBrands"); // context.dispatch("fetchBrands");
context.dispatch("fetchBuildTypes"); // context.dispatch("fetchBuildTypes");
context.dispatch("fetchShape"); // context.dispatch("fetchCondition");
context.commit("setInitialized", true); // context.commit("setInitialized", true);
} }
}; };

View File

@ -2,7 +2,7 @@
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "esnext",
"module": "esnext", "module": "esnext",
"strict": true, "strict": false,
"jsx": "preserve", "jsx": "preserve",
"moduleResolution": "node", "moduleResolution": "node",
"experimentalDecorators": true, "experimentalDecorators": true,
@ -34,7 +34,8 @@
"src/**/*.tsx", "src/**/*.tsx",
"src/**/*.vue", "src/**/*.vue",
"tests/**/*.ts", "tests/**/*.ts",
"tests/**/*.tsx" "tests/**/*.tsx",
"main.js"
], ],
"exclude": [ "exclude": [
"node_modules" "node_modules"