467 lines
19 KiB
JavaScript
467 lines
19 KiB
JavaScript
import 'babel-polyfill'
|
|
import NProgress from 'nprogress'
|
|
import io from 'socket.io-client'
|
|
import "core-js/stable";
|
|
|
|
window.onload = () => {
|
|
let div = document.createElement('div');
|
|
div.innerHTML =
|
|
`<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.10.0/styles/default.min.css">`;
|
|
|
|
document.head.append(...div.children);
|
|
}
|
|
import VueRouter from 'vue-router'
|
|
import Vuex from 'vuex'
|
|
import Vue from 'vue'
|
|
import './assets/buefy/buefy.css'
|
|
import Buefy from 'buefy'
|
|
import axios from 'axios'
|
|
import VueAxios from 'vue-axios'
|
|
import 'core-js/stable';
|
|
import linkExpander from './assets/js/linkExpander'
|
|
import App from './App'
|
|
import store from './store/index'
|
|
import VPaginator from 'vuejs-paginator'
|
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
|
import * as Sentry from "@sentry/browser";
|
|
import { Vue as VueIntegration } from "@sentry/integrations";
|
|
import { Integrations } from '@sentry/tracing';
|
|
import { faBell, faComment } from '@fortawesome/free-regular-svg-icons'
|
|
import VueMatomo from 'vue-matomo'
|
|
import { VueSpinners } from '@saeris/vue-spinners'
|
|
import moment from 'moment'
|
|
import VueSkipTo from '@vue-a11y/skip-to'
|
|
|
|
import {
|
|
faBars, faPlus, faGrin, faLink, faCode,
|
|
faTimes, faUnlockAlt, faReply, faHome, faTh,
|
|
faExclamationCircle, faUserCircle, faThumbsUp,
|
|
faComments, faUser, faCog, faLock, faCloudUploadAlt,
|
|
faSearch, faChevronDown, faSortAmountUp, faSortAmountDown,
|
|
faCheck, faQuoteRight, faMinus, faCaretUp, faCaretDown,
|
|
faHeart
|
|
} from '@fortawesome/free-solid-svg-icons'
|
|
|
|
library.add(
|
|
faBars, faPlus, faGrin, faLink, faCode,
|
|
faTimes, faBell, faUnlockAlt, faReply, faHome,
|
|
faTh, faExclamationCircle, faUserCircle, faThumbsUp,
|
|
faComments, faUser, faCog, faLock, faCloudUploadAlt,
|
|
faSearch, faChevronDown, faSortAmountUp, faSortAmountDown,
|
|
faComment, faCheck, faQuoteRight, faMinus, faCaretUp, faCaretDown,
|
|
faHeart
|
|
);
|
|
Vue.component('font-awesome-icon', FontAwesomeIcon);
|
|
|
|
|
|
const Index = () => import('./components/routes/Index')
|
|
const CategorySelect = () => import('./components/routes/CategorySelect')
|
|
const Home = () => import('./components/routes/Home')
|
|
const HomeAuthenticated = () => import('./components/routes/HomeAuthenticated')
|
|
|
|
const P = () => import('./components/routes/P')
|
|
const Thread = () => import('./components/routes/Thread')
|
|
const ThreadNew = () => import('./components/routes/ThreadNew')
|
|
const Games = () => import('./components/routes/Games')
|
|
const OutLink = () => import('./components/routes/OutLink')
|
|
|
|
const Search = () => import('./components/routes/Search')
|
|
const SearchUsersThreads = () => import('./components/routes/SearchUsersThreads')
|
|
|
|
const Teams = () => import('./components/routes/Teams')
|
|
const Team = () => import('./components/routes/Team')
|
|
const TeamSettings = () => import('./components/routes/TeamSettings')
|
|
const TeamRoles = () => import('./components/routes/TeamRoles')
|
|
const TeamGeneral = () => import('./components/routes/TeamGeneral')
|
|
const TeamPrivacy = () => import('./components/routes/TeamPrivacy')
|
|
const TeamRequests = () => import('./components/routes/TeamRequests')
|
|
const TeamUsers = () => import('./components/routes/TeamUsers')
|
|
const TeamWall = () => import('./components/routes/TeamWall')
|
|
const TeamMembers = () => import('./components/routes/TeamMembers')
|
|
const TeamInvite = () => import('./components/routes/TeamInvite')
|
|
const TeamInvites = () => import('./components/routes/TeamInvites')
|
|
|
|
const User = () => import('./components/routes/User')
|
|
const UserPosts = () => import('./components/routes/UserPosts')
|
|
const UserThreads = () => import('./components/routes/UserThreads')
|
|
const UserMarketplace = () => import('./components/routes/UserMarketplace')
|
|
const UserWall = () => import('./components/routes/UserWall')
|
|
const UserInventory = () => import('./components/routes/UserInventory')
|
|
const UserFriends = () => import('./components/routes/UserFriends')
|
|
const UsersList = () => import('./components/routes/UsersList')
|
|
const Notifications = () => import('./components/routes/Notifications')
|
|
const Banned = () => import('./components/routes/Banned')
|
|
const ToS = () => import('./components/routes/LegalToS')
|
|
const Privacy = () => import('./components/routes/LegalPrivacyPolicy')
|
|
const EmailVerify = () => import('./components/routes/EmailVerify')
|
|
const EmailVerifyCheck = () => import('./components/routes/EmailVerifyCheck')
|
|
const EmailVerifySuccess = () => import('./components/routes/EmailVerifySuccess')
|
|
const EmailVerifyError = () => import('./components/routes/EmailVerifyError')
|
|
const DeleteUndoCode = () => import('./components/routes/DeleteUndoCode')
|
|
const DeleteVerify = () => import('./components/routes/DeleteVerify')
|
|
const DeleteError = () => import('./components/routes/DeleteError')
|
|
|
|
const Recovery = () => import('./components/routes/Recovery')
|
|
|
|
const Chat = () => import('./components/routes/Chat')
|
|
const Conversation = () => import('./components/routes/Conversation')
|
|
const Friends = () => import('./components/routes/Friends')
|
|
|
|
const DeveloperPortal = () => import('./components/routes/DeveloperPortal')
|
|
const DeveloperDocs = () => import('./components/routes/DeveloperDocs')
|
|
|
|
const Hiring = () => import('./components/routes/Hiring')
|
|
const HiringApply = () => import('./components/routes/HiringApply')
|
|
const HiringThanks = () => import('./components/routes/HiringThanks')
|
|
|
|
const Settings = () => import('./components/routes/Settings')
|
|
const SettingsGeneral = () => import('./components/routes/SettingsGeneral')
|
|
const SettingsAccount = () => import('./components/routes/SettingsAccount')
|
|
const SettingsExperiments = () => import('./components/routes/SettingsExperiments')
|
|
const SettingsAbout = () => import('./components/routes/SettingsAbout')
|
|
const SettingsPrivacy = () => import('./components/routes/SettingsPrivacy')
|
|
const Character = () => import('./components/routes/Character')
|
|
|
|
const Admin = () => import('./components/routes/Admin')
|
|
const AdminDashboard = () => import('./components/routes/AdminDashboard')
|
|
const AdminModerationReports = () => import('./components/routes/AdminModerationReports')
|
|
const AdminModerationBannedUsers = () => import('./components/routes/AdminModerationBannedUsers')
|
|
const AdminGeneral = () => import('./components/routes/AdminGeneral')
|
|
const AdminUsers = () => import('./components/routes/AdminUsers')
|
|
const AdminOther = () => import('./components/routes/AdminOther')
|
|
const AdminBadges = () => import('./components/routes/AdminAudit')
|
|
const AdminApplications = () => import('./components/routes/AdminApplications')
|
|
const AdminPrivileges = () => import('./components/routes/AdminPrivileges')
|
|
const AdminTeams = () => import('./components/routes/AdminTeams')
|
|
const AdminMarketplace = () => import('./components/routes/AdminMarketplace')
|
|
|
|
const Licenses = () => import('./components/routes/LICENSES')
|
|
const ConnectionProblems = () => import('./components/routes/ConnectionProblems')
|
|
const Maintenance = () => import('./components/routes/Maintenance')
|
|
const Contributors = () => import('./components/routes/Contributors')
|
|
|
|
const Inventory = () => import('./components/routes/Inventory')
|
|
|
|
const Marketplace = () => import('./components/routes/Marketplace')
|
|
const MarketplaceCreate = () => import('./components/routes/MarketplaceCreate')
|
|
const MarketplaceItem = () => import('./components/routes/MarketplaceItem')
|
|
const MarketplaceItemAuction = () => import('./components/routes/MarketplaceItemAuction')
|
|
const TransactionLog = () => import('./components/routes/TransactionLog')
|
|
|
|
import NotFound from './components/routes/NotFound'
|
|
import Reserved from './components/routes/Reserved'
|
|
Vue.use(VueRouter)
|
|
Vue.use(Vuex)
|
|
Vue.use(VueAxios, axios)
|
|
Vue.use(linkExpander)
|
|
Vue.use(Buefy, { defaultIconPack: 'fas' })
|
|
Vue.use(VPaginator)
|
|
Vue.use(VueSpinners)
|
|
Vue.use(VueSkipTo)
|
|
Sentry.init({
|
|
dsn: "https://287b35aa71b54ffea9e66b5ce03d2e29@o444992.ingest.sentry.io/5420646",
|
|
integrations: [
|
|
new VueIntegration({
|
|
Vue,
|
|
tracing: true
|
|
}),
|
|
new Integrations.BrowserTracing()
|
|
],
|
|
tracesSampleRate: 1
|
|
});
|
|
Vue.use({
|
|
install (Vue) {
|
|
Vue.prototype.$socket = io(process.env.VUE_APP_GATEWAYENDPOINT)
|
|
}
|
|
})
|
|
|
|
const router = new VueRouter({
|
|
routes: [
|
|
{ path: '/', component: Home },
|
|
{ path: '/dashboard', redirect: '/', component: HomeAuthenticated },
|
|
{ path: '/category/select', component: CategorySelect },
|
|
{ path: '/category/:category', component: Index },
|
|
{ path: '/p/:id', component: P },
|
|
{ path: '/start', component: Reserved },
|
|
{ path: '/blog', component: Reserved },
|
|
{ path: '/blog/:slug/:id', component: Reserved },
|
|
{ path: '/blog/:slug', component: Reserved },
|
|
{ path: '/jobs', component: Hiring },
|
|
{ path: '/jobs/apply', component: HiringApply },
|
|
{ path: '/jobs/thank-you', component: HiringThanks },
|
|
{ path: '/premium', component: Reserved },
|
|
{ path: '/upgrade', redirect: '/premium', component: Reserved },
|
|
{ path: '/experiments', component: Reserved },
|
|
{ path: '/thread/:id', component: Thread },
|
|
{ path: '/thread/:id/:post_number', name: 'thread-post', component: Thread },
|
|
{ path: '/thread/new', component: ThreadNew },
|
|
{ path: '/marketplace', component: Marketplace },
|
|
{ path: '/marketplace/create', component: MarketplaceCreate },
|
|
{ path: '/transactions', component: TransactionLog },
|
|
{ path: '/m/:id', component: MarketplaceItem, children: [
|
|
{ path: 'auction', component: MarketplaceItemAuction }
|
|
] },
|
|
{ path: '/licenses', component: Licenses },
|
|
{ path: '/teams', component: Teams },
|
|
{ path: '/team/:username', redirect: '/team/:username/general', component: TeamSettings, children: [
|
|
{ path: 'general', component: TeamGeneral },
|
|
{ path: 'users', component: TeamUsers },
|
|
{ path: 'roles', component: TeamRoles },
|
|
{ path: 'privacy', component: TeamPrivacy },
|
|
{ path: 'requests', component: TeamRequests },
|
|
{ path: 'invites', component: TeamInvites }
|
|
] },
|
|
{ path: '/t/:username', component: Team, children: [
|
|
{ path: 'items', component: UserMarketplace },
|
|
{ path: 'wall', component: TeamWall },
|
|
{ path: 'members', component: TeamMembers }
|
|
] },
|
|
{ path: '/verify', component: EmailVerify },
|
|
{ path: '/verify/check', component: EmailVerifyCheck },
|
|
{ path: '/verify/error', component: EmailVerifyError },
|
|
{ path: '/verify/success', component: EmailVerifySuccess },
|
|
{ path: '/delete/', component: DeleteVerify },
|
|
{ path: '/delete/undo', component: DeleteUndoCode },
|
|
{ path: '/delete/error', component: DeleteError },
|
|
{ path: '/recovery', component: Recovery },
|
|
{ path: '/games', component: Games },
|
|
{ path: '/game', redirect: '/games', component: Index },
|
|
{ path: '/gaming', redirect: '/games', component: Index },
|
|
{ path: '/legal/privacy', component: Privacy },
|
|
{ path: '/legal/guidelines', redirect: '/legal/tos', component: ToS },
|
|
{ path: '/legal/tos', component: ToS },
|
|
{ path: '/g', redirect: '/games', component: Index },
|
|
{ path: '/out', redirect: '/', component: OutLink, children: [
|
|
{ path: '/out/https://*', redirect: '?uri=https%3A%2F%2F*', component: OutLink },
|
|
{ path: '/out/http://*', redirect: '?uri=http%3A%2F%2F*', component: OutLink },
|
|
{ path: '/out/:out*', component: OutLink }
|
|
] },
|
|
{ path: '/users', component: UsersList },
|
|
{ path: '/developers', redirect: '/developers/portal', component: DeveloperPortal, children: [
|
|
{ path: 'portal', component: DeveloperPortal },
|
|
{ path: 'docs', component: DeveloperDocs },
|
|
] },
|
|
{ path: '/forum', redirect: '/category/all', component: Index },
|
|
{ path: '/connection', component: ConnectionProblems },
|
|
{ path: '/maintenance', component: Maintenance },
|
|
{ path: '/contributors', component: Contributors },
|
|
{ path: '/friends', component: Friends },
|
|
{ path: '/forums', redirect: '/category/all', component: Index },
|
|
{ path: '/search/:q', component: Search },
|
|
{ path: '/search/users/:q', component: SearchUsersThreads, name: 'search/users' },
|
|
{ path: '/search/threads/:q', component: SearchUsersThreads, name: 'search/threads' },
|
|
{ path: '/user/:username', component: User, redirect: '/u/:username' },
|
|
{ path: '/user/:username/posts', component: User, redirect: '/u/:username/posts' },
|
|
{ path: '/user/:username/threads', component: User, redirect: '/u/:username/threads' },
|
|
{ path: '/user/:username/items', component: User, redirect: '/u/:username/items' },
|
|
{ path: '/user/:username/wall', component: User, redirect: '/u/:username/wall' },
|
|
{ path: '/invite/:code', component: TeamInvite },
|
|
{ path: '/notifications', component: Notifications },
|
|
{ path: '/inventory', component: Inventory },
|
|
{
|
|
path: '/chat',
|
|
component: Chat,
|
|
children: [
|
|
{ path: '/', component: Chat },
|
|
{ path: 'conversation', component: Conversation },
|
|
{ path: 'conversation/:id', component: Conversation, name: 'conversation' }
|
|
]
|
|
},
|
|
{ path: '/u/:username', redirect: '/u/:username/posts', component: User, children: [
|
|
{ path: 'posts', component: UserPosts },
|
|
{ path: 'threads', component: UserThreads },
|
|
{ path: 'items', component: UserMarketplace },
|
|
{ path: 'wall', component: UserWall },
|
|
{ path: 'inventory', component: UserInventory },
|
|
{ path: 'friends', component: UserFriends }
|
|
] },
|
|
{ path: '/settings', redirect: '/settings/general', component: Settings, children: [
|
|
{ path: 'general', component: SettingsGeneral },
|
|
{ path: 'account', component: SettingsAccount },
|
|
{ path: 'experiments', component: SettingsExperiments },
|
|
{ path: 'about', component: SettingsAbout },
|
|
{ path: 'privacy', component: SettingsPrivacy }
|
|
] },
|
|
{ path: '/character', component: Character, name: 'character' },
|
|
{ path: '/banned', component: Banned },
|
|
{ path: '/admin', redirect: '/admin/dashboard', component: Admin, children: [
|
|
{ path: 'dashboard', component: AdminDashboard },
|
|
{ path: 'general', component: AdminGeneral },
|
|
{ path: 'users', component: AdminUsers },
|
|
{ path: 'moderation', redirect: '/admin/moderation/reports' },
|
|
{ path: 'moderation/reports', component: AdminModerationReports },
|
|
{ path: 'moderation/bans', component: AdminModerationBannedUsers },
|
|
{ path: 'other', component: AdminOther },
|
|
{ path: 'logs', component: AdminBadges },
|
|
{ path: 'applications', component: AdminApplications },
|
|
{ path: 'privileges', component: AdminPrivileges },
|
|
{ path: 'teams', component: AdminTeams },
|
|
{ path: 'marketplace', component: AdminMarketplace },
|
|
] },
|
|
{ path: '*', component: NotFound }
|
|
],
|
|
mode: 'history'
|
|
})
|
|
|
|
router.beforeEach((to, from, next) => {
|
|
router.app.$store.commit('set404Page', false)
|
|
|
|
//Do not change progress bar when scrolling through posts on a thread
|
|
if(
|
|
(to.name !== 'thread-post' && from.name !== 'thread-post') &&
|
|
(!to.params.id || to.params.id !== from.params.id)
|
|
) {
|
|
NProgress.start()
|
|
}
|
|
|
|
next()
|
|
})
|
|
router.afterEach(() => {
|
|
NProgress.done()
|
|
})
|
|
|
|
Vue.filter('formatDate', function(value) {
|
|
if (value) {
|
|
return moment(String(value)).format('hh:mm A, DD/MM/YYYY')
|
|
}
|
|
})
|
|
Vue.filter('strLimit', function (value, size) {
|
|
if (!value) return '';
|
|
value = value.toString();
|
|
|
|
if (value.length <= size) {
|
|
return value;
|
|
}
|
|
return value.substr(0, size) + '...';
|
|
});
|
|
Vue.use(VueMatomo, {
|
|
// Configure your matomo server and site by providing
|
|
host: 'https://analytics.troplo.com',
|
|
siteId: 1,
|
|
|
|
// Changes the default .js and .php endpoint's filename
|
|
// Default: 'matomo'
|
|
trackerFileName: 'troplo',
|
|
|
|
// Overrides the autogenerated tracker endpoint entirely
|
|
// Default: undefined
|
|
// trackerUrl: 'https://example.com/whatever/endpoint/you/have',
|
|
|
|
// Overrides the autogenerated tracker script path entirely
|
|
// Default: undefined
|
|
// trackerScriptUrl: 'https://example.com/whatever/script/path/you/have',
|
|
|
|
// Enables automatically registering pageviews on the router
|
|
router: router,
|
|
|
|
// Enables link tracking on regular links. Note that this won't
|
|
// work for routing links (ie. internal Vue router links)
|
|
// Default: true
|
|
enableLinkTracking: true,
|
|
|
|
// Require consent before sending tracking information to matomo
|
|
// Default: false
|
|
requireConsent: false,
|
|
|
|
// Whether to track the initial page view
|
|
// Default: true
|
|
trackInitialView: true,
|
|
|
|
// Run Matomo without cookies
|
|
// Default: false
|
|
disableCookies: false,
|
|
|
|
// Enable the heartbeat timer (https://developer.matomo.org/guides/tracking-javascript-guide#accurately-measure-the-time-spent-on-each-page)
|
|
// Default: false
|
|
enableHeartBeatTimer: false,
|
|
|
|
// Set the heartbeat timer interval
|
|
// Default: 15
|
|
heartBeatTimerInterval: 15,
|
|
|
|
// Whether or not to log debug information
|
|
// Default: false
|
|
debug: false,
|
|
|
|
// UserID passed to Matomo (see https://developer.matomo.org/guides/tracking-javascript-guide#user-id)
|
|
// Default: undefined
|
|
userId: undefined,
|
|
|
|
// Share the tracking cookie across subdomains (see https://developer.matomo.org/guides/tracking-javascript-guide#measuring-domains-andor-sub-domains)
|
|
// Default: undefined, example '*.example.com'
|
|
cookieDomain: undefined,
|
|
|
|
// Tell Matomo the website domain so that clicks on these domains are not tracked as 'Outlinks'
|
|
// Default: undefined, example: '*.example.com'
|
|
domains: undefined,
|
|
|
|
// A list of pre-initialization actions that run before matomo is loaded
|
|
// Default: []
|
|
// Example: [
|
|
// ['API_method_name', parameter_list],
|
|
// ['setCustomVariable','1','VisitorType','Member'],
|
|
// ['appendToTrackingUrl', 'new_visit=1'],
|
|
// etc.
|
|
// ]
|
|
preInitActions: []
|
|
});
|
|
Vue.filter('stripTags', function (value) {
|
|
let doc = new DOMParser().parseFromString(value, 'text/html')
|
|
return doc.body.textContent || ''
|
|
});
|
|
|
|
Vue.filter('truncate', function (value, length) {
|
|
if(value.length <= length) {
|
|
return value
|
|
} else {
|
|
return value.slice(0, length) + '…'
|
|
}
|
|
});
|
|
Vue.filter('truncateMid', function (value, length) {
|
|
if(value.length <= length) {
|
|
return value
|
|
} else {
|
|
let firstLen = Math.round(length/2);
|
|
let secondLen = length - firstLen;
|
|
|
|
return value.slice(0, firstLen) + '…' + value.slice(value.length-secondLen, value.length)
|
|
}
|
|
});
|
|
|
|
Vue.filter('pluralize', function(number, value) {
|
|
if(number === 1) {
|
|
return value
|
|
} else {
|
|
return value + 's'
|
|
}
|
|
})
|
|
|
|
let Root = new Vue({
|
|
store,
|
|
router,
|
|
render: h => h(App)
|
|
}).$mount('#app');
|
|
|
|
|
|
let cookieDict = document.cookie
|
|
.split(';')
|
|
.map(a => a.split('=').map(a => a.trim()) )
|
|
.map(a => {
|
|
let k = a[0], v = a[1]
|
|
return { [k] : v }
|
|
})
|
|
.reduce((combinedObj, o) => {
|
|
let key = Object.keys(o)[0]
|
|
combinedObj[key] = o[key]
|
|
|
|
return combinedObj
|
|
}, {})
|
|
|
|
if(cookieDict.username) Root.$store.commit('setUsername', cookieDict.username)
|
|
if(cookieDict.admin === 'false') {
|
|
Root.$store.commit('setAdmin', false)
|
|
} else if(cookieDict.admin === 'true') {
|
|
Root.$store.commit('setAdmin', true)
|
|
}
|