populate events trough apicall and save active event in url
This commit is contained in:
parent
fbf6d9dc91
commit
cc9ba38dac
11 changed files with 137 additions and 61 deletions
2
.env.example
Normal file
2
.env.example
Normal file
|
@ -0,0 +1,2 @@
|
|||
VUE_APP_CONFIG_API_USER=rest api user
|
||||
VUE_APP_CONFIG_API_PASSWORD=rest api password
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,6 +3,7 @@ node_modules
|
|||
/dist
|
||||
|
||||
# local env files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
|
|
2
API.md
2
API.md
|
@ -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>``
|
|
@ -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",
|
||||
|
|
33
src/App.vue
33
src/App.vue
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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']),
|
||||
|
|
|
@ -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
18
src/router.js
Normal 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;
|
|
@ -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
48
src/views/Items.vue
Normal 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>
|
Loading…
Reference in a new issue