populate events trough apicall and save active event in url

This commit is contained in:
j3d1 2019-12-05 04:32:33 +01:00
parent fbf6d9dc91
commit cc9ba38dac
11 changed files with 137 additions and 61 deletions

2
.env.example Normal file
View file

@ -0,0 +1,2 @@
VUE_APP_CONFIG_API_USER=rest api user
VUE_APP_CONFIG_API_PASSWORD=rest api password

1
.gitignore vendored
View file

@ -3,6 +3,7 @@ node_modules
/dist
# local env files
.env
.env.local
.env.*.local

2
API.md
View file

@ -55,4 +55,4 @@ returns a list of all tracked events
### Files/Images
#### ``GET /api/images/<file.hash>``
#### ``GET /api/<version.major>/images/<file.hash>``

View file

@ -11,15 +11,20 @@
"@fortawesome/fontawesome-svg-core": "^1.2.25",
"@fortawesome/free-solid-svg-icons": "^5.11.2",
"@fortawesome/vue-fontawesome": "^0.1.8",
"axios": "^0.19.0",
"bootstrap": "^4.3.1",
"core-js": "^3.3.2",
"dotenv-webpack": "^1.7.0",
"jquery": "^3.4.1",
"lodash": "^4.17.15",
"node-sass": "^4.13.0",
"popper.js": "^1.16.0",
"ramda": "^0.26.1",
"sass-loader": "^8.0.0",
"vue": "^2.6.10",
"vuex": "^3.1.2"
"vue-router": "^3.1.3",
"vuex": "^3.1.2",
"vuex-router-sync": "^5.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.0.0",

View file

@ -1,46 +1,17 @@
<template>
<div id="app">
<Navbar/>
<div class="container-fluid px-xl-5 mt-3">
<div class="row" v-if="layout === 'table'">
<div class="col-xl-8 offset-xl-2">
<Table
:columns="['uid', 'description', 'box', 'image']"
:items="loadedItems"
:keyName="'uid'"
/>
</div>
</div>
<Cards
v-if="layout === 'cards'"
:columns="['uid', 'description', 'box', 'image']"
:items="loadedItems"
:keyName="'uid'"
v-slot="{ item }"
>
<img
:src="`https://picsum.photos/id/${item.image + 50}/200/200`"
alt="item"
class="card-img-top img-fluid"
>
<div class="card-body">
<h6 class="card-title">{{ item.description }}</h6>
<h6 class="card-subtitle text-secondary">uid: {{ item.uid }} box: {{ item.box }}</h6>
</div>
</Cards>
</div>
<router-view></router-view>
</div>
</template>
<script>
import Table from '@/components/Table';
import Navbar from '@/components/Navbar';
import Cards from '@/components/Cards';
import { mapState } from 'vuex';
export default {
name: 'app',
components: { Navbar, Table, Cards },
components: { Navbar },
computed: mapState(['loadedItems', 'layout'])
};
</script>

View file

@ -28,11 +28,11 @@
</div>
</div>
<div class="col-lg-9 col-xl-8">
<transition-group name="card-list" tag="div" class="card-columns">
<div class="card-columns">
<div class="card-list-item card bg-dark text-light" v-for="item in internalItems" :key="item[keyName]">
<slot v-bind:item="item"/>
</div>
</transition-group>
</div>
</div>
</div>
</template>
@ -48,14 +48,3 @@ export default {
}
};
</script>
<style>
.card-list-enter, .card-list-leave-to {
opacity: 0;
}
.card-list-leave-active {
position: absolute;
}
</style>

View file

