import '@mdi/font/css/materialdesignicons.css' import Vue from 'vue' import Vuetify from 'vuetify' import 'vuetify/dist/vuetify.min.css' import VueVirtualScroller from 'vue-virtual-scroller' import 'vue-virtual-scroller/dist/vue-virtual-scroller.css' import VueCodemirror from 'vue-codemirror' import 'codemirror/mode/shell/shell.js' import 'codemirror/lib/codemirror.css' import 'codemirror/theme/monokai.css' import Vuex from 'vuex' import globalStore from '@/store/global' import storeModules from '@/config/store' import axios from 'axios' import io from 'socket.io-client' import { router, registerRouterGuards } from '@/router' import VueI18n from 'vue-i18n' import i18nMessages from '@/config/i18n' import '@/assets/styles.css' Vue.config.performance = true Vue.config.productionTip = false Vue.use(Vuex) Object.keys(storeModules).forEach(key => { storeModules[key].namespaced = true }) globalStore.modules = storeModules var store = new Vuex.Store(globalStore) registerRouterGuards(store) Vue.use(VueI18n) const i18n = new VueI18n({ locale: store.state.settings.locale, silentTranslationWarn: true, messages: i18nMessages }) Vue.use(Vuetify) const vuetify = new Vuetify({ theme: { dark: store.state.settings.dark, themes: { light: { primary: '#0095ff' }, dark: { primary: '#0095ff' } } }, lang: { t: (key, ...params) => i18n.t(key, params) } }) Vue.use(VueVirtualScroller) Vue.use(VueCodemirror, { options: { theme: 'monokai', mode: 'shell', lineNumbers: true, viewportMargin: Infinity } }) axios.interceptors.response.use(null, error => { if (error && error.response.status === 401) { axios.post('/api/authentication/logout').then(response => { router.push('/login') socket.close() }) } if (error && error.response.status === 403) { let text = i18n.t('noPermission') if (error.response.data.permission) text += ': ' + error.response.data.permission store.commit('notifications/newSnackbar', { color: 'error', text }) } return Promise.reject(error) }) const socket = io({ autoConnect: false, transports: ['websocket'] }) socket.on('error', err => { console.log('Socket.io error: ' + err) if (err === 'TOKEN_MISSING' || err === 'TOKEN_INVALID') { socket.close() console.log('Closing socket.') } }) socket.open() Vue.prototype.$http = axios Vue.prototype.$socket = socket Vue.prototype.$alert = function (data, emit = true) { if (!data.id) data.id = '_' + Math.random().toString(36).substr(2, 9) if (emit) socket.emit('notifications newAlert', data) store.commit('notifications/newAlert', data) } Vue.prototype.$snackbar = function (data) { store.commit('notifications/newSnackbar', data) } // Loop that processes work in chunks to allow the UI to refresh inbetween and prevents freezing. Vue.prototype.$loop = function (count, chunksize, iteration, callback = () => {}) { var i = 0 var running = true const chunk = () => { if (!running) return var end = Math.min(i + chunksize, count) for (; i < end; i++) { iteration(i) } if (i < count) { setTimeout(chunk, 0) } else { running = false callback() } } setTimeout(chunk, 0) const loop = {} Object.defineProperty(loop, 'running', { get: () => running }) Object.defineProperty(loop, 'cancel', { value: () => { running = false } }) return loop } // Function for validating an email address. Vue.prototype.$validateEmail = email => { // TODO: Remove if email is not optional if (email === '') return true // Removed escape before [ because eslint told me so. var re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ return re.test(String(email).toLowerCase()) } new Vue({ store, router, i18n, vuetify, computed: { locale: () => store.state.settings.locale }, watch: { locale: v => { i18n.locale = v } }, template: '' }).$mount('#app')