prerelease3

This commit is contained in:
Troplo 2021-01-28 19:25:45 +11:00
parent 62a7fcb2dc
commit 15ee3dc914
11 changed files with 117 additions and 173 deletions

View file

@ -155,11 +155,13 @@
<section class="modal-card-body has-text-centered"> <section class="modal-card-body has-text-centered">
<h1 class="subtitle">What's new in {{$store.state.client.clientVersion}}?</h1> <h1 class="subtitle">What's new in {{$store.state.client.clientVersion}}?</h1>
<ul> <ul>
<li>Marketplace</li> <li>Improved pagination</li>
<li>Pagination Component</li> <li>Add friend page</li>
<li>Fix crashing when token is null</li> <li>Remove koin icon in buttons</li>
<li>User list pagination</li> <li>Add global wall</li>
<li>Marketplace Item</li> <li>Add blog</li>
<li>Add new friend count in Navbar User Menu</li>
<li>Add developmental forum</li>
</ul> </ul>
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
@ -314,7 +316,7 @@
</template> </template>
<template #end> <template #end>
<b-navbar-item v-if="$store.state.user.username && !loading" @click="dailyReward"> <b-navbar-item v-if="$store.state.user.username && !loading" @click="dailyReward(true)">
<img src="https://cdn.kaverti.com/icons/koins.svg">{{$store.state.user.koins}} <img src="https://cdn.kaverti.com/icons/koins.svg">{{$store.state.user.koins}}
</b-navbar-item> </b-navbar-item>
<div v-if="!loading"> <div v-if="!loading">
@ -337,7 +339,7 @@
<b-navbar-item tag="router-link" to="/creations">{{$t('navbar.user.creations')}}</b-navbar-item> <b-navbar-item tag="router-link" to="/creations">{{$t('navbar.user.creations')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/downloads">{{$t('navbar.user.downloads')}}</b-navbar-item> <b-navbar-item tag="router-link" to="/downloads">{{$t('navbar.user.downloads')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/admin" v-if="$store.state.user.admin">{{$t('navbar.user.admin')}}</b-navbar-item> <b-navbar-item tag="router-link" to="/admin" v-if="$store.state.user.admin">{{$t('navbar.user.admin')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/friends"><b-tag class="is-info" rounded> 1</b-tag>&nbsp; {{$t('navbar.user.friends')}}</b-navbar-item> <b-navbar-item tag="router-link" to="/friends"><b-tag class="is-info" rounded v-if="friendCount > 0"> {{ friendCount }}</b-tag>&nbsp;&nbsp;&nbsp;&nbsp;<p>{{$t('navbar.user.friends')}}</p></b-navbar-item>
<b-navbar-item @click="logout()">{{$t('navbar.user.logout')}}</b-navbar-item> <b-navbar-item @click="logout()">{{$t('navbar.user.logout')}}</b-navbar-item>
</b-navbar-dropdown> </b-navbar-dropdown>
<b-navbar-item v-if="loading"> <b-navbar-item v-if="loading">
@ -657,13 +659,15 @@ export default {
this.$buefy.snackbar.open(`WARNING: You have fake authenticated, you do not have authenticated API access. Use for debug purposes only.`) this.$buefy.snackbar.open(`WARNING: You have fake authenticated, you do not have authenticated API access. Use for debug purposes only.`)
Object.assign(axios.defaults, {headers: {Authorization: this.$store.state.user.token}}) Object.assign(axios.defaults, {headers: {Authorization: this.$store.state.user.token}})
}, },
dailyReward() { dailyReward(notify) {
this.axios.get( this.axios.get(
process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/reward' process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/reward'
).then(res => { ).then(res => {
this.$store.commit('setKoins', res.data.koins) this.$store.commit('setKoins', res.data.koins)
}).catch(e => { }).catch(e => {
if(notify) {
AjaxErrorHandler(this.$store)(e) AjaxErrorHandler(this.$store)(e)
}
}) })
}, },
getInfo() { getInfo() {
@ -723,17 +727,14 @@ export default {
this.loading = false this.loading = false
console.log(this.getBannerId()) console.log(this.getBannerId())
}) })
if(this.$store.state.username) { this.$nextTick(() => {
this.dailyReward() this.dailyReward(false)
this.showUpdate()
this.axios.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/getAllPendingCanAccept') this.axios.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/getAllPendingCanAccept')
.then(res => { .then(res => {
this.friendCount = res.data.count this.friendCount = res.data.count
}).catch(() => {
this.$buefy.snackbar.open({message: this.$t('errors.authFail'), type: 'is-warning'})
this.loading = false
}) })
} })
this.showUpdate()
} }
} }
</script> </script>

