diff --git a/src/components/Filters.vue b/src/components/Filters.vue
index c9e4c2d040dce593d55c60afe92e523706f576f4..07d21b79452501672718b164afd2349f262ef871 100644
--- a/src/components/Filters.vue
+++ b/src/components/Filters.vue
@@ -1,21 +1,6 @@
 <template>
   <b-menu>
     <div>
-      <b-menu-list label="minimum performance">
-        <b-slider
-          v-model="perfValue"
-          :min="0" :max="3"
-          :tooltip="false"
-          ticks
-          lazy
-          @change="changeTag"
-        >
-          <b-slider-tick :value="0">10</b-slider-tick>
-          <b-slider-tick :value="1">100</b-slider-tick>
-          <b-slider-tick :value="2">1000</b-slider-tick>
-          <b-slider-tick :value="3">10000</b-slider-tick>
-        </b-slider>
-      </b-menu-list>
       <b-menu-list v-for="category in tags" v-bind:key="category.name" :label="category.name">
         <div v-for="tag in category.tags" v-bind:key="tag" class="field">
           <b-checkbox
diff --git a/src/components/ModelTable.vue b/src/components/ModelTable.vue
index 817fec6a537a2b2557da157dee4a970db9da11e1..f080a5eb9bde06b222c3f4c5be549738f48f1480 100644
--- a/src/components/ModelTable.vue
+++ b/src/components/ModelTable.vue
@@ -6,7 +6,7 @@
       </b-table-column>
 
       <b-table-column field="vote" label="Votes" sortable>
-        {{ props.row.vote }}
+        {{ props.row.votes }}
       </b-table-column>
 
       <b-table-column field="date" label="Last modification" centered sortable>
@@ -20,7 +20,7 @@
       <b-table-column label="" centered>
         <b-button class="actionButton" icon-left="eye" type="is-info" tag="router-link" :to="{ name: 'Model', query: { id: props.row.id } }" outlined/>
         <b-button class="actionButton" icon-left="pencil" type="is-warning" tag="router-link" :to="{ name: 'ModelEdit', params: {model: props.row} }" outlined/>
-        <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removePrompt(props.row.id)" outlined/>
+        <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removePrompt(props.row.id, props.row.name)" outlined/>
       </b-table-column>
     </template>
   </b-table>
@@ -53,31 +53,30 @@ export default {
     edit (id) {
 
     },
-    removePrompt (id) {
-      const name = this.models[id].name
+    removePrompt (id, name) {
       this.$buefy.dialog.confirm({
         message: 'Delete ' + name + ' ?',
         cancelText: 'Abort',
         confirmText: 'Delete',
         type: 'is-danger',
         hasIcon: true,
-        onConfirm: () => this.remove(id)
+        onConfirm: () => this.remove(id, name)
       })
     },
-    async remove (id) {
-      const url = this.$$serverurl + 'models' + '?id=' + id
-      const name = this.models[id].name
+    async remove (id, name) {
+      const token = await localStorage.getItem('token')
+      const url = this.$serverurl + 'models' + '?id=' + id
       try {
         await fetch(url, {
           method: 'DELETE',
           headers: {
-            Authorization: 'Bearer ' + this.token
+            Authorization: 'Bearer ' + token
           }
         })
         this.$buefy.toast.open(name + ' deleted')
-        this.getData()
+        this.getModels()
       } catch (error) {
-        this.$buefy.toast.open('Delete error')
+        this.$buefy.toast.open('Delete error ' + error)
       }
     }
   }
diff --git a/src/components/ModelUpload.vue b/src/components/ModelUpload.vue
index e535dc5dd8b15b8c7104c188b2fd1663048ab2b7..b67ffa0c328a07cfee2fbead41436947849060b3 100644
--- a/src/components/ModelUpload.vue
+++ b/src/components/ModelUpload.vue
@@ -3,7 +3,7 @@
     <b-progress :value="progress" size="is-large" show-value :type="status">
       {{statusMessage}}
     </b-progress>
-    <b-progress v-if="subProgress" size="is-medium">
+    <b-progress v-if="subProgress" size="is-large">
       {{subMessage}}
     </b-progress>
     <b-button
@@ -116,8 +116,7 @@ export default {
             shortDescription: this.model.shortDescription,
             longDescription: this.model.longDescription,
             performance: this.model.performance,
-            tags: this.model.tags,
-            customLayers: this.model.customLayers
+            tags: this.model.tags
           })
         })
         return await response.json()
