some admin panel work
This commit is contained in:
parent
5575e9e4f6
commit
c9f75fda39
3693
package-lock.json
generated
3693
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
45
package.json
45
package.json
@ -8,8 +8,8 @@
|
|||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"css": "mkdir -p build/style && stylus -o build/style src/style/*.styl",
|
"css": "mkdir -p build/style && stylus -o build/style src/style/*.styl",
|
||||||
"css:watch": "mkdir -p build/style && stylus -w -o build/style src/style/*.styl",
|
"css:watch": "mkdir -p build/style && stylus -w -o build/style src/style/*.styl",
|
||||||
"js": "webpack",
|
"js": "webpack --config webpack.prod.js -p",
|
||||||
"js:watch": "webpack -w",
|
"js:watch": "webpack --config webpack.dev.js -w",
|
||||||
"watch": "concurrently --kill-others \"npm run css:watch\" \"npm run js:watch\"",
|
"watch": "concurrently --kill-others \"npm run css:watch\" \"npm run js:watch\"",
|
||||||
"clean": "rm -rf build/",
|
"clean": "rm -rf build/",
|
||||||
"build": "npm run clean && npm run css && npm run js"
|
"build": "npm run clean && npm run css && npm run js"
|
||||||
@ -30,43 +30,48 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/IcyNet/IcyNet.eu#readme",
|
"homepage": "https://github.com/IcyNet/IcyNet.eu#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel-core": "^6.25.0",
|
"babel-core": "^6.26.0",
|
||||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"bluebird": "^3.5.0",
|
"bluebird": "^3.5.1",
|
||||||
"body-parser": "^1.17.2",
|
"body-parser": "^1.18.2",
|
||||||
"connect-redis": "^3.3.0",
|
"connect-redis": "^3.3.2",
|
||||||
"connect-session-knex": "^1.3.4",
|
"connect-session-knex": "^1.4.0",
|
||||||
"email-templates": "^2.7.1",
|
"email-templates": "^2.7.1",
|
||||||
"express": "^4.15.3",
|
"express": "^4.16.2",
|
||||||
"express-rate-limit": "^2.9.0",
|
"express-rate-limit": "^2.9.0",
|
||||||
"express-session": "^1.15.3",
|
"express-session": "^1.15.6",
|
||||||
"fs-extra": "^4.0.2",
|
"fs-extra": "^4.0.2",
|
||||||
"gm": "^1.23.0",
|
"gm": "^1.23.0",
|
||||||
"knex": "^0.13.0",
|
"knex": "^0.13.0",
|
||||||
"multiparty": "^4.1.3",
|
"multiparty": "^4.1.3",
|
||||||
"mysql": "^2.13.0",
|
"mysql": "^2.15.0",
|
||||||
"nodemailer": "^4.0.1",
|
"nodemailer": "^4.4.0",
|
||||||
"notp": "^2.0.3",
|
"notp": "^2.0.3",
|
||||||
"oauth-libre": "^0.9.17",
|
"oauth-libre": "^0.9.17",
|
||||||
"objection": "^0.8.4",
|
"objection": "^0.8.9",
|
||||||
"pug": "^2.0.0-rc.3",
|
"pug": "^2.0.0-rc.4",
|
||||||
"serve-favicon": "^2.4.3",
|
"serve-favicon": "^2.4.5",
|
||||||
"stylus": "^0.54.5",
|
"stylus": "^0.54.5",
|
||||||
"thirty-two": "^1.0.2",
|
"thirty-two": "^1.0.2",
|
||||||
"toml": "^2.3.2",
|
"toml": "^2.3.3",
|
||||||
"uuid": "^3.1.0"
|
"uuid": "^3.1.0",
|
||||||
|
"vue": "^2.5.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "^3.5.0",
|
"babel-loader": "^7.1.2",
|
||||||
"eslint-plugin-import": "^2.7.0",
|
"babel-preset-env": "^1.6.1",
|
||||||
|
"concurrently": "^3.5.1",
|
||||||
|
"eslint-plugin-import": "^2.8.0",
|
||||||
"jquery": "^3.2.1",
|
"jquery": "^3.2.1",
|
||||||
"morgan": "^1.9.0",
|
"morgan": "^1.9.0",
|
||||||
"mustache": "^2.3.0",
|
"mustache": "^2.3.0",
|
||||||
"standard": "^10.0.3",
|
"standard": "^10.0.3",
|
||||||
"uglifyjs-webpack-plugin": "^0.4.6",
|
"uglifyjs-webpack-plugin": "^0.4.6",
|
||||||
|
"vue-resource": "^1.3.4",
|
||||||
"watch": "^1.0.2",
|
"watch": "^1.0.2",
|
||||||
"webpack": "^3.6.0"
|
"webpack": "^3.10.0",
|
||||||
|
"webpack-merge": "^4.1.1"
|
||||||
},
|
},
|
||||||
"standard": {
|
"standard": {
|
||||||
"env": {
|
"env": {
|
||||||
|
@ -1,284 +1,122 @@
|
|||||||
window.$ = require('jquery')
|
import Vue from 'vue'
|
||||||
var Mustache = require('mustache')
|
import VueResource from 'vue-resource'
|
||||||
|
|
||||||
function buildTemplateScript (id, ctx) {
|
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
||||||
var tmpl = $('#' + id)
|
|
||||||
if (!tmpl.length) return null
|
|
||||||
var data = tmpl.html()
|
|
||||||
Mustache.parse(data)
|
|
||||||
return Mustache.render(data, ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
function paginationButton (pages) {
|
Vue.use(VueResource)
|
||||||
var html = '<div class="pgn">'
|
|
||||||
html += '<span class="pagenum">Page ' + pages.page + ' of ' + pages.pages + '</span>'
|
|
||||||
|
|
||||||
if (pages.page > 1) {
|
Vue.component('Modal', {
|
||||||
html += '<div class="button" data-page="' + (pages.page - 1) + '">Previous</div>'
|
template: '#modal-template',
|
||||||
}
|
props: ['show'],
|
||||||
|
methods: {
|
||||||
for (var i = 0; i < pages.pages; i++) {
|
close: function () {
|
||||||
html += '<div class="button' + (i + 1 === pages.page ? ' active' : '') + '" data-page="' + (i + 1) + '">' + (i + 1) + '</div>'
|
this.$emit('close')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
if (pages.pages > pages.page) {
|
mounted: function () {
|
||||||
html += '<div class="button" data-page="' + (pages.page + 1) + '">Next</div>'
|
document.addEventListener('keydown', (e) => {
|
||||||
}
|
if (this.show && e.keyCode === 27) {
|
||||||
|
this.close()
|
||||||
html += '<span class="pagenum total">(' + pages.total + ' Total Entries)</span>'
|
|
||||||
html += '</div>'
|
|
||||||
return html
|
|
||||||
}
|
|
||||||
|
|
||||||
function banUser (id) {
|
|
||||||
window.Dialog.openTemplate('Ban User', 'banNew', {id: id})
|
|
||||||
$('#fnsubmit').submit(function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
$.post({
|
|
||||||
url: '/admin/api/ban',
|
|
||||||
data: $(this).serialize(),
|
|
||||||
success: function (data) {
|
|
||||||
window.Dialog.close()
|
|
||||||
loadBans(1)
|
|
||||||
},
|
|
||||||
error: function (e) {
|
|
||||||
if (e.responseJSON && e.responseJSON.error) {
|
|
||||||
$('form .message').show()
|
|
||||||
$('form .message').text(e.responseJSON.error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadBans (page) {
|
|
||||||
$.ajax({
|
|
||||||
type: 'get',
|
|
||||||
url: '/admin/api/bans',
|
|
||||||
data: {page: page},
|
|
||||||
success: function (data) {
|
|
||||||
$('#banlist').html('')
|
|
||||||
if (data.error) {
|
|
||||||
$('#banlist').html('<div class="message">' + data.error + '</div>')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var pgbtn = paginationButton(data.page)
|
|
||||||
$('#banlist').append(pgbtn)
|
|
||||||
$('#banlist .pgn .button').click(function (e) {
|
|
||||||
var pgnum = $(this).data('page')
|
|
||||||
if (pgnum == null) return
|
|
||||||
loadBans(parseInt(pgnum))
|
|
||||||
})
|
|
||||||
|
|
||||||
for (var u in data.bans) {
|
|
||||||
var ban = data.bans[u]
|
|
||||||
ban.created_at = new Date(ban.created_at)
|
|
||||||
ban.expires_at = ban.expires_at === null ? 'Never' : new Date(ban.expires_at)
|
|
||||||
var tmp = buildTemplateScript('ban', ban)
|
|
||||||
$('#banlist').append(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#banlist .remove').click(function (e) {
|
|
||||||
$.post({
|
|
||||||
url: '/admin/api/ban/pardon/' + parseInt($(this).data('id')),
|
|
||||||
success: function (data) {
|
|
||||||
loadBans(1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadUsers (page) {
|
|
||||||
$.ajax({
|
|
||||||
type: 'get',
|
|
||||||
url: '/admin/api/users',
|
|
||||||
data: {page: page},
|
|
||||||
success: function (data) {
|
|
||||||
$('#userlist').html('')
|
|
||||||
if (data.error) {
|
|
||||||
$('#userlist').html('<div class="message error">' + data.error + '</div>')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var pgbtn = paginationButton(data.page)
|
|
||||||
$('#userlist').append(pgbtn)
|
|
||||||
$('#userlist .pgn .button').click(function (e) {
|
|
||||||
var pgnum = $(this).data('page')
|
|
||||||
if (pgnum == null) return
|
|
||||||
loadUsers(parseInt(pgnum))
|
|
||||||
})
|
|
||||||
|
|
||||||
for (var u in data.users) {
|
|
||||||
var user = data.users[u]
|
|
||||||
user.created_at = new Date(user.created_at)
|
|
||||||
var tmp = buildTemplateScript('user', user)
|
|
||||||
$('#userlist').append(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#userlist .ban').click(function (e) {
|
|
||||||
banUser(parseInt($(this).data('id')))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function editClient (id) {
|
|
||||||
$.ajax({
|
|
||||||
type: 'get',
|
|
||||||
url: '/admin/api/client/' + id,
|
|
||||||
success: function (data) {
|
|
||||||
window.Dialog.openTemplate('Editing client', 'clientEdit', data)
|
|
||||||
$('#ffsubmit').submit(function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
$.ajax({
|
|
||||||
type: 'post',
|
|
||||||
url: '/admin/api/client/update',
|
|
||||||
data: $(this).serialize(),
|
|
||||||
success: function (data) {
|
|
||||||
window.Dialog.close()
|
|
||||||
loadClients(1)
|
|
||||||
},
|
|
||||||
error: function (e) {
|
|
||||||
if (e.responseJSON && e.responseJSON.error) {
|
|
||||||
$('form .message').show()
|
|
||||||
$('form .message').text(e.responseJSON.error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteClient (id) {
|
|
||||||
window.Dialog.openTemplate('Deleting client', 'clientRemove')
|
|
||||||
$('#fremove').click(function (e) {
|
|
||||||
$.post({
|
|
||||||
url: '/admin/api/client/delete/' + id,
|
|
||||||
success: function (data) {
|
|
||||||
window.Dialog.close()
|
|
||||||
loadClients(1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadClients (page) {
|
|
||||||
$.ajax({
|
|
||||||
type: 'get',
|
|
||||||
url: '/admin/api/clients',
|
|
||||||
data: {page: page},
|
|
||||||
success: function (data) {
|
|
||||||
$('#clientlist').html('')
|
|
||||||
if (data.error) {
|
|
||||||
$('#clientlist').html('<div class="message error">' + data.error + '</div>')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var pgbtn = paginationButton(data.page)
|
|
||||||
$('#clientlist').append(pgbtn)
|
|
||||||
$('#clientlist .pgn .button').click(function (e) {
|
|
||||||
var pgnum = $(this).data('page')
|
|
||||||
if (pgnum == null) return
|
|
||||||
loadClients(parseInt(pgnum))
|
|
||||||
})
|
|
||||||
|
|
||||||
for (var u in data.clients) {
|
|
||||||
var client = data.clients[u]
|
|
||||||
client.created_at = new Date(client.created_at)
|
|
||||||
var tmp = buildTemplateScript('client', client)
|
|
||||||
$('#clientlist').append(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#clientlist .edit').click(function (e) {
|
|
||||||
var client = $(this).data('client')
|
|
||||||
editClient(parseInt(client))
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#clientlist .delete').click(function (e) {
|
|
||||||
var client = $(this).data('client')
|
|
||||||
deleteClient(parseInt(client))
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#clientlist .newsecret').click(function (e) {
|
|
||||||
var client = $(this).data('client')
|
|
||||||
$.post({
|
|
||||||
url: '/admin/api/client/new_secret/' + parseInt(client),
|
|
||||||
success: function (e) {
|
|
||||||
loadClients(1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
|
||||||
window.Dialog = $('#dialog')
|
|
||||||
window.Dialog.open = function (title, content, pad) {
|
|
||||||
$('#dialog #title').text(title)
|
|
||||||
if (pad) {
|
|
||||||
content = '<div class="pad">' + content + '</div>'
|
|
||||||
}
|
|
||||||
$('#dialog #content').html(content)
|
|
||||||
$('#dialog').fadeIn()
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
window.Dialog.close = function () {
|
|
||||||
$('#dialog').fadeOut('fast', function () {
|
Vue.component('BanModal', {
|
||||||
$('#dialog #content').html('')
|
template: '#ban-modal-template',
|
||||||
})
|
props: ['show', 'id'],
|
||||||
}
|
data: function () {
|
||||||
|
return {
|
||||||
window.Dialog.openTemplate = function (title, template, data) {
|
error: '',
|
||||||
window.Dialog.open(title, buildTemplateScript(template, data || {}), true)
|
reason: '',
|
||||||
}
|
expires_at: null
|
||||||
|
}
|
||||||
$('#dialog #close').click(function (e) {
|
},
|
||||||
window.Dialog.close()
|
methods: {
|
||||||
})
|
close: function () {
|
||||||
|
this.$emit('close')
|
||||||
if ($('#userlist').length) {
|
this.error = ''
|
||||||
loadUsers(1)
|
this.reason = ''
|
||||||
}
|
this.expires_at = null
|
||||||
|
},
|
||||||
if ($('#banlist').length) {
|
submit: function () {
|
||||||
loadBans(1)
|
this.$http.post('/admin/api/ban', {
|
||||||
}
|
user_id: this.id,
|
||||||
|
reason: this.reason,
|
||||||
if ($('#clientlist').length) {
|
expires_at: this.expires_at,
|
||||||
loadClients(1)
|
csrf: csrfToken
|
||||||
|
}).then(data => {
|
||||||
$('#new').click(function (e) {
|
this.close()
|
||||||
window.Dialog.openTemplate('New Client', 'clientNew')
|
banList.getBans(1)
|
||||||
$('#fnsubmit').submit(function (e) {
|
}).catch(err => {
|
||||||
e.preventDefault()
|
console.log(err)
|
||||||
$.post({
|
if (err.body && err.body.error) this.error = err.body.error
|
||||||
url: '/admin/api/client/new',
|
})
|
||||||
data: $(this).serialize(),
|
}
|
||||||
success: function (data) {
|
}
|
||||||
window.Dialog.close()
|
})
|
||||||
loadClients(1)
|
|
||||||
},
|
const userList = new Vue({
|
||||||
error: function (e) {
|
el: '#userlist',
|
||||||
if (e.responseJSON && e.responseJSON.error) {
|
data: {
|
||||||
$('form .message').show()
|
pagination: {
|
||||||
$('form .message').text(e.responseJSON.error)
|
offset: 0,
|
||||||
}
|
page: 1,
|
||||||
}
|
pages: 1,
|
||||||
})
|
perPage: 6,
|
||||||
})
|
total: 0
|
||||||
})
|
},
|
||||||
}
|
users: [],
|
||||||
|
banning: 0
|
||||||
setInterval(function () {
|
},
|
||||||
$.get({
|
mounted: function () {
|
||||||
url: '/admin/access'
|
this.getUsers(1)
|
||||||
}).fail(function () {
|
},
|
||||||
window.location.reload()
|
methods: {
|
||||||
})
|
getUsers: function (page) {
|
||||||
}, 30000)
|
this.$http.get('/admin/api/users?page=' + page).then(data => {
|
||||||
|
if (data.body && data.body.error) return
|
||||||
|
this.pagination = data.body.page
|
||||||
|
this.users = data.body.users
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const banList = new Vue({
|
||||||
|
el: '#banlist',
|
||||||
|
data: {
|
||||||
|
pagination: {
|
||||||
|
offset: 0,
|
||||||
|
page: 1,
|
||||||
|
pages: 1,
|
||||||
|
perPage: 6,
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
error: '',
|
||||||
|
bans: []
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
this.getBans(1)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getBans: function (page) {
|
||||||
|
this.error = ''
|
||||||
|
this.pagination.total = 0
|
||||||
|
this.$http.get('/admin/api/bans?page=' + page).then(data => {
|
||||||
|
if (data.body && data.body.error) {
|
||||||
|
this.error = data.body.error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pagination = data.body.page
|
||||||
|
this.bans = data.body.bans
|
||||||
|
})
|
||||||
|
},
|
||||||
|
pardon: function (id) {
|
||||||
|
this.$http.post('/admin/api/ban/pardon/' + id).then(data => {
|
||||||
|
this.getBans(1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
@ -55,6 +55,21 @@ nav
|
|||||||
.username
|
.username
|
||||||
font-size: 80%
|
font-size: 80%
|
||||||
|
|
||||||
|
.info
|
||||||
|
.section
|
||||||
|
margin: 5px 0
|
||||||
|
.key
|
||||||
|
width: 120px
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
.list
|
||||||
|
padding: 10px
|
||||||
|
.list-item
|
||||||
|
background-color: #f5f5f5
|
||||||
|
padding: 10px
|
||||||
|
&:nth-child(even)
|
||||||
|
background-color: #fff
|
||||||
|
|
||||||
.application
|
.application
|
||||||
height: 200px
|
height: 200px
|
||||||
#hiddensecret
|
#hiddensecret
|
||||||
@ -66,6 +81,63 @@ nav
|
|||||||
cursor: pointer
|
cursor: pointer
|
||||||
display: inline-block
|
display: inline-block
|
||||||
|
|
||||||
|
.modal-mask
|
||||||
|
position: fixed
|
||||||
|
z-index: 9998
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
background-color: rgba(0, 0, 0, .5)
|
||||||
|
display: table
|
||||||
|
transition: opacity .3s ease
|
||||||
|
|
||||||
|
.modal-wrapper
|
||||||
|
display: table-cell
|
||||||
|
vertical-align: middle
|
||||||
|
|
||||||
|
.modal-container
|
||||||
|
width: 300px
|
||||||
|
margin: 0px auto
|
||||||
|
padding: 20px 30px
|
||||||
|
background-color: #fff
|
||||||
|
border-radius: 2px
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, .33)
|
||||||
|
transition: all .3s ease
|
||||||
|
font-family: Helvetica, Arial, sans-serif
|
||||||
|
|
||||||
|
.modal-header h3
|
||||||
|
margin-top: 0
|
||||||
|
color: #42b983
|
||||||
|
|
||||||
|
.modal-body
|
||||||
|
margin: 20px 0
|
||||||
|
|
||||||
|
.modal-default-button
|
||||||
|
float: right
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following styles are auto-applied to elements with
|
||||||
|
* transition="modal" when their visibility is toggled
|
||||||
|
* by Vue.js.
|
||||||
|
*
|
||||||
|
* You can easily play with the modal transition by editing
|
||||||
|
* these styles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.modal-enter
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
.modal-leave-active
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
.modal-enter .modal-container, .modal-leave-active .modal-container
|
||||||
|
-webkit-transform: scale(1.1)
|
||||||
|
transform: scale(1.1)
|
||||||
|
|
||||||
|
.modal-footer
|
||||||
|
min-height: 50px
|
||||||
|
|
||||||
form
|
form
|
||||||
.message
|
.message
|
||||||
display: none
|
display: none
|
||||||
|
@ -197,7 +197,7 @@ input:not([type="submit"])
|
|||||||
box-shadow: inset 2px 2px 5px #ddd
|
box-shadow: inset 2px 2px 5px #ddd
|
||||||
transition: border 0.1s linear
|
transition: border 0.1s linear
|
||||||
|
|
||||||
.button, input[type="submit"]
|
button, .button, input[type="submit"]
|
||||||
display: block
|
display: block
|
||||||
padding: 5px 10px
|
padding: 5px 10px
|
||||||
background-color: #fbfbfb
|
background-color: #fbfbfb
|
||||||
|
@ -5,65 +5,95 @@ block body
|
|||||||
.content
|
.content
|
||||||
h1 Welcome to the Admin Panel
|
h1 Welcome to the Admin Panel
|
||||||
.left
|
.left
|
||||||
.users
|
#userlist
|
||||||
h3 Registered Users
|
h3 Registered Users ({{ pagination.total }})
|
||||||
#userlist
|
.pgn
|
||||||
|
span.pagenum Page {{ pagination.page }} of {{ pagination.pages }}
|
||||||
|
.button(v-if="pagination.page > 1" v-on:click="getUsers(pagination.page - 1)") Previous
|
||||||
|
.button(v-for="n in pagination.pages" v-on:click="getUsers(n)" v-bind:class="{active: n == pagination.page}") {{ n }}
|
||||||
|
.button(v-if="pagination.page < pagination.pages" v-on:click="getUsers(pagination.page + 1)") Next
|
||||||
|
.list.users
|
||||||
|
.user.list-item(v-for="user in users")
|
||||||
|
.avatar
|
||||||
|
img(v-if="user.avatar_file" v-bind:src="'/usercontent/images/' + user.avatar_file")
|
||||||
|
img(v-else src="/static/image/avatar.png")
|
||||||
|
.info
|
||||||
|
.stamps
|
||||||
|
.noactive(v-if="user.activated == false" title="Not activated.")
|
||||||
|
i.fa.fa-fw.fa-envelope
|
||||||
|
.display_name {{ user.display_name }}
|
||||||
|
.username {{ user.id }} - {{ user.username }} ({{ user.uuid }})
|
||||||
|
.email {{ user.email }}
|
||||||
|
.privilege Privilege: level {{ user.nw_privilege }}
|
||||||
|
.timestamp {{ new Date(user.created_at).toString() }}
|
||||||
|
.external(v-if="!user.password")
|
||||||
|
b Used external login
|
||||||
|
.button.ban(v-if="user.bannable" v-on:click="banning = user.id")
|
||||||
|
i.fa.fa-fw.fa-ban
|
||||||
|
|Ban User
|
||||||
|
ban-modal(:show="banning", @close="banning = 0", :id="banning")
|
||||||
.right
|
.right
|
||||||
.users
|
#banlist
|
||||||
h3 Bans
|
h3 Bans ({{pagination.total}})
|
||||||
#banlist
|
.message.error(v-if="error") {{ error }}
|
||||||
|
.entry(v-else)
|
||||||
|
.pgn
|
||||||
|
span.pagenum Page {{ pagination.page }} of {{ pagination.pages }}
|
||||||
|
.button(v-if="pagination.page > 1" v-on:click="getBans(pagination.page - 1)") Previous
|
||||||
|
.button(v-for="n in pagination.pages" v-on:click="getBans(n)" v-bind:class="{active: n == pagination.page}") {{ n }}
|
||||||
|
.button(v-if="pagination.page < pagination.pages" v-on:click="getBans(pagination.page + 1)") Next
|
||||||
|
.list.bans
|
||||||
|
.ban.list-item(v-for="ban in bans")
|
||||||
|
.stamps
|
||||||
|
.noactive(title="Expired" v-if="ban.expired")
|
||||||
|
.fa.fa-fw.fa-ban
|
||||||
|
.info
|
||||||
|
.section
|
||||||
|
span.key User
|
||||||
|
span.value {{ ban.user.display_name }}
|
||||||
|
.section
|
||||||
|
span.key Admin
|
||||||
|
span.value {{ ban.admin.display_name }}
|
||||||
|
.section
|
||||||
|
span.key Reason
|
||||||
|
span.value {{ ban.reason }}
|
||||||
|
.section
|
||||||
|
span.key Placed
|
||||||
|
span.value {{ new Date(ban.created_at).toString() }}
|
||||||
|
.section
|
||||||
|
span.key Expires
|
||||||
|
span.value(v-if="ban.expires_at") {{ new Date(ban.expires_at).toString() }}
|
||||||
|
span.value(v-else)
|
||||||
|
b This ban is permanent.
|
||||||
|
.button.remove(@click="pardon(ban.id)") Pardon
|
||||||
.templates
|
.templates
|
||||||
script(type="x-tmpl-mustache" id="user").
|
script(type="text/x-template" id="modal-template").
|
||||||
<div class="user" id="user-{{id}}">
|
<transition name="modal">
|
||||||
<div class="avatar">
|
<div class="modal-mask" @click="close" v-show="show">
|
||||||
{{#avatar_file}}
|
<div class="modal-wrapper" @click.stop>
|
||||||
<img src="/usercontent/images/{{avatar_file}}">
|
<div class="modal-container">
|
||||||
{{/avatar_file}}
|
<slot></slot>
|
||||||
{{^avatar_file}}
|
</div>
|
||||||
<img src="/static/image/avatar.png">
|
</div>
|
||||||
{{/avatar_file}}
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<div class="stamps">
|
|
||||||
{{^activated}}
|
|
||||||
<div class="noactive" title="Not activated"><i class="fa fa-fw fa-envelope"></i></div>
|
|
||||||
{{/activated}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="display_name">{{display_name}}</div>
|
</transition>
|
||||||
<div class="username">{{id}} - {{username}} ({{uuid}})</div>
|
script(type="text/x-template" id="ban-modal-template").
|
||||||
<div class="email">{{email}}</div>
|
<modal :show="show" @close="close">
|
||||||
<div class="privilege">Privilege: level {{nw_privilege}}</div>
|
<div class="modal-header">
|
||||||
<div class="timestamp">{{created_at}}</div>
|
<h3>Ban user</h3>
|
||||||
{{^password}}
|
|
||||||
<div class="external"><b>Used external login</b></div>
|
|
||||||
{{/password}}
|
|
||||||
{{#bannable}}
|
|
||||||
<div class="button ban" data-id="{{id}}"><i class="fa fa-fw fa-ban"></i>Ban User</div>
|
|
||||||
{{/bannable}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
script(type="x-tmpl-mustache" id="ban").
|
|
||||||
<div class="ban" id="ban-{{user.id}}">
|
|
||||||
<div class="stamps">
|
|
||||||
{{#expired}}
|
|
||||||
<div class="noactive" title="Expired"><i class="fa fa-fw fa-ban"></i></div>
|
|
||||||
{{/expired}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="display_name">User: {{user.display_name}}</div>
|
|
||||||
<div class="display_name">Admin: {{admin.display_name}}</div>
|
<div class="modal-body">
|
||||||
<div class="description">Reason: {{reason}}</div>
|
<div class="message error" v-if="error">{{ error }}</div>
|
||||||
<div class="timestamp">Placed {{created_at}}</div>
|
<input type="hidden" name="user_id" :value="id">
|
||||||
<div class="timestamp">Expires {{expires_at}}</div>
|
<label for="reason">Reason</label>
|
||||||
<div class="button remove" data-id="{{id}}">Pardon</div>
|
<input type="text" id="reason" name="reason" v-model="reason">
|
||||||
</div>
|
<label for="expires_at">Expires</label>
|
||||||
script(type="x-tmpl-mustache" id="banNew").
|
<input type="date" id="expires_at" name="expires_at" v-model="expires_at">
|
||||||
<form id="fnsubmit">
|
</div>
|
||||||
<div class="message error"></div>
|
|
||||||
<input type="hidden" name="csrf" value="#{csrf}">
|
<div class="modal-footer text-right">
|
||||||
<input type="hidden" name="user_id" value="{{id}}">
|
<button @click="submit">Ban</button>
|
||||||
<label for="reason">Reason</label>
|
<button @click="close">Cancel</button>
|
||||||
<input type="text" id="reason" name="reason">
|
</div>
|
||||||
<label for="expires_at">Expires</label>
|
</modal>
|
||||||
<input type="date" id="expires_at" name="expires_at">
|
|
||||||
<input type="submit" value="Create">
|
|
||||||
</form>
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
html
|
html
|
||||||
head
|
head
|
||||||
meta(charset="utf8")
|
meta(charset="utf8")
|
||||||
|
meta(name="csrf-token", content=csrf)
|
||||||
block links
|
block links
|
||||||
link(rel="stylesheet", type="text/css", href="https://fonts.googleapis.com/css?family=Open+Sans")
|
link(rel="stylesheet", type="text/css", href="https://fonts.googleapis.com/css?family=Open+Sans")
|
||||||
link(rel="stylesheet", type="text/css", href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css")
|
link(rel="stylesheet", type="text/css", href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css")
|
||||||
@ -10,7 +11,6 @@ html
|
|||||||
window.variables = {
|
window.variables = {
|
||||||
server_time: parseInt('#{server_time}')
|
server_time: parseInt('#{server_time}')
|
||||||
};
|
};
|
||||||
script(src="/script/admin.js")
|
|
||||||
title
|
title
|
||||||
block title
|
block title
|
||||||
|Icy Network - Administration
|
|Icy Network - Administration
|
||||||
@ -37,3 +37,4 @@ html
|
|||||||
.content#content
|
.content#content
|
||||||
.wrapper
|
.wrapper
|
||||||
block body
|
block body
|
||||||
|
script(src="/script/admin.js")
|
||||||
|
37
webpack.common.js
Normal file
37
webpack.common.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: {
|
||||||
|
main: './src/script/main.js',
|
||||||
|
admin: './src/script/admin.js'
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, 'build', 'script'),
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /(node_modules|bower_components)/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
presets: [
|
||||||
|
'env'
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
'transform-es2015-modules-commonjs'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: []
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
const path = require('path')
|
|
||||||
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
entry: {
|
|
||||||
main: './src/script/main.js',
|
|
||||||
admin: './src/script/admin.js'
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
path: path.join(__dirname, 'build', 'script'),
|
|
||||||
filename: '[name].js'
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new UglifyJSPlugin()
|
|
||||||
]
|
|
||||||
}
|
|
6
webpack.dev.js
Normal file
6
webpack.dev.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const merge = require('webpack-merge')
|
||||||
|
const common = require('./webpack.common.js')
|
||||||
|
|
||||||
|
module.exports = merge(common, {
|
||||||
|
devtool: 'inline-source-map'
|
||||||
|
})
|
13
webpack.prod.js
Normal file
13
webpack.prod.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const webpack = require('webpack')
|
||||||
|
const merge = require('webpack-merge')
|
||||||
|
const common = require('./webpack.common.js')
|
||||||
|
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
|
||||||
|
|
||||||
|
module.exports = merge(common, {
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env.NODE_ENV': JSON.stringify('production')
|
||||||
|
}),
|
||||||
|
new UglifyJSPlugin()
|
||||||
|
]
|
||||||
|
})
|
Reference in New Issue
Block a user