View file

@ -1,5 +1,5 @@
<template> <template>
<div class='pagination'> <div>
<slot></slot> <slot></slot>
</div> </div>
</template> </template>

View file

@ -113,7 +113,8 @@
"dev": { "dev": {
"title": "Developer Options", "title": "Developer Options",
"fakeUser": "Fake User Auth", "fakeUser": "Fake User Auth",
"debug": "Debug Page" "debug": "Debug Page",
"brokenRoute": "Enable broken (disabled) routes"
}, },
"user": { "user": {
"title": "Unknown", "title": "Unknown",
@ -133,7 +134,8 @@
"discord": "Discord", "discord": "Discord",
"roadmap": "Roadmap", "roadmap": "Roadmap",
"documentation": "API Docs", "documentation": "API Docs",
"stats": "Kaverti Stats" "stats": "Kaverti Stats",
"blog": "Kaverti Blog"
}, },
"register": "Register", "register": "Register",
"login": "Login" "login": "Login"
@ -287,6 +289,11 @@
"originalPrice": "Original Price", "originalPrice": "Original Price",
"creator": "The Creator" "creator": "The Creator"
}, },
"friends": {
"pendingCanAccept": "Requests to you",
"pending": "Requests from you",
"accepted": "Accepted requests"
},
"currency": "Koins", "currency": "Koins",
"close": "Close", "close": "Close",
"tos": "Terms of Service", "tos": "Terms of Service",

View file

