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>
+                  &nbsp;&nbsp;&nbsp;&nbsp;{{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>