User search bar
This commit is contained in:
parent
61248119c5
commit
234744f5de
@ -154,6 +154,30 @@ const API = {
|
||||
|
||||
return {token}
|
||||
},
|
||||
// Search for users by terms and fields
|
||||
searchUsers: async function (terms, fields = ['email']) {
|
||||
let qb = Models.User.query()
|
||||
|
||||
terms = terms.replace(/_/g, '\\_').replace(/%/g, '\\%')
|
||||
|
||||
qb = qb.where(fields[0], 'like', '%' + terms + '%')
|
||||
if (fields.length >= 1) {
|
||||
for (let i = 1; i < fields.length; i++) {
|
||||
qb = qb.orWhere(fields[i], 'like', '%' + terms + '%')
|
||||
}
|
||||
}
|
||||
|
||||
let rows = await qb.limit(8)
|
||||
if (!rows.length) return { error: 'No results' }
|
||||
|
||||
let cleaned = []
|
||||
for (let i in rows) {
|
||||
let userRaw = rows[i]
|
||||
cleaned.push(await cleanUserObject(userRaw, null))
|
||||
}
|
||||
|
||||
return cleaned
|
||||
},
|
||||
// List all clients (paginated)
|
||||
getAllClients: async function (page) {
|
||||
let count = await Models.OAuth2Client.query().count('id as ids')
|
||||
|
@ -156,6 +156,31 @@ apiRouter.post('/user/reset_password', csrfVerify, wrap(async (req, res) => {
|
||||
res.jsonp(await API.sendPasswordEmail(id))
|
||||
}))
|
||||
|
||||
const availableScopes = ['uuid', 'email', 'username', 'display_name']
|
||||
apiRouter.get('/search/users', wrap(async (req, res) => {
|
||||
if (!req.query.terms) throw new Error('Please specify search terms!')
|
||||
|
||||
let scopes = []
|
||||
if (req.query.scopes) {
|
||||
let scq = req.query.scopes.split(',')
|
||||
|
||||
for (let i in scq) {
|
||||
scq[i] = scq[i].trim()
|
||||
|
||||
if (availableScopes.indexOf(scq[i]) !== -1) {
|
||||
scopes.push(scq[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!scopes.length) {
|
||||
scopes.push('email')
|
||||
}
|
||||
|
||||
let results = await API.searchUsers(req.query.terms, scopes)
|
||||
res.jsonp(results)
|
||||
}))
|
||||
|
||||
/* ===============
|
||||
* OAuth2 Data
|
||||
* ===============
|
||||
|
@ -3,7 +3,10 @@
|
||||
h3 Registered Users ({{ pagination.total }})
|
||||
pagination(:page="pagination.page" :pages="pagination.pages" v-on:page="getUsers")
|
||||
.list.users
|
||||
user(v-for='user in users' v-bind="user" :key="user.id")
|
||||
.searchbox
|
||||
input(v-model="search" placeholder="Begin typing a name or email address..")
|
||||
.message.error(v-if="error") {{ error }}
|
||||
user(v-else v-for='user in users' v-bind="user" :key="user.id")
|
||||
ban-modal(:show='banning' @close='banning = 0' :id='banning')
|
||||
user-modal(:show='editing' @close='editing = 0' :id='editing')
|
||||
</template>
|
||||
@ -13,6 +16,8 @@
|
||||
import User from './User.vue'
|
||||
import BanModal from './BanModal.vue'
|
||||
import UserModal from './UserModal.vue'
|
||||
|
||||
import qs from 'querystring'
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
||||
|
||||
export default {
|
||||
@ -27,7 +32,9 @@
|
||||
},
|
||||
users: [],
|
||||
banning: 0,
|
||||
editing: 0
|
||||
editing: 0,
|
||||
search: '',
|
||||
error: ''
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@ -35,11 +42,35 @@
|
||||
},
|
||||
methods: {
|
||||
getUsers: function (page) {
|
||||
this.error = ''
|
||||
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
|
||||
})
|
||||
},
|
||||
searchUsers: function () {
|
||||
this.error = ''
|
||||
this.$http.get('/admin/api/search/users?' + qs.stringify({
|
||||
terms: this.search,
|
||||
scopes: 'email,username,display_name'
|
||||
})).then(data => {
|
||||
if (data.body.error) {
|
||||
this.error = data.body.error
|
||||
return
|
||||
}
|
||||
|
||||
this.users = data.body
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
search: function () {
|
||||
if (this.search === '') {
|
||||
this.getUsers(1)
|
||||
} else {
|
||||
this.searchUsers(this.search)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
|
@ -133,6 +133,13 @@ nav
|
||||
border-bottom: 1px solid #ddd
|
||||
margin-bottom: 9px
|
||||
|
||||
.searchbox
|
||||
margin: 10px 0
|
||||
|
||||
input
|
||||
font-size: 140%
|
||||
display: block
|
||||
width: 100%
|
||||
|
||||
.modal-mask
|
||||
position: fixed
|
||||
|
Reference in New Issue
Block a user