@ -67,6 +67,11 @@ const routes = [
name: 'Forums', name: 'Forums',
component: route('Forums') component: route('Forums')
}, },
{
path: '/forums/create',
name: 'ForumThreadCreate',
component: route('ForumThreadCreate')
},
{ {
path: '/forums/:category', path: '/forums/:category',
name: 'Forums', name: 'Forums',
@ -77,11 +82,6 @@ const routes = [
name: 'ForumThread', name: 'ForumThread',
component: route('ForumThread') component: route('ForumThread')
}, },
{
path: '/forums/create',
name: 'ForumThreadCreate',
component: route('ForumThreadCreate')
},
{ {
path: '/roadmap', path: '/roadmap',
name: 'Roadmap', name: 'Roadmap',

View file

@ -8,7 +8,7 @@ export default new Vuex.Store({
wind: false, wind: false,
enableBrokenRoutes: false, enableBrokenRoutes: false,
client: { client: {
clientVersion: '1.0.0-prerelease2', clientVersion: '1.0.0-prerelease3',
latestClientVersion: '', latestClientVersion: '',
latestAPIVersion: '', latestAPIVersion: '',
bannerText: '', bannerText: '',

View file

@ -8,6 +8,7 @@
<img :src="'https://cdn.kaverti.com/user/avatars/headshot/' + post.User.picture + '.png'"> <img :src="'https://cdn.kaverti.com/user/avatars/headshot/' + post.User.picture + '.png'">
</div> </div>
<div class="media-content"> <div class="media-content">
<h2 class="subtitle">{{post.User.username}}</h2>
<div v-html="post.content"></div> <div v-html="post.content"></div>
</div> </div>
</div> </div>

View file

@ -1,5 +1,6 @@
<template> <template>
<main class="section"> <main>
<div class="section">
<h1 class="title has-text-centered">{{name}} ({{count}})</h1> <h1 class="title has-text-centered">{{name}} ({{count}})</h1>
<div class="tabs is-centered"> <div class="tabs is-centered">
<ul> <ul>
@ -8,15 +9,38 @@
<router-link tag="li" :to="'/friends/pending'" exact><a>{{ $t('friends.pending') }}</a></router-link> <router-link tag="li" :to="'/friends/pending'" exact><a>{{ $t('friends.pending') }}</a></router-link>
</ul> </ul>
</div> </div>
<div class="columns is-multiline"> <div class="columns is-multiline" v-if="friends.length && !loading">
<div class="column is-3 has-text-centered" v-for='(friend) in friends' :key='"friend-" + friend.id'> <div class="column is-3 has-text-centered" v-for='(friend) in friends' :key='"friend-" + friend.id'>
<h1 class="title has-text-centered">{{friend.friend2.username}}</h1> <h1 class="title has-text-centered">{{friend.friend2.username}}</h1>
<div class="box"> <div class="box">
<img :src="'https://cdn.kaverti.com/user/avatars/full/' + friend.friend2.picture + '.png'"><br> <img :src="'https://cdn.kaverti.com/user/avatars/full/' + friend.friend2.picture + '.png'"><br>
<b-button class="is-warning has-text-centered is-centered is-center" v-if="friend.type === 'pending'"><i class="fas fa-minus"></i>&nbsp;Cancel Friend Request</b-button> <div class="buttons">
<b-button class="is-warning has-text-centered is-centered is-center" v-if="friend.type === 'pendingCanAccept'"><i class="fas fa-minus"></i>&nbsp;Deny Friend Request</b-button> <b-button @click="removeFriend(friend)" class="is-warning has-text-centered is-centered is-center" v-if="friend.type === 'pending'"><i class="fas fa-minus"></i>&nbsp;Cancel Friend Request</b-button>
<b-button class="is-success has-text-centered is-centered is-center" v-if="friend.type === 'pendingCanAccept'"><i class="fas fa-plus"></i>&nbsp;Accept Friend Request</b-button> <b-button @click="removeFriend(friend)" class="is-warning has-text-centered is-centered is-center" v-if="friend.type === 'pendingCanAccept'"><i class="fas fa-minus"></i>&nbsp;Deny Friend Request</b-button>
<b-button class="is-danger has-text-centered is-centered is-center" v-if="friend.type === 'accepted'"><i class="fas fa-minus"></i>&nbsp;Remove Friend</b-button> <b-button @click="doRelationshipAccept(friend)" class="is-success has-text-centered is-centered is-center" v-if="friend.type === 'pendingCanAccept'"><i class="fas fa-plus"></i>&nbsp;Accept Friend Request</b-button>
<b-button @click="removeFriend(friend)" class="is-danger has-text-centered is-centered is-center" v-if="friend.type === 'accepted'"><i class="fas fa-minus"></i>&nbsp;Remove Friend</b-button>
</div>
</div>
</div>
</div>
<div class="section" v-if="!friends.length && !loading">
<NoItems type="friends"></NoItems>
</div>
<div class="section columns" v-if="loading">
<div class="column">
<div class="box">
<b-skeleton></b-skeleton>
</div>
</div>
<div class="column">
<div class="box">
<b-skeleton></b-skeleton>
</div>
</div>
<div class="column">
<div class="box">
<b-skeleton></b-skeleton>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -24,9 +48,12 @@
</template> </template>
<script> <script>
import AjaxErrorHandler from "../../assets/js/errorHandler"; import AjaxErrorHandler from "../../assets/js/errorHandler";
import NoItems from "../components/NoItems"
export default { export default {
name: 'Friends', name: 'Friends',
components: {
NoItems
},
data() { data() {
return { return {
friends: [], friends: [],
@ -55,126 +82,32 @@ export default {
} }
}, },
methods: { methods: {
removeFriend (username) { removeFriend (user) {
this.axios this.axios
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/remove', { .put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/remove', {
friend: username friend: user.friend2.username
}) })
.then(() => { .then(() => {
this.getItems() this.getItems()
}) })
.catch(e => { .catch(e => {
this.refreshFriend() this.getItems()
this.description.loading = false
AjaxErrorHandler(this.$store)(e, error => {
this.description.error = error.message
})
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `relationships/get/${this.$route.params.username}`)
.then(res => this.relationship = res.data, this.refreshFriend())
.catch(e => {
this.refreshFriend()
let invalidId = e.response.data.errors.find(error => {
return error.name === 'accountDoesNotExist'
})
if(invalidId) {
this.$store.commit('set404Page', true)
} else {
AjaxErrorHandler(this.$store)(e) AjaxErrorHandler(this.$store)(e)
}
})
}) })
}, },
doRelationship () { doRelationshipAccept (user) {
this.axios
.post(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/send', {
friend: this.$route.params.username
})
.then(() => {
this.refreshFriend()
this.description.loading = false
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `relationships/get/${this.$route.params.username}`)
.then(res => this.relationship = res.data)
.catch(e => {
let invalidId = e.response.data.errors.find(error => {
return error.name === 'accountDoesNotExist'
})
if(invalidId) {
this.$store.commit('set404Page', true)
} else {
AjaxErrorHandler(this.$store)(e)
}
})
})
.catch(e => {
this.refreshFriend()
this.description.loading = false
AjaxErrorHandler(this.$store)(e)
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `relationships/get/${this.$route.params.username}`)
.then(res => this.relationship = res.data)
.catch(e => {
let invalidId = e.response.data.errors.find(error => {
return error.name === 'accountDoesNotExist'
})
if(invalidId) {
this.$store.commit('set404Page', true)
} else {
AjaxErrorHandler(this.$store)(e)
}
})
})
},
doRelationshipAccept () {
this.axios this.axios
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/accept', { .put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/accept', {
friend: this.$route.params.username friend: user.friend2.username
}) })
.then(() => { .then(() => {
this.refreshFriend() this.getItems()
this.description.loading = false
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `relationships/get/${this.$route.params.username}`)
.then(res => this.relationship = res.data)
.catch(e => {
let invalidId = e.response.data.errors.find(error => {
return error.name === 'accountDoesNotExist'
}) })
.catch(e => {
this.getItems()
if(invalidId) {
this.$store.commit('set404Page', true)
} else {
AjaxErrorHandler(this.$store)(e) AjaxErrorHandler(this.$store)(e)
}
})
})
.catch(e => {
this.refreshFriend()
this.description.loading = false
AjaxErrorHandler(this.$store)(e, error => {
this.description.error = error.message
})
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `relationships/get/${this.$route.params.username}`)
.then(res => this.relationship = res.data)
.catch(e => {
let invalidId = e.response.data.errors.find(error => {
return error.name === 'accountDoesNotExist'
})
if(invalidId) {
this.$store.commit('set404Page', true)
} else {
AjaxErrorHandler(this.$store)(e)
}
})
}) })
}, },
getItems () { getItems () {

View file

@ -43,14 +43,13 @@
:paginate="paginate" :paginate="paginate"
@loadNext='getItems(false)' @loadNext='getItems(false)'
> >
<div class="column is-3" style="float: left;" v-for='(item) in items' :key='"marketplace-" + item.id'> <div class="column is-3 has-text-centered" style="float: left;" v-for='(item) in items' :key='"marketplace-" + item.id'>
<router-link :to="'/m/' + item.id" class="subtitle has-text-centered">{{item.name}}</router-link>
<div class="box"> <div class="box">
<router-link :to="'/m/' + item.id" class="subtitle">{{item.name}}</router-link>
<img :src="'https://cdn.kaverti.com/marketplace/avatars/' + item.previewFile + '.png'" width="40%"> <img :src="'https://cdn.kaverti.com/marketplace/avatars/' + item.previewFile + '.png'" width="40%">
<div class="buttons is-centered is-center"> <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-info" v-if="!item.saleEnabled">{{$t('user.inventoryTab.buyNow')}} {{item.price}} Koins</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 class="is-success" v-if="item.saleEnabled">{{$t('user.inventoryTab.buyNow')}} {{item.salePrice}} Koins <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> </div>
</div> </div>

View file

@ -30,11 +30,14 @@
</div> </div>
</div> </div>
<div class="columns" v-if="!loading"> <div class="columns" v-if="!loading">
<div class="column is-4"> <div class="column is-4 has-text-centered">
<h1 class="title has-text-centered">{{item.name}}</h1> <h1 class="title has-text-centered">{{item.name}}</h1>
<div class="box"> <div class="box">
<img :src="'https://cdn.kaverti.com/marketplace/avatars/' + item.previewFile + '.png'"> <img width=50% :src="'https://cdn.kaverti.com/marketplace/avatars/' + item.previewFile + '.png'">
</div> </div>
<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>
</div> </div>
<div class="column is-7"> <div class="column is-7">
<h1 class="title has-text-centered">{{$t('marketplaceItem.moreInfo')}}</h1> <h1 class="title has-text-centered">{{$t('marketplaceItem.moreInfo')}}</h1>
@ -43,9 +46,9 @@
<b-button class="is-success" v-if="item.saleEnabled && !purchased">Buy now for discounted price</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> <b-button disabled v-if="purchased">You own this item!</b-button>
<hr class="solid"> <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.price')}}: {{item.salePrice}} Koins</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.originalPrice')}}: {{item.price}} Koins</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 v-if="!item.saleEnabled">{{$t('marketplaceItem.price')}}: {{item.price}} Koins</p>
<p>Uploaded at: {{item.createdAt | formatDate()}}</p> <p>Uploaded at: {{item.createdAt | formatDate()}}</p>
</div> </div>
<h1 class="title has-text-centered">{{$t('marketplaceItem.creator')}}</h1> <h1 class="title has-text-centered">{{$t('marketplaceItem.creator')}}</h1>