@ -3,11 +3,11 @@
<div class="dropdown">
<button class="btn text-light dropdown-toggle btn-heading" type="button" id="dropdownMenuButton"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ activeEvent.slug }}
{{getEventSlug}}
</button>
<div class="dropdown-menu bg-dark" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item text-light" href="#" v-for="(event, index) in events" v-bind:key="index"
:class="{ active: event === activeEvent }" @click="changeEvent(event)">{{ event.slug }}</a>
:class="{ active: event.slug === getEventSlug }" @click="changeEvent(event)">{{ event.slug }}</a>
</div>
</div>
@ -58,7 +58,7 @@
</template>
<script>
import { mapState, mapActions, mapMutations } from 'vuex';
import { mapState, mapActions, mapMutations, mapGetters} from 'vuex';
export default {
@ -79,6 +79,7 @@ export default {
}),
computed: {
...mapState(['events', 'activeEvent', 'layout']),
...mapGetters(['getEventSlug']),
},
methods: {
...mapActions(['changeEvent']),

View file

@ -1,6 +1,8 @@
import Vue from 'vue';
import App from './App.vue';
import store from './store';
import router from './router';
import { sync } from 'vuex-router-sync';
// bootstrap
import 'jquery/dist/jquery.min.js';
@ -12,12 +14,17 @@ import { library } from '@fortawesome/fontawesome-svg-core';
import { faPlus, faCheckCircle, faEdit, faTrash, faCat, faSyncAlt, faSort, faSortUp, faSortDown, faTh, faList, faWindowClose } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
library.add(faPlus, faCheckCircle, faEdit, faTrash, faCat, faSyncAlt, faSort, faSortUp, faSortDown, faTh, faList, faWindowClose);
Vue.component('font-awesome-icon', FontAwesomeIcon);
sync(store, router);
new Vue({
el: '#app',
store,
router,
render: h => h(App),
});

18
src/router.js Normal file
View file

@ -0,0 +1,18 @@
import Items from './views/Items';
import VueRouter from 'vue-router';
import Vue from 'vue';
Vue.use(VueRouter);
const routes = [
{ path: '/:event', component: Items},
];
const router = new VueRouter({
mode: 'history',
routes
});
export default router;

View file

@ -1,16 +1,14 @@
import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios';
//import * as _ from 'lodash/fp';
import router from '../router';
Vue.use(Vuex);
export default new Vuex.Store({
const store = new Vuex.Store({
state: {
events: [
{'slug': '35C3'},
{'slug': 'camp19'},
{'slug': '36C3'}
],
activeEvent: {'slug': '36C3'},
events: Array,
layout: 'cards',
loadedItems: [
{ uid: 1, description: 'sleeping bag', box: 7, image: 41 },
@ -29,19 +27,55 @@ export default new Vuex.Store({
{ uid: 14, description: 'toy truck', box: 6, image: 51 }
]
},
getters: {
getEventSlug: state => state.route.params.event,
},
mutations: {
replaceEvents(state, events) {
state.events = events;
//if (!state.activeEvent || !events.includes(state.activeEvent))
// state.activeEvent = _.reverse(events)[0];
},
changeEvent(state, event) {
state.activeEvent = event;
router.push({path: `/${event.slug}`});
},
replaceLoadedItems(state, newItems) {
state.loadedItems = newItems;
},
setLayout(state, layout) {
state.layout = layout;
}
},
actions: {
changeEvent({ commit }, event) {
// todo: load items from server
// todo: load items from server
commit('changeEvent', event);
async loadEvents({ commit }) {
const resp = await axios.get('https://c3lf.de/api/1/events', {
auth: {
username: process.env.VUE_APP_CONFIG_API_USER,
password: process.env.VUE_APP_CONFIG_API_PASSWORD
}
});
commit('replaceEvents', resp.data);
},
changeEvent({ commit, dispatch }, eventName) {
commit('changeEvent', eventName);
dispatch('loadEventItems', eventName);
},
async loadEventItems({ commit, state }) {
const resp = await axios.get(`https://c3lf.de/api/1/${state.route.params.event}/items`, {
auth: {
username: process.env.VUE_APP_CONFIG_API_USER,
password: process.env.VUE_APP_CONFIG_API_PASSWORD
}
});
console.log(resp.data);
commit('replaceLoadedItems', resp.data);
}
}
});
export default store;
store.dispatch('loadEvents');

48
src/views/Items.vue Normal file
View file

@ -0,0 +1,48 @@
<template>
<div class="container-fluid px-xl-5 mt-3">
<div class="row" v-if="layout === 'table'">
<div class="col-xl-8 offset-xl-2">
<Table
:columns="['uid', 'description', 'box', 'image']"
:items="loadedItems"
:keyName="'uid'"
/>
</div>
</div>
<Cards
v-if="layout === 'cards'"
:columns="['uid', 'description', 'box', 'image']"
:items="loadedItems"
:keyName="'uid'"
v-slot="{ item }"
>
<img
:src="`https://picsum.photos/id/${item.image + 50}/200/200`"
alt="item"
class="card-img-top img-fluid"
>
<div class="card-body">
<h6 class="card-title">{{ item.description }}</h6>
<h6 class="card-subtitle text-secondary">uid: {{ item.uid }} box: {{ item.box }}</h6>
</div>
</Cards>
</div>
</template>
<script>
import Table from '@/components/Table';
import Cards from '@/components/Cards';
import { mapState } from 'vuex';
export default {
name: 'Items',
components: { Table, Cards },
created() {
console.log(this.$route.params.event);
},
computed: mapState(['loadedItems', 'layout']),
};
</script>
<style scoped>
</style>