@@ -127,10 +126,11 @@ export default {
     },
     async uploadModelFile () {
       const data = new FormData()
-      const url = this.$serverurl + 'models?id=' + this.modelId + '/upload'
+      const url = this.$serverurl + 'models/upload'
       const token = await localStorage.getItem('token')
 
-      data.append('model', this.model.file)
+      data.append('file', this.model.file)
+      data.append('id', this.modelId)
 
       try {
         const response = await fetch(url, {
@@ -152,14 +152,17 @@ export default {
       for (var i = 0; i < this.model.customLayers.length; i++) {
         const layer = this.model.customLayers[i]
         const data = new FormData()
-        const url = this.$serverurl + 'models?id=' + this.modelId + '/layer?id=' + i
+        const url = this.$serverurl + 'models/uploadLayer'
 
         this.subMessage = 'Uploading ' + layer.name
 
-        console.log('Upload layers ' + i + ' | ' + layer.file)
+        console.log('Uploading layer ' + i + ' | ' + layer.file)
         if (layer.file === undefined) continue
+        if (layer.name === undefined) continue
 
-        data.append('layer', layer.file)
+        data.append('file', layer.file)
+        data.append('name', layer.name)
+        data.append('id', this.modelId)
 
         try {
           const response = await fetch(url, {
diff --git a/src/components/Navbar.vue b/src/components/Navbar.vue
index 11b96f9680e71a1e9ecf778c41124f4f23a915e4..39801c581ec8953f8298571b061abff5444bea31 100644
--- a/src/components/Navbar.vue
+++ b/src/components/Navbar.vue
@@ -106,6 +106,8 @@ export default {
     logout () {
       this.isLogged = false
       localStorage.removeItem('token')
+      localStorage.removeItem('user_role')
+      localStorage.removeItem('user_id')
       this.$router.push({ name: 'Home' })
     }
   }
diff --git a/src/router/index.js b/src/router/index.js
index 0e97d71d61db92392316d137351afac962c9353f..25e57a8fef78b0c158ab7043d2973d089be7c588 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -59,6 +59,14 @@ const routes = [
     meta: {
       requiresAuth: true
     }
+  },
+  {
+    path: '/admin',
+    name: 'Admin',
+    component: () => import('../views/Admin.vue'),
+    meta: {
+      requiresAuth: true
+    }
   }
 ]
 
diff --git a/src/views/Account.vue b/src/views/Account.vue
index dd88602c61d38ad968de53bb7dd1a4881d198d01..67c5b826ccb88c30919469facc563106a9e421e5 100644
--- a/src/views/Account.vue
+++ b/src/views/Account.vue
@@ -19,6 +19,16 @@
         >
         Change account details
         </b-button>
+
+        <b-button
+         v-if="account.role == 'ROLE_ADMIN'"
+         icon-left="cctv"
+         type="is-info"
+         tag="router-link"
+         :to="{ name: 'Admin' }"
+        >
+        Admin panel
+        </b-button>
       </div>
     </div>
     <div class="box">
@@ -43,6 +53,8 @@ export default {
   },
   async mounted () {
     this.account = await this.getAccount()
+    await localStorage.setItem('user_role', this.account.role)
+    await localStorage.setItem('user_id', this.account.id)
   },
   methods: {
     async getAccount () {
diff --git a/src/views/Admin.vue b/src/views/Admin.vue
new file mode 100644
index 0000000000000000000000000000000000000000..317f7238a4c35c33864829fbe05f93c20544e09f
--- /dev/null
+++ b/src/views/Admin.vue
@@ -0,0 +1,95 @@
+<template>
+  <div class="adminDiv container">
+    <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-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="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-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-table-column field="email" label="Email" 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-tabs>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Admin',
+  data () {
+    return {
+      isLoading: true,
+      userList: null,
+      modelList: null
+    }
+  },
+  async mounted () {
+    this.modelList = await this.getModelList()
+    this.userList = await this.getUserList()
+  },
+  methods: {
+    async getModelList () {
+      const token = await localStorage.getItem('token')
+      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 getUserList () {
+      const token = await localStorage.getItem('token')
+      const url = this.$serverurl + 'model/list'
+      try {
+        const response = await fetch(url, { headers: { Authorization: 'Bearer ' + token } })
+        return await response.json()
+      } catch (error) {
+        return null
+      }
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>
diff --git a/src/views/Model.vue b/src/views/Model.vue
index 5687df5c0371c15d8acd9fc44fc2126d002414a4..caa5690a3be524994429570c813bc31dd9f6e409 100644
--- a/src/views/Model.vue
+++ b/src/views/Model.vue
@@ -14,7 +14,12 @@
           </b-taglist>
         </div>
         <div class="column infoColumn">
-          <h1 class="title is-4">{{model.vote}} votes <b-button size="is-small" icon-left="heart-outline" style="top:-2px"/></h1>
+          <div v-if="isAuthor">
+            <b-button icon-left="pencil" type="is-warning" tag="router-link" :to="{ name: 'ModelEdit', params: {model: model} }">Edit model</b-button>
+            <br>
+            <br>
+          </div>
+          <h1 class="title is-4">{{model.votes}} votes <b-button size="is-small" icon-left="heart-outline" style="top:-2px"/></h1>
           <small>Author: </small><strong>{{model.author.username}}</strong>
           <br>
           <small>Added: </small><strong>{{new Date(model.addedDate).toLocaleDateString()}}</strong>
@@ -66,7 +71,8 @@ export default {
     return {
       model: '',
       isError: false,
-      isLoading: true
+      isLoading: true,
+      isAuthor: false
     }
   },
   computed: {
@@ -79,6 +85,12 @@ export default {
     this.model = await this.getModel(id)
     if (this.model == null) this.isError = true
     this.isLoading = false
+
+    const userId = await localStorage.getItem('user_id')
+    if (parseInt(userId) === this.model.author.id) this.isAuthor = true
+
+    const userRole = await localStorage.getItem('user_role')
+    if (userRole === 'ROLE_ADMIN') this.isAuthor = true
   },
   methods: {
     async getModel (id) {
diff --git a/src/views/ModelEdit.vue b/src/views/ModelEdit.vue
index d088c265c0990f1e798826cda221bf8821e6af29..f15565d94009b36cbbede21e70447d1d6a1705b1 100644
--- a/src/views/ModelEdit.vue
+++ b/src/views/ModelEdit.vue
@@ -13,12 +13,12 @@
       </b-field>
 
       <b-field label="Long description">
-        <markdownEditor v-bind:input="model.longDescription"/>
+        <markdownEditor v-bind:input="model.longDescription" v-on:update-description="model.longDescription = $event"/>
       </b-field>
 
       <hr>
       <h1 class="title">Tags</h1>
-      <tagEditor v-bind:tags="model.tags"/>
+      <tagEditor v-bind:modelTags="model.tags" v-on:update-tags="model.tags = $event"/>
 
       <hr>
       <h1 class="title">Files</h1>
@@ -35,16 +35,22 @@
                 </div>
               </section>
             </b-upload>
+            <span v-if="model.file" class="file-name">{{ model.file.name }}</span>
           </b-field>
         </div>
 
         <div class="column rightColumn">
-          <layersEditor v-bind:layers="model.customLayers"/>
+          <layersEditor v-bind:layers="model.customLayers" v-on:update-layers="model.customLayers = $event"/>
         </div>
       </div>
 
     </div>
+
     <div class="box">
+      <b-button type="is-danger" @click="removePrompt" expanded>Delete model</b-button>
+    </div>
+
+    <div class="box buttons">
       <b-button tag="router-link" :to="{ name: 'Account' }">Cancel</b-button>
       <b-button type="is-success" @click="openUploadModal">Save</b-button>
     </div>
@@ -82,9 +88,45 @@ export default {
       isUploadModalActive: false
     }
   },
+  mounted () {
+    this.model.tags = this.convertTag()
+  },
   methods: {
+    convertTag () {
+      var list = []
+      this.model.tags.forEach(tag => {
+        list.push(tag.name)
+      })
+      return list
+    },
     openUploadModal () {
       this.isUploadModalActive = true
+    },
+    removePrompt () {
+      this.$buefy.dialog.confirm({
+        message: 'Delete ' + this.model.name + ' ?',
+        cancelText: 'Abort',
+        confirmText: 'Delete',
+        type: 'is-danger',
+        hasIcon: true,
+        onConfirm: () => this.remove()
+      })
+    },
+    async remove () {
+      const token = await localStorage.getItem('token')
+      const url = this.$serverurl + 'models' + '?id=' + this.model.id
+      try {
+        await fetch(url, {
+          method: 'DELETE',
+          headers: {
+            Authorization: 'Bearer ' + token
+          }
+        })
+        this.$buefy.toast.open(this.model.name + ' deleted')
+        this.getModels()
+      } catch (error) {
+        this.$buefy.toast.open('Delete error ' + error)
+      }
     }
   }
 }
diff --git a/src/views/Search.vue b/src/views/Search.vue
index e547c4f73ac6d1c5c476f3c379ef7ee5fc6decb0..c4fca1d459a76827475eecee2b6e159378bc4689 100644
--- a/src/views/Search.vue
+++ b/src/views/Search.vue
@@ -16,15 +16,15 @@
             expanded
             />
           <b-select placeholder="Order by" icon="filter" @input="setOrder">
-            <option value="vote">Most vote</option>
-            <option value="date">Most recent</option>
+            <option value="votes">Most vote</option>
+            <option value="lastModified">Most recent</option>
           </b-select>
         </b-field>
-        <h1 class="title is-6">{{result.total}} results - page {{result.page}}</h1>
+        <h1 class="title is-6">{{result.totalResult}} results - page {{result.page}} of {{result.totalPage}}</h1>
         <div v-for="model in result.models" v-bind:key="model.name">
           <ModelCard v-bind:model="model"/>
         </div>
-        <b-pagination :total="result.total" :current.sync="result.page" :per-page="resultSize" @change="changePage"/>
+        <b-pagination :total="result.totalResult" :current.sync="result.page" :per-page="resultSize" @change="changePage"/>
       </div>
       <div v-else class="column is-four-fifths">
         <h1 class="title">no modelo</h1>
@@ -95,9 +95,9 @@ export default {
       const params = new URLSearchParams()
 
       if (this.paramSearch != null) params.append('name', this.paramSearch)
-      if (this.paramTags != null) params.append('tag', this.paramTags)
+      if (this.paramTags != null) params.append('tags', this.paramTags)
       if (this.paramPerf != null) params.append('param', this.paramPerf)
-      if (this.paramOrder != null) params.append('order', this.paramOrder)
+      if (this.paramOrder != null) params.append('sort', this.paramOrder)
 
       params.append('size', this.resultSize)
       params.append('page', this.page)