View file

@ -10,7 +10,7 @@
<div class="column is-4 is-vcentered has-text-centered"> <div class="column is-4 is-vcentered has-text-centered">
<h1 class="title">{{user.username}}&nbsp;<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}}&nbsp;<Badges :username="user.username" :system="user.system" :hidden="user.hidden" :admin="user.admin" :booster="user.booster" :bot="user.bot"></Badges></h1>
<div class="box"> <div class="box">
<img :src="'https://cdn.kaverti.com/user/avatars/full/' + $store.state.user.avatar + '.png'" :alt="$store.state.user.username + '\'s avatar'" width=25%> <img :src="'https://cdn.kaverti.com/user/avatars/full/' + user.picture + '.png'" :alt="user.username + '\'s avatar'" width=25%>
</div> </div>
<div class="buttons is-centered"> <div class="buttons is-centered">
<b-button @click="doRelationship" class="is-success" v-if="relationships.type === 'notFriends' && user.username !== $store.state.user.username"><i class="fas fa-plus"></i> &nbsp;{{$t('relationships.notFriends')}}</b-button> <b-button @click="doRelationship" class="is-success" v-if="relationships.type === 'notFriends' && user.username !== $store.state.user.username"><i class="fas fa-plus"></i> &nbsp;{{$t('relationships.notFriends')}}</b-button>

