prerelease2
MarketplaceItem, Marketplace, Pagination, Update modal popup for new releases
This commit is contained in:
parent
4a173a4474
commit
51ac44116a
15 changed files with 550 additions and 38 deletions
|
@ -15,6 +15,7 @@
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"crypto-random-string": "^3.3.0",
|
"crypto-random-string": "^3.3.0",
|
||||||
"dotenv-webpack": "^6.0.0",
|
"dotenv-webpack": "^6.0.0",
|
||||||
|
"lodash.throttle": "^4.1.1",
|
||||||
"socket.io": "^3.1.0",
|
"socket.io": "^3.1.0",
|
||||||
"to-boolean": "^1.0.0",
|
"to-boolean": "^1.0.0",
|
||||||
"v-offline": "^1.3.0",
|
"v-offline": "^1.3.0",
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
"vue-axios": "^3.2.2",
|
"vue-axios": "^3.2.2",
|
||||||
"vue-i18n": "^8.17.3",
|
"vue-i18n": "^8.17.3",
|
||||||
"vue-keypress": "^2.1.1",
|
"vue-keypress": "^2.1.1",
|
||||||
|
"vue-matomo": "^3.14.0-0",
|
||||||
"vue-router": "^3.2.0",
|
"vue-router": "^3.2.0",
|
||||||
"vue-socket.io": "^3.0.10",
|
"vue-socket.io": "^3.0.10",
|
||||||
"vuex": "^3.4.0"
|
"vuex": "^3.4.0"
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
<div id="router content-wrapper">
|
<div id="router content-wrapper">
|
||||||
<router-view/>
|
<router-view/>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<Footer/>
|
<Footer/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,6 +29,11 @@ export default {
|
||||||
Footer
|
Footer
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
if(JSON.parse(
|
||||||
|
localStorage.getItem('token'))) {
|
||||||
|
this.$store.commit('setToken', JSON.parse(
|
||||||
|
localStorage.getItem('token')))
|
||||||
|
}
|
||||||
if(JSON.parse(
|
if(JSON.parse(
|
||||||
localStorage.getItem('wind404'))) {
|
localStorage.getItem('wind404'))) {
|
||||||
var wind = JSON.parse(
|
var wind = JSON.parse(
|
||||||
|
|
|
@ -142,6 +142,34 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
|
<b-modal :active="updateModal" @update:active="value => updateModal = value" :width="640" scroll="keep">
|
||||||
|
<form>
|
||||||
|
<div class="modal-card" style="width: auto">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<p class="modal-card-title">{{$t('update.title')}}</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="delete"
|
||||||
|
@click="registerModal = false"/>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body has-text-centered">
|
||||||
|
<h1 class="subtitle">What's new in {{$store.state.client.clientVersion}}?</h1>
|
||||||
|
<ul>
|
||||||
|
<li>Marketplace</li>
|
||||||
|
<li>Pagination Component</li>
|
||||||
|
<li>Fix crashing when token is null</li>
|
||||||
|
<li>User list pagination</li>
|
||||||
|
<li>Marketplace Item</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot">
|
||||||
|
<b-button
|
||||||
|
:label="$t('close')"
|
||||||
|
@click="updateDismissed" />
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</b-modal>
|
||||||
<b-modal :active="registerModal" @update:active="value => registerModal = value" :width="640" scroll="keep">
|
<b-modal :active="registerModal" @update:active="value => registerModal = value" :width="640" scroll="keep">
|
||||||
<form>
|
<form>
|
||||||
<div class="modal-card" style="width: auto">
|
<div class="modal-card" style="width: auto">
|
||||||
|
@ -354,6 +382,7 @@ export default {
|
||||||
showBanner: true,
|
showBanner: true,
|
||||||
showOutdatedBanner: true,
|
showOutdatedBanner: true,
|
||||||
friendCount: 0,
|
friendCount: 0,
|
||||||
|
updateModal: false,
|
||||||
settings: {
|
settings: {
|
||||||
tab: 0,
|
tab: 0,
|
||||||
general: {
|
general: {
|
||||||
|
@ -513,6 +542,17 @@ export default {
|
||||||
this.showBanner = true
|
this.showBanner = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateDismissed() {
|
||||||
|
localStorage.setItem("update-" + this.$store.state.client.clientVersion, true)
|
||||||
|
this.updateModal = false
|
||||||
|
},
|
||||||
|
showUpdate() {
|
||||||
|
if(!localStorage.getItem("update-" + this.$store.state.client.clientVersion)) {
|
||||||
|
this.updateModal = true
|
||||||
|
} else {
|
||||||
|
this.updateModal = false
|
||||||
|
}
|
||||||
|
},
|
||||||
removeBannerId() {
|
removeBannerId() {
|
||||||
localStorage.setItem(this.$store.state.client.bannerId, true)
|
localStorage.setItem(this.$store.state.client.bannerId, true)
|
||||||
this.$store.state.client.bannerEnabled = false
|
this.$store.state.client.bannerEnabled = false
|
||||||
|
@ -699,6 +739,7 @@ export default {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
this.showUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
66
src/components/Pagination.vue
Normal file
66
src/components/Pagination.vue
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<template>
|
||||||
|
<div class='pagination'>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import throttle from 'lodash.throttle'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Pagination',
|
||||||
|
props: ['loading', 'query-selector', 'padding-bottom', 'padding-top', 'paginate'],
|
||||||
|
computed: {
|
||||||
|
element () {
|
||||||
|
if(this.querySelector){
|
||||||
|
return document.querySelector(this.querySelector);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onScroll: throttle(function () {
|
||||||
|
let paddingBottom = this.paddingBottom || 300;
|
||||||
|
let paddingTop = this.paddingTop || 150;
|
||||||
|
|
||||||
|
let scrollBottom, scrollTop;
|
||||||
|
|
||||||
|
//If already loading then do not fire
|
||||||
|
if(this.loading) return;
|
||||||
|
|
||||||
|
if(this.element) {
|
||||||
|
scrollBottom = Math.floor(
|
||||||
|
this.element.scrollTop +
|
||||||
|
this.element.getBoundingClientRect().height +
|
||||||
|
paddingBottom -
|
||||||
|
this.element.scrollHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
scrollTop = paddingTop - this.element.scrollTop;
|
||||||
|
} else {
|
||||||
|
scrollBottom =
|
||||||
|
window.innerHeight + window.pageYOffset +
|
||||||
|
paddingBottom -
|
||||||
|
document.body.scrollHeight;
|
||||||
|
|
||||||
|
scrollTop = paddingTop - document.body.scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scrollBottom > 0) {
|
||||||
|
if(this.paginate) {
|
||||||
|
this.$emit('loadNext');
|
||||||
|
}
|
||||||
|
} else if(scrollTop > 0) {
|
||||||
|
this.$emit('loadPrevious');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
(this.element || window).addEventListener('scroll', this.onScroll);
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
(this.element || window).removeEventListener('scroll', this.onScroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -175,7 +175,8 @@
|
||||||
"relationships": {
|
"relationships": {
|
||||||
"pending": "Cancel Friend Request",
|
"pending": "Cancel Friend Request",
|
||||||
"notFriends": "Send Friend Request",
|
"notFriends": "Send Friend Request",
|
||||||
"pendingCanAccept": "Accept Friend Request"
|
"pendingCanAccept": "Accept Friend Request",
|
||||||
|
"accepted": "Remove friend"
|
||||||
},
|
},
|
||||||
"modifyUser": {
|
"modifyUser": {
|
||||||
"title": "Modify User",
|
"title": "Modify User",
|
||||||
|
@ -266,6 +267,25 @@
|
||||||
"soon": "(SOON)"
|
"soon": "(SOON)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"marketplace": {
|
||||||
|
"hats": "Hats",
|
||||||
|
"faces": "Faces",
|
||||||
|
"shirts": "Shirts",
|
||||||
|
"pants": "Pants",
|
||||||
|
"collections": "Collections",
|
||||||
|
"moreInfo": "More info",
|
||||||
|
"filter": "Filters",
|
||||||
|
"search": "Search the Marketplace"
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"title": "Changelog for new update"
|
||||||
|
},
|
||||||
|
"marketplaceItem": {
|
||||||
|
"moreInfo": "Information and Stats",
|
||||||
|
"price": "Price",
|
||||||
|
"originalPrice": "Original Price",
|
||||||
|
"creator": "The Creator"
|
||||||
|
},
|
||||||
"currency": "Koins",
|
"currency": "Koins",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"tos": "Terms of Service",
|
"tos": "Terms of Service",
|
||||||
|
|
|
@ -6,10 +6,16 @@ import Buefy, {Snackbar} from 'buefy'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import VueAxios from 'vue-axios'
|
import VueAxios from 'vue-axios'
|
||||||
import i18n from './i18n'
|
import i18n from './i18n'
|
||||||
|
import moment from 'moment'
|
||||||
Vue.use(VueAxios, axios)
|
Vue.use(VueAxios, axios)
|
||||||
Vue.use(Buefy)
|
Vue.use(Buefy)
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
Vue.prototype.$snackbar = Snackbar
|
Vue.prototype.$snackbar = Snackbar
|
||||||
|
Vue.filter('formatDate', function(value) {
|
||||||
|
if (value) {
|
||||||
|
return moment(String(value)).format('hh:mm A, DD/MM/YYYY')
|
||||||
|
}
|
||||||
|
})
|
||||||
new Vue({
|
new Vue({
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
|
|
|
@ -77,6 +77,22 @@ const routes = [
|
||||||
name: 'Roadmap',
|
name: 'Roadmap',
|
||||||
component: route('Roadmap')
|
component: route('Roadmap')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/marketplace/',
|
||||||
|
redirect: '/marketplace/HATS',
|
||||||
|
name: 'Marketplace',
|
||||||
|
component: route('Marketplace')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/marketplace/:category',
|
||||||
|
name: 'Marketplace',
|
||||||
|
component: route('Marketplace')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/m/:id',
|
||||||
|
name: 'MarketplaceItem',
|
||||||
|
component: route('MarketplaceItem')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/stats',
|
path: '/stats',
|
||||||
name: 'Stats',
|
name: 'Stats',
|
||||||
|
|
|
@ -2,21 +2,13 @@ import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import tb from 'to-boolean';
|
import tb from 'to-boolean';
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
if(JSON.parse(
|
|
||||||
localStorage.getItem('token'))) {
|
|
||||||
var token = JSON.parse(
|
|
||||||
localStorage.getItem('token'))
|
|
||||||
} else {
|
|
||||||
// eslint-disable-next-line no-redeclare
|
|
||||||
var token = ''
|
|
||||||
}
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
debug: tb(process.env.VUE_APP_STAGING),
|
debug: tb(process.env.VUE_APP_STAGING),
|
||||||
wind: false,
|
wind: false,
|
||||||
enableBrokenRoutes: false,
|
enableBrokenRoutes: false,
|
||||||
client: {
|
client: {
|
||||||
clientVersion: '1.0.0-prerelease',
|
clientVersion: '1.0.0-prerelease2',
|
||||||
latestClientVersion: '',
|
latestClientVersion: '',
|
||||||
latestAPIVersion: '',
|
latestAPIVersion: '',
|
||||||
bannerText: '',
|
bannerText: '',
|
||||||
|
@ -48,7 +40,7 @@ export default new Vuex.Store({
|
||||||
avatar: 'default',
|
avatar: 'default',
|
||||||
bot: '',
|
bot: '',
|
||||||
system: '',
|
system: '',
|
||||||
token: token,
|
token: '',
|
||||||
koins: 0,
|
koins: 0,
|
||||||
emailVerified: false,
|
emailVerified: false,
|
||||||
modeler: false,
|
modeler: false,
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-left">
|
<div class="media-left">
|
||||||
Created At: {{thread.createdAt}}
|
Created At: {{thread.createdAt | formatDate()}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
@ -120,7 +120,6 @@ export default {
|
||||||
},
|
},
|
||||||
$route () {
|
$route () {
|
||||||
this.selectedCategory = this.$route.path.split('/')[2].toUpperCase()
|
this.selectedCategory = this.$route.path.split('/')[2].toUpperCase()
|
||||||
this.newThreads = 0
|
|
||||||
this.getThreads(true)
|
this.getThreads(true)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,220 @@
|
||||||
<template>
|
<template>
|
||||||
<main>
|
<main class="section">
|
||||||
|
<div class="column" style="float: left;">
|
||||||
|
<nav class="panel">
|
||||||
|
<p class="panel-heading">
|
||||||
|
{{ $t('marketplace.filter') }} ({{category}})
|
||||||
|
</p>
|
||||||
|
<div class="panel-block">
|
||||||
|
<p class="control has-icons-left">
|
||||||
|
<b-input v-model="search" type="text" :placeholder="$t('marketplace.search')"></b-input>
|
||||||
|
<span class="icon is-left">
|
||||||
|
<i class="fas fa-search" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="tabs">
|
||||||
|
<ul>
|
||||||
|
<router-link tag="li" :to="'/marketplace/hats'" exact><a>{{ $t('marketplace.hats') }}</a></router-link>
|
||||||
|
<router-link tag="li" :to="'/marketplace/faces'" exact><a>{{ $t('marketplace.faces') }}</a></router-link>
|
||||||
|
<router-link tag="li" :to="'/marketplace/shirts'" exact><a>{{ $t('marketplace.shirts') }}</a></router-link>
|
||||||
|
<router-link tag="li" :to="'/marketplace/pants'" exact><a>{{ $t('marketplace.pants') }}</a></router-link>
|
||||||
|
<router-link tag="li" :to="'/marketplace/collections'" exact><a>{{ $t('marketplace.collections') }}</a></router-link>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<a class="panel-block">
|
||||||
|
Recent
|
||||||
|
</a>
|
||||||
|
<a class="panel-block">
|
||||||
|
Most popular
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="columns is-multiline" v-if="!loading">
|
||||||
|
<div v-if="!items.length" class="column">
|
||||||
|
<NoItems type="marketplace items">
|
||||||
|
</NoItems>
|
||||||
|
</div>
|
||||||
|
<Pagination
|
||||||
|
class='columns is-multiline'
|
||||||
|
v-if='items.length'
|
||||||
|
:loading='loading'
|
||||||
|
:paginate="paginate"
|
||||||
|
@loadNext='getItems(false)'
|
||||||
|
>
|
||||||
|
<div class="column is-3" style="float: left;" v-for='(item) in items' :key='"marketplace-" + item.id'>
|
||||||
|
<router-link :to="'/m/' + item.id" class="subtitle">{{item.name}}</router-link>
|
||||||
|
<div class="box">
|
||||||
|
<img :src="'https://cdn.kaverti.com/marketplace/avatars/' + item.previewFile + '.png'" width="40%">
|
||||||
|
<div class="buttons is-centered is-center">
|
||||||
|
<b-button class="is-info" v-if="!item.saleEnabled">{{$t('user.inventoryTab.buyNow')}} <img style="vertical-align: middle" src="https://cdn.kaverti.com/icons/koins-white.svg" width="8%">{{item.price}}</b-button>
|
||||||
|
<b-button class="is-success" v-if="item.saleEnabled">{{$t('user.inventoryTab.buyNow')}} <img style="vertical-align: middle" src="https://cdn.kaverti.com/icons/koins-white.svg" width="12%">{{item.salePrice}} <b-tooltip class="is-success" :label="$t('user.inventoryTab.onSale')"><i class="fas fa-info-circle"></i></b-tooltip></b-button>
|
||||||
|
<b-button tag="router-link" :to="'/m/' + item.id" class="is-success">{{$t('marketplace.moreInfo')}}</b-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Pagination>
|
||||||
|
</div>
|
||||||
|
<div class="columns is-multiline" v-if="loading">
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div> <div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div> <div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div> <div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div> <div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="box">
|
||||||
|
<h1 class="title">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</h1>
|
||||||
|
<b-skeleton height="100px"></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
<script>
|
||||||
|
import AjaxErrorHandler from "../../assets/js/errorHandler";
|
||||||
|
import NoItems from "../components/NoItems"
|
||||||
|
import Pagination from "../components/Pagination"
|
||||||
|
export default {
|
||||||
|
name: 'Marketplace',
|
||||||
|
components: {
|
||||||
|
NoItems,
|
||||||
|
Pagination
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
items: [],
|
||||||
|
last: [],
|
||||||
|
search: '',
|
||||||
|
limit: 30,
|
||||||
|
loading: true,
|
||||||
|
paginate: true,
|
||||||
|
offset: 0,
|
||||||
|
nextURL: null,
|
||||||
|
category: this.$route.params.category
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
doSearch() {
|
||||||
|
this.items = []
|
||||||
|
this.loading = true
|
||||||
|
this.offset = 0
|
||||||
|
this.paginate = true
|
||||||
|
this.axios
|
||||||
|
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'marketplace/' + this.category + '?search=' + this.search + '&offset=' + this.offset)
|
||||||
|
.then(res => {
|
||||||
|
this.items = res.data.Items
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.loading = false
|
||||||
|
AjaxErrorHandler(this.$store)(e)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getItems (initial) {
|
||||||
|
this.loading = true
|
||||||
|
this.axios
|
||||||
|
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'marketplace/' + this.category + '?offset=' + this.offset)
|
||||||
|
.then(res => {
|
||||||
|
if(res.data.length < this.limit) {
|
||||||
|
this.offset = null;
|
||||||
|
} else {
|
||||||
|
this.offset+= this.limit;
|
||||||
|
}
|
||||||
|
if(!initial && !res.data.Items.length) {
|
||||||
|
this.paginate = false
|
||||||
|
}
|
||||||
|
if(initial) {
|
||||||
|
this.items = res.data.Items
|
||||||
|
} else {
|
||||||
|
this.items.push(...res.data.Items)
|
||||||
|
this.last = []
|
||||||
|
this.last = res.data.Items
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.loading = false
|
||||||
|
AjaxErrorHandler(this.$store)(e)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
search () {
|
||||||
|
this.doSearch()
|
||||||
|
},
|
||||||
|
$route () {
|
||||||
|
this.items = []
|
||||||
|
this.offset = 0
|
||||||
|
this.paginate = true
|
||||||
|
this.category = this.$route.params.category
|
||||||
|
this.getItems(true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getItems(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
111
src/views/MarketplaceItem.vue
Normal file
111
src/views/MarketplaceItem.vue
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
<template>
|
||||||
|
<main>
|
||||||
|
<div class="section">
|
||||||
|
<div class="columns" v-if="loading">
|
||||||
|
<div class="column is-4">
|
||||||
|
<h1 class="title has-text-centered"><b-skeleton></b-skeleton></h1>
|
||||||
|
<div class="box">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-7">
|
||||||
|
<h1 class="title has-text-centered"><b-skeleton></b-skeleton></h1>
|
||||||
|
<div class="box has-text-right">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</div>
|
||||||
|
<h1 class="title has-text-centered"><b-skeleton></b-skeleton></h1>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content">
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
<b-skeleton></b-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="columns" v-if="!loading">
|
||||||
|
<div class="column is-4">
|
||||||
|
<h1 class="title has-text-centered">{{item.name}}</h1>
|
||||||
|
<div class="box">
|
||||||
|
<img :src="'https://cdn.kaverti.com/marketplace/avatars/' + item.previewFile + '.png'">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-7">
|
||||||
|
<h1 class="title has-text-centered">{{$t('marketplaceItem.moreInfo')}}</h1>
|
||||||
|
<div class="box has-text-right">
|
||||||
|
<b-button class="is-info" v-if="!item.saleEnabled && !purchased">Buy now</b-button>
|
||||||
|
<b-button class="is-success" v-if="item.saleEnabled && !purchased">Buy now for discounted price</b-button>
|
||||||
|
<b-button disabled v-if="purchased">You own this item!</b-button>
|
||||||
|
<hr class="solid">
|
||||||
|
<p v-if="item.saleEnabled">{{$t('marketplaceItem.price')}}: <img style="vertical-align: middle" src="https://cdn.kaverti.com/icons/koins.svg" width="5%">{{item.salePrice}}</p>
|
||||||
|
<p v-if="item.saleEnabled">{{$t('marketplaceItem.originalPrice')}}: <img style="vertical-align: middle" src="https://cdn.kaverti.com/icons/koins.svg" width="5%">{{item.price}}</p>
|
||||||
|
<p v-if="!item.saleEnabled">{{$t('marketplaceItem.price')}}: <img style="vertical-align: middle" src="https://cdn.kaverti.com/icons/koins.svg" width="5%">{{item.price}}</p>
|
||||||
|
<p>Uploaded at: {{item.createdAt | formatDate()}}</p>
|
||||||
|
</div>
|
||||||
|
<h1 class="title has-text-centered">{{$t('marketplaceItem.creator')}}</h1>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-left">
|
||||||
|
<figure class="image is-48x48">
|
||||||
|
<img :src="'https://cdn.kaverti.com/user/avatars/headshot/default.png'" alt="Avatar Image">
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
<div class="media-content">
|
||||||
|
<router-link :to="'/u/' + item.User.username" class="title">{{item.User.username}}</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content" v-if="item.User.description">
|
||||||
|
{{item.User.description}}
|
||||||
|
</div>
|
||||||
|
<div class="content" v-if="!item.User.description">
|
||||||
|
{{$t('user.defaultDesc')}} {{item.User.username}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import AjaxErrorHandler from '../../assets/js/errorHandler'
|
||||||
|
export default {
|
||||||
|
name: 'MarketplaceItem',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
modifyUserModal: true,
|
||||||
|
loading: true,
|
||||||
|
item: {
|
||||||
|
name: "Loading",
|
||||||
|
description: "Loading",
|
||||||
|
price: 0,
|
||||||
|
previewFile: 'loading',
|
||||||
|
User: {
|
||||||
|
username: 'Loading'
|
||||||
|
},
|
||||||
|
createdAt: "2020-01-01T00:00:00.000Z"
|
||||||
|
},
|
||||||
|
purchased: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.axios
|
||||||
|
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `marketplace/view/${this.$route.params.id}`)
|
||||||
|
.then(res => this.item = res.data, this.loading = false)
|
||||||
|
.catch((e) => {
|
||||||
|
AjaxErrorHandler(this.$store)(e)
|
||||||
|
})
|
||||||
|
this.axios
|
||||||
|
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `marketplace/check/${this.$route.params.id}`)
|
||||||
|
.then(res => this.purchased = res.data.purchased)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -26,7 +26,7 @@
|
||||||
<div class="box limit">
|
<div class="box limit">
|
||||||
<div v-if="user.description">{{ $t('user.description') }}: {{user.description}}</div><br>
|
<div v-if="user.description">{{ $t('user.description') }}: {{user.description}}</div><br>
|
||||||
<div v-if="!user.description">{{$t('user.description')}}: {{$t('user.defaultDesc')}} {{user.username}}</div>
|
<div v-if="!user.description">{{$t('user.description')}}: {{$t('user.defaultDesc')}} {{user.username}}</div>
|
||||||
{{ $t('user.created') }}: {{user.createdAt}}<br>
|
{{ $t('user.created') }}: {{user.createdAt | formatDate()}}<br>
|
||||||
{{ $t('user.marketplace') }}:
|
{{ $t('user.marketplace') }}:
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
import AjaxErrorHandler from '../../assets/js/errorHandler'
|
import AjaxErrorHandler from '../../assets/js/errorHandler'
|
||||||
import Badges from '../components/Badges'
|
import Badges from '../components/Badges'
|
||||||
export default {
|
export default {
|
||||||
name: 'user',
|
name: 'User',
|
||||||
components: {
|
components: {
|
||||||
Badges
|
Badges
|
||||||
},
|
},
|
||||||
|
@ -313,7 +313,7 @@ export default {
|
||||||
return selectedIndex
|
return selectedIndex
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
mounted () {
|
||||||
this.resetFetchData()
|
this.resetFetchData()
|
||||||
this.selected = this.getIndexFromRoute(this.$route.path)
|
this.selected = this.getIndexFromRoute(this.$route.path)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,14 @@
|
||||||
<NoItems :connection="true" type="users">
|
<NoItems :connection="true" type="users">
|
||||||
</NoItems>
|
</NoItems>
|
||||||
</div>
|
</div>
|
||||||
|
<Pagination
|
||||||
|
key='user-row'
|
||||||
|
class='columns is-multiline'
|
||||||
|
v-if='users.length'
|
||||||
|
:loading='loading'
|
||||||
|
:paginate="paginate"
|
||||||
|
@loadNext='getUsers(false)'
|
||||||
|
>
|
||||||
<div class="column is-3" v-for='(user) in users' :key='"user-" + user.id'>
|
<div class="column is-3" v-for='(user) in users' :key='"user-" + user.id'>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<h1 class="title">{{user.username}} <Badges :username="user.username" :system="user.system" :hidden="user.hidden" :admin="user.admin" :booster="user.booster" :bot="user.bot"></Badges></h1>
|
<h1 class="title">{{user.username}} <Badges :username="user.username" :system="user.system" :hidden="user.hidden" :admin="user.admin" :booster="user.booster" :bot="user.bot"></Badges></h1>
|
||||||
|
@ -13,6 +21,7 @@
|
||||||
<b-button tag="router-link" :to='"/u/" + user.username' class="is-centered is-info">View Profile</b-button>
|
<b-button tag="router-link" :to='"/u/" + user.username' class="is-centered is-info">View Profile</b-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</Pagination>
|
||||||
</div>
|
</div>
|
||||||
<div class="columns is-multiline" v-if="loading">
|
<div class="columns is-multiline" v-if="loading">
|
||||||
<div class="column is-4">
|
<div class="column is-4">
|
||||||
|
@ -90,37 +99,58 @@
|
||||||
import AjaxErrorHandler from "../../assets/js/errorHandler";
|
import AjaxErrorHandler from "../../assets/js/errorHandler";
|
||||||
import Badges from "../components/Badges"
|
import Badges from "../components/Badges"
|
||||||
import NoItems from "../components/NoItems"
|
import NoItems from "../components/NoItems"
|
||||||
|
import Pagination from "../components/Pagination"
|
||||||
export default {
|
export default {
|
||||||
name: 'Users',
|
name: 'Users',
|
||||||
components: {
|
components: {
|
||||||
Badges,
|
Badges,
|
||||||
NoItems
|
NoItems,
|
||||||
|
Pagination
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
users: [],
|
users: [],
|
||||||
offset: 0,
|
offset: 0,
|
||||||
limit: 15,
|
paginate: true,
|
||||||
|
limit: 30,
|
||||||
loading: true
|
loading: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
methods: {
|
||||||
|
getUsers(initial) {
|
||||||
|
if(initial) {
|
||||||
|
this.users = []
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
this.offset = 0
|
||||||
|
this.paginate = true
|
||||||
|
}
|
||||||
this.axios
|
this.axios
|
||||||
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `user?offset=${this.offset};`)
|
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'user/' + '?offset=' + this.offset)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.users.push(...res.data);
|
if(res.data < this.limit) {
|
||||||
if(res.data.length < this.limit) {
|
|
||||||
this.offset = null;
|
this.offset = null;
|
||||||
} else {
|
} else {
|
||||||
this.offset+= this.limit;
|
this.offset+= this.limit;
|
||||||
}
|
}
|
||||||
|
if(!initial && !res.data.length) {
|
||||||
|
this.paginate = false
|
||||||
|
}
|
||||||
|
if(initial) {
|
||||||
|
this.users = res.data
|
||||||
|
} else {
|
||||||
|
this.users.push(...res.data)
|
||||||
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch((e) => {
|
||||||
|
this.loading = false
|
||||||
AjaxErrorHandler(this.$store)(e)
|
AjaxErrorHandler(this.$store)(e)
|
||||||
this.loading = false
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loading = true
|
||||||
|
this.getUsers()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -1,7 +1,7 @@
|
||||||
const Dotenv = require('dotenv-webpack');
|
const Dotenv = require('dotenv-webpack');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
devServer: {
|
devServer: {
|
||||||
proxy: 'http://localhost:23981'
|
proxy: 'http://localhost:23982'
|
||||||
},
|
},
|
||||||
|
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -8234,6 +8234,11 @@ lodash.templatesettings@^4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash._reinterpolate "^3.0.0"
|
lodash._reinterpolate "^3.0.0"
|
||||||
|
|
||||||
|
lodash.throttle@^4.1.1:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||||
|
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||||
|
|
||||||
lodash.transform@^4.6.0:
|
lodash.transform@^4.6.0:
|
||||||
version "4.6.0"
|
version "4.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.transform/-/lodash.transform-4.6.0.tgz#12306422f63324aed8483d3f38332b5f670547a0"
|
resolved "https://registry.yarnpkg.com/lodash.transform/-/lodash.transform-4.6.0.tgz#12306422f63324aed8483d3f38332b5f670547a0"
|
||||||
|
@ -12671,6 +12676,11 @@ vue-loader@^15.9.2:
|
||||||
vue-hot-reload-api "^2.3.0"
|
vue-hot-reload-api "^2.3.0"
|
||||||
vue-style-loader "^4.1.0"
|
vue-style-loader "^4.1.0"
|
||||||
|
|
||||||
|
vue-matomo@^3.14.0-0:
|
||||||
|
version "3.14.0-0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue-matomo/-/vue-matomo-3.14.0-0.tgz#f8e668c26ec1f2f7b4498f758edfb7c387259735"
|
||||||
|
integrity sha512-i1IkZGSXNY84zg1gVU8TOuaqajYDWQYl4Vs7M1mEb21cNhlMZKUxxgElvj+xmv7ytYUc/6ekZbxIS+y6W4qTMQ==
|
||||||
|
|
||||||
vue-router@^3.2.0:
|
vue-router@^3.2.0:
|
||||||
version "3.4.9"
|
version "3.4.9"
|
||||||
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.4.9.tgz#c016f42030ae2932f14e4748b39a1d9a0e250e66"
|
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.4.9.tgz#c016f42030ae2932f14e4748b39a1d9a0e250e66"
|
||||||
|
|
Loading…
Reference in a new issue