fileupload and sync with backend
This commit is contained in:
parent
1e01ba7439
commit
01ae5558cc
12
README.md
12
README.md
|
@ -1,5 +1,17 @@
|
||||||
# billibox-vue
|
# billibox-vue
|
||||||
|
|
||||||
|
Datenbank zur Verwaltung alter Kameras und Zubehör.
|
||||||
|
|
||||||
|
Authentifizierung erfolgt über Keycloak open-id-connect
|
||||||
|
|
||||||
|
Backend ist eine in node-js geschriebene Komponente, die JSON-Collections entgegen nimmt.
|
||||||
|
Die Daten werden zunächst lokal in einer IndexedDB vorgehalten und mit dem Backend asynchron gesichert.
|
||||||
|
|
||||||
|
|
||||||
|
Das Backend ist im Projekt billibox-fpg zu finden.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Project setup
|
## Project setup
|
||||||
```
|
```
|
||||||
npm install
|
npm install
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"@fortawesome/vue-fontawesome": "^3.0.0-4",
|
"@fortawesome/vue-fontawesome": "^3.0.0-4",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"bootstrap": "^5.1.3",
|
"bootstrap": "^5.3.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",
|
||||||
|
@ -1991,9 +1991,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@popperjs/core": {
|
"node_modules/@popperjs/core": {
|
||||||
"version": "2.11.4",
|
"version": "2.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.4.tgz",
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||||
"integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==",
|
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
|
@ -4015,15 +4015,21 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/bootstrap": {
|
"node_modules/bootstrap": {
|
||||||
"version": "5.1.3",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
|
||||||
"integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
|
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
|
||||||
"funding": {
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/twbs"
|
||||||
|
},
|
||||||
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/bootstrap"
|
"url": "https://opencollective.com/bootstrap"
|
||||||
},
|
}
|
||||||
|
],
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@popperjs/core": "^2.10.2"
|
"@popperjs/core": "^2.11.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
|
@ -4179,9 +4185,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001322",
|
"version": "1.0.30001524",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001322.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz",
|
||||||
"integrity": "sha512-neRmrmIrCGuMnxGSoh+x7zYtQFFgnSY2jaomjU56sCkTA6JINqQrxutF459JpWcWRajvoyn95sOXq4Pqrnyjew==",
|
"integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -4191,6 +4197,10 @@
|
||||||
{
|
{
|
||||||
"type": "tidelift",
|
"type": "tidelift",
|
||||||
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -13785,9 +13795,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@popperjs/core": {
|
"@popperjs/core": {
|
||||||
"version": "2.11.4",
|
"version": "2.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.4.tgz",
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||||
"integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==",
|
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"@sideway/address": {
|
"@sideway/address": {
|
||||||
|
@ -15377,9 +15387,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
"version": "5.1.3",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
|
||||||
"integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
|
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
|
@ -15487,9 +15497,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"caniuse-lite": {
|
"caniuse-lite": {
|
||||||
"version": "1.0.30001322",
|
"version": "1.0.30001524",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001322.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz",
|
||||||
"integrity": "sha512-neRmrmIrCGuMnxGSoh+x7zYtQFFgnSY2jaomjU56sCkTA6JINqQrxutF459JpWcWRajvoyn95sOXq4Pqrnyjew==",
|
"integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"case-sensitive-paths-webpack-plugin": {
|
"case-sensitive-paths-webpack-plugin": {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"@fortawesome/vue-fontawesome": "^3.0.0-4",
|
"@fortawesome/vue-fontawesome": "^3.0.0-4",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"bootstrap": "^5.1.3",
|
"bootstrap": "^5.3.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",
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
|
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<router-link to="/list" class="nav-link">Startseite</router-link>
|
<router-link to="/list" class="nav-link">Startseite</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<router-link to="/shop/item/create" class="nav-link">Neue Kamera</router-link>
|
<router-link to="/admin/camera/create" class="nav-link">Neue Kamera</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<router-link to="/auth" class="nav-link">Auth</router-link>
|
<router-link to="/auth" class="nav-link">Auth</router-link>
|
||||||
|
|
|
@ -1,14 +1,31 @@
|
||||||
<template>
|
<template>
|
||||||
|
<form @submit="submitFile">
|
||||||
<div>
|
<div class="form-row">
|
||||||
|
<div class="form-group col-md-8 offset-2">
|
||||||
<label for="fileUpload">Datei</label>
|
<label for="fileDescription">Beschreibung</label>
|
||||||
<input id="fileUpload" type="file"
|
<input id="fileDescription" name="description" type="text"
|
||||||
|
/><br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group col-md-8 offset-2">
|
||||||
|
<label class="form-label" for="fileUpload">Datei</label>
|
||||||
|
<input class="form-control" id="fileUpload" name="file" type="file"
|
||||||
@change="handleFileUpload( $event) "
|
@change="handleFileUpload( $event) "
|
||||||
/><br>
|
/><br>
|
||||||
<button v-on:click="submitFile()">Upload</button>
|
|
||||||
</div>
|
</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">Hochladen</span>
|
||||||
|
<span v-else class="spinner-border spinner-border-sm"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -17,7 +34,16 @@ import axios from 'axios';
|
||||||
export default {
|
export default {
|
||||||
name: "FileUpload",
|
name: "FileUpload",
|
||||||
|
|
||||||
|
props: {
|
||||||
|
store: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
activeStore: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -28,9 +54,10 @@ export default {
|
||||||
handleFileUpload(event) {
|
handleFileUpload(event) {
|
||||||
this.file = event.target.files[0];
|
this.file = event.target.files[0];
|
||||||
},
|
},
|
||||||
submitFile() {
|
submitFile(event) {
|
||||||
let formData = new FormData();
|
event.preventDefault();
|
||||||
formData.append('file',this.file);
|
const form = event.target;
|
||||||
|
let formData = new FormData(form);
|
||||||
localStorage.debug = "axios";
|
localStorage.debug = "axios";
|
||||||
const api = axios.create({baseURL: 'http://127.0.0.1:4000'})
|
const api = axios.create({baseURL: 'http://127.0.0.1:4000'})
|
||||||
const apiLogger = require('debug')('api');
|
const apiLogger = require('debug')('api');
|
||||||
|
@ -48,6 +75,13 @@ export default {
|
||||||
|
|
||||||
).then((res) => {
|
).then((res) => {
|
||||||
console.log("FileUpload Success", res.data);
|
console.log("FileUpload Success", res.data);
|
||||||
|
console.log("StoreID Success", this.store.id)
|
||||||
|
|
||||||
|
const uploadItem = {key: res.data.rows[0].key, value: res.data.rows[0].value};
|
||||||
|
this.$store.dispatch("insertNameKeyObject", {
|
||||||
|
storeType: this.store.id,
|
||||||
|
item: uploadItem
|
||||||
|
})
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,14 +11,13 @@
|
||||||
@click="toggleNew"
|
@click="toggleNew"
|
||||||
class="billi-store-add billi-close billi-secondary" icon="xmark"/>
|
class="billi-store-add billi-close billi-secondary" icon="xmark"/>
|
||||||
|
|
||||||
|
|
||||||
<transition
|
<transition
|
||||||
enter-active-class="animate__animated animate__fadeInDown"
|
enter-active-class="animate__animated animate__fadeInDown"
|
||||||
leave-active-class="animate__animated animate__fadeOutUp"
|
leave-active-class="animate__animated animate__fadeOutUp"
|
||||||
mode="out-in"
|
mode="out-in"
|
||||||
appear
|
appear
|
||||||
>
|
>
|
||||||
<section class="billi-store-edit" v-if="add && isActive">
|
<section class="billi-store-edit" v-if="add && isActive && this.store.type !== 'filestore'">
|
||||||
<Form @submit="submitData" :validation-schema="schema" v-slot="{ errors }">
|
<Form @submit="submitData" :validation-schema="schema" v-slot="{ errors }">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-8 offset-2">
|
<div class="form-group col-md-8 offset-2">
|
||||||
|
@ -84,7 +83,7 @@
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<section class="billi-store-edit" v-if="add && isActive && this.store.type === 'filestore'">
|
<section class="billi-store-edit" v-if="add && isActive && this.store.type === 'filestore'">
|
||||||
<FileUpload></FileUpload>
|
<FileUpload :active-store="activeStore" :store="store" ></FileUpload>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import {urlComponents} from "@/types";
|
||||||
|
|
||||||
|
|
||||||
|
export const backendAPI:urlComponents = {
|
||||||
|
host : 'localhost',
|
||||||
|
port : 4000,
|
||||||
|
protocol : 'http'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const port = process.env.PORT || 3000;
|
||||||
|
|
||||||
|
export const indexDB = {
|
||||||
|
id: 'billibox',
|
||||||
|
version: 3
|
||||||
|
}
|
|
@ -1,11 +1,16 @@
|
||||||
|
import axios from "axios";
|
||||||
|
import {collectionExists, createCollection, putItem} from "@/store/backend";
|
||||||
|
import {DatabaseItem, NameKeyStore} from "@/store/interfaces/NameKeyStore";
|
||||||
|
|
||||||
|
|
||||||
export default class BilliDB {
|
export default class BilliDB {
|
||||||
DB_VERSION: number;
|
DB_VERSION: number;
|
||||||
DB_NAME: string;
|
DB_NAME: string;
|
||||||
constructor(dbName:string, dbVersion:number) {
|
BACKEND_URL: string;
|
||||||
|
constructor(dbName:string, dbVersion:number, backendUrl:string) {
|
||||||
this.DB_NAME = dbName;
|
this.DB_NAME = dbName;
|
||||||
this.DB_VERSION = dbVersion;
|
this.DB_VERSION = dbVersion;
|
||||||
|
this.BACKEND_URL = backendUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,8 +62,33 @@ export default class BilliDB {
|
||||||
|
|
||||||
|
|
||||||
async saveItem(item, storeId:string) {
|
async saveItem(item, storeId:string) {
|
||||||
const db = await this.getDb();
|
console.log("-->saveItem", storeId, item);
|
||||||
|
const itemClean = {...item}
|
||||||
|
console.log("-->saveItem clean", storeId, itemClean);
|
||||||
|
|
||||||
|
const request = window.indexedDB.open(this.DB_NAME, this.DB_VERSION);
|
||||||
|
request.onsuccess = (event) => {
|
||||||
|
console.log("DB Request done");
|
||||||
|
const transaction = request.result
|
||||||
|
.transaction([storeId], 'readwrite');
|
||||||
|
const objectStore = transaction.objectStore(storeId);
|
||||||
|
|
||||||
|
const requestUpdate = objectStore.put(itemClean);
|
||||||
|
requestUpdate.onsuccess = (event) => {
|
||||||
|
console.log("Data update complete")
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.oncomplete = (event) => {
|
||||||
|
console.log("Transaction complete")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.onerror = (err) => {
|
||||||
|
console.log("DB Error" , err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
console.log("Starting Add Transaction");
|
console.log("Starting Add Transaction");
|
||||||
|
|
||||||
|
@ -87,6 +117,7 @@ export default class BilliDB {
|
||||||
console.log("onsuccess on Store", e)
|
console.log("onsuccess on Store", e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
async saveItems(items, storeId:string) {
|
async saveItems(items, storeId:string) {
|
||||||
const db = await this.getDb();
|
const db = await this.getDb();
|
||||||
|
@ -159,6 +190,70 @@ export default class BilliDB {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async syncDatabase(storeId:string) {
|
||||||
|
console.log("-->syncDatabase");
|
||||||
|
let db;
|
||||||
|
const request = window.indexedDB.open(this.DB_NAME, this.DB_VERSION);
|
||||||
|
request.onsuccess = (event) => {
|
||||||
|
if (navigator.onLine) {
|
||||||
|
db = request.result;
|
||||||
|
console.log("..onsuccess", db)
|
||||||
|
|
||||||
|
for(const collection of db.objectStoreNames) {
|
||||||
|
console.log("working on: ", collection);
|
||||||
|
|
||||||
|
createCollection(collection).then( exist => {
|
||||||
|
console.log(exist);
|
||||||
|
const transaction = db.transaction(collection,'readwrite');
|
||||||
|
const objectStore = transaction.objectStore(collection);
|
||||||
|
console.log("working on objectstore: ", objectStore);
|
||||||
|
const cursorRequest = objectStore.openCursor();
|
||||||
|
cursorRequest.onsuccess = (e) => {
|
||||||
|
const cursor = e.target.result;
|
||||||
|
if(cursor) {
|
||||||
|
const value = cursor.value;
|
||||||
|
console.log(cursor.key, cursor.value, value);
|
||||||
|
|
||||||
|
putItem(collection, value);
|
||||||
|
cursor.continue();
|
||||||
|
} else {
|
||||||
|
console.log("no cursor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursorRequest.onerror = (err) => {
|
||||||
|
console.log("cursor error", err);
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
const objectStore = transaction.objectStore('brand111s');
|
||||||
|
const cursorRequest = objectStore.openCursor();
|
||||||
|
|
||||||
|
cursorRequest.onsuccess = (e) => {
|
||||||
|
const cursor = e.target.result;
|
||||||
|
if (cursor) {
|
||||||
|
|
||||||
|
console.log("Cursor: ", cursor.value());
|
||||||
|
|
||||||
|
// axios.put('', cursor.value())
|
||||||
|
// Perform synchronization logic here
|
||||||
|
cursor.continue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test if we have connection to the Internet
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
56
src/main.ts
56
src/main.ts
|
@ -3,6 +3,7 @@ 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 VueKeyCloak from '@dsb-norge/vue-keycloak-js'
|
||||||
|
import 'bootstrap/dist/css/bootstrap.css'
|
||||||
|
|
||||||
import { KeycloakInstance } from "keycloak-js";
|
import { KeycloakInstance } from "keycloak-js";
|
||||||
import { VueKeycloakInstance } from "@dsb-norge/vue-keycloak-js/dist/types";
|
import { VueKeycloakInstance } from "@dsb-norge/vue-keycloak-js/dist/types";
|
||||||
|
@ -23,6 +24,8 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||||
|
|
||||||
library.add(faUserSecret);
|
library.add(faUserSecret);
|
||||||
|
|
||||||
|
const SKIP_KEYCLOAK = false;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -46,12 +49,12 @@ createApp(App);
|
||||||
app.use(store)
|
app.use(store)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.component("font-awesome-icon", FontAwesomeIcon);
|
app.component("font-awesome-icon", FontAwesomeIcon);
|
||||||
app.use(VueKeyCloak, {
|
if (!SKIP_KEYCLOAK) app.use(VueKeyCloak, {
|
||||||
config: {
|
config: {
|
||||||
url: 'https://auth.toking.de/',
|
url: 'https://auth.toking.de/',
|
||||||
realm: 'toking',
|
realm: 'toking',
|
||||||
clientId: 'billibox',
|
clientId: 'billibox',
|
||||||
redirectUri: 'http://127.0.0.1:8080/',
|
redirectUri: 'http://127.0.0.1:8081/',
|
||||||
onLoad: 'login-required',
|
onLoad: 'login-required',
|
||||||
enableLogging: true,
|
enableLogging: true,
|
||||||
scope: 'open-id'
|
scope: 'open-id'
|
||||||
|
@ -82,52 +85,3 @@ declare module '@vue/runtime-core' {
|
||||||
$keycloak: VueKeycloakInstance
|
$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");
|
|
||||||
// });
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ export default {
|
||||||
else return ['alert-secondary'];
|
else return ['alert-secondary'];
|
||||||
},
|
},
|
||||||
setActiveStore(key) {
|
setActiveStore(key) {
|
||||||
|
console.log("setting Active store to: ", key);
|
||||||
this.activeStore = key
|
this.activeStore = key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import CreateCameraPage from "@/pages/CreateCameraPage.vue";
|
import CreateCameraPage from "@/pages/CreateCameraPage.vue";
|
||||||
import ReadNameKeyPage from "@/pages/ReadNameKeyPage.vue";
|
import ReadNameKeyPage from "@/pages/ReadNameKeyPage.vue";
|
||||||
const shopRoutes = [
|
const shopRoutes = [
|
||||||
{
|
// {
|
||||||
path: "/admin/camera/create",
|
// path: "/admin/camera/create",
|
||||||
component: CreateCameraPage,
|
// component: CreateCameraPage,
|
||||||
meta: {
|
// meta: {
|
||||||
requiresAuth: true
|
// requiresAuth: true
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/admin/namekey",
|
// path: "/admin/namekey",
|
||||||
component: ReadNameKeyPage,
|
// component: ReadNameKeyPage,
|
||||||
props: true,
|
// props: true,
|
||||||
meta: {
|
// meta: {
|
||||||
requiresAuth: false,
|
// requiresAuth: false,
|
||||||
// enterTransition: "rubberBand"
|
// // enterTransition: "rubberBand"
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
];
|
];
|
||||||
export default shopRoutes;
|
export default shopRoutes;
|
||||||
//# sourceMappingURL=admin-routes.js.map
|
//# sourceMappingURL=admin-routes.js.map
|
|
@ -142,7 +142,7 @@ export const brands = [
|
||||||
description: 'APS-Kameras, Digitalkameras, Kleinbildkameras, Mittelformatkameras.'
|
description: 'APS-Kameras, Digitalkameras, Kleinbildkameras, Mittelformatkameras.'
|
||||||
},
|
},
|
||||||
{key: 'fandolfi', name: 'Gandolfi', description: 'Großformatkameras.'},
|
{key: 'fandolfi', name: 'Gandolfi', description: 'Großformatkameras.'},
|
||||||
{key: 'fottschalt', name: 'Gottschalt', description: 'Fachkameras.'},
|
{key: 'gottschalt', name: 'Gottschalt', description: 'Fachkameras.'},
|
||||||
{key: 'hasselblad', name: 'Hasselblad', description: 'Kleinbildkameras, Mittelformatkameras.'},
|
{key: 'hasselblad', name: 'Hasselblad', description: 'Kleinbildkameras, Mittelformatkameras.'},
|
||||||
{key: 'hitachi', name: 'Hitachi', description: 'Digitalkameras.'},
|
{key: 'hitachi', name: 'Hitachi', description: 'Digitalkameras.'},
|
||||||
{key: 'hewlett-Packard (HP)', name: 'Hewlett-Packard (HP)', description: 'Digitalkameras.'},
|
{key: 'hewlett-Packard (HP)', name: 'Hewlett-Packard (HP)', description: 'Digitalkameras.'},
|
||||||
|
@ -300,7 +300,7 @@ export const manufacturers = [
|
||||||
description: 'APS-Kameras, Digitalkameras, Kleinbildkameras, Mittelformatkameras.'
|
description: 'APS-Kameras, Digitalkameras, Kleinbildkameras, Mittelformatkameras.'
|
||||||
},
|
},
|
||||||
{key: 'fandolfi', name: 'Gandolfi', description: 'Großformatkameras.'},
|
{key: 'fandolfi', name: 'Gandolfi', description: 'Großformatkameras.'},
|
||||||
{key: 'fottschalt', name: 'Gottschalt', description: 'Fachkameras.'},
|
{key: 'gottschalt', name: 'Gottschalt', description: 'Fachkameras.'},
|
||||||
{key: 'hasselblad', name: 'Hasselblad', description: 'Kleinbildkameras, Mittelformatkameras.'},
|
{key: 'hasselblad', name: 'Hasselblad', description: 'Kleinbildkameras, Mittelformatkameras.'},
|
||||||
{key: 'hitachi', name: 'Hitachi', description: 'Digitalkameras.'},
|
{key: 'hitachi', name: 'Hitachi', description: 'Digitalkameras.'},
|
||||||
{key: 'hewlett-Packard (HP)', name: 'Hewlett-Packard (HP)', description: 'Digitalkameras.'},
|
{key: 'hewlett-Packard (HP)', name: 'Hewlett-Packard (HP)', description: 'Digitalkameras.'},
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import axios from "axios";
|
||||||
|
import {backendAPI, indexDB} from "@/config";
|
||||||
|
import Util from "@/util";
|
||||||
|
import {DatabaseItem} from "@/store/interfaces/NameKeyStore";
|
||||||
|
|
||||||
|
|
||||||
|
export async function collectionExists(collectionName: string) {
|
||||||
|
const apiBase = Util.getURL(backendAPI);
|
||||||
|
const endpoint = `${apiBase}/pgadmin/${indexDB.id}/${collectionName}`;
|
||||||
|
try {
|
||||||
|
const rawResult = await axios.get(endpoint);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createCollection(collectionName: string) {
|
||||||
|
const apiBase = Util.getURL(backendAPI);
|
||||||
|
const endpoint = `${apiBase}/pgadmin/${indexDB.id}/${collectionName}`;
|
||||||
|
try {
|
||||||
|
const rawResult = await axios.post(endpoint);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function putItem(collectionName: string, item:DatabaseItem) {
|
||||||
|
console.log("-->putItem", item);
|
||||||
|
const apiBase = Util.getURL(backendAPI);
|
||||||
|
const endpoint = `${apiBase}/pg/${indexDB.id}/${collectionName}/${item.key}`;
|
||||||
|
try {
|
||||||
|
const rawResult = await axios.put(endpoint,item);
|
||||||
|
return rawResult.data;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,11 @@
|
||||||
interface NameKeyStore {
|
export interface NameKeyStore {
|
||||||
name:string;
|
name:string;
|
||||||
id:string;
|
id:string;
|
||||||
identifier:string;
|
identifier:string;
|
||||||
type:( "nameKey" | "filestore" | "object")
|
type:( "nameKey" | "filestore" | "object")
|
||||||
}
|
}
|
||||||
|
export interface DatabaseItem {
|
||||||
|
key:string,
|
||||||
|
value:object,
|
||||||
|
lastchanged?:Date
|
||||||
|
}
|
|
@ -203,10 +203,11 @@ const mutations = {
|
||||||
const actions = {
|
const actions = {
|
||||||
storeNameKeyObject(context, payload) {
|
storeNameKeyObject(context, payload) {
|
||||||
console.log("actions.storeNameKeyObject", payload);
|
console.log("actions.storeNameKeyObject", payload);
|
||||||
db.saveItem(payload.item, payload.storeType).then((res) => {
|
|
||||||
|
db.saveItem(payload, payload.storeType).then((res) => {
|
||||||
console.log("Item stored in Database");
|
console.log("Item stored in Database");
|
||||||
});
|
});
|
||||||
context.commit("storeNameKey", payload.item);
|
context.commit("storeNameKey", {...payload});
|
||||||
},
|
},
|
||||||
insertNameKeyObject(context, payload) {
|
insertNameKeyObject(context, payload) {
|
||||||
console.log("actions.insertNameKeyObject", payload);
|
console.log("actions.insertNameKeyObject", payload);
|
||||||
|
@ -289,6 +290,7 @@ const actions = {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log("SEEDING skipped");
|
console.log("SEEDING skipped");
|
||||||
|
db.syncDatabase();
|
||||||
context.dispatch("loadDataFromLocalDB")
|
context.dispatch("loadDataFromLocalDB")
|
||||||
.then(() => console.log("Store Data loaded"))
|
.then(() => console.log("Store Data loaded"))
|
||||||
.catch((e) => console.log("Error loading StoreData", e));
|
.catch((e) => console.log("Error loading StoreData", e));
|
||||||
|
|
|
@ -8,9 +8,12 @@ import InventoryItem from "@/store/classes/InventoryItem";
|
||||||
import Camera from "@/store/classes/Camera";
|
import Camera from "@/store/classes/Camera";
|
||||||
import Lens from "@/store/classes/Lens";
|
import Lens from "@/store/classes/Lens";
|
||||||
import InventorySet from "@/store/classes/InventorySet";
|
import InventorySet from "@/store/classes/InventorySet";
|
||||||
|
import {backendAPI, indexDB} from "@/config";
|
||||||
|
import Util from "@/util";
|
||||||
|
import {NameKeyStore} from "@/store/interfaces/NameKeyStore";
|
||||||
|
|
||||||
|
|
||||||
const db = new BilliDB("billibox", 3);
|
const db = new BilliDB(indexDB.id, 3, Util.getURL(backendAPI));
|
||||||
|
|
||||||
|
|
||||||
const stores:NameKeyStore[] = [
|
const stores:NameKeyStore[] = [
|
||||||
|
@ -147,7 +150,8 @@ const mutations = {
|
||||||
},
|
},
|
||||||
|
|
||||||
storeNameKey(state:any, payload:any) {
|
storeNameKey(state:any, payload:any) {
|
||||||
const objNK:NameKey = state[payload.storeType].find( (item) => item.key === payload.itemOld.key);
|
console.log("mutation.storeNameKey", state, payload.storeType);
|
||||||
|
const objNK:NameKey = state[payload.storeType].find( (item) => item.key === payload.item.key);
|
||||||
if(objNK.key) objNK.key = payload.item.key;
|
if(objNK.key) objNK.key = payload.item.key;
|
||||||
objNK.name = payload.item.name;
|
objNK.name = payload.item.name;
|
||||||
objNK.description = payload.item.description;
|
objNK.description = payload.item.description;
|
||||||
|
@ -257,7 +261,7 @@ const actions = {
|
||||||
console.log("Item stored in Database")
|
console.log("Item stored in Database")
|
||||||
})
|
})
|
||||||
|
|
||||||
context.commit("storeNameKey", payload.item);
|
context.commit("storeNameKey", {...payload});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -367,6 +371,7 @@ const actions = {
|
||||||
localStorage.setItem("SEED_VERSION", seed.SEED_VERSION.toString())
|
localStorage.setItem("SEED_VERSION", seed.SEED_VERSION.toString())
|
||||||
} else {
|
} else {
|
||||||
console.log("SEEDING skipped");
|
console.log("SEEDING skipped");
|
||||||
|
db.syncDatabase("test");
|
||||||
context.dispatch("loadDataFromLocalDB")
|
context.dispatch("loadDataFromLocalDB")
|
||||||
.then(() => console.log("Store Data loaded"))
|
.then(() => console.log("Store Data loaded"))
|
||||||
.catch((e) => console.log("Error loading StoreData", e));
|
.catch((e) => console.log("Error loading StoreData", e));
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface urlComponents {
|
||||||
|
host: string,
|
||||||
|
port: number,
|
||||||
|
protocol: 'http'|'https'
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import {urlComponents} from "@/types";
|
||||||
|
|
||||||
|
export default class Util {
|
||||||
|
|
||||||
|
public static getURL(components:urlComponents) {
|
||||||
|
|
||||||
|
return `${components.protocol}://${components.host}${(components.port)?':'+components.port:''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue