Add dashboard page

This commit is contained in:
zema1 2018-01-04 11:42:54 +08:00 committed by virusdefender
parent c108202e4e
commit 30295670ae
6 changed files with 237 additions and 37 deletions

View File

@ -18,7 +18,8 @@ const vendors = [
'vuex',
'axios',
'moment',
'raven-js'
'raven-js',
'browser-detect'
];
// clear old dll

View File

@ -281,8 +281,14 @@ export default {
data
})
},
getLatestVersion () {
return ajax('admin/new_version', 'get')
getReleaseNotes () {
return ajax('admin/versions', 'get')
},
getDashboardInfo () {
return ajax('admin/dashboard_info', 'get')
},
getSessions () {
return ajax('sessions', 'get')
}
}

View File

@ -2,7 +2,7 @@ import Vue from 'vue'
import VueRouter from 'vue-router'
// 引入 view 组件
import { Announcement, Conf, Contest, ContestList, Home, JudgeServer, Login,
Problem, ProblemList, User, PruneTestCase } from './views'
Problem, ProblemList, User, PruneTestCase, Dashboard } from './views'
Vue.use(VueRouter)
export default new VueRouter({
@ -21,7 +21,7 @@ export default new VueRouter({
children: [
{
path: '',
component: Announcement
component: Dashboard
},
{
path: '/announcement',

View File

@ -20,22 +20,6 @@
Build Version: {{ version }}
</div>
</div>
<el-dialog :visible.sync="newVersionDialog" :title="'New Version Available! - ' + newVersion.title">
<div class="version-body">
<p>Level: {{newVersion.level}}</p>
<div>
<p>Details:</p>
<ul v-for="detail in newVersion.details" :key="detail">
<li v-html="detail"></li>
</ul>
</div>
<p>Please upgrade to the latest version to enjoy the new features. </p>
<p>Reference: <a href="http://docs.onlinejudge.me/#/onlinejudge/guide/upgrade" target="_blank">
http://docs.onlinejudge.me/#/onlinejudge/guide/upgrade</a>
</p>
</div>
</el-dialog>
</div>
</template>
@ -50,9 +34,7 @@
name: 'app',
data () {
return {
version: process.env.VERSION,
newVersionDialog: false,
newVersion: {}
version: process.env.VERSION
}
},
components: {
@ -71,15 +53,6 @@
}
})
},
mounted () {
api.getLatestVersion().then(resp => {
let latestVersion = resp.data.data
if (latestVersion && latestVersion.version) {
this.newVersionDialog = true
this.newVersion = latestVersion
}
})
},
methods: {
handleCommand (command) {
if (command === 'logout') {
@ -162,8 +135,6 @@
animation: fadeInUp .8s;
}
.version-body {
margin-top: -20px;
}
</style>

View File

@ -0,0 +1,221 @@
<template>
<el-row type="flex" :gutter="20">
<el-col :md="10" :lg="8">
<el-card class="admin-info">
<el-row :gutter="20">
<el-col :span="10">
<img class="avatar" src="/public/avatar/default.png"/>
</el-col>
<el-col :span="14">
<p class="admin-info-name">{{user.username}}</p>
<p>{{user.admin_type}}</p>
</el-col>
</el-row>
<hr/>
<div class="last-info">
<p class="last-info-title">Last Login</p>
<el-form label-width="80px" class="last-info-body">
<el-form-item label="Time:">
<span>{{session.last_activity | localtime}}</span>
</el-form-item>
<el-form-item label="IP:">
<span>{{session.ip}}</span>
</el-form-item>
<el-form-item label="OS">
<span>{{os}}</span>
</el-form-item>
<el-form-item label="Browser:">
<span>{{browser}}</span>
</el-form-item>
</el-form>
</div>
</el-card>
<panel title="System Overview">
<p>Judge Server: {{infoData.judge_server_count}}</p>
<p>HTTPS Status:
<el-tag :type="https ? 'success' : 'danger'" size="small">
{{ https ? 'Enabled' : 'Disabled'}}
</el-tag>
</p>
<p>Force HTTPS:
<el-tag :type="forceHttps ? 'success' : 'danger'" size="small">
{{forceHttps ? 'Enabled' : 'Disabled'}}
</el-tag>
</p>
<p>CDN HOST:
<el-tag :type="cdn ? 'success' : 'warning'" size="small">
{{cdn ? cdn : 'Not Use'}}
</el-tag>
</p>
</panel>
</el-col>
<el-col :md="14" :lg="16">
<div class="info-container">
<info-card color="#909399" icon="el-icon-fa-users" message="Total Users" iconSize="30px" class="info-item"
:value="infoData.user_count"></info-card>
<info-card color="#67C23A" icon="el-icon-fa-list" message="Today Submissions" class="info-item"
:value="infoData.today_submission_count"></info-card>
<info-card color="#409EFF" icon="el-icon-fa-trophy" message="Recent Contests" class="info-item"
:value="infoData.recent_contest_count"></info-card>
</div>
<panel>
<span slot="title" v-loading="loadingReleases">Release Notes
<el-popover placement="right" trigger="hover">
<i slot="reference" class="el-icon-fa-question-circle import-user-icon"></i>
<p>Please upgrade to the latest version to enjoy the new features. </p>
<p>Reference: <a href="http://docs.onlinejudge.me/#/onlinejudge/guide/upgrade" target="_blank">
http://docs.onlinejudge.me/#/onlinejudge/guide/upgrade</a>
</p>
</el-popover>
</span>
<el-collapse v-model="activeNames" v-for="release, index in releases" :key="'release' + index">
<el-collapse-item :name="index+1">
<template slot="title">
<div v-if="release.new_version">{{release.title}}
<el-tag size="mini" type="success">New Version</el-tag>
</div>
<span v-else>{{release.title}}</span>
</template>
<p>Level: {{release.level}}</p>
<p>Details: </p>
<div class="release-body">
<ul v-for="detail in release.details">
<li v-html="detail"></li>
</ul>
</div>
</el-collapse-item>
</el-collapse>
</panel>
</el-col>
</el-row>
</template>
<script>
import { mapGetters } from 'vuex'
import browserDetector from 'browser-detect'
import InfoCard from '@admin/components/infoCard.vue'
import api from '@admin/api'
export default {
name: 'dashboard',
components: {
InfoCard
},
data () {
return {
infoData: {
user_count: 0,
recent_contest_count: 0,
today_submission_count: 0,
judge_server_count: 0,
env: {}
},
activeNames: [1],
session: {},
loadingReleases: true,
releases: []
}
},
mounted () {
api.getDashboardInfo().then(resp => {
this.infoData = resp.data.data
}, () => {
})
api.getSessions().then(resp => {
this.parseSession(resp.data.data)
}, () => {
})
api.getReleaseNotes().then(resp => {
this.loadingReleases = false
let data = resp.data.data
if (!data) {
return
}
let currentVersion = data.local_version
data.update.forEach(release => {
if (release.version > currentVersion) {
release.new_version = true
}
})
this.releases = data.update
}, () => {
this.loadingReleases = false
})
},
methods: {
parseSession (sessions) {
let session = sessions[0]
if (sessions.length > 1) {
session = sessions.filter(s => !s.current_session).sort((a, b) => {
return a.last_activity < b.last_activity
})[0]
}
this.session = session
}
},
computed: {
...mapGetters(['profile', 'user']),
cdn () {
return this.infoData.env.STATIC_CDN_HOST
},
https () {
return document.URL.slice(0, 4) === 'https'
},
forceHttps () {
return this.infoData.env.FORCE_HTTPS
},
browser () {
let b = browserDetector(this.session.user_agent)
if (b.name && b.version) {
return b.name + ' ' + b.version
} else {
return 'Unknown'
}
},
os () {
let b = browserDetector(this.session.user_agent)
return b.os ? b.os : 'Unknown'
}
}
}
</script>
<style lang="less">
.admin-info {
margin-bottom: 20px;
&-name {
font-size: 24px;
font-weight: 700;
margin-bottom: 10px;
color: #409EFF;
}
.avatar {
max-width: 100%;
}
.last-info {
&-title {
font-size: 16px;
}
&-body {
.el-form-item {
margin-bottom: 5px;
}
}
}
}
.info-container {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
.info-item {
flex: 1 0 auto;
min-width: 200px;
margin-bottom: 10px;
}
}
</style>

View File

@ -1,3 +1,4 @@
import Dashboard from './general/Dashboard.vue'
import Announcement from './general/Announcement.vue'
import User from './general/User.vue'
import Conf from './general/Conf.vue'
@ -12,5 +13,5 @@ import Home from './Home.vue'
export {
Announcement, User, Conf, JudgeServer, Problem, ProblemList, Contest,
ContestList, Login, Home, PruneTestCase
ContestList, Login, Home, PruneTestCase, Dashboard
}