summaryrefslogtreecommitdiffstats
path: root/webapp/src/main.js
blob: db7c60864879b4316ad756c440ec6f7f21e69e8b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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: '<router-view/>'
}).$mount('#app')