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",
|
||||
"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",
|
||||
"js": "webpack",
|
||||
"js:watch": "webpack -w",
|
||||
"js": "webpack --config webpack.prod.js -p",
|
||||
"js:watch": "webpack --config webpack.dev.js -w",
|
||||
"watch": "concurrently --kill-others \"npm run css:watch\" \"npm run js:watch\"",
|
||||
"clean": "rm -rf build/",
|
||||
"build": "npm run clean && npm run css && npm run js"
|
||||
@ -30,43 +30,48 @@
|
||||
},
|
||||
"homepage": "https://github.com/IcyNet/IcyNet.eu#readme",
|
||||
"dependencies": {
|
||||
"babel-core": "^6.25.0",
|
||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"bluebird": "^3.5.0",
|
||||
"body-parser": "^1.17.2",
|
||||
"connect-redis": "^3.3.0",
|
||||
"connect-session-knex": "^1.3.4",
|
||||
"bluebird": "^3.5.1",
|
||||
"body-parser": "^1.18.2",
|
||||
"connect-redis": "^3.3.2",
|
||||
"connect-session-knex": "^1.4.0",
|
||||
"email-templates": "^2.7.1",
|
||||
"express": "^4.15.3",
|
||||
"express": "^4.16.2",
|
||||
"express-rate-limit": "^2.9.0",
|
||||
"express-session": "^1.15.3",
|
||||
"express-session": "^1.15.6",
|
||||
"fs-extra": "^4.0.2",
|
||||
"gm": "^1.23.0",
|
||||
"knex": "^0.13.0",
|
||||
"multiparty": "^4.1.3",
|
||||
"mysql": "^2.13.0",
|
||||
"nodemailer": "^4.0.1",
|
||||
"mysql": "^2.15.0",
|
||||
"nodemailer": "^4.4.0",
|
||||
"notp": "^2.0.3",
|
||||
"oauth-libre": "^0.9.17",
|
||||
"objection": "^0.8.4",
|
||||
"pug": "^2.0.0-rc.3",
|
||||
"serve-favicon": "^2.4.3",
|
||||
"objection": "^0.8.9",
|
||||
"pug": "^2.0.0-rc.4",
|
||||
"serve-favicon": "^2.4.5",
|
||||
"stylus": "^0.54.5",
|
||||
"thirty-two": "^1.0.2",
|
||||
"toml": "^2.3.2",
|
||||
"uuid": "^3.1.0"
|
||||
"toml": "^2.3.3",
|
||||
"uuid": "^3.1.0",
|
||||
"vue": "^2.5.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^3.5.0",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"concurrently": "^3.5.1",
|
||||
"eslint-plugin-import": "^2.8.0",
|
||||
"jquery": "^3.2.1",
|
||||
"morgan": "^1.9.0",
|
||||
"mustache": "^2.3.0",
|
||||
"standard": "^10.0.3",
|
||||
"uglifyjs-webpack-plugin": "^0.4.6",
|
||||
"vue-resource": "^1.3.4",
|
||||
"watch": "^1.0.2",
|
||||
"webpack": "^3.6.0"
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-merge": "^4.1.1"
|
||||
},
|
||||
"standard": {
|
||||
"env": {
|
||||
|
@ -1,284 +1,122 @@
|
||||
window.$ = require('jquery')
|
||||
var Mustache = require('mustache')
|
||||
import Vue from 'vue'
|
||||
import VueResource from 'vue-resource'
|
||||
|
||||
function buildTemplateScript (id, ctx) {
|
||||
var tmpl = $('#' + id)
|
||||
if (!tmpl.length) return null
|
||||
var data = tmpl.html()
|
||||
Mustache.parse(data)
|
||||
return Mustache.render(data, ctx)
|
||||
}
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
||||
|
||||
function paginationButton (pages) {
|
||||
var html = '<div class="pgn">'
|
||||
html += '<span class="pagenum">Page ' + pages.page + ' of ' + pages.pages + '</span>'
|
||||
Vue.use(VueResource)
|
||||
|
||||
if (pages.page > 1) {
|
||||
html += '<div class="button" data-page="' + (pages.page - 1) + '">Previous</div>'
|
||||
}
|
||||
|
||||
for (var i = 0; i < pages.pages; i++) {
|
||||
html += '<div class="button' + (i + 1 === pages.page ? ' active' : '') + '" data-page="' + (i + 1) + '">' + (i + 1) + '</div>'
|
||||
}
|
||||
|
||||
if (pages.pages > pages.page) {
|
||||
html += '<div class="button" data-page="' + (pages.page + 1) + '">Next</div>'
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
Vue.component('Modal', {
|
||||
template: '#modal-template',
|
||||
props: ['show'],
|
||||
methods: {
|
||||
close: function () {
|
||||
this.$emit('close')
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (this.show && e.keyCode === 27) {
|
||||
this.close()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
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 () {
|
||||
$('#dialog #content').html('')
|
||||
})
|
||||
}
|
||||
|
||||
window.Dialog.openTemplate = function (title, template, data) {
|
||||
window.Dialog.open(title, buildTemplateScript(template, data || {}), true)
|
||||
}
|
||||
|
||||
$('#dialog #close').click(function (e) {
|
||||
window.Dialog.close()
|
||||
})
|
||||
|
||||
if ($('#userlist').length) {
|
||||
loadUsers(1)
|
||||
}
|
||||
|
||||
if ($('#banlist').length) {
|
||||
loadBans(1)
|
||||
}
|
||||
|
||||
if ($('#clientlist').length) {
|
||||
loadClients(1)
|
||||
|
||||
$('#new').click(function (e) {
|
||||
window.Dialog.openTemplate('New Client', 'clientNew')
|
||||
$('#fnsubmit').submit(function (e) {
|
||||
e.preventDefault()
|
||||
$.post({
|
||||
url: '/admin/api/client/new',
|
||||
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)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
setInterval(function () {
|
||||
$.get({
|
||||
url: '/admin/access'
|
||||
}).fail(function () {
|
||||
window.location.reload()
|
||||
})
|
||||
}, 30000)
|
||||
})
|
||||
|
||||
Vue.component('BanModal', {
|
||||
template: '#ban-modal-template',
|
||||
props: ['show', 'id'],
|
||||
data: function () {
|
||||
return {
|
||||
error: '',
|
||||
reason: '',
|
||||
expires_at: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close: function () {
|
||||
this.$emit('close')
|
||||
this.error = ''
|
||||
this.reason = ''
|
||||
this.expires_at = null
|
||||
},
|
||||
submit: function () {
|
||||
this.$http.post('/admin/api/ban', {
|
||||
user_id: this.id,
|
||||
reason: this.reason,
|
||||
expires_at: this.expires_at,
|
||||
csrf: csrfToken
|
||||
}).then(data => {
|
||||
this.close()
|
||||
banList.getBans(1)
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
if (err.body && err.body.error) this.error = err.body.error
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const userList = new Vue({
|
||||
el: '#userlist',
|
||||
data: {
|
||||
pagination: {
|
||||
offset: 0,
|
||||
page: 1,
|
||||
pages: 1,
|
||||
perPage: 6,
|
||||
total: 0
|
||||
},
|
||||
users: [],
|
||||
banning: 0
|
||||
},
|
||||
mounted: function () {
|
||||
this.getUsers(1)
|
||||
},
|
||||
methods: {
|
||||
getUsers: function (page) {
|
||||
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
|
||||
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
|
||||
height: 200px
|
||||
#hiddensecret
|
||||
@ -66,6 +81,63 @@ nav
|
||||
cursor: pointer
|
||||
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
|
||||
.message
|
||||
display: none
|
||||
|
@ -197,7 +197,7 @@ input:not([type="submit"])
|
||||
box-shadow: inset 2px 2px 5px #ddd
|
||||
transition: border 0.1s linear
|
||||
|
||||
.button, input[type="submit"]
|
||||
button, .button, input[type="submit"]
|
||||
display: block
|
||||
padding: 5px 10px
|
||||
background-color: #fbfbfb
|
||||
|
@ -5,65 +5,95 @@ block body
|
||||
.content
|
||||
h1 Welcome to the Admin Panel
|
||||
.left
|
||||
.users
|
||||
h3 Registered Users
|
||||
#userlist
|
||||
#userlist
|
||||
h3 Registered Users ({{ pagination.total }})
|
||||
.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
|
||||
.users
|
||||
h3 Bans
|
||||
#banlist
|
||||
#banlist
|
||||
h3 Bans ({{pagination.total}})
|
||||
.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
|
||||
script(type="x-tmpl-mustache" id="user").
|
||||
<div class="user" id="user-{{id}}">
|
||||
<div class="avatar">
|
||||
{{#avatar_file}}
|
||||
<img src="/usercontent/images/{{avatar_file}}">
|
||||
{{/avatar_file}}
|
||||
{{^avatar_file}}
|
||||
<img src="/static/image/avatar.png">
|
||||
{{/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}}
|
||||
script(type="text/x-template" id="modal-template").
|
||||
<transition name="modal">
|
||||
<div class="modal-mask" @click="close" v-show="show">
|
||||
<div class="modal-wrapper" @click.stop>
|
||||
<div class="modal-container">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="display_name">{{display_name}}</div>
|
||||
<div class="username">{{id}} - {{username}} ({{uuid}})</div>
|
||||
<div class="email">{{email}}</div>
|
||||
<div class="privilege">Privilege: level {{nw_privilege}}</div>
|
||||
<div class="timestamp">{{created_at}}</div>
|
||||
{{^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}}
|
||||
</transition>
|
||||
script(type="text/x-template" id="ban-modal-template").
|
||||
<modal :show="show" @close="close">
|
||||
<div class="modal-header">
|
||||
<h3>Ban user</h3>
|
||||
</div>
|
||||
<div class="display_name">User: {{user.display_name}}</div>
|
||||
<div class="display_name">Admin: {{admin.display_name}}</div>
|
||||
<div class="description">Reason: {{reason}}</div>
|
||||
<div class="timestamp">Placed {{created_at}}</div>
|
||||
<div class="timestamp">Expires {{expires_at}}</div>
|
||||
<div class="button remove" data-id="{{id}}">Pardon</div>
|
||||
</div>
|
||||
script(type="x-tmpl-mustache" id="banNew").
|
||||
<form id="fnsubmit">
|
||||
<div class="message error"></div>
|
||||
<input type="hidden" name="csrf" value="#{csrf}">
|
||||
<input type="hidden" name="user_id" value="{{id}}">
|
||||
<label for="reason">Reason</label>
|
||||
<input type="text" id="reason" name="reason">
|
||||
<label for="expires_at">Expires</label>
|
||||
<input type="date" id="expires_at" name="expires_at">
|
||||
<input type="submit" value="Create">
|
||||
</form>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="message error" v-if="error">{{ error }}</div>
|
||||
<input type="hidden" name="user_id" :value="id">
|
||||
<label for="reason">Reason</label>
|
||||
<input type="text" id="reason" name="reason" v-model="reason">
|
||||
<label for="expires_at">Expires</label>
|
||||
<input type="date" id="expires_at" name="expires_at" v-model="expires_at">
|
||||
</div>
|
||||
|
||||
<div class="modal-footer text-right">
|
||||
<button @click="submit">Ban</button>
|
||||
<button @click="close">Cancel</button>
|
||||
</div>
|
||||
</modal>
|
||||
|
@ -1,6 +1,7 @@
|
||||
html
|
||||
head
|
||||
meta(charset="utf8")
|
||||
meta(name="csrf-token", content=csrf)
|
||||
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://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css")
|
||||
@ -10,7 +11,6 @@ html
|
||||
window.variables = {
|
||||
server_time: parseInt('#{server_time}')
|
||||
};
|
||||
script(src="/script/admin.js")
|
||||
title
|
||||
block title
|
||||
|Icy Network - Administration
|
||||
@ -37,3 +37,4 @@ html
|
||||
.content#content
|
||||
.wrapper
|
||||
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