View file

@ -8,8 +8,8 @@
<h1 class="subtitle">{{item.Item.name}}</h1> <h1 class="subtitle">{{item.Item.name}}</h1>
<div class="box"> <div class="box">
<img v-if="item.Item.approved" width="128px" height="128px" :src="'https://cdn.kaverti.com/marketplace/avatars/' + item.Item.previewFile + '.png'"> <img v-if="item.Item.approved" width="128px" height="128px" :src="'https://cdn.kaverti.com/marketplace/avatars/' + item.Item.previewFile + '.png'">
<b-button class="is-info" v-if="!item.Item.offSale && !item.Item.saleEnabled">{{$t('user.inventoryTab.buyNow')}} <img style="vertical-align: middle" src="https://cdn.kaverti.com/icons/koins-white.svg" width="12%">{{item.Item.price}}</b-button> <b-button class="is-info" v-if="!item.Item.offSale && !item.Item.saleEnabled">{{$t('user.inventoryTab.buyNow')}} {{item.Item.price}} Koins</b-button>
<b-button class="is-success" v-if="item.Item.saleEnabled">{{$t('user.inventoryTab.buyNow')}} <img style="vertical-align: middle" src="https://cdn.kaverti.com/icons/koins-white.svg" width="12%">{{item.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 class="is-success" v-if="item.Item.saleEnabled">{{$t('user.inventoryTab.buyNow')}} {{item.Item.salePrice}} Koins <b-tooltip class="is-success" :label="$t('user.inventoryTab.onSale')"><i class="fas fa-info-circle"></i></b-tooltip></b-button>
<b-button disabled v-if="item.Item.offSale">{{$t('user.inventoryTab.unavailable')}}</b-button> <b-button disabled v-if="item.Item.offSale">{{$t('user.inventoryTab.unavailable')}}</b-button>
</div> </div>
</div> </div>