diff --git a/src/views/Admin.vue b/src/views/Admin.vue index 317f7238a4c35c33864829fbe05f93c20544e09f..2d47afb646350a3a954dce1d84fc61e72c660933 100644 --- a/src/views/Admin.vue +++ b/src/views/Admin.vue @@ -3,49 +3,80 @@ <div class="box"> <h1 class="title">Admin panel</h1> <b-tabs> - <b-tab-item label="Models"> - <b-table :data="modelList" :loading="isLoading" striped hoverable> - <template slot-scope="props"> - <b-table-column field="name" label="Model name" searchable sortable> - {{ props.row.name }} - </b-table-column> + <b-tab-item label="Models"> + <b-table :data="modelList" :loading="isLoading" striped hoverable> + <template slot-scope="props"> + <b-table-column field="name" label="Model name" searchable sortable> + {{ props.row.name }} + </b-table-column> - <b-table-column field="vote" label="Votes" sortable> - {{ props.row.votes }} - </b-table-column> + <b-table-column field="vote" label="Votes" sortable> + {{ props.row.votes }} + </b-table-column> - <b-table-column field="date" label="Last modification" centered sortable> - {{ new Date(props.row.modificationDate).toLocaleDateString() }} - </b-table-column> + <b-table-column field="date" label="Last modification" centered sortable> + {{ new Date(props.row.modificationDate).toLocaleDateString() }} + </b-table-column> - <b-table-column field="date" label="Added" centered sortable> - {{ new Date(props.row.addedDate).toLocaleDateString() }} - </b-table-column> + <b-table-column field="date" label="Added" centered sortable> + {{ new Date(props.row.addedDate).toLocaleDateString() }} + </b-table-column> - <b-table-column label="" centered> - <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removeUserPrompt(props.row.id, props.row.name)" outlined/> - </b-table-column> - </template> - </b-table> - </b-tab-item> + <b-table-column label="" centered> + <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removePrompt(props.row.id, props.row.name, 'model')" outlined/> + </b-table-column> + </template> + </b-table> + </b-tab-item> - <b-tab-item label="Users"> - <b-table :data="userList" :loading="isLoading" striped hoverable> - <template slot-scope="props"> - <b-table-column field="username" label="Username" searchable sortable> - {{ props.row.name }} - </b-table-column> + <b-tab-item label="Tags"> + <div class="buttons"> + <b-button type="is-info" @click="addNewCategoryDialog">Add Category</b-button> + </div> - <b-table-column field="email" label="Email" searchable sortable> - {{ props.row.name }} - </b-table-column> + <b-table :data="tagList" :loading="isLoading" striped hoverable detailed> + <template slot-scope="props"> + <b-table-column field="name" label="Category" searchable sortable> + {{ props.row.name }} + </b-table-column> - <b-table-column label="" centered> - <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removeModelPrompt(props.row.id, props.row.name)" outlined/> - </b-table-column> - </template> - </b-table> - </b-tab-item> + <b-table-column label="" centered> + <b-button class="actionButton" icon-left="plus" type="is-info" @click="addNewTagDialog(props.row.id)">Add Tag</b-button> + <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removePrompt(props.row.id, props.row.name, 'category')" outlined>Remove category</b-button> + </b-table-column> + </template> + + <template slot="detail" slot-scope="props"> + <tr v-for="tag in props.row.tags" :key="tag.name"> + <td> + {{tag.name}} + </td> + <td> + <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removePrompt(tag.id, tag.name, 'tag')" outlined/> + </td> + </tr> + </template> + + </b-table> + </b-tab-item> + + <b-tab-item label="Users"> + <b-table :data="userList" :loading="isLoading" striped hoverable> + <template slot-scope="props"> + <b-table-column field="username" label="Username" searchable sortable> + {{ props.row.username }} + </b-table-column> + + <b-table-column field="email" label="Email" searchable sortable> + {{ props.row.email }} + </b-table-column> + + <b-table-column label="" centered> + <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removePrompt(props.row.id, props.row.username, 'user')" outlined/> + </b-table-column> + </template> + </b-table> + </b-tab-item> </b-tabs> </div> </div> @@ -57,18 +88,21 @@ export default { data () { return { isLoading: true, - userList: null, - modelList: null + userList: [], + modelList: [], + tagList: [] } }, async mounted () { this.modelList = await this.getModelList() this.userList = await this.getUserList() + this.tagList = await this.getTags() + this.isLoading = false }, methods: { async getModelList () { const token = await localStorage.getItem('token') - const url = this.$serverurl + 'user/list' + const url = this.$serverurl + 'models/list' try { const response = await fetch(url, { headers: { Authorization: 'Bearer ' + token } }) return await response.json() @@ -78,18 +112,135 @@ export default { }, async getUserList () { const token = await localStorage.getItem('token') - const url = this.$serverurl + 'model/list' + const url = this.$serverurl + 'user/list' try { const response = await fetch(url, { headers: { Authorization: 'Bearer ' + token } }) return await response.json() } catch (error) { return null } + }, + async getTags () { + const url = this.$serverurl + 'models/tags' + const response = await fetch(url) + try { + return await response.json() + } catch (error) { + return null + } + }, + removePrompt (id, name, mode) { + this.$buefy.dialog.confirm({ + message: 'Delete ' + name + ' ?', + cancelText: 'Abort', + confirmText: 'Delete', + type: 'is-danger', + hasIcon: true, + onConfirm: async () => { + switch (mode) { + case 'user' : this.remove(id, name, 'user'); break + case 'model' : this.remove(id, name, 'models'); break + case 'tag' : this.remove(id, name, 'models/tags'); break + case 'category' : this.remove(id, name, 'models/category'); break + } + this.modelList = await this.getModelList() + this.userList = await this.getUserList() + this.tagList = await this.getTags() + } + }) + }, + async remove (id, name, type) { + const token = await localStorage.getItem('token') + const url = this.$serverurl + type + '?id=' + id + try { + await fetch(url, { + method: 'DELETE', + headers: { + Authorization: 'Bearer ' + token + } + }) + this.$buefy.toast.open(name + ' deleted') + } catch (error) { + this.$buefy.toast.open('Delete error ' + error) + } + }, + addNewTagDialog (categoryId) { + this.$buefy.dialog.prompt({ + message: 'Tag', + inputAttrs: { + maxlength: 20 + }, + confirmText: 'Add', + onConfirm: async (value) => { + await this.addNewTag(value, categoryId) + this.tagList = await this.getTags() + } + }) + }, + async addNewTag (tag, categoryId) { + const url = this.$serverurl + 'models/tags' + const token = await localStorage.getItem('token') + try { + const response = await fetch( + url, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + Authorization: 'Bearer ' + token + }, + body: JSON.stringify({ + name: tag, + categoryId: categoryId + }) + } + ) + return await response.json() + } catch (error) { + return null + } + }, + addNewCategoryDialog () { + this.$buefy.dialog.prompt({ + message: 'Category', + inputAttrs: { + maxlength: 20 + }, + confirmText: 'Add', + onConfirm: async (value) => { + await this.addNewCategory(value) + this.tagList = await this.getTags() + } + }) + }, + async addNewCategory (name) { + const url = this.$serverurl + 'models/category' + const token = await localStorage.getItem('token') + try { + const response = await fetch( + url, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + Authorization: 'Bearer ' + token + }, + body: JSON.stringify({ + name: name + }) + } + ) + return await response.json() + } catch (error) { + return null + } } } } </script> -<style> - +<style scoped> +.actionButton { + margin-left:8px; +} </style>