awedasdads

This commit is contained in:
Troplo 2021-01-17 00:20:05 +11:00
parent 4d744d92c4
commit 33112cb7ae
18 changed files with 12668 additions and 2935 deletions

62
assets/js/linkExpander.js Normal file
View file

@ -0,0 +1,62 @@
let cache = {};
export default {
install (Vue) {
//Takes a HTML string then parses it and replaces appropriate
//links with the relevant expansion
//Returns a callback with the 'expanded' HTML string
Vue.prototype.$linkExpander = function (HTML, cb) {
let completed = 0;
let completedAPICall = () => {
completed++;
if(completed === links.length) {
cb(parsed.innerHTML);
}
};
let replaceLink = (html, link) => {
if(html.length) {
let div = document.createElement('div');
div.innerHTML = html;
link.parentNode.replaceChild(
div.children[0],
link
);
}
completedAPICall();
};
let parsed = document.createElement('div');
parsed.innerHTML = HTML;
let links = Array
.from(parsed.querySelectorAll('p a[href]'))
.filter(a => {
return (
a.parentNode.parentNode === parsed &&
a.parentNode.childNodes.length === 1 &&
a.innerHTML === a.href
)
});
links.forEach(link => {
let cached = cache[link.href];
if(cached) {
replaceLink(cached, link);
} else {
Vue.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/link_preview?url=' + link.href)
.then(res => {
cache[link.href] = res.data;
replaceLink(res.data, link);
})
.catch(completedAPICall);
}
})
}
}
}

View file

@ -6,7 +6,7 @@
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build",
"lint": "vue-cli-service lint", "lint": "vue-cli-service lint",
"i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'" "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales 'src/locales/**/*.json'"
}, },
"dependencies": { "dependencies": {
"@vue/cli": "^4.5.10", "@vue/cli": "^4.5.10",

View file

@ -68,6 +68,75 @@
</div> </div>
</form> </form>
</b-modal> </b-modal>
<b-modal :active="settingsModal" @update:active="value => settingsModal = value" :width="640" scroll="keep">
<form>
<div class="modal-card" style="width: auto">
<header class="modal-card-head">
<p class="modal-card-title">{{ $t('settings.title') }}</p>
<button
type="button"
class="delete"
@click="loginModal = false"/>
</header>
<section class="modal-card-body">
<b-tabs position="is-centered" class="block">
<b-tab-item :label="$t('settings.general.title')">
<h1 class="title">{{$t('settings.general.title')}}</h1>
<div>
<h1 class="subtitle">{{$t('settings.general.about')}}</h1>
<h4>
{{ $t('settings.general.description') }}
</h4>
<b-input type="textarea"
:placeholder="$t('settings.general.hi') + ' ' + $store.state.user.username"
maxlength="256"
v-model='settings.general.description.value'
:error='settings.general.description.error'
></b-input>
<b-button
class='button is-info'
:loading='settings.general.description.loading'
@click='fakeUser()'
>
{{$t('settings.general.saveDesc')}}
</b-button>
</div>
<div>
<h2>{{$t('settings.general.preferences')}}</h2>
<b-switch class="is-info" v-model="settings.general.preferences.developerMode">{{$t('settings.general.devMode')}}</b-switch><br>
<b-button
class='button is-info'
:loading='settings.general.preferences.loading'
@click='fakeUser()'
>
{{$t('settings.general.savePref')}}
</b-button>
</div>
</b-tab-item>
<b-tab-item :label="$t('settings.security.title')">
Debug
</b-tab-item>
<b-tab-item :label="$t('settings.privacy.title')">
Debug
</b-tab-item>
<b-tab-item :label="$t('settings.experiments.title')">
Debug
</b-tab-item>
<b-tab-item :label="$t('settings.about.title')">
<div>
<center>
<img src="https://cdn.kaverti.com/icon.png" width="10%">
<h1>Kaverti v{{this.$store.state.client.clientVersion}}</h1>
<p>Latest client version: v{{this.$store.state.client.latestClientVersion}}</p>
<p>API version: v{{this.$store.state.client.latestAPIVersion}}</p>
</center>
</div>
</b-tab-item>
</b-tabs>
</section>
</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">
@ -145,16 +214,19 @@
</b-navbar-item> </b-navbar-item>
</template> </template>
<template #start> <template #start>
<b-navbar-item href="#"> <b-navbar-item tag="router-link" to="/">
{{$t('navbar.home')}} {{$t('navbar.home')}}
</b-navbar-item> </b-navbar-item>
<b-navbar-item href="#"> <b-navbar-item tag="router-link" to="/marketplace">
{{$t('navbar.marketplace')}} {{$t('navbar.marketplace')}}
</b-navbar-item> </b-navbar-item>
<b-navbar-item href="#"> <b-navbar-item tag="router-link" to="/users">
{{$t('navbar.users')}}
</b-navbar-item>
<b-navbar-item tag="router-link" to="/teams">
{{$t('navbar.teams')}} {{$t('navbar.teams')}}
</b-navbar-item> </b-navbar-item>
<b-navbar-item href="#"> <b-navbar-item tag="router-link" to="/games">
{{$t('navbar.games')}} {{$t('navbar.games')}}
</b-navbar-item> </b-navbar-item>
<div v-if="$store.state.debug" class="navbar-item has-dropdown is-hoverable is-info"> <div v-if="$store.state.debug" class="navbar-item has-dropdown is-hoverable is-info">
@ -166,9 +238,25 @@
<b-navbar-item @click="fakeUser()">{{$t('navbar.dev.fakeUser')}}</b-navbar-item> <b-navbar-item @click="fakeUser()">{{$t('navbar.dev.fakeUser')}}</b-navbar-item>
</div> </div>
</div> </div>
<div v-if="$store.state.debug" class="navbar-item has-dropdown is-hoverable is-info">
<a class="navbar-link">
<p>{{$t('navbar.more.title')}}</p>
</a>
<div class="navbar-dropdown">
<b-navbar-item tag="a" href="https://twitter.com/Kaverti">{{$t('navbar.more.twitter')}}</b-navbar-item>
<b-navbar-item tag="a" href="https://discord.gg/Q3HAWFdBPK">{{$t('navbar.more.discord')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/roadmap">{{$t('navbar.more.roadmap')}}</b-navbar-item>
<b-navbar-item tag="a" href="soon">{{$t('navbar.more.documentation')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/downloads">{{$t('navbar.downloads')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/stats">{{$t('navbar.more.stats')}}</b-navbar-item>
</div>
</div>
</template> </template>
<template #end> <template #end>
<b-navbar-item v-if="$store.state.user.username">
{{$store.state.user.koins}} {{$t('currency')}}
</b-navbar-item>
<div v-if="!loading"> <div v-if="!loading">
<b-navbar-item v-if="!$store.state.user.username" tag="div"> <b-navbar-item v-if="!$store.state.user.username" tag="div">
<div class="buttons"> <div class="buttons">
@ -180,14 +268,14 @@
</b-button> </b-button>
</div> </div>
</b-navbar-item> </b-navbar-item>
<b-navbar-item v-if="$store.state.user.username"> <b-navbar-item v-if="$store.state.user.username">
<div class="navbar-item has-dropdown is-hoverable is-info"> <div class="navbar-item has-dropdown is-hoverable is-info">
<a class="navbar-link"> <a class="navbar-link">
<p>{{$store.state.user.username}}</p> <p>{{$store.state.user.username}}</p>
</a> </a>
<div class="navbar-dropdown"> <div class="navbar-dropdown">
<b-navbar-item tag="router-link" :to="'/u/' + $store.state.user.username">{{$t('navbar.user.profile')}}</b-navbar-item> <b-navbar-item tag="router-link" :to="'/u/' + $store.state.user.username">{{$t('navbar.user.profile')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/settings">{{$t('navbar.user.settings')}}</b-navbar-item> <b-navbar-item @click="settingsModal = true">{{$t('navbar.user.settings')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/transactions">{{$t('navbar.user.transactions')}}</b-navbar-item> <b-navbar-item tag="router-link" to="/transactions">{{$t('navbar.user.transactions')}}</b-navbar-item>
<b-navbar-item tag="router-link" to="/character">{{$t('navbar.user.avatar')}}</b-navbar-item> <b-navbar-item tag="router-link" to="/character">{{$t('navbar.user.avatar')}}</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="/creations">{{$t('navbar.user.creations')}}</b-navbar-item>
@ -218,6 +306,89 @@ export default {
loginModal: false, loginModal: false,
registerModal: false, registerModal: false,
loading: true, loading: true,
settingsModal: false,
settings: {
tab: 0,
general: {
description: {
value: '',
loading: false,
error: ''
},
preferences: {
theme: '',
developerMode: '',
loading: false,
error: ''
},
},
privacy: {
wall: false,
loading: false
},
experiments: {
theme: 'light',
loading: false,
error: '',
relationships: false,
wall: false,
marketplace: false,
teams: false,
newsettings: true,
corrupt: false,
local: []
},
account: {
showLogoutModal: false,
password: {
loading: false,
current: '',
new: '',
errors: {
'new password': '',
'current password': ''
}
},
email: {
loading: false,
loadingChange: false,
currentPassword: '',
new: '',
errors: {
'new password': '',
'email current password': ''
}
},
username: {username: '',
password: '',
errors: {
'username': '',
'password': '',
},
loading: false,
},
deleteAcc: {
loading: false,
password: '',
errors: {
'current password': ''
}
},
totp: {loading: false
},
deleteAccountLoading: false,
invalidateSessionLoading: false,
emailCheckDelete: false,
showLoginModal: false
}
},
login: { login: {
username: '', username: '',
password: '', password: '',

68
src/components/Post.vue Normal file
View file

@ -0,0 +1,68 @@
<template>
<div class="post">
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-content">
<p class="title is-4">{{post.Thread.name | truncateMid(50)}}</p>
<p class="subtitle is-6">{{username}}</p>
</div>
</div>
</div>
<div class="content">
<div tabindex='-1'
class='post__content'
v-html='postContentHTML'
@mouseup='setShowQuote'
@blur='showQuote = false'
></div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ThreadPost',
props: [
'post',
'highlight',
'showReply',
'showThread',
'showSelect',
'clickForPost',
'allowQuote'
],
data() {
let post = this.post
return {
hover: false,
showShareModal: false,
showReportPostModal: false,
postURL: `${location.origin}/p/${post.id}`,
selected: false,
showQuote: false,
quoteX: 0,
quoteY: 0,
quoteSelection: '',
postContentHTML: post.content
}
},
computed: {
username () {
if(this.post.User) {
return this.post.User.username
} else {
return '[deleted]'}
},
showActions () {
return this.hover || this.showShareModal || this.showReportPostModal
}
},
mounted () {
this.$linkExpander(this.post.content, v => this.postContentHTML = v);
}
}
</script>

View file

@ -125,6 +125,14 @@
"settings": "Settings", "settings": "Settings",
"logout": "Logout" "logout": "Logout"
}, },
"more": {
"title": "More",
"twitter": "Twitter",
"discord": "Discord",
"roadmap": "Roadmap",
"documentation": "API Docs",
"stats": "Kaverti Stats"
},
"register": "Register", "register": "Register",
"login": "Login" "login": "Login"
}, },
@ -150,6 +158,38 @@
"disableDebug": "Debug mode disabled, you will no longer have access to development features until you refresh.", "disableDebug": "Debug mode disabled, you will no longer have access to development features until you refresh.",
"authSuccess": "Request successful, your token is valid, and the Kaverti server instance is running correctly." "authSuccess": "Request successful, your token is valid, and the Kaverti server instance is running correctly."
}, },
"user": {
"title": "Loading",
"about": "About",
"more": "More of",
"posts": "Posts",
"threads": "Threads",
"inventory": "Inventory",
"awards": "Awards",
"items": "Items",
"wall": "User Wall",
"description": "Description",
"created": "Registered at"
},
"stats": {
"title": "Stats",
"users": "Registered users",
"purchased": "Purchased items",
"items": "Uploaded items",
"posts": "Forum posts",
"threads": "Threads",
"teams": "Teams"
},
"settings": {
"title": "User Settings",
"general": {
"title": "General"
},
"security": {
"title": "Security"
}
},
"currency": "Koins",
"close": "Close", "close": "Close",
"tos": "Terms of Service", "tos": "Terms of Service",
"gotIt": "Got it!", "gotIt": "Got it!",

View file

@ -1,4 +1,11 @@
{ {
"404": {
"title": "systemctl start httpd??",
"text": "Error 521 Ray ID: 4f3226667865dc3b how to fix",
"quoteText": "There is currently 2900 WIND quotes available",
"windQuote": "without https works",
"home": "£1m"
},
"login": { "login": {
"title": "dont tell anyone the new domain", "title": "dont tell anyone the new domain",
"login": "im never firing you btw your my best friend xzd xd", "login": "im never firing you btw your my best friend xzd xd",
@ -17,14 +24,99 @@
"login": "can i get my twitter handle back lol", "login": "can i get my twitter handle back lol",
"agree": "Price has been reduced to £10 " "agree": "Price has been reduced to £10 "
}, },
"teams": {
"createTeam": "Create Team",
"joinTeam": "Join Team",
"join": "Join",
"invite": "Invite",
"viewPermissions": "View role permissions",
"devBanner": "Teams are currently in development, expect missing features.",
"view": "View",
"viewTeam": "View Team",
"memberRoles": "Members and Roles",
"members": "Members",
"roles": "Roles",
"items": "Created Items",
"foundedAt": "Team was founded at",
"teamWall": "Team Wall",
"teamWallText": "'s Team Wall",
"verified": "Verified Team",
"admin": {
"text": "Team Administration",
"nav": {
"general": "General",
"roles": "Roles",
"members": "Members",
"privacy": "Privacy",
"invites": "Invites",
"forum": "Forum",
"verification": "Verification"
},
"general": {
"title": "General",
"name": "Name",
"description": "Description",
"saveTeam": "Save Team",
"modifyPicture": "Modify Team avatar"
},
"roles": {
"title": "Roles",
"addRole": "Add Role",
"saveOrder": "Save role order",
"modifying": "Modifying",
"name": "Chosen role name",
"permissions": "Permissions",
"creating": "Creating a role"
},
"members": {
"title": "Members",
"modifyRoles": "Modify user roles",
"removeAllRoles": "Remove all roles from user"
},
"privacy": {
"title": "Team Privacy",
"teamWall": "Opt out of team walls",
"disallowForum": "Disallow anyone from viewing/creating on your Team Forum"
},
"invites": {
"title": "Invites",
"code": "Code",
"uses": "Uses",
"maxUses": "Max Uses",
"createdBy": "Created by",
"date": "Date",
"delete": "Delete selected",
"generate": "Generate invite"
},
"invite": {
"title": "Invite people to",
"amountUses": "Amount of uses (0 is Unlimited)",
"role": "Please select a role for the user to be auto assigned (optional)",
"refresh": "Refresh",
"inviteURL": "Invite URL",
"domain": "https://kaverti.com/invite/"
}
},
"permissionTypes": {
"inviteUsers": "Invite users",
"administrator": "Administrator",
"modifyRoles": "Modify roles/permissions/users",
"modifyTeamSettings": "Modify team settings",
"teamForum": "Modify team forum configuration",
"forumModerator": "Forum moderation permissions",
"forumAdmin": "Forum administrator",
"submitMarketplace": "Submit Marketplace items",
"priorityValue": "Set priority value"
}
},
"navbar": { "navbar": {
"home": "ok £50 extra", "home": "ok £50 extra",
"forums": "can u fix that for £10 extra", "forums": "can u fix that for £10 extra",
"marketplace": "£30 Its the last thing im asking for troplo.", "marketplace": "£30 Its the last thing im asking for troplo.",
"downloads": "dont tell anyone who i am here", "downloads": "dont tell anyone who i am here",
"games": "have u seen bloxtopia's games", "games": "have u seen bloxtopia's games",
"users": "Users", "users": "as i was not payed yet",
"teams": "gonna help kyle also bring tetrimus back", "teams": "leave me alone",
"dev": { "dev": {
"title": "i might come back to development", "title": "i might come back to development",
"fakeUser": "user : root", "fakeUser": "user : root",
@ -32,7 +124,7 @@
}, },
"user": { "user": {
"title": "Unknown", "title": "Unknown",
"profile": "", "profile": "My Profile",
"creations": "My Creations", "creations": "My Creations",
"downloads": "Downloads", "downloads": "Downloads",
"avatar": "My Avatar", "avatar": "My Avatar",
@ -40,16 +132,17 @@
"settings": "Settings", "settings": "Settings",
"logout": "Logout" "logout": "Logout"
}, },
"more": {
"title": "a",
"twitter": "Twitter",
"discord": "Discord",
"roadmap": "Roadmap",
"documentation": "API Docs",
"stats": "Kaverti Stats"
},
"register": "u got the .net?", "register": "u got the .net?",
"login": "/phpmyadmin" "login": "/phpmyadmin"
}, },
"404": {
"title": "systemctl start httpd??",
"text": "Error 521 Ray ID: 4f3226667865dc3b how to fix",
"quoteText": "There is currently 2900 WIND quotes available",
"windQuote": "without https works",
"home": "£1m"
},
"debug": { "debug": {
"title": "Debug mode enabled", "title": "Debug mode enabled",
"authUser": "Authenticated user", "authUser": "Authenticated user",
@ -65,6 +158,38 @@
"disableDebug": "Debug mode disabled, you will no longer have access to development features until you refresh.", "disableDebug": "Debug mode disabled, you will no longer have access to development features until you refresh.",
"authSuccess": "Request successful, your token is valid, and the Kaverti server instance is running correctly." "authSuccess": "Request successful, your token is valid, and the Kaverti server instance is running correctly."
}, },
"user": {
"title": "Loading",
"about": "About",
"more": "More of",
"posts": "Posts",
"threads": "Threads",
"inventory": "Inventory",
"awards": "Awards",
"items": "Items",
"wall": "User Wall",
"description": "Description",
"created": "Registered at"
},
"stats": {
"title": "Stats",
"users": "Registered users",
"purchased": "Purchased items",
"items": "Uploaded items",
"posts": "Forum posts",
"threads": "Threads",
"teams": "Teams"
},
"settings": {
"title": "User Settings",
"general": {
"title": "General"
},
"security": {
"title": "Security"
}
},
"currency": "fuck you",
"close": "I've just told the full truth to logan", "close": "I've just told the full truth to logan",
"tos": "get the fuck over it, it was never a scam", "tos": "get the fuck over it, it was never a scam",
"gotIt": "that is wind for you", "gotIt": "that is wind for you",

View file

@ -23,6 +23,30 @@ const routes = [
name: 'Debug', name: 'Debug',
component: route('Debug') component: route('Debug')
}, },
{ path: '/u/:username', redirect: '/u/:username/posts', component: route('User'), children: [
{ path: 'posts', component: route('UserPosts') },
{ path: 'threads', component: route('UserThreads') },
{ path: 'items', component: route('UserMarketplace') },
{ path: 'wall', component: route('UserWall') },
{ path: 'inventory', component: route('UserInventory') },
{ path: 'friends', component: route('UserFriends') },
{ path: 'awards', component: route('UserAwards') }
] },
{
path: '/users',
name: 'Users',
component: route('Users')
},
{
path: '/roadmap',
name: 'Roadmap',
component: route('Roadmap')
},
{
path: '/stats',
name: 'Stats',
component: route('Stats')
},
{ {
path: '*', path: '*',
name: '404', name: '404',

View file

@ -15,6 +15,11 @@ export default new Vuex.Store({
name: "Kaverti", name: "Kaverti",
debug: tb(process.env.VUE_APP_STAGING), debug: tb(process.env.VUE_APP_STAGING),
wind: false, wind: false,
client: {
clientVersion: '1.0.0-prerelease',
latestClientVersion: '',
latestAPIVersion: '',
},
errors: { errors: {
errors: null, errors: null,
modal: false modal: false
@ -80,6 +85,12 @@ export default new Vuex.Store({
}, },
setWind (state, value) { setWind (state, value) {
state.wind = value state.wind = value
},
setKoins (state, value) {
state.user.koins = value
},
setAdmin (state, value) {
state.user.admin = value
} }
}, },
actions: { actions: {

File diff suppressed because it is too large Load diff

View file

@ -10,20 +10,7 @@
<div class="column is-6"> <div class="column is-6">
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<div class="media"> test
<div class="media-content">
<p class="title is-4">John Smith</p>
<p class="subtitle is-6">@johnsmith</p>
</div>
</div>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Phasellus nec iaculis mauris. <a>@bulmaio</a>.
<a href="#">#css</a> <a href="#">#responsive</a>
<br>
<time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
</div>
</div> </div>
</div> </div>
</div> </div>

5
src/views/Roadmap.vue Normal file
View file

@ -0,0 +1,5 @@
<template>
<main>
</main>
</template>

92
src/views/Stats.vue Normal file
View file

@ -0,0 +1,92 @@
<template>
<main>
<div class="column is-vcentered">
<h1 class="title">{{$t('stats.title')}}</h1>
</div>
<div class="columns is-centered">
<div class="column is-vcentered has-text-centered">
<h1 class="title">{{$t('stats.users')}}</h1>
<div class="box">
<h1 class="title" v-if="!loading">
{{users}}
</h1>
<b-skeleton size="is-large" :active="loading" :count="2"></b-skeleton>
</div>
</div>
<div class="column is-vcentered has-text-centered">
<h1 class="title">{{$t('stats.posts')}}</h1>
<div class="box">
<h1 class="title" v-if="!loading">
{{posts}}
</h1>
<b-skeleton size="is-large" :active="loading" :count="2"></b-skeleton>
</div>
</div>
<div class="column is-vcentered has-text-centered">
<h1 class="title">{{$t('stats.purchased')}}</h1>
<div class="box">
<h1 class="title" v-if="!loading">
{{inventory}}
</h1>
<b-skeleton size="is-large" :active="loading" :count="2"></b-skeleton>
</div>
</div>
<div class="column is-vcentered has-text-centered">
<h1 class="title">{{$t('stats.teams')}}</h1>
<div class="box">
<h1 class="title" v-if="!loading">
{{teams}}
</h1>
<b-skeleton size="is-large" :active="loading" :count="2"></b-skeleton>
</div>
</div>
<div class="column is-vcentered has-text-centered">
<h1 class="title">{{$t('stats.items')}}</h1>
<div class="box">
<h1 class="title" v-if="!loading">
{{items}}
</h1>
<b-skeleton size="is-large" :active="loading" :count="2"></b-skeleton>
</div>
</div>
<div class="column is-vcentered has-text-centered">
<h1 class="title">{{$t('stats.threads')}}</h1>
<div class="box">
<h1 class="title" v-if="!loading">
{{threads}}
</h1>
<b-skeleton size="is-large" :active="loading" :count="2"></b-skeleton>
</div>
</div>
</div>
</main>
</template>
<script>
export default {
data() {
return {
users: 0,
posts: 0,
inventory: 0,
items: 0,
teams: 0,
threads: 0,
loading: true
}
},
mounted() {
this.axios.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'kaverti/stats')
.then(res => {
this.users = res.data.users
this.posts = res.data.posts
this.inventory = res.data.inventory
this.items = res.data.items
this.teams = res.data.teams
this.threads = res.data.threads
this.loading = false
}).catch(() => {
this.$buefy.snackbar.open({message:this.$t('errors.authFail'), type: 'is-warning'})
})
}
}
</script>

333
src/views/User.vue Normal file
View file

@ -0,0 +1,333 @@
<style>
.limit{
margin-top: 0.5rem;
word-break: break-all;
}
</style>
<template>
<main>
<div class="columns is-centered">
<div class="column is-4 is-vcentered has-text-centered">
<h1 class="title">{{user.username}}</h1>
<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="70%">
</div>
<h1 class="subtitle">
{{ $t('user.about') }} {{user.username}}
</h1>
<div class="box limit">
{{ $t('user.description') }}: {{user.description}}<br>
{{ $t('user.created') }}: {{user.createdAt}}
</div>
</div>
<div class="column is-6 is-vcentered has-text-centered">
<h1 class="title">{{ $t('user.more') }} {{user.username}}</h1>
<div>
<div class="tabs">
<ul>
<router-link tag="li" :to="'/u/' + user.username + '/posts'" exact><a>{{ $t('user.posts') }}</a></router-link>
<router-link tag="li" :to="'/u/' + user.username + '/threads'" exact><a>{{ $t('user.threads') }}</a></router-link>
<router-link tag="li" :to="'/u/' + user.username + '/wall'" exact><a>{{ $t('user.wall') }}</a></router-link>
<router-link tag="li" :to="'/u/' + user.username + '/items'" exact><a>{{ $t('user.items') }}</a></router-link>
<router-link tag="li" :to="'/u/' + user.username + '/inventory'" exact><a>{{ $t('user.inventory') }}</a></router-link>
<router-link tag="li" :to="'/u/' + user.username + '/awards'" exact><a>{{ $t('user.awards') }}</a></router-link>
</ul>
</div>
</div>
<div class="card">
<div class="card-content">
<router-view></router-view>
</div>
</div>
</div>
</div>
</main>
</template>
<script>
import AjaxErrorHandler from '../../assets/js/errorHandler'
export default {
name: 'user',
data () {
return {
menuItems: [
/* { name: 'Wall', route: 'wall' }, */
{ name: 'Posts', route: 'posts' },
{ name: 'Threads', route: 'threads' },
/* { name: 'Friends', route: 'friends' } */
],
selected: 0,
username: this.$route.params.username,
user: {
username: "Loading",
description: "Loading",
createdAt: "2020-01-01T00:00:00.000Z"
},
relationship: false,
relationships: {
type: ''
}
}
},
watch: {
$route (to) {
this.selected = this.getIndexFromRoute(to.path)
}
},
computed: {
userColor () {
if(this.user) {
return this.user.color
} else {
return null
}
},
userPicture () {
if(this.user && this.user.picture) {
return 'https://cdn.kaverti.com/user/avatars/full/' + this.user.picture + '.png'
} else {
return null
}
}
},
methods: {
resetFetchData () {
this.offset = 0;
this.users = [];
this.fetchData();
},
fetchData () {
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `user/${this.$route.params.username}`)
.then(res => this.user = 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)
}
})
},
scrubDesc () {
this.axios
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'admin/user/scrub', {
description: "descscram",
user: this.username
})
.then(() => {
this.resetFetchData()
})
.catch(AjaxErrorHandler(this.$store))
},
refreshAvatar () {
this.axios
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'admin/user/avatar', {
user: this.username
})
.then(() => {
this.resetFetchData()
})
.catch(AjaxErrorHandler(this.$store))
},
scrubUsername () {
this.axios
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'admin/user/scrub', {
username: "usernamescram",
user: this.username
})
.then(() => {
this.description.loading = false
})
.catch(AjaxErrorHandler(this.$store))
},
refreshFriend() {
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)
},
removeFriend () {
this.axios
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/remove', {
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, 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)
}
})
})
.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, 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)
}
})
})
},
doRelationship () {
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, 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)
}
})
})
},
doRelationshipAccept () {
this.axios
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/accept', {
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, 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)
}
})
})
},
getIndexFromRoute (path) {
let selectedIndex
let route = path.split('/')[3]
this.menuItems.forEach((item, index) => {
if(item.route === route) {
selectedIndex = index
}
})
return selectedIndex
}
},
created () {
this.resetFetchData()
this.selected = this.getIndexFromRoute(this.$route.path)
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `user/${this.$route.params.username}`)
.then(res => this.user = res.data)
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)
}
})
}
}
</script>

View file

@ -0,0 +1,3 @@
<template>
<main>TEST2</main>
</template>

102
src/views/UserPosts.vue Normal file
View file

@ -0,0 +1,102 @@
<template>
<div class='' :class='{ "user_posts--no_border_bottom": posts && !posts.length }'>
<div class='user_posts__title'>Posts by {{username}}</div>
<template v-if='!posts'>
<thread-post-placeholder v-if='!posts'>
</thread-post-placeholder>
</template>
<scroll-load
:loading='loadingPosts'
@loadNext='loadNewPosts'
v-else-if='posts.length'
>
<thread-post
v-for='(post, index) in posts'
:key='"thread-post-" + post.id'
:post='post'
:show-thread='true'
:click-for-post='true'
:class='{"post--last": index === posts.length-1}'
></thread-post>
<template v-if='loadingPosts'>
<b-skeleton
></b-skeleton>
</template>
</scroll-load>
<template v-else>This user hasn't posted anything yet</template>
</div>
</template>
<script>
import AjaxErrorHandler from '../../assets/js/errorHandler'
import ThreadPost from '../components/Post'
export default {
name: 'UserPosts',
props: ['username'],
components: {
ThreadPost
},
data () {
return {
posts: null,
loadingPosts: false,
nextPostsCount: 0,
nextURL: ''
}
},
methods: {
loadNewPosts () {
if(this.nextURL === null) return
this.loadingPosts = true
this.axios
.get(this.nextURL)
.then(res => {
this.loadingPosts = false
if(!this.posts) this.posts = []
let currentPostsIds = this.posts.map(p => p.id)
let filteredPosts =
res.data.Posts.filter(p => !currentPostsIds.includes(p.id))
this.posts.push(...filteredPosts)
this.nextURL = res.data.meta.nextURL
this.nextPostsCount = res.data.meta.nextPostsCount
})
.catch((e) => {
this.loadingPosts = false
AjaxErrorHandler(this.$store)(e)
})
}
},
created () {
this.$store.dispatch('setTitle', this.$route.params.username + ' - Posts')
this.axios
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + `/` + `user/${this.$route.params.username}?posts=true`)
.then(res => {
this.posts = res.data.Posts
this.nextURL = res.data.meta.nextURL
this.nextPostsCount = res.data.meta.nextPostsCount
})
.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)
}
})
}
}
</script>

View file

@ -0,0 +1,3 @@
<template>
<main>TEST</main>
</template>

3
src/views/UserWall.vue Normal file
View file

@ -0,0 +1,3 @@
<template>
<main>TEST</main>
</template>

5
src/views/Users.vue Normal file
View file

@ -0,0 +1,5 @@
<template>
<main>
</main>
</template>