diff --git a/package-lock.json b/package-lock.json
index be11d3290fd232d29cd0a8f6856cd9637dc185d2..b1afc0f861ef12d7327b6791b3a2325fd2121ec6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1104,6 +1104,32 @@
         "to-fast-properties": "^2.0.0"
       }
     },
+    "@fortawesome/fontawesome-common-types": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz",
+      "integrity": "sha512-wBaAPGz1Awxg05e0PBRkDRuTsy4B3dpBm+zreTTyd9TH4uUM27cAL4xWyWR0rLJCrRwzVsQ4hF3FvM6rqydKPA=="
+    },
+    "@fortawesome/fontawesome-svg-core": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.2.tgz",
+      "integrity": "sha512-853G/Htp0BOdXnPoeCPTjFrVwyrJHpe8MhjB/DYE9XjwhnNDfuBCd3aKc2YUYbEfHEcBws4UAA0kA9dymZKGjA==",
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "6.1.2"
+      }
+    },
+    "@fortawesome/free-solid-svg-icons": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.2.tgz",
+      "integrity": "sha512-lTgZz+cMpzjkHmCwOG3E1ilUZrnINYdqMmrkv30EC3XbRsGlbIOL8H9LaNp5SV4g0pNJDfQ4EdTWWaMvdwyLiQ==",
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "6.1.2"
+      }
+    },
+    "@fortawesome/vue-fontawesome": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-2.0.8.tgz",
+      "integrity": "sha512-SRmP0q9Ox4zq8ydDR/hrH+23TVU1bdwYVnugLVaAIwklOHbf56gx6JUGlwES7zjuNYqzKgl8e39iYf6ph8qSQw=="
+    },
     "@hapi/address": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
@@ -1154,6 +1180,27 @@
         "postcss": "^7.0.0"
       }
     },
+    "@kouts/vue-modal": {
+      "version": "2.1.9",
+      "resolved": "https://registry.npmjs.org/@kouts/vue-modal/-/vue-modal-2.1.9.tgz",
+      "integrity": "sha512-VuW/4o2Gdrm67fKIJk7L9HIy/G/3fBJE+ZXus0mVqlLUdua+u1MQIPI9lsEm64zyYCSrgRKcsQrn5jnbanX4wA==",
+      "dev": true,
+      "requires": {
+        "vue": "^2.6.14"
+      },
+      "dependencies": {
+        "vue": {
+          "version": "2.7.9",
+          "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.9.tgz",
+          "integrity": "sha512-GeWCvAUkjzD5q4A3vgi8ka5r9bM6g8fmNmx/9VnHDKCaEzBcoVw+7UcQktZHrJ2jhlI+Zv8L57pMCIwM4h4MWg==",
+          "dev": true,
+          "requires": {
+            "@vue/compiler-sfc": "2.7.9",
+            "csstype": "^3.1.0"
+          }
+        }
+      }
+    },
     "@mrmlnc/readdir-enhanced": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@@ -1170,6 +1217,20 @@
       "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
       "dev": true
     },
+    "@revolist/revogrid": {
+      "version": "4.2.0-next.1",
+      "resolved": "https://registry.npmjs.org/@revolist/revogrid/-/revogrid-4.2.0-next.1.tgz",
+      "integrity": "sha512-eW9xGbX/mauVpdB2qgDHj4JHqG7vB9Vc2Y9pkEP21J7nygmdgSJnAIlRGVyFez0fuzQgrCiVS2wckfVb/h+WCQ=="
+    },
+    "@revolist/vue-datagrid": {
+      "version": "4.2.0-next.1",
+      "resolved": "https://registry.npmjs.org/@revolist/vue-datagrid/-/vue-datagrid-4.2.0-next.1.tgz",
+      "integrity": "sha512-Xaj40sOY9+C6jkwb6156xccf7QqNrC9l1rt6/grdhyCTxdOQObIn5p6eY8WSnYrzju/06tOC8pLLPdrmKPDCmA==",
+      "requires": {
+        "@revolist/revogrid": "^4.2.0-next.1",
+        "@stencil/core": "^2.17.3"
+      }
+    },
     "@soda/friendly-errors-webpack-plugin": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.0.tgz",
@@ -1240,6 +1301,11 @@
       "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==",
       "dev": true
     },
+    "@stencil/core": {
+      "version": "2.17.3",
+      "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.17.3.tgz",
+      "integrity": "sha512-qw2DZzOpyaltLLEfYRTj3n+XbvRtkmv4QQimYDJubC6jMY0NXK9r6H2+VyszdbbVmvK1D9GqZtyvY0NmOrztsg=="
+    },
     "@types/anymatch": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
@@ -1779,63 +1845,6 @@
           "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
           "dev": true
         },
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-          "dev": true,
-          "optional": true
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "loader-utils": {
-          "version": "2.0.2",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
-          "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
         "ssri": {
           "version": "8.0.1",
           "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
@@ -1844,28 +1853,6 @@
           "requires": {
             "minipass": "^3.1.1"
           }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        },
-        "vue-loader-v16": {
-          "version": "npm:vue-loader@16.8.3",
-          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
-          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "chalk": "^4.1.0",
-            "hash-sum": "^2.0.0",
-            "loader-utils": "^2.0.0"
-          }
         }
       }
     },
@@ -1889,6 +1876,42 @@
         "strip-ansi": "^6.0.0"
       }
     },
+    "@vue/compiler-sfc": {
+      "version": "2.7.9",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.9.tgz",
+      "integrity": "sha512-TD2FvT0fPUezw5RVP4tfwTZnKHP0QjeEUb39y7tORvOJQTjbOuHJEk4GPHUPsRaTeQ8rjuKjntyrYcEIx+ODxg==",
+      "dev": true,
+      "requires": {
+        "@babel/parser": "^7.18.4",
+        "postcss": "^8.4.14",
+        "source-map": "^0.6.1"
+      },
+      "dependencies": {
+        "@babel/parser": {
+          "version": "7.18.11",
+          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
+          "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==",
+          "dev": true
+        },
+        "postcss": {
+          "version": "8.4.16",
+          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
+          "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
+          "dev": true,
+          "requires": {
+            "nanoid": "^3.3.4",
+            "picocolors": "^1.0.0",
+            "source-map-js": "^1.0.2"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
     "@vue/component-compiler-utils": {
       "version": "3.2.0",
       "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz",
@@ -2146,6 +2169,15 @@
       "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
       "dev": true
     },
+    "a11y-dialog": {
+      "version": "7.5.2",
+      "resolved": "https://registry.npmjs.org/a11y-dialog/-/a11y-dialog-7.5.2.tgz",
+      "integrity": "sha512-zfWtVvrbGbP3AFnEJ1aJFtu7GvedgjOEKbkyEUSeaNWDzmFJk9O5nuolDQrRDyRDE5fqSJRiBJtD5bUYKveoUg==",
+      "dev": true,
+      "requires": {
+        "focusable-selectors": "^0.4.0"
+      }
+    },
     "abbrev": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@@ -2261,7 +2293,6 @@
       "version": "3.2.1",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
       "requires": {
         "color-convert": "^1.9.0"
       }
@@ -3174,7 +3205,6 @@
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
       "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
       "requires": {
         "ansi-styles": "^3.2.1",
         "escape-string-regexp": "^1.0.5",
@@ -3531,7 +3561,6 @@
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
       "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
       "requires": {
         "color-name": "1.1.3"
       }
@@ -3539,8 +3568,7 @@
     "color-name": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-      "dev": true
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
     },
     "color-string": {
       "version": "1.5.5",
@@ -3944,8 +3972,7 @@
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-      "dev": true
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
     "cosmiconfig": {
       "version": "5.2.1",
@@ -4259,6 +4286,12 @@
         }
       }
     },
+    "csstype": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
+      "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
+      "dev": true
+    },
     "currently-unhandled": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@@ -4283,6 +4316,11 @@
         "assert-plus": "^1.0.0"
       }
     },
+    "date-fns": {
+      "version": "2.29.1",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.1.tgz",
+      "integrity": "sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw=="
+    },
     "de-indent": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
@@ -4729,6 +4767,14 @@
       "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
       "dev": true
     },
+    "downloadify": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/downloadify/-/downloadify-1.0.2.tgz",
+      "integrity": "sha512-7WrGWRhiUGA3SwuRHfFaDoKYnSugUw0tqKKZcS4JOL9fkMReRoIZ24aVHncBTC/72ZuXpQcVQRVNUjidgZo1FA==",
+      "requires": {
+        "mime": "^2.4.6"
+      }
+    },
     "duplexer": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
@@ -4937,8 +4983,7 @@
     "escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-      "dev": true
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
     },
     "eslint": {
       "version": "6.8.0",
@@ -5886,6 +5931,11 @@
         "schema-utils": "^2.5.0"
       }
     },
+    "file-saver": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
+      "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
+    },
     "file-uri-to-path": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
@@ -6019,6 +6069,12 @@
         "readable-stream": "^2.3.6"
       }
     },
+    "focusable-selectors": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/focusable-selectors/-/focusable-selectors-0.4.0.tgz",
+      "integrity": "sha512-tc/236hUU3xemsRLu1RKhRQ5UWHjRM9iJTli1zdac43h7b1biRSgG0mILM0qrcsKaGCHcOPJ6NKbk12ouKHLpw==",
+      "dev": true
+    },
     "follow-redirects": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
@@ -6388,8 +6444,7 @@
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-      "dev": true
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
     },
     "has-symbols": {
       "version": "1.0.2",
@@ -6522,6 +6577,11 @@
       "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
       "dev": true
     },
+    "howler": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.3.tgz",
+      "integrity": "sha512-QM0FFkw0LRX1PR8pNzJVAY25JhIWvbKMBFM4gqk+QdV+kPXOhleWGCB6AiAF/goGjIHK2e/nIElplvjQwhr0jg=="
+    },
     "hpack.js": {
       "version": "2.1.6",
       "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
@@ -6832,6 +6892,11 @@
       "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
       "dev": true
     },
+    "immediate": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+      "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
+    },
     "import-cwd": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
@@ -6961,8 +7026,7 @@
     "inherits": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
     "inquirer": {
       "version": "7.3.3",
@@ -7457,8 +7521,7 @@
     "isarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-      "dev": true
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
     },
     "isexe": {
       "version": "2.0.0",
@@ -7605,6 +7668,17 @@
         "verror": "1.10.0"
       }
     },
+    "jszip": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
+      "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
+      "requires": {
+        "lie": "~3.3.0",
+        "pako": "~1.0.2",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "^1.0.5"
+      }
+    },
     "killable": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -7646,6 +7720,14 @@
         "type-check": "~0.3.2"
       }
     },
+    "lie": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+      "requires": {
+        "immediate": "~3.0.5"
+      }
+    },
     "lines-and-columns": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
@@ -7788,6 +7870,11 @@
       "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
       "dev": true
     },
+    "lodash.isequal": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+      "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
+    },
     "lodash.kebabcase": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
@@ -7888,6 +7975,11 @@
         "object-visit": "^1.0.0"
       }
     },
+    "material-icons": {
+      "version": "1.11.10",
+      "resolved": "https://registry.npmjs.org/material-icons/-/material-icons-1.11.10.tgz",
+      "integrity": "sha512-1nGlVYwH98BQGSoxHf1QCCDll6AmnkxuATjTHREvy8BSEc6EfRkvcsQwEmSgAY7qcKLV3Ip81u9YEiH/sjQgkg=="
+    },
     "md5.js": {
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -8112,8 +8204,7 @@
     "mime": {
       "version": "2.5.2",
       "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz",
-      "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==",
-      "dev": true
+      "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg=="
     },
     "mime-db": {
       "version": "1.47.0",
@@ -8324,6 +8415,12 @@
       "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
       "dev": true
     },
+    "nanoid": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+      "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+      "dev": true
+    },
     "nanomatch": {
       "version": "1.2.13",
       "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -8959,8 +9056,7 @@
     "pako": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
-      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
-      "dev": true
+      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
     },
     "parallel-transform": {
       "version": "1.2.0",
@@ -9163,6 +9259,12 @@
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
       "dev": true
     },
+    "picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+      "dev": true
+    },
     "picomatch": {
       "version": "2.2.3",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
@@ -9916,8 +10018,7 @@
     "process-nextick-args": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
-      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
-      "dev": true
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
     },
     "progress": {
       "version": "2.0.3",
@@ -10185,7 +10286,6 @@
       "version": "2.3.7",
       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
       "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-      "dev": true,
       "requires": {
         "core-util-is": "~1.0.0",
         "inherits": "~2.0.3",
@@ -10429,6 +10529,12 @@
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
       "dev": true
     },
+    "resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==",
+      "dev": true
+    },
     "resolve": {
       "version": "1.20.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
@@ -10540,8 +10646,7 @@
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "dev": true
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
     },
     "safe-regex": {
       "version": "1.1.0",
@@ -10927,8 +11032,7 @@
     "setimmediate": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
-      "dev": true
+      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
     },
     "setprototypeof": {
       "version": "1.1.1",
@@ -11211,6 +11315,12 @@
       "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
       "dev": true
     },
+    "source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+      "dev": true
+    },
     "source-map-resolve": {
       "version": "0.5.3",
       "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
@@ -11489,7 +11599,6 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
       "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dev": true,
       "requires": {
         "safe-buffer": "~5.1.0"
       }
@@ -11569,7 +11678,6 @@
       "version": "5.5.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
       "requires": {
         "has-flag": "^3.0.0"
       }
@@ -12310,8 +12418,7 @@
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
-      "dev": true
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
     },
     "util.promisify": {
       "version": "1.0.1",
@@ -12393,6 +12500,11 @@
       "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
       "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg=="
     },
+    "vue-class-component": {
+      "version": "7.2.6",
+      "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.2.6.tgz",
+      "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w=="
+    },
     "vue-eslint-parser": {
       "version": "7.6.0",
       "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.6.0.tgz",
@@ -12419,12 +12531,30 @@
         }
       }
     },
+    "vue-good-table": {
+      "version": "2.21.11",
+      "resolved": "https://registry.npmjs.org/vue-good-table/-/vue-good-table-2.21.11.tgz",
+      "integrity": "sha512-OpVPdxbBTahtfq1aXxEa5P1CMy1wiLcBg4mo7k6Qs537l9v8KVrvF+fXqbnxqNrAfmd1Mw9LidcjgTErjmVU8g==",
+      "requires": {
+        "date-fns": "^2.17.0",
+        "lodash.isequal": "^4.5.0"
+      }
+    },
     "vue-hot-reload-api": {
       "version": "2.3.4",
       "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
       "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==",
       "dev": true
     },
+    "vue-js-modal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/vue-js-modal/-/vue-js-modal-2.0.1.tgz",
+      "integrity": "sha512-5FUwsH2zoxRKX4a7wkFAqX0eITCcIMunJDEfIxzHs2bHw9o20+Iqm+uQvBcg1jkzyo1+tVgThR/7NGU8djbD8Q==",
+      "dev": true,
+      "requires": {
+        "resize-observer-polyfill": "^1.5.1"
+      }
+    },
     "vue-loader": {
       "version": "15.9.7",
       "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.7.tgz",
@@ -12446,11 +12576,117 @@
         }
       }
     },
+    "vue-loader-v16": {
+      "version": "npm:vue-loader@16.8.3",
+      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
+      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "chalk": "^4.1.0",
+        "hash-sum": "^2.0.0",
+        "loader-utils": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true,
+          "optional": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "loader-utils": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
+          "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "vue-property-decorator": {
+      "version": "8.5.1",
+      "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-8.5.1.tgz",
+      "integrity": "sha512-O6OUN2OMsYTGPvgFtXeBU3jPnX5ffQ9V4I1WfxFQ6dqz6cOUbR3Usou7kgFpfiXDvV7dJQSFcJ5yUPgOtPPm1Q==",
+      "requires": {
+        "vue-class-component": "^7.1.0"
+      }
+    },
+    "vue-rate": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/vue-rate/-/vue-rate-2.5.0.tgz",
+      "integrity": "sha512-JMP1hm7fX+PO3fUdB+RPqadabflIOMqo/waZ5LL0HI1sRcF7Cj8rvJHNfv6eH3AQPUwvSNm7rZwDVwqMwIlcMw==",
+      "requires": {
+        "vue": "^2.5.21"
+      }
+    },
     "vue-router": {
       "version": "3.5.1",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz",
       "integrity": "sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw=="
     },
+    "vue-slider-component": {
+      "version": "3.2.20",
+      "resolved": "https://registry.npmjs.org/vue-slider-component/-/vue-slider-component-3.2.20.tgz",
+      "integrity": "sha512-S5+4d6zdL+/ClpDQoIgImIdXRv2b+75PIy3cDGsZsakhroJD6cSFA0juY/AblGqhvIkNcBIU354eOw6T26DWbA==",
+      "requires": {
+        "core-js": "^3.6.5",
+        "vue-property-decorator": "^8.0.0"
+      }
+    },
     "vue-style-loader": {
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@@ -12485,6 +12721,15 @@
       "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
       "dev": true
     },
+    "vuesax": {
+      "version": "3.12.2",
+      "resolved": "https://registry.npmjs.org/vuesax/-/vuesax-3.12.2.tgz",
+      "integrity": "sha512-fdzcTPsrVklhWXtC8o07n9+SCmdQ8rxD9cZxNUx8KnbSH/Ss5azIHLLwMoNQuwT6kBFUcRzxVTfDh8jHzoSXaw==",
+      "requires": {
+        "chalk": "^2.4.2",
+        "vue": "^2.6.9"
+      }
+    },
     "watchpack": {
       "version": "1.7.5",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
@@ -13299,6 +13544,12 @@
         "async-limiter": "~1.0.0"
       }
     },
+    "xmodal-vue": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/xmodal-vue/-/xmodal-vue-1.0.5.tgz",
+      "integrity": "sha512-XqqqARzjXhmvwNSJ6qDQD74tI8TvNE9+rwMwfeXx/ZATW4cwvf9ncFjS9GRtPGm6R/t+v5Ne0hmyhWBml0cIZQ==",
+      "dev": true
+    },
     "xtend": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
index f8b6f290c662e1dce90f81bbdfdf3f685591f32a..67e72ce20e24071b1d63e9d43c42f144cf746c4b 100644
--- a/package.json
+++ b/package.json
@@ -8,20 +8,35 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@fortawesome/fontawesome-svg-core": "^6.1.2",
+    "@fortawesome/free-solid-svg-icons": "^6.1.2",
+    "@fortawesome/vue-fontawesome": "^2.0.8",
+    "@revolist/vue-datagrid": "^4.2.0-next.1",
     "axios": "^0.21.1",
     "core-js": "^3.6.5",
+    "downloadify": "^1.0.2",
+    "file-saver": "^2.0.5",
+    "howler": "^2.2.3",
+    "jszip": "^3.10.1",
+    "material-icons": "^1.11.10",
     "vue": "^2.6.11",
+    "vue-good-table": "^2.21.11",
+    "vue-rate": "^2.5.0",
     "vue-router": "^3.2.0",
+    "vue-slider-component": "^3.2.20",
+    "vuesax": "^3.12.2",
     "wavesurfer.js": "^5.1.0",
     "wavesurfer.js-vue": "^1.0.0"
   },
   "devDependencies": {
+    "@kouts/vue-modal": "^2.1.9",
     "@types/wavesurfer.js": "^5.1.0",
     "@vue/cli-plugin-babel": "~4.5.0",
     "@vue/cli-plugin-eslint": "~4.5.0",
     "@vue/cli-plugin-router": "~4.5.0",
     "@vue/cli-service": "~4.5.0",
     "@vue/eslint-config-standard": "^5.1.2",
+    "a11y-dialog": "^7.5.2",
     "babel-eslint": "^10.1.0",
     "eslint": "^6.7.2",
     "eslint-plugin-import": "^2.20.2",
@@ -31,7 +46,9 @@
     "eslint-plugin-vue": "^6.2.2",
     "node-sass": "^4.12.0",
     "sass-loader": "^8.0.2",
-    "vue-template-compiler": "^2.6.11"
+    "vue-js-modal": "^2.0.1",
+    "vue-template-compiler": "^2.6.11",
+    "xmodal-vue": "^1.0.5"
   },
   "eslintConfig": {
     "root": true,
diff --git a/src/App.vue b/src/App.vue
index 404b9f24af82e9b245cc23121a48bf2b396a5ddb..8c9acdb9b36810282776b08481cb10c22af6d4fa 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,15 +1,15 @@
 <template>
   <div id="orchive3">
-    <aside>
-      <SearchBar id="SearchContainer">
-      </SearchBar>
+    <aside id="side-id" class="side">
+      <NavigationMenu class="side-content"  v-if="!isSearch"  id="NavigationContainer"></NavigationMenu>
+      <SearchBar class="side-content" v-else id="SearchBarContainer"></SearchBar>
       <div class="dividers">
         <div class="dividerSmall"></div>
         <div class="divider"></div>
         <div class="dividerSmall"></div>
       </div>
     </aside>
-    <main>
+    <main v-bind:style="{marginLeft: (this.asideWidth) + 'px'}">
       <transition name="fade" mode="out-in">
         <router-view :key="$route.path"/>
       </transition>
@@ -18,13 +18,36 @@
 </template>
 
 <script>
-import SearchBar from './components/SearchBar.vue'
+
+import NavigationMenu from '@/components/NavigationMenu'
+import SearchBar from '@/components/SearchBar'
 
 export default {
   components: {
-    SearchBar
+    SearchBar,
+    NavigationMenu
+  },
+  data () {
+    return {
+      asideWidth: 0,
+      audio: null,
+      isSearch: false
+    }
+  },
+  mounted () {
+    this.resizeObserver = new ResizeObserver(this.onResize)
+    this.resizeObserver.observe(document.getElementById('side-id'))
+    this.onResize()
+  },
+  watch: {
+    $route (to, from) {
+      this.isSearch = (to.name === 'SearchContextView')
+    }
   },
   methods: {
+    onResize () {
+      this.asideWidth = document.getElementById('side-id').offsetWidth
+    }
   }
 }
 </script>
@@ -50,29 +73,25 @@ export default {
 body {
   overflow-x: hidden;
   height: 100vh;
-  margin: 0px
+  margin: 0
 }
 
 #orchive3 {
   font-family: Avenir, Helvetica, Arial, sans-serif;
   height: 100vh;
-  /* -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50; */
   display: flex;
   >aside {
     height: 100vh;
-    width: 30%;
-    margin-left: 20px;
     display: inline-flex;
-    overflow: hidden;
+    position: fixed;
+  }
+  >main {
+    width: 100%;
   }
 }
-#SearchContainer{
-  margin: auto 0;
-  width: 95%;
-  margin-top: calc(5vh + 20px);
+
+.side-content {
+  margin-left: 25px;
 }
 
 .dividers {
@@ -94,7 +113,7 @@ body {
   background: $dark-blue;
 }
 
-#timelineOverviewContainer{
+#timelineOverviewContainer {
   width: 13%;
   min-width: 80px;
   // padding-right: 20px;
@@ -105,30 +124,12 @@ body {
   margin: auto;
 }
 
-main {
-  width: 70%;
-  // overflow: scroll;
-  height: 100vh
-}
-
 #mainContainer {
   width: 87%;
   overflow-y: scroll;
   height: 100vh;
   article {
-    padding: 20px;
+    padding: 0px;
   }
 }
-/*#nav {
-  padding: 30px;
-}
-
-#nav a {
-  font-weight: bold;
-  color: #2c3e50;
-}
-
-#nav a.router-link-exact-active {
-  color: #42b983;
-}*/
 </style>
diff --git a/src/assets/audio/001A.mp3 b/src/assets/audio/001A.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..30ea094d2d361d2c4006a8ddb4c08df43e8ee984
Binary files /dev/null and b/src/assets/audio/001A.mp3 differ
diff --git a/src/assets/audio/001A1.mp3 b/src/assets/audio/001A1.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..3a87fbaf3a8ad0515d525437001cd7b6142a3efa
Binary files /dev/null and b/src/assets/audio/001A1.mp3 differ
diff --git a/src/assets/cancel_icon.svg b/src/assets/cancel_icon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..448555e98e806791943212ae6acac30269cae4d2
--- /dev/null
+++ b/src/assets/cancel_icon.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="17.828" height="17.828" viewBox="0 0 17.828 17.828">
+  <polygon points="2.828 17.828 8.914 11.742 15 17.828 17.828 15 11.742 8.914 17.828 2.828 15 0 8.914 6.086 2.828 0 0 2.828 6.085 8.914 0 15 2.828 17.828"/>
+</svg>
diff --git a/src/assets/check_icon.svg b/src/assets/check_icon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2c16674c8895159aff27a1f4b36b284934cd28ef
--- /dev/null
+++ b/src/assets/check_icon.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="22.903" height="19.395" viewBox="0 0 22.903 19.395">
+  <polygon points="22.903 2.828 20.075 0 6.641 13.435 3.102 9.09 0 11.616 6.338 19.395 22.903 2.828"/>
+</svg>
diff --git a/src/assets/download.svg b/src/assets/download.svg
new file mode 100644
index 0000000000000000000000000000000000000000..63c84661311eafda0aa6d37214be405a00427066
--- /dev/null
+++ b/src/assets/download.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="19.799" viewBox="0 0 20 19.799">
+  <path d="M8,0a10,10,0,1,0,4,0V8.8h2l-4,4-4-4H8Z"/>
+</svg>
diff --git a/src/assets/minus_icon.svg b/src/assets/minus_icon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6eace0add1de65d52bef33cdee88d9bae0848b2e
--- /dev/null
+++ b/src/assets/minus_icon.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve">
+<g id="_x32_">
+	<path style="fill:#303030;" d="M125.61,71.238H2.39c-1.32,0-2.39-1.07-2.39-2.39v-9.787c0-1.32,1.07-2.39,2.39-2.39h123.22
+		c1.32,0,2.39,1.07,2.39,2.39v9.787C128,70.168,126.93,71.238,125.61,71.238z"/>
+</g>
+<g id="Layer_1">
+</g>
+</svg>
diff --git a/src/assets/plus_icon.svg b/src/assets/plus_icon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..220f3f26da58cafb2fc9a222561bb294343a46d5
--- /dev/null
+++ b/src/assets/plus_icon.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve">
+<g id="_x33_">
+	<path style="fill:#303030;" d="M128,63.954c0,2.006-0.797,3.821-2.136,5.127c-1.308,1.337-3.125,2.133-5.166,2.133H71.302v49.356
+		c0,4.012-3.284,7.292-7.302,7.292c-2.009,0-3.827-0.828-5.166-2.134c-1.308-1.337-2.136-3.152-2.136-5.159V71.214H7.302
+		c-4.05,0-7.302-3.248-7.302-7.26c0-2.006,0.797-3.853,2.136-5.159c1.308-1.306,3.125-2.134,5.166-2.134h49.395V7.306
+		c0-4.012,3.284-7.26,7.302-7.26c2.009,0,3.827,0.828,5.166,2.133c1.308,1.306,2.136,3.121,2.136,5.127v49.356h49.395
+		C124.747,56.662,128,59.91,128,63.954z"/>
+</g>
+<g id="Layer_1">
+</g>
+</svg>
diff --git a/src/classes/AlphaColor.js b/src/classes/AlphaColor.js
new file mode 100644
index 0000000000000000000000000000000000000000..8dc5124aea46b27ea6a1a5fbf57cf2126f915651
--- /dev/null
+++ b/src/classes/AlphaColor.js
@@ -0,0 +1,53 @@
+class AlphaColor {
+  constructor (color) {
+    this.color = color
+  }
+
+  parseAlphaColor () {
+    if (/^rgba\((\d{1,3}%?\s*,\s*){3}(\d*(?:\.\d+)?)\)$/.test(this.color)) {
+      return this.parseRgba()
+    } else if (/^hsla\(\d+\s*,\s*([\d.]+%\s*,\s*){2}(\d*(?:\.\d+)?)\)$/.test(this.color)) {
+      return this.parseHsla()
+    } else if (/^#([0-9A-Fa-f]{4}|[0-9A-Fa-f]{8})$/.test(this.color)) {
+      return this.parseAlphaHex()
+    } else if (/^transparent$/.test(this.color)) {
+      return this.parseTransparent()
+    }
+
+    return {
+      color: this.color,
+      opacity: '1'
+    }
+  }
+
+  parseRgba () {
+    return {
+      color: this.color.replace(/,(?!.*,).*(?=\))|a/g, ''),
+      opacity: this.color.match(/\.\d+|[01](?=\))/)[0]
+    }
+  }
+
+  parseHsla () {
+    return {
+      color: this.color.replace(/,(?!.*,).*(?=\))|a/g, ''),
+      opacity: this.color.match(/\.\d+|[01](?=\))/)[0]
+    }
+  }
+
+  parseAlphaHex () {
+    return {
+      color: this.color.length === 5 ? this.color.substring(0, 4) : this.color.substring(0, 7),
+      opacity: this.color.length === 5 ? (parseInt(this.color.substring(4, 5) + this.color.substring(4, 5), 16) / 255).toFixed(2) : (parseInt(this.color.substring(7, 9), 16) / 255).toFixed(2)
+
+    }
+  }
+
+  parseTransparent () {
+    return {
+      color: '#fff',
+      opacity: 0
+    }
+  }
+}
+
+module.exports = AlphaColor
diff --git a/src/components/AudioAndFrequencyPlayer.vue b/src/components/AudioAndFrequencyPlayer.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0c40a438e36eac247a9489d7eb4e282d78293cac
--- /dev/null
+++ b/src/components/AudioAndFrequencyPlayer.vue
@@ -0,0 +1,330 @@
+<template>
+  <table>
+    <tr class="row1">
+      <td class="column1">
+        <div class="audioTitle"> Audio Spectrum </div>
+      </td>
+      <td class="column2">
+        <div></div>
+      </td>
+      <td class="audio">
+        <div v-bind:id="wavesurfer_spectrum_id">
+        </div>
+      </td>
+    </tr>
+    <tr class="row1">
+      <td class="column1">
+        <div class="audioTitle"> Audio Waveform </div>
+      </td>
+      <td class="column2">
+        <div class="playOrca" @click="playPauseSegment" :class="{noAudio: isError || isLoading, isError: isError}">
+          <img class="playIcon" v-if="!isPlaying" src="../assets/play-circle-solid.svg" alt="">
+          <img class="pauseIcon" v-else src="../assets/pause-circle-solid.svg" alt="">
+        </div>
+        <div class="loading" v-if="isLoading && !isError">
+          <div class="loader"></div>
+        </div>
+        <div class="loading error" v-if="isError">
+          audio could not be loaded!
+        </div>
+      </td>
+      <td class="audio">
+        <div v-bind:id="wavesurfer_audio_id">
+        </div>
+      </td>
+    </tr>
+  </table>
+</template>
+
+<script>
+import WaveSurfer from 'wavesurfer.js'
+import RegionsPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.regions'
+import SpectrogramPlugin from 'wavesurfer.js/src/plugin/spectrogram'
+import { Bus } from '@/main'
+import axios from 'axios'
+
+export default {
+  name: 'AudioAndFrequencyPlayer',
+  props: {
+    tape_name: String,
+    tape_year: Number,
+    tape_channel: String,
+    timestamp_start_ms: Number,
+    timestamp_end_ms: Number,
+    sequences: { type: Array, required: true },
+    is_editable: Boolean,
+    component_id: String
+  },
+  data () {
+    return {
+      wavesurfer_audio_id: 'waveSegment' + this.component_id,
+      wavesurfer_spectrum_id: 'spectrumSegment' + this.component_id,
+      bufferedAudioTapes: {},
+      isPlaying: false,
+      isError: false,
+      isLoading: true,
+      wavesurfer: null,
+      playAll: false,
+      setup: true,
+      panChannel: 0
+    }
+  },
+  async mounted () {
+    this.wavesurfer = WaveSurfer.create({
+      container: '#waveSegment' + this.component_id,
+      fillParent: true,
+      barWidth: 7,
+      interact: this.is_editable,
+      waveColor: '#912',
+      plugins: [
+        RegionsPlugin.create({
+        }),
+        SpectrogramPlugin.create({
+          container: '#spectrumSegment' + this.component_id,
+          fftSamples: 256,
+          labels: true,
+          height: 128,
+          frequencyMax: 10000
+        })
+      ]
+    })
+    // add channel support
+    this.wavesurfer.panner = this.wavesurfer.backend.ac.createStereoPanner()
+    this.panChannel = 0
+    if (localStorage.isLive !== undefined && localStorage.isLive === 'true') {
+      this.panChannel = 1
+    }
+    this.wavesurfer.panner.pan.value = Number(this.panChannel)
+    this.wavesurfer.backend.setFilter(this.wavesurfer.panner)
+    this.wavesurfer.on('ready', await (() => {
+      this.isLoading = false
+      this.wavesurfer.clearRegions()
+      if (this.is_editable) {
+        this.wavesurfer.enableDragSelection({})
+      }
+      for (let i = 0; i < this.sequences.length; i++) {
+        const regionToAdd = {
+          start: ((this.sequences[i].timestamp_start_ms - this.timestamp_start_ms) / 1000),
+          end: ((this.sequences[i].timestamp_end_ms - this.timestamp_start_ms) / 1000),
+          id: this.sequences[i].orca_sequence_id,
+          drag: this.is_editable,
+          resize: this.is_editable
+        }
+        this.wavesurfer.addRegion(regionToAdd)
+      }
+      this.setup = false
+    }))
+    this.wavesurfer.on('finish', await (() => {
+      this.isPlaying = false
+    }))
+    this.wavesurfer.on('region-click', await ((region, e) => {
+      this.playAll = false
+      e.stopPropagation()
+      region.wavesurfer.play(region.start, region.end)
+      this.isPlaying = true
+      Bus.$emit('selected-sequence', region)
+    }))
+    this.wavesurfer.on('region-out', await ((region, e) => {
+      if (!this.playAll) {
+        this.isPlaying = false
+      }
+    }))
+    this.wavesurfer.on('region-created', await ((region, e) => {
+      if (!this.setup) {
+        Bus.$emit('created-sequence', region)
+      }
+    }))
+    this.wavesurfer.on('region-update-end', await ((region, e) => {
+      if (!this.setup) {
+        Bus.$emit('updated-sequence', region)
+      }
+    }))
+    this.wavesurfer.on('error', await ((e) => {
+    }))
+  },
+  destroyed () {
+    this.$destroy()
+    Bus.$off()
+    this.wavesurfer.unAll()
+    this.wavesurfer.destroy()
+    if (this.wavesurfer.backend !== null) {
+      delete this.wavesurfer.backend.buffer
+    }
+  },
+  created () {
+    Bus.$on('segment_index_changed', (actualIndex) => {
+      this.setup = true
+      this.isLoading = true
+      this.isError = false
+      this.isPlaying = false
+    })
+    Bus.$on('player-stop', (stop) => {
+      this.isPlaying = false
+      this.wavesurfer.pause()
+    })
+    this.$eventHub.$on('live_queue_settings', (queueSettings) => {
+      if (this.panChannel === 0 && queueSettings.isLive) {
+        this.panChannel = 1
+        this.wavesurfer.panner.pan.value = Number(this.panChannel)
+        this.wavesurfer.backend.setFilter(this.wavesurfer.panner)
+        this.wavesurfer.reload()
+      } else if (this.panChannel === 1 && !queueSettings.isLive) {
+        this.panChannel = 0
+        this.wavesurfer.panner.pan.value = Number(this.panChannel)
+        this.wavesurfer.backend.setFilter(this.wavesurfer.panner)
+        this.wavesurfer.reload()
+      }
+    })
+  },
+  beforeDestroy () {
+    this.wavesurfer.destroy()
+    this.wavesurfer.unAll()
+  },
+  methods: {
+    async loadAudioFile (year, name, channel) {
+      if (this.bufferedAudioTapes[this.tape_name] === undefined) {
+        // buffer is buggy
+      }
+      let orcaPath = ''
+      if (this.component_id === 'mark') {
+        orcaPath = '/files/tapes/' + this.tape_year + '/' + this.tape_name + '/' + this.tape_channel + '.mp3'
+      } else {
+        orcaPath = '/files/tapes/' + year + '/' + name + '/' + channel + '.mp3'
+      }
+      console.log(orcaPath)
+      // const orcaPath = require('../assets/audio/001A1.mp3')
+      const config = { url: orcaPath, method: 'get', responseType: 'blob' }
+      const response = await axios.request(config)
+      this.bufferedAudioTapes[this.tape_name] = response.data
+      // buffer is buggy
+      const blobAudio = this.bufferedAudioTapes[this.tape_name]
+      const size = blobAudio.size
+      const duration = 48 * 60 * 1000
+      const bytePerMillisecond = size / duration
+      const startBytes = bytePerMillisecond * this.timestamp_start_ms
+      const endBytes = bytePerMillisecond * this.timestamp_end_ms
+      const blobAudioSliced = blobAudio.slice(startBytes, endBytes)
+      const sizeSliced = blobAudioSliced.size
+      console.log(
+        ' size: ' + size +
+        '\n duration: ' + duration +
+        '\n bytePerMillisecond: ' + bytePerMillisecond +
+        '\n startBytes: ' + startBytes +
+        '\n endBytes: ' + endBytes +
+        '\n sizeSliced: ' + sizeSliced
+      )
+      this.wavesurfer.loadBlob(blobAudioSliced)
+      // this.wavesurfer.load(orcaPath)
+    },
+    playPauseSegment () {
+      if (this.wavesurfer.isPlaying()) {
+        this.isPlaying = false
+        this.wavesurfer.pause()
+      } else {
+        Bus.$emit('player-stop', this.isPlaying)
+        this.isPlaying = true
+        this.playAll = true
+        this.wavesurfer.play()
+      }
+    },
+    removeSequence (id) {
+      const regions = this.wavesurfer.regions.list
+      regions[id].remove()
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+@import '@/assets/color.scss';
+.isError {
+  top: 44px !important;
+}
+.loading {
+  left: 140%;
+  position: relative;
+  top: -28px;
+  width: 100%;
+  &.error {
+    color: $dark-blue;
+    font-weight: bold;
+    text-transform: uppercase;
+    color: lightcoral;
+  }
+  // class loader: https://www.w3schools.com/howto/howto_css_loader.asp, besucht am 07.10.21
+  .loader {
+    border: 5px solid $light-grey-2;
+    border-top: 5px solid $dark-blue;
+    border-radius: 50%;
+    width: 25px;
+    height: 25px;
+    animation: spin 2s linear infinite;
+    @keyframes spin {
+      0% { transform: rotate(0deg); }
+      100% { transform: rotate(360deg); }
+    }
+  }
+}
+
+.noAudio {
+  top: 17.5px;
+  position: relative;
+  cursor: unset;
+  pointer-events: none;
+  .playIcon {
+    filter: $filter-light-grey-2;
+    cursor: unset;
+    pointer-events: none;
+  }
+}
+
+.row1{
+  padding-bottom: 28.2px;
+}
+
+.column1{
+  width: 95px;
+  text-align: right;
+  padding-right: 17.5px;
+}
+
+.column2{
+  height: 50px;
+  width: 50px;
+  padding-right: 17.5px;
+}
+
+.playIcon{
+  width: 50px;
+  height: 50px;
+  filter: $filter-dark-blue;
+  cursor: pointer;
+}
+
+.pauseIcon{
+  width: 50px;
+  height: 50px;
+  filter: $filter-light-blue;
+  cursor: pointer;
+}
+
+.audio {
+  width: 80%;
+  height: 50px;
+}
+
+marker {
+  &:hover {
+    span {
+      display: block;
+    }
+  }
+
+  span {
+    display: none;
+    z-index: 100;
+    background: white;
+    opacity: 0.8;
+  }
+}
+</style>
diff --git a/src/components/DetailHeader.vue b/src/components/DetailHeader.vue
index 989f4a950f2c8d82d1fc46243d5dc7ae415c6e6b..d949b8cd857d5890f292dee0e232ba0b0e1270f3 100644
--- a/src/components/DetailHeader.vue
+++ b/src/components/DetailHeader.vue
@@ -16,10 +16,9 @@
               }"
               class="previous"
             >
-            &lt;
             </router-link>
             <div class="noPrevious" v-else> &lt; </div>
-            <p>
+            <p class="next">
                 {{indexThisYear}} / {{countThisYear}} Tape
             </p>
             <router-link v-if="tapes.nextTape != null" @click="sendNextTape"
diff --git a/src/components/EditSequenceModel.vue b/src/components/EditSequenceModel.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a0e214aec69ac0dc7a9ac93a0eebe0d9a010cd97
--- /dev/null
+++ b/src/components/EditSequenceModel.vue
@@ -0,0 +1,79 @@
+<template>
+  <div class="modal-overlay">
+    <div class="modal">
+      <img class="check" alt="" />
+      <h6>Saved!</h6>
+      <p>Your Details have been saved Successfully</p>
+      <button>Go Home</button>
+    </div>
+    <div class="close">
+      <img class="close-img" alt=""/>
+    </div>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: 'EditSequenceModel',
+  methods: {
+  }
+}
+</script>
+
+<style scoped>
+
+.modal-overlay {
+  position: fixed;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  display: flex;
+  justify-content: center;
+  background-color: #000000da;
+}
+
+.modal {
+  text-align: center;
+  background-color: white;
+  height: 500px;
+  width: 500px;
+  margin-top: 10%;
+  padding: 60px 0;
+  border-radius: 20px;
+}
+.close {
+  margin: 10% 0 0 16px;
+  cursor: pointer;
+}
+
+.close-img {
+  width: 25px;
+}
+
+.check {
+  width: 150px;
+}
+
+h6 {
+  font-weight: 500;
+  font-size: 28px;
+  margin: 20px 0;
+}
+
+p {
+  font-size: 16px;
+  margin: 20px 0;
+}
+
+button {
+  background-color: #ac003e;
+  width: 150px;
+  height: 40px;
+  color: white;
+  font-size: 14px;
+  border-radius: 16px;
+  margin-top: 50px;
+}
+</style>
diff --git a/src/components/FilterSegments.vue b/src/components/FilterSegments.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a893f6f09c9ae26048b43c7e23d4715c9d3f4f66
--- /dev/null
+++ b/src/components/FilterSegments.vue
@@ -0,0 +1,171 @@
+<template>
+  <div>
+    <div v-if="!loading">
+      <div v-if="canFilterId">
+        Filter Year:
+        <SearchAutoComplete ref="sYear" :clear="false" class="content" :items="allYears" ></SearchAutoComplete>
+        Filter Tape:
+        <SearchAutoComplete ref="sTape" :clear="false" class="content" :items="allTapes" ></SearchAutoComplete>
+        Filter Duration:  Max: {{this.maxMin}}s Use: &lt; 3 (shorter), &gt; 5 (longer) or 3 &lt; 5 (between)
+        <SearchAutoComplete :suggest="false" ref="sDuration"  :clear="false" class="content" :items="[]"></SearchAutoComplete>
+      </div>
+      <div v-if="canSearchId">
+        Find Id:
+        <SearchAutoComplete :suggest="false" ref="sId" :clear="false" class="content" :items="[]" ></SearchAutoComplete>
+      </div>
+    </div>
+    <div v-else>
+      loading...
+    </div>
+  </div>
+</template>
+
+<script>
+import SearchAutoComplete from '../components/SearchAutocomplete'
+
+export default {
+  components: {
+    SearchAutoComplete
+  },
+  name: 'FilterSegments',
+  props: ['info', 'loading'],
+  data () {
+    return {
+      rows: [],
+      allYears: [],
+      allTapes: [],
+      maxMin: 0,
+      filtered: [],
+      canSearchId: true,
+      canFilterId: true
+    }
+  },
+  mounted () {
+    this.$refs.sTape.$on('onkeychange', this.setOptions)
+    this.$refs.sDuration.$on('onkeychange', this.setOptions)
+    this.$refs.sYear.$on('onkeychange', this.setOptions)
+    this.$refs.sId.$on('onkeychange', this.setOptions)
+    this.$refs.sTape.$on('enter', this.setOptions)
+    this.$refs.sDuration.$on('enter', this.setOptions)
+    this.$refs.sYear.$on('enter', this.setOptions)
+    this.$refs.sId.$on('enter', this.setOptions)
+  },
+  methods: {
+    onOpenPopup () {
+      this.setOptions()
+    },
+    setOptions () {
+      const it = this.getFilter()
+      this.canSearchId = true
+      this.canFilterId = true
+      let filterIt = {}
+      Object.assign(filterIt, this.info)
+      if (it.id !== '') {
+        this.canFilterId = true
+      }
+      if (it.year !== '' && this.info[it.year] !== undefined) {
+        filterIt = {}
+        filterIt[it.year] = this.info[it.year]
+        this.canSearchId = true
+      }
+      if (it.tape !== '') {
+        const tmpFilter = {}
+        Object.assign(tmpFilter, filterIt)
+        const allKeys = Object.keys(filterIt)
+        for (let i = 0; i < allKeys.length; i++) {
+          if (!filterIt[allKeys[i]].tapes.includes(it.tape)) {
+            delete filterIt[allKeys[i]]
+          }
+        }
+        if (Object.keys(filterIt).length === 0) {
+          filterIt = tmpFilter
+        }
+        this.canSearchId = true
+      }
+      this.allYears = Object.keys(filterIt)
+      this.allTapes = []
+      this.maxMin = 0
+      // console.log('keys: ' + this.allYears)
+
+      for (let i = 0; i < this.allYears.length; i++) {
+        const tapes = filterIt[this.allYears[i]].tapes
+        for (let i = 0; i < tapes.length; i++) {
+          const tape = (tapes[i]).toString()
+          // console.log(tape)
+          this.allTapes.push(tape)
+        }
+        // console.log('duration: ' + filterIt[this.allYears[i]].maxMin)
+        if (this.maxMin < filterIt[this.allYears[i]].maxMin) {
+          this.maxMin = filterIt[this.allYears[i]].maxMin
+        }
+      }
+      this.allTapes = [...new Set(this.allTapes)]
+    },
+    resetValues () {
+      this.$refs.sYear.setValue('')
+      this.$refs.sTape.setValue('')
+      this.$refs.sId.setValue('')
+      this.$refs.sDuration.setValue('')
+    },
+    setFilter (filter) {
+      this.$refs.sYear.setValue(filter.year)
+      this.$refs.sTape.setValue(filter.tape)
+      this.$refs.sId.setValue(filter.id)
+      this.$refs.sDuration.setValue(filter.duration)
+    },
+    getFilter () {
+      const it = {
+        year: '',
+        id: '',
+        tape: '',
+        duration: ''
+      }
+      if (this.$refs.sYear !== undefined) {
+        it.year = this.$refs.sYear.getValue()
+      }
+      if (this.$refs.sTape !== undefined) {
+        it.tape = this.$refs.sTape.getValue()
+      }
+      if (this.$refs.sDuration !== undefined) {
+        it.duration = this.$refs.sDuration.getValue()
+      }
+      if (this.$refs.sId !== undefined) {
+        it.id = this.$refs.sId.getValue()
+      }
+      return it
+    },
+    getDurationFromString (duration) {
+      const durations = {
+        min: 0,
+        max: Infinity
+      }
+
+      if (duration !== '') {
+        if (duration.includes('<')) {
+          const split = duration.split('<')
+          if (split[0].replace(' ', '') === '') {
+            durations.max = parseInt(split[1])
+          } else {
+            durations.min = parseInt(split[0])
+            durations.max = parseInt(split[1])
+          }
+        } else if (duration.includes('>')) {
+          const split = duration.split('>')
+          durations.min = parseInt(split[1])
+        }
+      }
+      return durations
+    }
+  }
+}
+</script>
+
+<style scoped>
+.search {
+  width: 100%;
+  border-radius: 10px;
+  padding: 5px;
+  margin-right: 20px;
+  margin-top: 10px;
+}
+</style>
diff --git a/src/components/NavigationMenu.vue b/src/components/NavigationMenu.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c36f6827aeff8a2fe0e83cd961980afd80b556f0
--- /dev/null
+++ b/src/components/NavigationMenu.vue
@@ -0,0 +1,439 @@
+<template>
+  <div class="navigationMenu">
+    <router-link :to="{ name: 'AnnualOverview'}">
+      <img class="OrchiveLogo" src="../assets/Orchive.svg">
+    </router-link>
+    <div class="navigationContainer">
+      <div class="containerItem" v-for="(item, index) in this.sites" :key=index>
+        <button class="navigationButton" v-bind:class="{ selected: actualIndex === index }" @click="navigateTo(index)" >{{item}}</button>
+      </div>
+      <RandomOrcaPlayer
+        class="randomOrcaPlayer"
+        :is-playing="false"
+        :length="10"
+        :speed="5">
+      </RandomOrcaPlayer>
+      <div class="sequenceCount">
+        <p v-if="sequenceQueue.length > 0">{{sequenceQueue.length}} orca sequence(s) added</p>
+        <p v-else>No orca sequence added</p>
+      </div>
+      <div class="containerItemUserChange">
+        <vs-button @click="onOpenUserUpdate" radius color="danger" type="gradient" icon="person"></vs-button>
+      </div>
+      <div class="containerItemUserChange1">
+        <vs-button @click="onOpenSequencesList" radius color="primary" type="gradient" icon="list"></vs-button>
+      </div>
+      <div style="display: none" v-if="queueSettings.isLive">
+        <audio autoplay v-for="sequence in sequenceQueue.filter(x => canPlay.includes(x.orca_sequence_id))"
+               @ended="sequenceEnded(sequence.orca_sequence_id)"
+               v-bind:id="sequence.orca_sequence_id"
+               v-on:canplay="canPlaySequence(sequence.orca_sequence_id)"
+               v-bind:key="sequence.orca_sequence_id">
+          <source v-bind:src="sequence.url" type="audio/mp3" />
+        </audio>
+      </div>
+    </div>
+    <vs-popup class="holamundo"  title="User" :active.sync="userPopupActive">
+      <SearchAutoComplete @enter="onUserChange" @onkeychange="onUserChange" :search="userName" :clear="false" class="content" :items="allUsers" ></SearchAutoComplete>
+      <div class="content">
+        <vs-button class="popupButton" @click="onUserUpdate" color="success" type="filled">Change User</vs-button>
+        <vs-button class="popupButton" @click="userPopupActive=false" color="danger" type="filled">Discard</vs-button>
+      </div>
+    </vs-popup>
+    <vs-popup class="homeland"  title="Sequences" :active.sync="sequencesListPopupActive">
+      <vs-list v-for="item in sequenceQueue" v-bind:key="item.orca_sequence_id">
+        {{ item.orca_sequence_id }}
+      </vs-list>
+    </vs-popup>
+  </div>
+</template>
+
+<script>
+import SearchAutoComplete from '../components/SearchAutocomplete'
+import RandomOrcaPlayer from '@/components/RandomOrcaPlayer'
+import { Bus } from '@/main'
+import axios from 'axios'
+
+export default {
+  components: {
+    SearchAutoComplete,
+    RandomOrcaPlayer
+  },
+  data () {
+    return {
+      audioContext: {},
+      audioElement: {},
+      stereoNode: {},
+      track: {},
+      userName: '',
+      userPopupActive: false,
+      sequencesListPopupActive: false,
+      allUsers: [],
+      actualIndex: 0,
+      isRandomPlayerPlaying: false,
+      sites: [
+        'Overview',
+        'Search',
+        'Mark sequences',
+        'Find sequences',
+        'Organize sequences'
+      ],
+      navigation: [
+        'AnnualOverview',
+        'SearchContextView',
+        'MarkSequencesView',
+        'FindSequencesView',
+        'OrganizeSequencesView'
+      ],
+      queueSettings: {
+        length: 10,
+        speed: [2, 10],
+        isLive: false
+      },
+      mock: false,
+      audio: {},
+      sequenceQueue: [],
+      canPlay: []
+    }
+  },
+  created () {
+    Bus.$on('set-user', () => {
+      this.userPopupActive = true
+    })
+    this.$eventHub.$on('live_queue_settings', (queueSettingsTemp) => {
+      localStorage.isLive = queueSettingsTemp.isLive
+      console.log('New queue settings: ' + JSON.stringify(queueSettingsTemp))
+      const elemsToDelete = this.sequenceQueue.length - queueSettingsTemp.length
+      // const tempSequenceQueue = []
+
+      if (elemsToDelete > 0) {
+        /* for (let i = elemsToDelete; i < this.sequenceQueue.length; i++) {
+          tempSequenceQueue.push(this.sequenceQueue[i])
+        } */
+
+        this.sequenceQueue.splice(0, elemsToDelete)
+
+        const data = []
+        for (let i = 0; i < this.sequenceQueue.length; i++) {
+          data.push(this.sequenceQueue[i].orca_sequence_id)
+        }
+        this.$eventHub.$emit('change-queue-event', data)
+      }
+      if (!queueSettingsTemp.isLive) {
+        console.log('Stop audio player')
+        this.canPlay = []
+      } else if (queueSettingsTemp.isLive && !this.queueSettings.isLive) {
+        console.log('Start audio player')
+        this.queueSettings = Object.assign({}, queueSettingsTemp)
+        this.startSequences()
+      }
+      // this.queueSettings = Object.create(queueSettingsTemp)
+      this.queueSettings = Object.assign({}, queueSettingsTemp)
+    })
+    this.$eventHub.$on('live_add_to_queue', async (sequence) => {
+      console.log('Add request get')
+      if (this.sequenceQueue.length > this.queueSettings.length - 1) {
+        this.sequenceQueue.splice(0, 1)
+      }
+      // first we have to load before adding
+      sequence.url = await this.audioSourceForSequence(sequence)
+      if (this.queueSettings.isLive) {
+        this.canPlay.push(sequence.orca_sequence_id)
+      }
+
+      this.sequenceQueue.push(sequence)
+      this.updateStorage()
+    })
+    this.$eventHub.$on('live_remove_from_queue', (id) => {
+      this.sequenceQueue = this.sequenceQueue.filter(x => x.orca_sequence_id !== id)
+
+      if (this.canPlay.includes(id)) {
+        this.canPlay.splice(this.canPlay.indexOf(id), 1)
+      }
+
+      this.updateStorage()
+    })
+    this.$eventHub.$on('live_set_queue', async (sequences) => {
+      this.canPlay = []
+      this.sequenceQueue.length = 0
+      if (sequences.length > this.queueSettings.length) {
+        confirm('Too much sequences selected. The current maximum size of the queue is ' + this.queueSettings.length)
+        return
+      }
+      for (let i = 0; i < sequences.length; i++) {
+        sequences[i].url = await this.audioSourceForSequence(sequences[i])
+        this.sequenceQueue.push(sequences[i])
+      }
+      this.updateStorage()
+      if (this.queueSettings.isLive) {
+        await this.startSequences()
+      }
+    })
+  },
+  beforeDestroy () {
+    Bus.$off()
+    this.$destroy()
+  },
+  async mounted () {
+    if (this.mock) {
+      const sequences = this.mockSequences()
+      for (let i = 0; i < sequences.length; i++) {
+        sequences[i].url = await this.audioSourceForSequence(sequences[i])
+        if (this.queueSettings.isLive) {
+          this.canPlay.push(sequences[i].orca_sequence_id)
+        }
+        this.sequenceQueue.push(sequences[i])
+      }
+    }
+
+    this.userName = localStorage.user
+    if (this.userName === undefined || this.userName === 'null' || this.userName === '') {
+      this.userPopupActive = true
+    }
+
+    try {
+      const result = await axios.get('/api/browse/mark/orca_sequences/user_names')
+      this.allUsers = Object.keys(result.data)
+    } catch (error) {
+      console.log(error)
+    }
+    if (localStorage.sequenceQueue) {
+      localStorage.sequenceQueue = ''
+    }
+  },
+  methods: {
+    async audioSourceForSequence (sequence) {
+      console.log(sequence)
+      let orcaPath = '/files/tapes/' + sequence.tape_year + '/' + sequence.tape_name + '/' + sequence.tape_channel + '.mp3'
+
+      if (this.mock) {
+        orcaPath = require('../assets/audio/001A1.mp3')
+      }
+      const config = { url: orcaPath, method: 'get', responseType: 'blob' }
+      const response = await axios.request(config)
+      const blobAudio = response.data
+      const size = blobAudio.size
+      const duration = 48 * 60 * 1000
+      const bytePerMillisecond = size / duration
+      const startBytes = bytePerMillisecond * sequence.timestamp_start_ms
+      const endBytes = bytePerMillisecond * sequence.timestamp_end_ms
+      const blobAudioSliced = blobAudio.slice(startBytes, endBytes)
+      const url = window.URL.createObjectURL(blobAudioSliced)
+      console.log(url)
+      return url
+    },
+    async sequenceEnded (id) {
+      console.log('ended ' + id)
+      this.canPlay.splice(this.canPlay.indexOf(id), 1)
+      console.log('removed from can play: ' + this.canPlay)
+
+      if (this.sequenceQueue.filter(sequence => sequence.orca_sequence_id === id).length > 0) {
+        await this.delay(this.getRandomValue(this.queueSettings.speed))
+        this.canPlay.push(id)
+        console.log('added to can play: ' + this.canPlay)
+      }
+
+      for (let i = 0; i < this.canPlay.length; i++) {
+        if (this.sequenceQueue.filter(sequence => sequence.orca_sequence_id === this.canPlay[i]).length <= 0) {
+          this.canPlay.splice(i, 1)
+        }
+      }
+      console.log('actual can play: ' + this.canPlay)
+    },
+    onUserChange (name) {
+      this.userName = name
+    },
+    navigateTo (viewId) {
+      this.$router.push({
+        name: this.navigation[viewId]
+      }).catch((error) => {
+        console.log(error)
+      })
+    },
+    onOpenUserUpdate () {
+      this.userPopupActive = true
+    },
+    onOpenSequencesList () {
+      this.sequencesListPopupActive = true
+    },
+    onUserUpdate () {
+      if (this.userName === '') {
+        return
+      }
+      this.userPopupActive = false
+      localStorage.user = this.userName
+      Bus.$emit('user-set')
+    },
+    updateStorage () {
+      const data = []
+      for (let i = 0; i < this.sequenceQueue.length; i++) {
+        data.push(this.sequenceQueue[i].orca_sequence_id)
+      }
+      localStorage.sequenceQueue = data
+      console.log('Local storage updated:' + JSON.stringify(localStorage.sequenceQueue))
+      this.$eventHub.$emit('change-queue-event', data)
+    },
+    mockSequences () {
+      return [
+        {
+          orca_sequence_id: '0',
+          timestamp_start_ms: 100000,
+          timestamp_end_ms: 102000
+        },
+        {
+          orca_sequence_id: '1',
+          timestamp_start_ms: 102000,
+          timestamp_end_ms: 104000
+        },
+        {
+          orca_sequence_id: '2',
+          timestamp_start_ms: 106000,
+          timestamp_end_ms: 108000
+        },
+        {
+          orca_sequence_id: '3',
+          timestamp_start_ms: 38000,
+          timestamp_end_ms: 40000
+        },
+        {
+          orca_sequence_id: '4',
+          timestamp_start_ms: 200000,
+          timestamp_end_ms: 210000
+        }
+      ]
+    },
+    async startSequences () {
+      const times = {}
+      for (let i = 0; i < this.sequenceQueue.length; i++) {
+        times[this.sequenceQueue[i].orca_sequence_id] = this.getRandomValue(this.queueSettings.speed)
+      }
+
+      for (let i = 0; i < this.queueSettings.speed[1]; i++) {
+        for (let j = 0; j < this.sequenceQueue.length; j++) {
+          if (times[this.sequenceQueue[j].orca_sequence_id] === i) {
+            this.canPlay.push(this.sequenceQueue[j].orca_sequence_id)
+          }
+        }
+        if (!this.queueSettings.isLive) {
+          return
+        }
+        await this.delay(1)
+        if (!this.queueSettings.isLive) {
+          return
+        }
+      }
+    },
+    getRandomValue (range) {
+      return Math.floor(Math.random() * (range[1] - range[0] + 1) + range[0])
+    },
+    async delay (n) {
+      return new Promise(function (resolve) {
+        setTimeout(resolve, n * 1000)
+      })
+    },
+    canPlaySequence (id) {
+      console.log('can play adjusted')
+
+      if (this.audioContext[id] !== undefined) {
+        return
+      }
+      const audio = document.getElementById(id)
+      console.log(audio)
+      if (audio === undefined || audio === null) {
+        return
+      }
+      this.audioContext[id] = new AudioContext()
+      this.track[id] = this.audioContext[id].createMediaElementSource(audio)
+      this.stereoNode[id] = new StereoPannerNode(this.audioContext[id], { pan: -1 })
+      this.track[id].connect(this.stereoNode[id]).connect(this.audioContext[id].destination)
+
+      // remove other keys
+      const keys = Object.keys(this.track)
+      for (let i = 0; i < keys.length; i++) {
+        this.audioContext[keys[i]] = undefined
+        this.track[keys[i]] = undefined
+        this.stereoNode[keys[i]] = undefined
+      }
+    }
+  },
+  watch: {
+    $route (to, from) {
+      const index = this.navigation.indexOf(to.name)
+      if (index === -1) {
+        this.actualIndex = 0
+      } else {
+        this.actualIndex = index
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+@import '@/assets/color.scss';
+
+.OrchiveLogo{
+  width: 65%;
+  margin-bottom: 1.5em;
+}
+
+::placeholder{
+  color: white;
+  font-size: 15pt;
+}
+
+.navigationContainer{
+  margin-right: 30px;
+}
+
+.navigationButton{
+  color: white;
+  background-color: rgba(38, 106, 133, 0.49);
+  border: 1px solid $dark-blue;
+  border-radius: 12px;
+  width: 100%;
+  font-size: 12pt;
+  margin-top: 5px;
+  margin-bottom: 5px;
+  outline: 0;
+  box-sizing: border-box;
+}
+
+.selected{
+  background-color: #266A85;
+}
+
+.containerItemUserChange {
+  position: absolute;
+  bottom: 10px;
+}
+
+.containerItemUserChange1 {
+  position: absolute;
+  bottom: 10px;
+  left: 80px;
+}
+
+.popupButton {
+  margin: 5px;
+}
+
+.content {
+  margin-left: 5px;
+  margin-right: 5px;
+  padding-top: 10px;
+  padding-bottom: 10px;
+  margin-top: 5px;
+}
+
+.sequenceCount {
+  font-size: 0.8em;
+  padding-top: 20px;
+}
+
+.test {
+  align-items: center;
+  font-size: 1.2em;
+}
+
+</style>
diff --git a/src/components/RandomOrcaPlayer.vue b/src/components/RandomOrcaPlayer.vue
new file mode 100644
index 0000000000000000000000000000000000000000..51973731520c72105d50229b66151e1647267cb0
--- /dev/null
+++ b/src/components/RandomOrcaPlayer.vue
@@ -0,0 +1,136 @@
+<template>
+  <div class="randomPlayerContainer">
+    <div class="titlePlayer">Orca Player</div>
+    <div class="randomPlayerItem">
+      <div class="playOrcaRandomPlayer" @click="playRandomPlayer">
+        <img class="playIconRandomPlayer" v-if="!isPlayerPlaying" src="../assets/play-circle-solid.svg" alt="">
+        <img class="pauseIconRandomPlayer" v-else src="../assets/pause-circle-solid.svg" alt="">
+      </div>
+    </div>
+    <div class="titleSlider">Choose range of delay between noise:</div>
+    <vue-slider
+                class="sliderSpeed"
+                ref="sliderSpeed"
+                v-model="valueRange"
+                :enable-cross="false"
+                :min="2"
+                :max="60"
+                :min-range="3"
+                :max-range="58"
+                :interval="1"
+                :tooltip-placement="'bottom'"
+                @drag-end="this.onSliderSpeedChanged">
+    </vue-slider>
+    <div class="titleSlider">Choose length of queue:</div>
+    <vue-slider
+      class="sliderAmount"
+      ref="sliderAmount"
+      v-model="valueSliderAmount"
+      :min="2"
+      :max="15"
+      :interval="1"
+      :tooltip-placement="'bottom'"
+      @drag-end="this.onSliderAmountChanged">
+    </vue-slider>
+  </div>
+</template>
+
+<script>
+import VueSlider from 'vue-slider-component'
+import 'vue-slider-component/theme/default.css'
+import { Bus } from '@/main'
+
+export default {
+  components: {
+    VueSlider
+  },
+  name: 'RandomOrcaPlayer',
+  props: {
+    length: Number,
+    speed: Number,
+    isPlaying: Boolean
+  },
+  data () {
+    return {
+      valueRange: [2, 10],
+      valueSliderSpeed: 1,
+      valueSliderAmount: 2,
+      isPlayerPlaying: false,
+      queueSettings: {
+        length: 10,
+        speed: [2, 10],
+        isLive: false
+      }
+    }
+  },
+  mounted () {
+    this.queueSettings.isLive = this.isPlaying
+    this.queueSettings.length = this.length
+    this.$refs.sliderAmount.setValue(this.queueSettings.length)
+    this.$eventHub.$emit('live_queue_settings', this.queueSettings)
+  },
+  destroyed () {
+    this.$destroy()
+    Bus.$off()
+  },
+  methods: {
+    onSliderSpeedChanged (index) {
+      this.queueSettings.speed = this.$refs.sliderSpeed.getValue()
+      this.$eventHub.$emit('live_queue_settings', this.queueSettings)
+    },
+    onSliderAmountChanged (index) {
+      this.queueSettings.length = this.$refs.sliderAmount.getValue()
+      this.$eventHub.$emit('live_queue_settings', this.queueSettings)
+    },
+    playRandomPlayer () {
+      this.isPlayerPlaying = !this.isPlayerPlaying
+      this.queueSettings.isLive = this.isPlayerPlaying
+      this.$eventHub.$emit('live_queue_settings', this.queueSettings)
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+@import '@/assets/color.scss';
+
+.playIconRandomPlayer{
+  width: 100px;
+  height: 100px;
+  filter: $filter-dark-blue;
+  display: block;
+  margin-top: 10px;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.pauseIconRandomPlayer{
+  width: 100px;
+  height: 100px;
+  filter: $filter-light-blue;
+  cursor: pointer;
+  display: block;
+  margin-top: 10px;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.sliderSpeed {
+  margin-top: 10px;
+}
+
+.sliderAmount {
+  margin-top: 10px;
+}
+
+.titleSlider {
+  font-size: 0.8em;
+  padding-top: 10px;
+}
+
+.titlePlayer {
+  font-size: 1.2em;
+  margin-top: 10px;
+  text-align: center;
+}
+</style>
diff --git a/src/components/SearchAutocomplete.vue b/src/components/SearchAutocomplete.vue
new file mode 100644
index 0000000000000000000000000000000000000000..37c93f297f921c053719ad73692b731ffa794945
--- /dev/null
+++ b/src/components/SearchAutocomplete.vue
@@ -0,0 +1,190 @@
+<template>
+  <div class="autocomplete">
+    <input
+      type="text"
+      class="search"
+      autocomplete="off"
+      @input="onChange"
+      v-model="search"
+      @keyup="onChangeText"
+      @keydown.down="onArrowDown"
+      @keydown.up="onArrowUp"
+      @keydown.enter="onEnter"
+    />
+    <ul
+      id="autocomplete-results"
+      v-show="isOpen && suggest"
+      class="autocomplete-results"
+    >
+      <li
+        class="loading"
+        v-if="isLoading"
+      >
+        Loading results...
+      </li>
+      <li
+        v-else
+        v-for="(result, i) in results"
+        :key="i"
+        @click="setResult(result)"
+        class="autocomplete-result"
+        :class="{ 'is-active': i === arrowCounter }"
+      >
+        {{ result }}
+      </li>
+    </ul>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'SearchAutocomplete',
+  props: {
+    search: {
+      type: String,
+      required: false,
+      default: () => ''
+    },
+    clear: {
+      type: Boolean,
+      required: false,
+      default: () => true
+    },
+    items: {
+      type: Array,
+      required: false,
+      default: () => []
+    },
+    isAsync: {
+      type: Boolean,
+      required: false,
+      default: false
+    },
+    suggest: {
+      type: Boolean,
+      required: false,
+      default: true
+    }
+  },
+  data () {
+    return {
+      isOpen: false,
+      results: [],
+      isLoading: false,
+      arrowCounter: -1
+    }
+  },
+  watch: {
+    items: function (value, oldValue) {
+      if (value.length !== oldValue.length) {
+        this.results = value
+        this.isLoading = false
+      }
+    }
+  },
+  mounted () {
+    document.addEventListener('click', this.handleClickOutside)
+  },
+  destroyed () {
+    document.removeEventListener('click', this.handleClickOutside)
+  },
+  methods: {
+    setValue (value) {
+      this.search = value
+    },
+    getValue () {
+      return this.search
+    },
+    onChangeText () {
+      this.$emit('onkeychange', this.search)
+    },
+    setResult (result) {
+      this.$emit('enter', result)
+      if (this.clear) {
+        this.search = ''
+      } else {
+        this.search = result
+      }
+      this.isOpen = false
+    },
+    filterResults () {
+      this.results = this.items.filter((item) => {
+        return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1
+      })
+    },
+    onChange () {
+      if (this.isAsync) {
+        this.isLoading = true
+      } else {
+        this.filterResults()
+        this.isOpen = true
+      }
+    },
+    handleClickOutside (event) {
+      if (!this.$el.contains(event.target)) {
+        this.isOpen = false
+        this.arrowCounter = -1
+      }
+    },
+    onArrowDown () {
+      if (this.arrowCounter < this.results.length) {
+        this.arrowCounter = this.arrowCounter + 1
+      }
+    },
+    onArrowUp () {
+      if (this.arrowCounter > 0) {
+        this.arrowCounter = this.arrowCounter - 1
+      }
+    },
+    onEnter () {
+      if (this.arrowCounter === -1) {
+        this.$emit('enter', this.search)
+      } else {
+        this.$emit('enter', this.results[this.arrowCounter])
+      }
+      if (this.clear) {
+        this.search = ''
+      } else if (this.arrowCounter === -1) {
+      } else {
+        this.search = this.results[this.arrowCounter]
+      }
+      this.isOpen = false
+      this.arrowCounter = -1
+    }
+  }
+}
+</script>
+
+<style>
+.autocomplete {
+  position: relative;
+}
+
+.autocomplete-results {
+  padding: 0;
+  margin: 0;
+  border: 1px solid #eeeeee;
+  height: 120px;
+  overflow: auto;
+  border-radius: 10px;
+}
+
+.autocomplete-result {
+  list-style: none;
+  text-align: left;
+  padding: 5px;
+  cursor: pointer;
+}
+
+.autocomplete-result.is-active,
+.autocomplete-result:hover {
+  background-color: #4AAE9B;
+  color: white;
+}
+
+.search {
+  width: 100%;
+  border-radius: 10px;
+  padding: 5px;
+}
+</style>
diff --git a/src/components/SearchBar.vue b/src/components/SearchBar.vue
index d1b62bc8c10fa30aae0508d4f0049c6364cb3052..5a31962c6b251f5891545186a5bf73b4c65c8461 100644
--- a/src/components/SearchBar.vue
+++ b/src/components/SearchBar.vue
@@ -3,8 +3,7 @@
         <router-link :to="{ name: 'AnnualOverview'}" @click.native="deleteQuery">
             <img class="OrchiveLogo" src="../assets/Orchive.svg">
         </router-link>
-
-        <div class="searchContainer">
+      <div class="searchContainer">
             <div class="searchHeader">
                 <h2 class="searchH1">Search</h2>
                 <router-link @click.native="deleteQuery" :to="{ name: 'AnnualOverview'}" >
diff --git a/src/components/SegmentHeader.vue b/src/components/SegmentHeader.vue
new file mode 100644
index 0000000000000000000000000000000000000000..603b6938d320b133d683acbe67ec8f0546b93efa
--- /dev/null
+++ b/src/components/SegmentHeader.vue
@@ -0,0 +1,172 @@
+<template>
+  <div class="detailHeader">
+    <div class="change">
+      <div class="PDFIconContainer">
+        <img class="detailPDFIcon" src="@/assets/tape.svg">
+      </div>
+      <div class="selectPreviousOrNextLabbook">
+        <div style="cursor: pointer;" class="previous" v-if="this.actualIndex > 0" @click="changeSegment(-1)"> &lt; </div>
+        <div class="noPrevious" v-else> &lt; </div>
+        <p class="next">
+          {{actualIndex + 1}} / {{segments_count}} Segment
+        </p>
+        <div style="cursor: pointer;" class="next" v-if="this.actualIndex < this.segments_count - 1" @click="changeSegment(1)"> &gt; </div>
+        <div class="noNext" v-else> &gt; </div>
+      </div>
+    </div>
+    <div class="infoLabbook">
+      <h1> {{segment_id}} </h1>
+      <p class="labbookDate"> Orca probability: {{segment_probability}} </p>
+      <p class="labbookDate"> Already showed: {{segment_assessed}} </p>
+    </div>
+    <div class="infoLabbook">
+      <router-link
+        :to="{
+          name: 'DetailView',
+          params: {
+            year: this.tape_year,
+            type: 'Tape',
+            name: this.tape_name
+          },
+        }"
+      >
+        <h1> {{tape_name}} </h1>
+      </router-link>
+      <p class="labbookDate"> {{tape_year}} </p>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Bus } from '@/main'
+
+export default {
+  name: 'SegmentHeader',
+  props: {
+    segments_count: {
+      type: Number,
+      required: true
+    },
+    tape_name: {
+      type: String,
+      required: true
+    },
+    tape_year: {
+      type: Number,
+      required: true
+    },
+    segment_id: {
+      type: String
+    },
+    segment_probability: {
+      type: String,
+      required: true
+    },
+    segment_assessed: {
+      type: Boolean,
+      required: true
+    }
+  },
+  data () {
+    return {
+      actualIndex: 0
+    }
+  },
+  mounted () {
+  },
+  methods: {
+    changeSegment (direction) {
+      this.actualIndex = this.actualIndex + direction
+      Bus.$emit('segment_index_changed', this.actualIndex)
+    },
+    resetIndex () {
+      this.actualIndex = 0
+      Bus.$emit('segment_index_changed', this.actualIndex)
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+@import '@/assets/color.scss';
+
+.detailHeader {
+  display: flex;
+  justify-content: space-between;
+}
+
+.detailHeader button {
+  cursor: pointer;
+  border: none;
+  background: none;
+  color: $dark-blue;
+  font-weight: bold;
+}
+
+.changeLabbook {
+  display: flex;
+  flex-direction: column;
+}
+
+.change {
+  padding-top: 18px;
+}
+
+.detailPDFIcon {
+  filter: invert(36%) sepia(5%) saturate(5710%) hue-rotate(152deg) brightness(94%) contrast(84%);
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+  width: 35px;
+}
+
+.selectPreviousOrNextLabbook {
+  display: flex;
+  color: $dark-blue;
+  font-weight: bold;
+  margin-top: -6px;
+}
+
+.detailHeader h1 {
+  text-align: right;
+  margin-bottom: 6px;
+  margin-top: 8px;
+}
+
+.labbookDate {
+  margin-top: 0px;
+  text-align: right;
+}
+
+.previous {
+  margin-top: 16px;
+  margin-bottom: 16px;
+  margin-right: 5px;
+  text-decoration: none;
+  color: $dark-blue;
+}
+
+.noPrevious {
+  margin-top: 16px;
+  margin-bottom: 16px;
+  margin-right: 5px;
+  text-decoration: none;
+  color: $light-grey-2;
+}
+
+.next {
+  margin-top: 16px;
+  margin-bottom: 16px;
+  margin-left: 5px;
+  text-decoration: none;
+  color: $dark-blue;
+}
+
+.noNext {
+  margin-top: 16px;
+  margin-bottom: 16px;
+  margin-left: 5px;
+  text-decoration: none;
+  color: $light-grey-2;
+}
+</style>
diff --git a/src/components/SequenceHeader.vue b/src/components/SequenceHeader.vue
new file mode 100644
index 0000000000000000000000000000000000000000..eacccf885b6e0eaa522c6c180e82761902bc1f2b
--- /dev/null
+++ b/src/components/SequenceHeader.vue
@@ -0,0 +1,171 @@
+<template>
+  <div class="detailHeader">
+    <div class="sequenceInfo">
+      <h1> {{orca_sequence_id}} </h1>
+      <p class="detailedInfo"> Timestamp: {{Math.trunc(timestamp_start/60000)}}min {{((timestamp_start % 60000)/1000).toFixed(0)}}s - {{Math.trunc(timestamp_end/60000)}}min {{((timestamp_end % 60000)/1000).toFixed(0)}}s </p>
+      <p v-if="rating > 0" class="detailedInfo"><StarRating :read-only="true" :star-size="20" :rating="rating" :show-rating="false"/></p>
+    </div>
+    <div class="infoLabbook">
+      <router-link
+        :to="{
+          name: 'DetailView',
+          params: {
+            year: this.tape_year,
+            type: 'Tape',
+            name: this.tape_name
+          },
+        }"
+      >
+        <h1> {{tape_name}} </h1>
+      </router-link>
+      <p class="labbookDate"> {{tape_year}} </p>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Bus } from '@/main'
+import StarRating from '../components/StarRating.vue'
+
+export default {
+  name: 'SequenceHeader',
+  components: {
+    StarRating
+  },
+  props: {
+    orca_sequence_id: {
+      type: String,
+      required: true
+    },
+    tape_name: {
+      type: String,
+      required: true
+    },
+    tape_year: {
+      type: Number,
+      required: true
+    },
+    timestamp_start: {
+      type: Number,
+      required: true
+    },
+    timestamp_end: {
+      type: Number,
+      required: true
+    },
+    rating: {
+      type: Number,
+      required: true
+    }
+  },
+  data () {
+    return {
+      actualIndex: 0
+    }
+  },
+  mounted () {
+  },
+  methods: {
+    changeSegment (direction) {
+      this.actualIndex = this.actualIndex + direction
+      Bus.$emit('segment_index_changed', this.actualIndex)
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+@import '@/assets/color.scss';
+
+.detailHeader {
+  display: flex;
+  justify-content: space-between;
+}
+
+.detailHeader button {
+  cursor: pointer;
+  border: none;
+  background: none;
+  color: $dark-blue;
+  font-weight: bold;
+}
+
+.changeLabbook {
+  display: flex;
+  flex-direction: column;
+}
+
+.change {
+  padding-top: 18px;
+}
+
+.detailPDFIcon {
+  filter: invert(36%) sepia(5%) saturate(5710%) hue-rotate(152deg) brightness(94%) contrast(84%);
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+  width: 35px;
+}
+
+.selectPreviousOrNextLabbook {
+  display: flex;
+  color: $dark-blue;
+  font-weight: bold;
+  margin-top: -6px;
+}
+
+.detailHeader h1 {
+  text-align: right;
+  margin-bottom: 6px;
+  margin-top: 8px;
+}
+
+.labbookDate {
+  margin-top: 0px;
+  text-align: right;
+}
+
+.sequenceInfo {
+  margin-top: 0px;
+  text-align: left;
+  margin-right: 100px;
+}
+
+.detailedInfo {
+  margin-top: 0px;
+  text-align:left;
+  alignment: left;
+}
+
+.previous {
+  margin-top: 16px;
+  margin-bottom: 16px;
+  margin-right: 5px;
+  text-decoration: none;
+  color: $dark-blue;
+}
+
+.noPrevious {
+  margin-top: 16px;
+  margin-bottom: 16px;
+  margin-right: 5px;
+  text-decoration: none;
+  color: $light-grey-2;
+}
+
+.next {
+  margin-top: 16px;
+  margin-bottom: 16px;
+  margin-left: 5px;
+  text-decoration: none;
+  color: $dark-blue;
+}
+
+.noNext {
+  margin-top: 16px;
+  margin-bottom: 16px;
+  margin-left: 5px;
+  text-decoration: none;
+  color: $light-grey-2;
+}
+</style>
diff --git a/src/components/Star.vue b/src/components/Star.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d206bdcdaddd279f5b57c48830e8e999c4ecd031
--- /dev/null
+++ b/src/components/Star.vue
@@ -0,0 +1,259 @@
+<template>
+  <svg
+    :class="['vue-star-rating-star', {'vue-star-rating-star-rotate' : shouldAnimate}]"
+    :height="starSize"
+    :width="starSize"
+    :viewBox="viewBox"
+    @mousemove="mouseMoving"
+    @click="selected"
+    @touchstart="touchStart"
+    @touchend="touchEnd"
+  >
+
+    <linearGradient
+      :id="grad"
+      x1="0"
+      x2="100%"
+      y1="0"
+      y2="0"
+    >
+      <stop
+        :offset="starFill"
+        :stop-color="(rtl) ? getColor(inactiveColor) : getColor(activeColor)"
+        :stop-opacity="(rtl) ? getOpacity(inactiveColor) : getOpacity(activeColor)"
+      />
+      <stop
+        :offset="starFill"
+        :stop-color="(rtl) ? getColor(activeColor) : getColor(inactiveColor)"
+        :stop-opacity="(rtl) ? getOpacity(activeColor) : getOpacity(inactiveColor)"
+      />
+    </linearGradient>
+
+    <filter
+      :id="glowId"
+      height="130%"
+      width="130%"
+      filterUnits="userSpaceOnUse"
+    >
+      <feGaussianBlur
+        :stdDeviation="glow"
+        result="coloredBlur"
+      />
+      <feMerge>
+        <feMergeNode in="coloredBlur" />
+        <feMergeNode in="SourceGraphic" />
+      </feMerge>
+    </filter>
+
+    <polygon
+      v-show="glowColor && glow > 0 && fill > 0"
+      :points="starPointsToString"
+      :fill="gradId"
+      :stroke="glowColor"
+      :filter="'url(#'+glowId+')'"
+      :stroke-width="border"
+    />
+
+    <polygon
+      :points="starPointsToString"
+      :fill="gradId"
+      :stroke="getBorderColor"
+      :stroke-width="border"
+      :stroke-linejoin="strokeLinejoin"
+    />
+    <polygon
+      :points="starPointsToString"
+      :fill="gradId"
+    />
+  </svg>
+</template>
+
+<script type="text/javascript">
+import AlphaColor from '../classes/AlphaColor'
+
+export default {
+  name: 'Star',
+  props: {
+    fill: {
+      type: Number,
+      default: 0
+    },
+    points: {
+      type: Array,
+      default () {
+        return []
+      }
+    },
+    size: {
+      type: Number,
+      default: 50
+    },
+    starId: {
+      type: Number,
+      required: true
+    },
+    activeColor: {
+      type: String,
+      required: true
+    },
+    inactiveColor: {
+      type: String,
+      required: true
+    },
+    borderColor: {
+      type: String,
+      default: '#000'
+    },
+    activeBorderColor: {
+      type: String,
+      default: '#000'
+    },
+    borderWidth: {
+      type: Number,
+      default: 0
+    },
+    roundedCorners: {
+      type: Boolean,
+      default: false
+    },
+    rtl: {
+      type: Boolean,
+      default: false
+    },
+    glow: {
+      type: Number,
+      default: 0
+    },
+    glowColor: {
+      type: String,
+      default: null,
+      required: false
+    },
+    animate: {
+      type: Boolean,
+      default: false
+    }
+  },
+  emits: ['star-mouse-move', 'star-selected'],
+  data () {
+    return {
+      starPoints: [19.8, 2.2, 6.6, 43.56, 39.6, 17.16, 0, 17.16, 33, 43.56],
+      grad: '',
+      glowId: '',
+      isStarActive: true
+    }
+  },
+  computed: {
+    starPointsToString () {
+      return this.starPoints.join(',')
+    },
+    gradId () {
+      return 'url(#' + this.grad + ')'
+    },
+    starSize () {
+      // Adjust star size when rounded corners are set with no border, to account for the 'hidden' border
+      const size = (this.roundedCorners && this.borderWidth <= 0) ? parseInt(this.size) - parseInt(this.border) : this.size
+      return parseInt(size) + parseInt(this.border)
+    },
+    starFill () {
+      return (this.rtl) ? 100 - this.fill + '%' : this.fill + '%'
+    },
+    border () {
+      return (this.roundedCorners && this.borderWidth <= 0) ? 6 : this.borderWidth
+    },
+    getBorderColor () {
+      if (this.roundedCorners && this.borderWidth <= 0) {
+        // create a hidden border
+        return (this.fill <= 0) ? this.inactiveColor : this.activeColor
+      }
+
+      return (this.fill <= 0) ? this.borderColor : this.activeBorderColor
+    },
+    maxSize () {
+      return this.starPoints.reduce(function (a, b) {
+        return Math.max(a, b)
+      })
+    },
+    viewBox () {
+      return '0 0 ' + this.maxSize + ' ' + this.maxSize
+    },
+    shouldAnimate () {
+      return this.animate && this.isStarActive
+    },
+    strokeLinejoin () {
+      return this.roundedCorners ? 'round' : 'miter'
+    }
+  },
+  created () {
+    this.starPoints = (this.points.length) ? this.points : this.starPoints
+    this.calculatePoints()
+    this.grad = this.getRandomId()
+    this.glowId = this.getRandomId()
+  },
+  methods: {
+    mouseMoving ($event) {
+      if ($event.touchAction !== 'undefined') {
+        this.$emit('star-mouse-move', {
+          event: $event,
+          position: this.getPosition($event),
+          id: this.starId
+        })
+      }
+    },
+    touchStart () {
+      this.$nextTick(() => {
+        this.isStarActive = true
+      })
+    },
+    touchEnd () {
+      this.$nextTick(() => {
+        this.isStarActive = false
+      })
+    },
+    getPosition ($event) {
+      // calculate position in percentage.
+      const starWidth = (92 / 100) * this.size
+      const offset = (this.rtl) ? Math.min($event.offsetX, 45) : Math.max($event.offsetX, 1)
+      const position = Math.round((100 / starWidth) * offset)
+
+      return Math.min(position, 100)
+    },
+    selected ($event) {
+      this.$emit('star-selected', {
+        id: this.starId,
+        position: this.getPosition($event)
+      })
+    },
+    getRandomId () {
+      return Math.random().toString(36).substring(7)
+    },
+    calculatePoints () {
+      this.starPoints = this.starPoints.map((point, i) => {
+        const offset = i % 2 === 0 ? this.border * 1.5 : 0
+        return ((this.size / this.maxSize) * point) + offset
+      })
+    },
+    getColor (color) {
+      return new AlphaColor(color).parseAlphaColor().color
+    },
+    getOpacity (color) {
+      return new AlphaColor(color).parseAlphaColor().opacity
+    }
+  }
+}
+</script>
+
+<style scoped>
+.vue-star-rating-star {
+  overflow: visible !important;
+}
+
+.vue-star-rating-star-rotate {
+  transition: all .25s;
+}
+
+.vue-star-rating-star-rotate:hover {
+  transition: transform 0.25s;
+  transform: rotate(-15deg) scale(1.3)
+}
+</style>
diff --git a/src/components/StarRating.vue b/src/components/StarRating.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c1c43282ae11140f627cb191d6650002933acee7
--- /dev/null
+++ b/src/components/StarRating.vue
@@ -0,0 +1,309 @@
+<template>
+    <div :class="['vue-star-rating', {'vue-star-rating-rtl':rtl}, {'vue-star-rating-inline': inline}]">
+        <div class="sr-only">
+            <slot
+                    name="screen-reader"
+                    :rating="selectedRating"
+                    :stars="maxRating"
+            >
+                <span>Rated {{ selectedRating }} stars out of {{ maxRating }}</span>
+            </slot>
+        </div>
+
+        <div
+                class="vue-star-rating"
+                @mouseleave="resetRating"
+        >
+      <span
+              v-for="n in maxRating"
+              :key="n"
+              :class="[{'vue-star-rating-pointer': !readOnly }, 'vue-star-rating-star']"
+              :style="{'margin-right': margin + 'px'}"
+      >
+        <star
+                :fill="fillLevel[n-1]"
+                :size="starSize"
+                :points="starPoints"
+                :star-id="n"
+                :step="step"
+                :active-color="currentActiveColor"
+                :inactive-color="inactiveColor"
+                :border-color="borderColor"
+                :active-border-color="currentActiveBorderColor"
+                :border-width="borderWidth"
+                :rounded-corners="roundedCorners"
+                :rtl="rtl"
+                :glow="glow"
+                :glow-color="glowColor"
+                :animate="animate"
+                @star-selected="setRating($event, true)"
+                @star-mouse-move="setRating"
+        />
+      </span>
+            <span
+                    v-if="showRating"
+                    :class="['vue-star-rating-rating-text', textClass]"
+            > {{ formattedRating }}</span>
+        </div>
+    </div>
+</template>
+<script type="text/javascript">
+import Star from '../components/Star'
+
+export default {
+
+  name: 'VueStarRating',
+  components: {
+    Star
+  },
+  props: {
+    rowId: {
+      type: String,
+      default: ''
+    },
+    increment: {
+      type: Number,
+      default: 1
+    },
+    rating: {
+      type: Number,
+      default: 0
+    },
+    roundStartRating: {
+      type: Boolean,
+      default: true
+    },
+    activeColor: {
+      type: [String, Array],
+      default: '#ffd055'
+    },
+    inactiveColor: {
+      type: String,
+      default: '#d8d8d8'
+    },
+    maxRating: {
+      type: Number,
+      default: 5
+    },
+    starPoints: {
+      type: Array,
+      default () {
+        return []
+      }
+    },
+    starSize: {
+      type: Number,
+      default: 50
+    },
+    showRating: {
+      type: Boolean,
+      default: true
+    },
+    readOnly: {
+      type: Boolean,
+      default: false
+    },
+    textClass: {
+      type: String,
+      default: ''
+    },
+    inline: {
+      type: Boolean,
+      default: false
+    },
+    borderColor: {
+      type: String,
+      default: '#999'
+    },
+    activeBorderColor: {
+      type: [String, Array],
+      default: null
+    },
+    borderWidth: {
+      type: Number,
+      default: 0
+    },
+    roundedCorners: {
+      type: Boolean,
+      default: false
+    },
+    padding: {
+      type: Number,
+      default: 0
+    },
+    rtl: {
+      type: Boolean,
+      default: false
+    },
+    fixedPoints: {
+      type: Number,
+      default: null
+    },
+    glow: {
+      type: Number,
+      default: 0
+    },
+    glowColor: {
+      type: String,
+      default: '#fff'
+    },
+    clearable: {
+      type: Boolean,
+      default: false
+    },
+    activeOnClick: {
+      type: Boolean,
+      default: false
+    },
+    animate: {
+      type: Boolean,
+      default: false
+    }
+  },
+  emits: ['update-rating', 'hover-rating'],
+
+  data () {
+    return {
+      step: 0,
+      fillLevel: [],
+      currentRating: 0,
+      selectedRating: 0,
+      ratingSelected: false
+    }
+  },
+  computed: {
+    formattedRating () {
+      return (this.fixedPoints === null) ? this.currentRating : this.currentRating.toFixed(this.fixedPoints)
+    },
+    shouldRound () {
+      return this.ratingSelected || this.roundStartRating
+    },
+    margin () {
+      return this.padding + this.borderWidth
+    },
+    activeColors () {
+      if (Array.isArray(this.activeColor)) {
+        return this.padColors(this.activeColor, this.maxRating, this.activeColor.slice(-1)[0])
+      }
+
+      return new Array(this.maxRating).fill(this.activeColor)
+    },
+    currentActiveColor () {
+      if (!this.activeOnClick) {
+        return (this.currentRating > 0) ? this.activeColors[Math.ceil(this.currentRating) - 1] : this.inactiveColor
+      }
+      return (this.selectedRating > 0) ? this.activeColors[Math.ceil(this.selectedRating) - 1] : this.inactiveColor
+    },
+    activeBorderColors () {
+      if (Array.isArray(this.activeBorderColor)) {
+        return this.padColors(this.activeBorderColor, this.maxRating, this.activeBorderColor.slice(-1)[0])
+      }
+      const borderColor = (this.activeBorderColor) ? this.activeBorderColor : this.borderColor
+      return new Array(this.maxRating).fill(borderColor)
+    },
+    currentActiveBorderColor () {
+      if (!this.activeOnClick) {
+        return (this.currentRating > 0) ? this.activeBorderColors[Math.ceil(this.currentRating) - 1] : this.borderColor
+      }
+      return (this.selectedRating > 0) ? this.activeBorderColors[Math.ceil(this.selectedRating) - 1] : this.borderColor
+    },
+    roundedRating () {
+      const inv = 1.0 / this.increment
+      return Math.min(this.maxRating, Math.ceil(this.currentRating * inv) / inv)
+    }
+  },
+  watch: {
+    rating (val) {
+      this.currentRating = val
+      this.selectedRating = val
+      this.createStars(this.shouldRound)
+    }
+  },
+  created () {
+    this.step = this.increment * 100
+    this.currentRating = this.rating
+    this.selectedRating = this.currentRating
+    this.createStars(this.roundStartRating)
+  },
+  methods: {
+    setRating ($event, persist) {
+      if (!this.readOnly) {
+        const position = (this.rtl) ? (100 - $event.position) / 100 : $event.position / 100
+        this.currentRating = (($event.id + position) - 1).toFixed(2)
+        this.currentRating = (this.currentRating > this.maxRating) ? this.maxRating : this.currentRating
+        if (persist) {
+          this.createStars(true, true)
+          this.selectedRating = (this.clearable && this.currentRating === this.selectedRating) ? 0 : this.currentRating
+          this.$emit('update-rating', this.selectedRating, this.rowId)
+          this.ratingSelected = true
+        } else {
+          this.createStars(true, !this.activeOnClick)
+          this.$emit('hover-rating', this.selectedRating, this.rowId)
+        }
+      }
+    },
+    resetRating () {
+      if (!this.readOnly) {
+        this.currentRating = this.selectedRating
+        this.createStars(this.shouldRound)
+      }
+    },
+    createStars (round = true, applyFill = true) {
+      this.currentRating = (round) ? this.roundedRating : this.currentRating
+      for (let i = 0; i < this.maxRating; i++) {
+        let level = 0
+        if (i < this.currentRating) {
+          level = (this.currentRating - i > 1) ? 100 : (this.currentRating - i) * 100
+        }
+        if (applyFill) {
+          this.fillLevel[i] = Math.round(level)
+        }
+      }
+    },
+    padColors (array, minLength, fillValue) {
+      return Object.assign(new Array(minLength).fill(fillValue), array)
+    }
+  }
+}
+</script>
+<style scoped>
+.vue-star-rating-star {
+    display: inline-block;
+    -webkit-tap-highlight-color: transparent;
+}
+
+.vue-star-rating-pointer {
+    cursor: pointer;
+}
+
+.vue-star-rating {
+    display: flex;
+    align-items: center;
+}
+
+.vue-star-rating-inline {
+    display: inline-flex;
+}
+
+.vue-star-rating-rating-text {
+    margin-left: 7px;
+}
+
+.vue-star-rating-rtl {
+    direction: rtl;
+}
+
+.vue-star-rating-rtl .vue-star-rating-rating-text {
+    margin-right: 10px;
+    direction: rtl;
+}
+
+.sr-only {
+    position: absolute;
+    left: -10000px;
+    top: auto;
+    width: 1px;
+    height: 1px;
+    overflow: hidden;
+}
+</style>
diff --git a/src/main.js b/src/main.js
index 37ed7008d24bb57a4588b8f1cd1e40dc390a2a62..87f8a5674cf7ebaf7c1c100ea8fb459a7bf2ae15 100644
--- a/src/main.js
+++ b/src/main.js
@@ -2,12 +2,20 @@ import Vue from 'vue'
 import App from './App.vue'
 import router from './router'
 import WaveSurferVue from 'wavesurfer.js-vue'
+import VueGoodTable from 'vue-good-table'
+import 'vue-good-table/dist/vue-good-table.css'
+import 'vuesax/dist/vuesax.css'
+import Vuesax from 'vuesax'
+import 'material-icons/iconfont/material-icons.css'
 
 Vue.config.productionTip = false
-
+Vue.config.devtools = true
 export const Bus = new Vue()
+Vue.prototype.$eventHub = new Vue()
 
 Vue.use(WaveSurferVue)
+Vue.use(VueGoodTable)
+Vue.use(Vuesax)
 
 new Vue({
   router,
diff --git a/src/router/index.js b/src/router/index.js
index 38bedb032360ec7f43dedbb2c770b67787dcb5e9..348e175393092f6d919e9ab2e62ce22fccbbd769 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -31,6 +31,21 @@ const routes = [
 
     props: route => ({ query: route.query })
   },
+  {
+    path: '/mark',
+    name: 'MarkSequencesView',
+    component: () => import('../views/MarkSequencesView.vue')
+  },
+  {
+    path: '/find',
+    name: 'FindSequencesView',
+    component: () => import('../views/FindSequencesView.vue')
+  },
+  {
+    path: '/organize',
+    name: 'OrganizeSequencesView',
+    component: () => import('../views/OrganizeSequencesView.vue')
+  },
   {
     path: '/:year',
     name: 'MonthlyOverview',
diff --git a/src/views/DetailView.vue b/src/views/DetailView.vue
index fc7675fcbd0950aaf5e87362e36fa4319f1c5cc0..2d1e58d7671b4129e105f9e03750437a703597cf 100644
--- a/src/views/DetailView.vue
+++ b/src/views/DetailView.vue
@@ -110,6 +110,11 @@ export default {
     this.tapeName = this.tapeNames[this.audioNo - 1]
   },
   created () {
+    Bus.$on('goToTape', (tapeName, year, type) => {
+      this.name = tapeName
+      this.year = year
+      this.type = type
+    })
     Bus.$on('sendPreviousTape', (tapeName, year, type) => {
       this.name = tapeName
       this.year = year
diff --git a/src/views/ErrorView.vue b/src/views/ErrorView.vue
index 9e20ec79fe6de65ca86fd70fda9940ba00c8b0f7..96320332982612de0b2ffe665bb5ac5e84231b6b 100644
--- a/src/views/ErrorView.vue
+++ b/src/views/ErrorView.vue
@@ -43,6 +43,7 @@
 }
 </style>
 <script>
+
 export default {
   name: 'ErrorView',
   props: {
diff --git a/src/views/FindSequencesView.vue b/src/views/FindSequencesView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c2768bc0b047f36e8d48bda5c0d9872bba134755
--- /dev/null
+++ b/src/views/FindSequencesView.vue
@@ -0,0 +1,535 @@
+<template>
+  <div class="findSequences">
+    <div v-if="this.sequence_count <= 0">
+        <p1> No marked sequences found </p1>
+    </div>
+    <div v-if="this.sequence_count > 0" class="sequenceHeader">
+      <div class="changeSequence">
+        <div class="TapeIconContainer">
+          <img class="tapeIcon" src="@/assets/tape.svg">
+        </div>
+        <div class="selectPreviousOrNextSequence">
+          <div style="cursor: pointer;" class="previous" v-if="this.actual_sequence_index > 0" @click="changeSequence(-1)"> &lt; </div>
+          <div class="noPrevious" v-else> &lt; </div>
+          <p class="next">
+            {{actual_sequence_index + 1}} / {{sequence_count}} Sequence
+          </p>
+          <div style="cursor: pointer;" class="next" v-if="this.actual_sequence_index < this.sequence_count - 1" @click="changeSequence(1)"> &gt; </div>
+          <div class="noNext" v-else> &gt; </div>
+        </div>
+      </div>
+      <SequenceHeader
+        ref="sequence_header_1"
+        :orca_sequence_id="this.actual_sequence.orca_sequence_id"
+        :tape_name="this.actual_sequence.tape_name"
+        :tape_year="this.actual_sequence.tape_year"
+        :timestamp_start="this.actual_sequence.timestamp_start_ms"
+        :timestamp_end="this.actual_sequence.timestamp_end_ms"
+        :rating="this.actual_sequence.rating">
+      </SequenceHeader>
+    </div>
+    <AudioAndFrequencyPlayer
+          v-if="this.sequence_count > 0"
+          class="expand-width-first"
+          :is_editable="false"
+          :tape_name="this.actual_sequence.tape_name"
+          :tape_year="this.actual_sequence.tape_year"
+          :tape_channel="this.actual_sequence.tape_channel"
+          :timestamp_start_ms="this.actual_sequence.timestamp_start_ms"
+          :timestamp_end_ms="this.actual_sequence.timestamp_end_ms"
+          :sequences="this.regions"
+          :component_id="'first'"
+          ref="wavesurferComponentFirst"></AudioAndFrequencyPlayer>
+    <div v-if="this.sequence_count_similar_sequence > 0" class="similarSequenceHeader">
+      <div class="changeSimilarSequence">
+        <div class="TapeIconContainerSimilar">
+          <img class="tapeIconSimilar" src="@/assets/tape.svg">
+        </div>
+        <div class="selectPreviousOrNextSimilarSequence">
+          <div style="cursor: pointer;" class="previousSimilar" v-if="this.actual_sequence_index_similar_sequence > 0" @click="changeSequenceSimilar(-1)"> &lt; </div>
+          <div class="noPreviousSimilar" v-else> &lt; </div>
+          <p class="next">
+            {{actual_sequence_index_similar_sequence + 1}} / {{sequence_count_similar_sequence}} Sequence
+          </p>
+          <div style="cursor: pointer;" class="nextSimilar" v-if="this.actual_sequence_index_similar_sequence < this.sequence_count_similar_sequence - 1" @click="changeSequenceSimilar(1)"> &gt; </div>
+          <div class="noNextSimilar" v-else> &gt; </div>
+        </div>
+      </div>
+      <SequenceHeader
+        ref="sequence_header_2"
+        :orca_sequence_id="this.embedding_info.embedding_name"
+        :tape_name="this.embedding_info.tape_name"
+        :tape_year="this.embedding_info.year"
+        :timestamp_start="this.embedding_info.timestamp_start_ms"
+        :timestamp_end="this.embedding_info.timestamp_end_ms"
+        :rating="this.embedding_info.rating">
+      </SequenceHeader>
+    </div>
+    <AudioAndFrequencyPlayer
+      v-if="this.sequence_count_similar_sequence > 0"
+      class="expand-width-first"
+      :is_editable="false"
+      :origin_tape_name="this.embedding_info.tape_name"
+      :year="this.embedding_info.year"
+      :timestamp_start_ms="this.embedding_info.timestamp_start_ms"
+      :timestamp_end_ms="this.embedding_info.timestamp_end_ms"
+      :sequences="this.regions"
+      :component_id="'second'"
+      ref="wavesurferComponentSecond"></AudioAndFrequencyPlayer>
+    <div v-if="this.sequence_count_similar_sequence > 0" class="saveSimilarSequence">
+      <div>
+        <vue-good-table
+          :columns="columns"
+          :rows="rows"
+          @on-cell-click="onCellClick">
+          <template slot="table-row" slot-scope="props">
+              <span title="Similar" @click="similar" v-if="props.column.field === 'similar'">
+                <img class="similarIcon" src="../assets/check_icon.svg" alt="">
+              </span>
+            <div v-if="props.column.field === 'rating'">
+              <StarRating :read-only="false" @update-rating="onRatingChanged" :row-id="props.row.orca_sequence_id" :star-size="20" :rating="props.row.rating" :show-rating="false"></StarRating>
+            </div>
+            <span v-else>
+                {{props.formattedRow[props.column.field]}}
+              </span>
+          </template>
+        </vue-good-table>
+      </div>
+      <vs-popup class="holamundo"  title="Tags" :active.sync="tagPopupActive">
+        <div class="content">
+          <vs-chip v-for="tag in embedding_info.tags" v-bind:key="{tag}">
+            <div class="chip-content">{{tag}}</div>
+            <div class="chip-content" title="Delete" @click="onTagRemove(tag)">
+              <img class="deleteIcon" src="../assets/trash-alt-solid.svg" alt="">
+            </div>
+          </vs-chip>
+        </div>
+        <SearchAutoComplete @enter="onEnter" class="content" :items="allTags" ></SearchAutoComplete>
+        <div class="content">
+          <vs-button class="popupButton" @click="onTagsUpdate" color="success" type="filled">Update</vs-button>
+          <vs-button class="popupButton" @click="tagPopupActive=false" color="danger" type="filled">Discard</vs-button>
+        </div>
+      </vs-popup>
+    </div>
+    <div v-if="(this.sequence_count_similar_sequence <= 0) && this.sequence_count > 0" class="bottom">
+      <div class="infoLabbook">
+        <p1> {{this.message}} </p1>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import AudioAndFrequencyPlayer from '@/components/AudioAndFrequencyPlayer'
+import StarRating from '../components/StarRating.vue'
+import SearchAutoComplete from '../components/SearchAutocomplete'
+import SequenceHeader from '@/components/SequenceHeader'
+import axios from 'axios'
+import { Bus } from '@/main'
+
+export default ({
+  name: 'FindSequencesView',
+  components: {
+    AudioAndFrequencyPlayer,
+    StarRating,
+    SearchAutoComplete,
+    SequenceHeader
+  },
+  data () {
+    return {
+      sequence_count: 0,
+      actual_sequence_index: 0,
+      sequences: [],
+      message: 'An error occured.',
+      actual_sequence: {
+        orca_sequence_id: '',
+        tape_year: 0,
+        tape_name: '',
+        tape_channel: '',
+        audio_segment: '',
+        timestamp_start_ms: 0,
+        timestamp_end_ms: 0,
+        rating: 0,
+        tags: [],
+        user_name: ''
+      },
+      sequence_count_similar_sequence: 0,
+      actual_sequence_index_similar_sequence: 0,
+      similar_sequences: [],
+      embedding_info: {
+        embedding_name: '',
+        orca_sequence_id: '',
+        origin_audio_segment: '',
+        tape_name: '',
+        tape_channel: '',
+        year: 0,
+        timestamp_start_ms: 0,
+        timestamp_end_ms: 0,
+        rating: 0,
+        tags: [],
+        user_name: ''
+      },
+      columns: [
+        {
+          label: 'Similar',
+          field: 'similar',
+          sortable: false
+        },
+        {
+          label: 'ID',
+          field: 'orca_sequence_id',
+          sortable: false
+        },
+        {
+          label: 'Tags',
+          field: 'tags',
+          sortable: false
+        },
+        {
+          label: 'Rating',
+          field: 'rating',
+          type: 'number',
+          sortable: false
+        },
+        {
+          label: 'Duration',
+          field: 'duration',
+          sortable: false
+        },
+        {
+          label: 'Username',
+          field: 'user_name',
+          sortable: false
+        }
+
+      ],
+      rows: [
+        { orca_sequence_id: '', tags: '', rating: 0, duration: '', user_name: '' }
+      ],
+      regions: [],
+      allTags: [],
+      tagPopupActive: false,
+      channelRequestBody: {
+        _id: '',
+        name: '',
+        year: 0,
+        left: '',
+        right: ''
+      }
+    }
+  },
+  beforeDestroy () {
+    Bus.$off()
+  },
+  async mounted () {
+    // Waveform für das Orca Audio
+    try {
+      const response = await axios.get('/api/browse/mark/orca_sequences/embeddings_available/true')
+      this.sequences = response.data
+      this.sequence_count = response.data.length
+      const responseTags = await axios.get('/api/browse/mark/orca_sequences/tags')
+      this.allTags = Object.keys(responseTags.data)
+      await this.loadSequence()
+      await this.loadSimilarSequences(true)
+    } catch (error) {
+      console.log(error)
+    }
+  },
+  updated () {
+  },
+
+  methods: {
+    async similar () {
+      const url = this.createSequence()
+      await axios.post('/api/orca_sequence/', url)
+        .then((response) => {
+          console.log('Following data was saved:')
+          console.log(response.data)
+          this.$vs.notify({
+            title: 'Sequence saved',
+            text: 'Sequence ID: ' + this.embedding_info.orca_sequence_id,
+            color: 'success',
+            icon: 'verified_user'
+          })
+          this.loadSimilarSequences(true)
+        })
+        .catch((error) => {
+          console.log(error)
+          confirm(error)
+          this.$vs.notify({
+            title: 'Error while saving',
+            text: error,
+            color: 'warning',
+            icon: 'error'
+          })
+        })
+    },
+    onTagRemove (tag) {
+      const index = this.embedding_info.tags.indexOf(tag)
+      if (index !== -1) {
+        this.embedding_info.tags.splice(index, 1)
+      }
+      this.createRow()
+      console.log(JSON.stringify(this.embedding_info.tags))
+    },
+    async onTagsUpdate (tag) {
+      this.tagPopupActive = false
+      this.createRow()
+    },
+    onEnter (tag) {
+      if (tag === '' || this.embedding_info.tags.includes(tag)) {
+        return
+      }
+      if (!this.allTags.includes(tag)) {
+        this.allTags.push(tag)
+      }
+      this.embedding_info.tags.push(tag)
+      this.createRow()
+    },
+    onCellClick (params) {
+      if (params.column.label === 'Tags') {
+        this.tagPopupActive = true
+      }
+    },
+    onRatingChanged (selectedRating, rowId) {
+      this.embedding_info.rating = selectedRating
+      this.createRow()
+    },
+    getTimestampInSeconds () {
+      return Math.floor(Date.now() / 1000)
+    },
+    createSequence () {
+      return {
+        orca_sequence_id: this.embedding_info.orca_sequence_id,
+        tape_year: parseInt(this.embedding_info.year),
+        tape_name: this.embedding_info.tape_name,
+        tape_channel: this.embedding_info.tape_channel,
+        audio_segment: this.embedding_info.origin_audio_segment,
+        timestamp_start_ms: parseInt(this.embedding_info.timestamp_start_ms),
+        timestamp_end_ms: parseInt(this.embedding_info.timestamp_end_ms),
+        rating: this.embedding_info.rating,
+        tags: this.embedding_info.tags,
+        user_name: localStorage.user
+      }
+    },
+    createRow () {
+      console.log('Create row:')
+      console.log(JSON.stringify(this.embedding_info.tags))
+      if (Array.isArray(this.embedding_info.tags)) {
+        let tagsString = ''
+        for (let i = 0; i < this.embedding_info.tags.length; i++) {
+          tagsString += this.embedding_info.tags[i]
+          if (i < this.embedding_info.tags.length - 1) {
+            tagsString += ', '
+          }
+        }
+        this.rows[0].tags = tagsString
+      } else {
+        this.rows[0].tags = ''
+      }
+      this.rows[0].orca_sequence_id = this.embedding_info.orca_sequence_id
+      this.rows[0].rating = this.embedding_info.rating
+      const durationInt = (this.embedding_info.timestamp_end_ms - this.embedding_info.timestamp_start_ms) / 1000
+      this.rows[0].duration = String(durationInt) + 's'
+      this.rows[0].user_name = localStorage.user
+    },
+    getPosition (string, subString, index) {
+      return string.split(subString, index).join(subString).length
+    },
+    async createSimilarSequenceInfo (embeddingName) {
+      this.embedding_info.embedding_name = embeddingName
+      this.embedding_info.orca_sequence_id = 'orca_sequence_' + this.getTimestampInSeconds()
+      this.embedding_info.tape_name = embeddingName.substring(this.getPosition(embeddingName, '_', 3) + 1, this.getPosition(embeddingName, '_', 4))
+      const timestampStart = embeddingName.substring(this.getPosition(embeddingName, '_', 4) + 1, this.getPosition(embeddingName, '_', 5))
+      this.embedding_info.timestamp_start_ms = parseInt(timestampStart)
+      const timestampEnd = embeddingName.substring(this.getPosition(embeddingName, '_', 5) + 1, this.getPosition(embeddingName, '_', 6))
+      this.embedding_info.timestamp_end_ms = parseInt(timestampEnd)
+      this.embedding_info.user_name = localStorage.user
+      this.embedding_info.origin_audio_segment = 'audio_segment_' + this.embedding_info.year + '_' + this.embedding_info.tape_name + '_' + timestampStart + '_' + timestampEnd
+      this.embedding_info.year = parseInt(embeddingName.substring(this.getPosition(embeddingName, '_', 2) + 1, this.getPosition(embeddingName, '_', 3)))
+      this.embedding_info.tags = []
+      this.embedding_info.rating = 0
+      await this.getChannel(this.embedding_info.tape_name, this.embedding_info.year)
+    },
+    async getChannel (name, year) {
+      try {
+        const url = '/api/search-audio_tape/tape_name/' + name + '/tape_year/' + year
+        const response = await axios.get(url)
+        this.channelRequestBody = response.data
+        if (this.channelRequestBody[0].left === 'orca') {
+          this.embedding_info.tape_channel = 'left'
+        } else if (this.channelRequestBody[0].right === 'orca') {
+          this.embedding_info.tape_channel = 'right'
+        } else {
+          this.embedding_info.tape_channel = 'None'
+        }
+      } catch (error) {
+        console.log(error)
+        confirm(error)
+      }
+    },
+    async loadSequence () {
+      const id = String(this.sequences[this.actual_sequence_index])
+      try {
+        await axios.get('/api/browse/mark/orca_sequence/' + id).then((response) => {
+          this.actual_sequence = response.data
+          console.log(JSON.stringify(this.actual_sequence))
+          this.$refs.wavesurferComponentFirst.loadAudioFile(this.actual_sequence.tape_year, this.actual_sequence.tape_name, this.actual_sequence.tape_channel)
+        })
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async loadSimilarSequences (reloadIndex) {
+      const id = String(this.sequences[this.actual_sequence_index])
+      try {
+        await axios.get('/api/search-audio_segments/' + id).then(async (responseEmbedding) => {
+          this.sequence_count_similar_sequence = responseEmbedding.data.length
+          if (reloadIndex) {
+            this.actual_sequence_index_similar_sequence = 0
+          }
+          console.log('Following sequence data was received:')
+          console.log(responseEmbedding.data[this.actual_sequence_index_similar_sequence])
+          await this.createSimilarSequenceInfo(responseEmbedding.data[this.actual_sequence_index_similar_sequence]).then((dummy) => {
+            this.createRow()
+            this.$refs.wavesurferComponentSecond.loadAudioFile(this.embedding_info.year, this.embedding_info.tape_name, this.embedding_info.tape_channel)
+            this.$vs.notify({
+              title: 'New sequence',
+              text: 'New sequence loaded: ' + this.embedding_info.orca_sequence_id,
+              color: 'success',
+              icon: 'verified_user'
+            })
+          })
+        })
+      } catch (error) {
+        this.sequence_count_similar_sequence = 0
+        this.similar_sequences = []
+        this.message = error.response.data.message
+        console.log(error.response)
+      }
+    },
+    changeSequence (direction) {
+      this.actual_sequence_index = this.actual_sequence_index + direction
+      this.loadSequence()
+      this.loadSimilarSequences(true)
+    },
+    changeSequenceSimilar (direction) {
+      this.actual_sequence_index_similar_sequence = this.actual_sequence_index_similar_sequence + direction
+      this.loadSimilarSequences(false)
+    }
+  }
+})
+</script>
+
+<style lang="scss">
+@import '@/assets/color.scss';
+
+.sequenceHeader {
+  display: flex;
+  justify-content: space-between;
+}
+
+.similarSequenceHeader {
+  display: flex;
+  justify-content: space-between;
+  clear:both;
+}
+
+.changeSequence {
+  padding-top: 18px;
+}
+
+.tapeIcon {
+  filter: invert(36%) sepia(5%) saturate(5710%) hue-rotate(152deg) brightness(94%) contrast(84%);
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+  width: 35px;
+}
+
+.tapeIconSimilar {
+  filter: invert(36%) sepia(5%) saturate(5710%) hue-rotate(152deg) brightness(94%) contrast(84%);
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+  width: 35px;
+}
+
+.selectPreviousOrNextSequence {
+  display: flex;
+  color: $dark-blue;
+  font-weight: bold;
+  margin-top: -6px;
+}
+
+.selectPreviousOrNextSimilarSequence {
+  display: flex;
+  color: $dark-blue;
+  font-weight: bold;
+  margin-top: -6px;
+}
+
+.saveSimilarSequence {
+  float: left;
+  margin: 5px;
+  width:70%;
+}
+
+.top{
+  float:top
+}
+
+.bottom{
+  float:bottom;
+}
+
+li {
+  display: inline-block;
+  vertical-align: top;
+  margin: 5px;
+}
+
+.expand-width-first {
+  width: 95%;
+  padding-right: 25px;
+}
+
+.findSequences {
+  margin: 25px;
+}
+
+.similarIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 20px;
+  height: 20px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.deleteIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 20px;
+  height: 20px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.popupButton {
+  margin: 5px;
+}
+
+.content {
+  margin-left: 5px;
+  margin-right: 5px;
+  padding-top: 10px;
+  padding-bottom: 10px;
+  margin-top: 5px;
+}
+
+.chip-content {
+  padding: 5px;
+}
+
+</style>
diff --git a/src/views/MarkSequencesView.vue b/src/views/MarkSequencesView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..9f7a49f5ed1bfbdf75c6f9ebdbd10d798c4ea961
--- /dev/null
+++ b/src/views/MarkSequencesView.vue
@@ -0,0 +1,703 @@
+<template>
+  <div class="markSequences">
+    <SegmentHeader
+      ref="segmentHeader"
+      :segments_count="this.segments_count"
+      :tape_name="this.actual_segment.tape_name"
+      :tape_year="this.actual_segment.tape_year"
+      :segment_probability="this.actual_segment.orca_probability.toFixed(2)"
+      :segment_id="this.actual_segment.segment_id"
+      :segment_assessed="this.actual_segment.already_assessed"
+    ></SegmentHeader>
+    <vs-button class="popupButton" @click="onFilterOpen" color="success" type="filled">Filter</vs-button>
+    <AudioAndFrequencyPlayer
+      class="expand-width"
+      :is_editable="this.isEditable"
+      :tape_name="this.actual_segment.tape_name"
+      :tape_year="this.actual_segment.tape_year"
+      :tape_channel="this.actual_segment.tape_channel"
+      :timestamp_start_ms="this.actual_segment.timestamp_start_ms"
+      :timestamp_end_ms="this.actual_segment.timestamp_end_ms"
+      :sequences="this.rows"
+      :component_id="'mark'"
+      ref="wavesurferComponent"></AudioAndFrequencyPlayer>
+    <vue-good-table
+      id="table_id"
+      class="table"
+      title="Sequences"
+      :paginate="true"
+      :columns="columns"
+      :fixed-header="true"
+      :row-style-class="rowStyleClassFn"
+      @on-cell-click="onCellClick"
+      :sort-options="{
+        enabled: false
+      }"
+      :select-options="{
+        enabled: false
+      }"
+      :filter-options="{
+        enabled: false
+      }"
+      :pagination-options="{
+        enabled: false,
+        mode: 'records'
+      }"
+      :rows="rows"
+    >
+      <template slot="table-row" slot-scope="props">
+        <span title="Delete" @click="deleteCommand(props.row.orca_sequence_id)" v-if="props.column.field === 'delete'">
+            <img class="deleteIcon" src="../assets/trash-alt-solid.svg" alt="">
+        </span>
+        <div v-else-if="props.column.field === 'rating'">
+          <StarRating :read-only="!isEditable" @update-rating="onRatingChanged" :row-id="props.row.orca_sequence_id" :star-size="20" :rating="props.row.rating" :show-rating="false"></StarRating>
+        </div>
+        <span v-else-if="props.column.field === 'add_remove'" @click="addRandomPlayerCommand(props.row.orca_sequence_id)">
+          <img v-if="randomPlayerQueue && randomPlayerQueue.includes(props.row.orca_sequence_id)" class="removeIcon" src="../assets/minus_icon.svg" alt="">
+          <img v-else class="addIcon" src="../assets/plus_icon.svg" alt="">
+        </span>
+        <div v-else-if="props.column.field === 'add_remove'" @click="addRandomPlayerCommand(props.row.orca_sequence_id)">
+          <img v-if="randomPlayerQueue && randomPlayerQueue.includes(props.row.orca_sequence_id)" class="removeIcon" src="../assets/minus_icon.svg" alt="">
+          <img v-else class="addIcon" src="../assets/plus_icon.svg" alt="">
+        </div>
+        <span v-else>
+        {{props.formattedRow[props.column.field]}}
+        </span>
+      </template>
+      <div slot="emptystate">
+        No sequences available
+      </div>
+    </vue-good-table>
+    <vs-popup class="holamundo"  title="Tags" :active.sync="tagPopupActive">
+      <div class="content">
+        <vs-chip v-for="tag in actualTags" v-bind:key="{tag}">
+          <div class="chip-content">{{tag}}</div>
+          <div class="chip-content" title="Delete" @click="onTagRemove(tag)">
+            <img class="deleteIcon" src="../assets/trash-alt-solid.svg" alt="">
+          </div>
+        </vs-chip>
+      </div>
+      <SearchAutoComplete @enter="onEnter" class="content" :items="allTags" ></SearchAutoComplete>
+      <div class="content">
+        <vs-button class="popupButton" @click="onTagsUpdate" color="success" type="filled">Update</vs-button>
+        <vs-button class="popupButton" @click="tagPopupActive=false" color="danger" type="filled">Discard</vs-button>
+      </div>
+    </vs-popup>
+    <vs-popup class="holamundo"  title="Filter" :active.sync="filterPopupActive">
+      <FilterSegments ref="filterSeg" :loading="requested" :info="this.idInformation"></FilterSegments>
+      <div class="content">
+        <vs-button class="popupButton" @click="onFilterChange" color="success" type="filled">Use Filter</vs-button>
+        <vs-button class="popupButton" @click="onFilterDiscard" color="warning" type="filled">Discard Filter</vs-button>
+        <vs-button class="popupButton" @click="onFilterReset" color="danger" type="filled">Reset Filter</vs-button>
+      </div>
+    </vs-popup>
+  </div>
+</template>
+
+<script>
+import axios from 'axios'
+import AudioAndFrequencyPlayer from '@/components/AudioAndFrequencyPlayer'
+import SegmentHeader from '@/components/SegmentHeader'
+import { Bus } from '@/main'
+import StarRating from '../components/StarRating.vue'
+import SearchAutoComplete from '../components/SearchAutocomplete'
+import FilterSegments from '@/components/FilterSegments'
+
+export default ({
+  name: 'MarkSequencesView',
+  components: {
+    AudioAndFrequencyPlayer,
+    SegmentHeader,
+    StarRating,
+    SearchAutoComplete,
+    FilterSegments
+  },
+  data () {
+    return {
+      filterPopupActive: false,
+      regionIdUploading: '',
+      isEditable: false,
+      tagPopupActive: false,
+      active: true,
+      actualIndex: 0,
+      isPlayingOrca: false,
+      displayRegion: false,
+      playAll: true,
+      segments: [],
+      tmpFilterOld: {},
+      filteredSegments: [],
+      segments_count: 0,
+      actual_segment: {
+        tape_year: 0,
+        tape_name: '',
+        tape_channel: '',
+        timestamp_start_ms: 0,
+        timestamp_end_ms: 0,
+        already_assessed: true,
+        orca_probability: 0
+      },
+      selected_sequence_id: -1,
+      actualTags: [],
+      setup: true,
+      user: '',
+      allTags: [],
+      columns: [
+        {
+          label: 'Delete',
+          field: 'delete',
+          sortable: false
+        },
+        {
+          label: 'Add or remove',
+          field: 'add_remove',
+          sortable: false
+        },
+        {
+          label: 'ID',
+          field: 'orca_sequence_id'
+        },
+        {
+          label: 'Tags',
+          field: 'tags'
+        },
+        {
+          label: 'Rating',
+          field: 'rating',
+          type: 'number'
+        },
+        {
+          label: 'Duration',
+          field: 'duration'
+        },
+        {
+          label: 'Username',
+          field: 'user_name'
+        }
+      ],
+      rows: [],
+      idInformation: {},
+      requested: false,
+      randomPlayerQueue: ['dummy']
+    }
+  },
+  created () {
+    Bus.$on('segment_index_changed', (actualIndex) => {
+      this.onIndexChanged(actualIndex)
+    })
+    Bus.$on('created-sequence', (region) => {
+      if (this.regionIdUploading === region.id) {
+        return
+      }
+      this.regionIdUploading = region.id
+      this.saveSequenceRegion(region)
+    })
+    Bus.$on('updated-sequence', (region) => {
+      const sequence = this.rows.find(sequence => sequence.orca_sequence_id === region.id)
+
+      if (sequence === undefined || sequence.timestamp_end_ms === undefined) {
+        return
+      }
+      const endTime = (this.actual_segment.timestamp_start_ms + region.end * 1000).toFixed(2)
+      const startTime = (this.actual_segment.timestamp_start_ms + region.start * 1000).toFixed(2)
+      if (
+        sequence.timestamp_end_ms !== endTime ||
+        sequence.timestamp_start_ms !== startTime
+      ) {
+        const sequenceToUpdate = this.rows.find(sequence => sequence.orca_sequence_id === region.id)
+        sequenceToUpdate.timestamp_end_ms = endTime
+        sequenceToUpdate.timestamp_start_ms = startTime
+        this.updateSequence(sequenceToUpdate)
+      }
+    })
+    Bus.$on('selected-sequence', (region) => {
+      this.selected_sequence_id = region.id
+    })
+    Bus.$on('user-set', () => {
+      this.isEditable = true
+    })
+    this.$eventHub.$on('change-queue-event', (sequences) => {
+      console.log(JSON.stringify(sequences))
+      this.randomPlayerQueue = sequences
+      console.log(JSON.stringify(this.randomPlayerQueue))
+    })
+  },
+  async mounted () {
+    try {
+      /*
+      this.idInformation = {}
+      this.idInformation['2017'] = { tapes: ['001A', '001B'], maxMin: 10 }
+      this.idInformation['2018'] = { tapes: ['005A', '005B'], maxMin: 5 }
+      this.idInformation['2019'] = { tapes: ['0010A', '001B'], maxMin: 20 }
+       */
+      const response = await axios.get('/api/browse/tapes')
+      this.idInformation = response.data
+    } catch (error) {
+      console.log(error)
+    }
+    if (localStorage.user === undefined || localStorage.user === 'null' || localStorage.user === '') {
+      Bus.$emit('set-user')
+    } else {
+      this.isEditable = true
+    }
+    try {
+      const response = await axios.get('/api/browse/mark/audio_segments')
+      this.segments = response.data
+      this.filteredSegments = this.segments
+      this.segments_count = response.data.length
+      await this.loadSegment()
+      const responseTags = await axios.get('/api/browse/mark/orca_sequences/tags')
+      this.allTags = Object.keys(responseTags.data)
+    } catch (error) {
+      console.log(error)
+    }
+    /*
+    this.segments = [
+      'asdads_asdasd_tape1_1998_10000_20000',
+      'asdads_asda22_tape2_1998_15000_20000',
+      'asdads_asda33_tape3_1997_5000_30000',
+      'asdads_asda44_tape4_1997_20000_25000'
+    ]
+    this.filteredSegments = this.segments
+    this.segments_count = this.filteredSegments.length
+    */
+    if (localStorage.sequenceQueue !== undefined) {
+      this.randomPlayerQueue = localStorage.sequenceQueue.split(',')
+    }
+  },
+  beforeDestroy () {
+    Bus.$off()
+  },
+  methods: {
+    onIndexChanged (actualIndex) {
+      this.actualIndex = actualIndex
+      this.updateSegment()
+      this.loadSegment()
+      /*
+      if (this.bufferedRows[actualIndex] === undefined ||
+        this.bufferedSegments[actualIndex] === undefined) {
+        this.updateSegment()
+        this.loadSegment()
+      } else {
+        this.setup = true
+        this.rows = this.bufferedRows[actualIndex]
+        this.actual_segment = this.bufferedSegments[actualIndex]
+        this.$refs.wavesurferComponent.loadAudioFile()
+      }
+      */
+    },
+    async onRatingChanged (selectedRating, rowId) {
+      await this.updateRating(rowId, selectedRating)
+    },
+    async updateRating (rowId, selectedRating) {
+      try {
+        const uploadSequence = {
+          orca_sequence_id: rowId,
+          rating: selectedRating
+        }
+        await axios.put('/api/orca_sequence/rating/' + uploadSequence.orca_sequence_id, uploadSequence)
+        this.sequence = this.rows.find(sequence => sequence.orca_sequence_id === uploadSequence.orca_sequence_id)
+        this.sequence.rating = selectedRating
+        // this.bufferedRows[this.actualIndex] = this.rows
+        this.$vs.notify({
+          title: 'Successfully updated',
+          text: 'Sequence ID: ' + uploadSequence.orca_sequence_id,
+          color: 'success',
+          icon: 'verified_user'
+        })
+      } catch (error) {
+        console.log(error)
+        this.$vs.notify({
+          title: 'Update with error',
+          text: error,
+          color: 'warning',
+          icon: 'error'
+        })
+        return false
+      }
+      return true
+    },
+    deleteCommand (id) {
+      if (!this.isEditable) {
+        return
+      }
+      axios.delete('/api/orca_sequence/' + id)
+        .then((response) => {
+          this.rows = this.rows.filter(sequence => sequence.orca_sequence_id !== id)
+          this.$refs.wavesurferComponent.removeSequence(id)
+          // this.bufferedRows[this.actualIndex] = this.rows
+          this.$vs.notify({
+            title: 'Successfully deleted',
+            text: 'Sequence ID: ' + id,
+            color: 'success',
+            icon: 'verified_user'
+          })
+          this.randomPlayerQueue = this.randomPlayerQueue.filter(e => e !== id)
+          this.$eventHub.$emit('live_remove_from_queue', id)
+        })
+        .catch((error) => {
+          console.log(error)
+          this.$vs.notify({
+            title: 'Delete with error',
+            text: error,
+            color: 'warning',
+            icon: 'error'
+          })
+        })
+      this.wavesurfer.pause()
+      this.isPlaying = false
+    },
+    async addRandomPlayerCommand (id) {
+      if (localStorage.sequenceQueue !== undefined) {
+        this.randomPlayerQueue = localStorage.sequenceQueue.split(',')
+      }
+      if (this.randomPlayerQueue.includes(id)) {
+        this.randomPlayerQueue = this.randomPlayerQueue.filter(e => e !== id)
+        this.$eventHub.$emit('live_remove_from_queue', id)
+        console.log('remove')
+        console.log(JSON.stringify(this.randomPlayerQueue))
+      } else {
+        const sequence = this.rows.find(sequence => sequence.orca_sequence_id === id)
+        this.$eventHub.$emit('live_add_to_queue', sequence)
+        this.randomPlayerQueue.push(id)
+      }
+    },
+    onCellClick (params) {
+      if (!this.isEditable) {
+        return
+      }
+      if (params.column.label === 'Tags') {
+        this.selected_sequence_id = params.row.orca_sequence_id
+        if (params.row.tags.length === 0) {
+          this.actualTags = []
+        } else {
+          this.actualTags = params.row.tags.split(', ')
+        }
+        this.tagPopupActive = true
+      }
+    },
+    rowStyleClassFn (row) {
+      return row.orca_sequence_id === this.selected_sequence_id ? 'isSelected' : 'isNormal'
+    },
+    onTagRemove (tag) {
+      const index = this.actualTags.indexOf(tag)
+      if (index !== -1) {
+        this.actualTags.splice(index, 1)
+      }
+    },
+    async onTagsUpdate () {
+      this.tagPopupActive = false
+      const sequence = this.rows.find(sequence => sequence.orca_sequence_id === this.selected_sequence_id)
+      const sequenceToUpdate = Object.assign({}, sequence)
+      sequenceToUpdate.tags = ''
+      for (let i = 0; i < this.actualTags.length; i++) {
+        sequenceToUpdate.tags += this.actualTags[i]
+        if (i < (this.actualTags.length - 1)) {
+          sequenceToUpdate.tags += ', '
+        }
+      }
+      await this.updateSequence(sequenceToUpdate)
+    },
+    onEnter (tag) {
+      if (tag === '' || this.actualTags.includes(tag)) {
+        return
+      }
+      if (!this.allTags.includes(tag)) {
+        this.allTags.push(tag)
+      }
+      this.actualTags.push(tag)
+    },
+    async saveSequenceRegion (region) {
+      if (this.isUploading === true) {
+        return
+      }
+      this.isUploading = true
+      const ids = this.rows.find(sequence => sequence.orca_sequence_id === region.id)
+      if (ids !== undefined) {
+        return
+      }
+      const sequenceToSave = this.createSequenceByRegion(region)
+      try {
+        console.log('TRY: ' + JSON.stringify(sequenceToSave))
+        await axios.post('/api/orca_sequence/', sequenceToSave)
+        const sequenceToDisplay = this.createSequenceToDisplay(sequenceToSave)
+        this.rows.push(sequenceToDisplay)
+        this.rows.sort(this.objectComparisonCallback)
+        // this.bufferedRows[this.actualIndex] = this.rows
+        // this.bufferedSegments[this.actualIndex] = this.actual_segment
+        console.log('SUCCESS: ' + JSON.stringify(sequenceToSave))
+        this.$vs.notify({
+          title: 'Successfully saved',
+          text: 'Sequence ID: ' + sequenceToSave.orca_sequence_id,
+          color: 'success',
+          icon: 'verified_user'
+        })
+      } catch (error) {
+        console.log(error)
+        console.log('ERROR: ' + JSON.stringify(sequenceToSave))
+        this.$vs.notify({
+          title: 'Save with error',
+          text: error,
+          color: 'warning',
+          icon: 'error'
+        })
+      }
+      this.isUploading = false
+    },
+    async updateSegment () {
+      try {
+        const updateSequence = {
+          audio_segment_id: this.actual_segment.segment_id,
+          already_assessed: true
+        }
+        await axios.put('/api/audio_segment/' + this.actual_segment.segment_id, updateSequence)
+        this.actual_segment.already_assessed = true
+        // this.bufferedSegments[this.actualIndex] = this.actual_segment
+      } catch (error) {
+        console.log(error)
+        return false
+      }
+      return true
+    },
+    async updateSequence (sequenceToUpdate) {
+      try {
+        const uploadSequence = this.createSequenceToUpload(sequenceToUpdate)
+        await axios.put('/api/orca_sequence/' + uploadSequence.orca_sequence_id, uploadSequence)
+        this.rows = this.rows.filter(sequence => sequence.orca_sequence_id !== sequenceToUpdate.orca_sequence_id)
+        const sequenceToDisplay = this.createSequenceToDisplay(sequenceToUpdate)
+        this.rows.push(sequenceToDisplay)
+        this.rows.sort(this.objectComparisonCallback)
+        // this.bufferedRows[this.actualIndex] = this.rows
+        // this.bufferedSegments[this.actualIndex] = this.actual_segment
+        this.$vs.notify({
+          title: 'Successfully updated',
+          text: 'Sequence ID: ' + uploadSequence.orca_sequence_id,
+          color: 'success',
+          icon: 'verified_user'
+        })
+      } catch (error) {
+        console.log(error)
+        this.$vs.notify({
+          title: 'Update with error',
+          text: error,
+          color: 'warning',
+          icon: 'error'
+        })
+        return false
+      }
+      return true
+    },
+    createSequenceByRegion (region) {
+      return {
+        orca_sequence_id: region.id,
+        tape_year: this.actual_segment.tape_year,
+        tape_name: this.actual_segment.tape_name,
+        tape_channel: this.actual_segment.tape_channel,
+        audio_segment: this.actual_segment.segment_id,
+        timestamp_start_ms: parseInt((this.actual_segment.timestamp_start_ms + region.start * 1000).toFixed(2)),
+        timestamp_end_ms: parseInt((this.actual_segment.timestamp_start_ms + region.end * 1000).toFixed(2)),
+        rating: 0,
+        tags: [],
+        user_name: localStorage.user
+      }
+    },
+    clearSequences () {
+      this.rows = []
+    },
+    async loadSegment () {
+      this.setup = true
+      this.clearSequences()
+      const tempIndex = this.actualIndex
+      const id = String(this.filteredSegments[this.actualIndex])
+      try {
+        const response = await axios.get('/api/browse/mark/audio_segment/' + id)
+        this.actual_segment = response.data
+        this.actual_segment.segment_id = id
+        const responseSequences = await axios.get('/api/browse/mark/orca_sequences/audio_segment/' + id)
+        for (let i = 0; i < responseSequences.data.length; i++) {
+          const sequenceId = responseSequences.data[i]
+          const responseSequence = await axios.get('/api/browse/mark/orca_sequence/' + sequenceId)
+          const sequence = responseSequence.data
+          sequence.orca_sequence_id = sequenceId
+          const displaySequence = this.createSequenceToDisplay(sequence)
+          this.rows.push(displaySequence)
+          this.rows.sort(this.objectComparisonCallback)
+          if (this.actualIndex !== tempIndex) {
+            this.rows = []
+            return
+          }
+        }
+        // this.bufferedRows[this.actualIndex] = this.rows
+        // this.bufferedSegments[this.actualIndex] = this.actual_segment
+      } catch (error) {
+        console.log(error)
+      }
+      this.$refs.wavesurferComponent.loadAudioFile()
+    },
+    createSequenceToDisplay (sequence) {
+      const sequenceToDisplay = Object.assign({}, sequence)
+      if (Array.isArray(sequence.tags)) {
+        let tagsString = ''
+        for (let i = 0; i < sequence.tags.length; i++) {
+          tagsString += sequence.tags[i]
+          if (i < sequence.tags.length - 1) {
+            tagsString += ', '
+          }
+        }
+        sequenceToDisplay.tags = tagsString
+      }
+      sequenceToDisplay.duration = ((sequence.timestamp_end_ms - sequence.timestamp_start_ms) / 1000).toFixed(2)
+      sequenceToDisplay.add_remove = false
+      return sequenceToDisplay
+    },
+    createSequenceToUpload (sequence) {
+      return {
+        orca_sequence_id: sequence.orca_sequence_id,
+        tape_year: sequence.tape_year,
+        tape_name: sequence.tape_name,
+        tape_channel: sequence.tape_channel,
+        audio_segment: sequence.audio_segment,
+        timestamp_start_ms: parseInt(sequence.timestamp_start_ms),
+        timestamp_end_ms: parseInt(sequence.timestamp_end_ms),
+        rating: sequence.rating,
+        tags: sequence.tags.split(', '),
+        user_name: localStorage.user
+      }
+    },
+    objectComparisonCallback (a, b) {
+      const textA = a.orca_sequence_id.toUpperCase()
+      const textB = b.orca_sequence_id.toUpperCase()
+      return (textA < textB) ? -1 : (textA > textB) ? 1 : 0
+    },
+    async onFilterChange () {
+      const actualFilter = this.$refs.filterSeg.getFilter()
+      this.requested = true
+      this.filteredSegments = []
+      if (actualFilter.id !== '') {
+        // search id
+        this.filteredSegments = [actualFilter.id]
+      } else if (actualFilter.year !== '' || actualFilter.tape !== '' || actualFilter.duration !== '') {
+        // filter ids
+        if (actualFilter.year === '') {
+          actualFilter.year = '*'
+        }
+        if (actualFilter.tape === '') {
+          actualFilter.tape = '*'
+        }
+        if (actualFilter.duration === '') {
+          actualFilter.duration = '*'
+        }
+        try {
+          const response = await axios.get('/api/browse/mark/audio_segments/year/' + actualFilter.year + '/tape/' + actualFilter.tape + '/timequery/' + actualFilter.duration)
+          this.filteredSegments = response.data
+          this.segments_count = response.data.length
+        } catch (error) {
+          console.log(error)
+        }
+      } else {
+        // load random ones
+        this.filteredSegments = this.segments
+      }
+      this.segments_count = this.filteredSegments.length
+      if (this.segments_count === 0) {
+        this.requested = false
+        this.$vs.notify({
+          title: 'No segments found',
+          text: 'Change filter parameters',
+          color: 'warning',
+          icon: 'error'
+        })
+        this.$refs.filterSeg.setFilter(actualFilter)
+      } else {
+        this.filterPopupActive = false
+        this.$refs.segmentHeader.resetIndex()
+      }
+    },
+    onFilterDiscard () {
+      this.filterPopupActive = false
+      this.$refs.filterSeg.setFilter(this.tmpFilterOld)
+    },
+    onFilterReset () {
+      this.$refs.filterSeg.resetValues()
+    },
+    onFilterOpen () {
+      this.requested = false
+      this.filterPopupActive = true
+      this.$refs.filterSeg.onOpenPopup()
+      this.tmpFilterOld = this.$refs.filterSeg.getFilter()
+    }
+  }
+})
+</script>
+
+<style lang="scss">
+@import '@/assets/color.scss';
+@import '@/assets/grid.scss';
+
+.markSequences {
+  margin: 25px;
+}
+
+.expand-width {
+  width: 95%;
+  padding-right: 25px;
+}
+
+.table {
+  margin-top: 50px;
+  padding-bottom: 50px;
+  padding-left: 25px;
+  padding-right: 25px;
+  width: 95%;
+}
+
+.isSelected {
+  background: #87B394;
+}
+
+.isNormal {
+}
+
+.deleteIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 20px;
+  height: 20px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.addIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 20px;
+  height: 20px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.removeIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 20px;
+  height: 20px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.popupButton {
+  margin: 5px;
+}
+
+.content {
+  margin-left: 5px;
+  margin-right: 5px;
+  padding-top: 10px;
+  padding-bottom: 10px;
+  margin-top: 5px;
+}
+
+.chip-content {
+  padding: 5px;
+}
+
+</style>
diff --git a/src/views/OrganizeSequencesView.vue b/src/views/OrganizeSequencesView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..aae111091e666a723f15f06498b35686cb7ab92a
--- /dev/null
+++ b/src/views/OrganizeSequencesView.vue
@@ -0,0 +1,521 @@
+<template>
+  <div id='app'>
+    <vue-good-table
+      ref="table_ref"
+      id="table_id"
+      class="table"
+      title="Sequences"
+      styleClass="vgt-table striped"
+      @on-selected-rows-change="selectionChanged"
+      :paginate="true"
+      :columns="columns"
+      :fixed-header="true"
+      :select-options="{
+        enabled: true,
+        selectOnCheckboxOnly: true,
+        selectionInfoClass: 'selected',
+        selectionText: 'rows selected',
+        clearSelectionText: 'clear',
+        disableSelectInfo: true,
+        selectAllByGroup: true
+      }"
+      :pagination-options="{
+        enabled: true,
+        mode: 'records'
+      }"
+      :rows="rows"
+    >
+      <template slot="table-row" slot-scope="props">
+        <div class="row" v-if="props.column.field === 'action'">
+          <div title="Play/Pause" @click="playPauseRow(props.row)">
+            <img class="playIcon" v-if="rowIdPlaying !== props.row.orca_sequence_id" src="../assets/play-circle-solid.svg">
+            <img class="pauseIcon" v-else src="../assets/pause-circle-solid.svg">
+          </div>
+          <div title="Download" @click="downloadCommand(props.row)">
+            <img class="deleteIcon" src="../assets/download.svg">
+          </div>
+          <div title="Delete" @click="deleteCommand(props.row.orca_sequence_id)">
+            <img class="deleteIcon" src="../assets/trash-alt-solid.svg">
+          </div>
+          <div title="Add or remove random player" @click="addRandomPlayerCommand(props.row.orca_sequence_id)">
+            <img v-if="randomPlayerQueue && randomPlayerQueue.includes(props.row.orca_sequence_id)" class="removeIcon" src="../assets/minus_icon.svg" alt="">
+            <img v-else class="addIcon" src="../assets/plus_icon.svg" alt="">
+          </div>
+        </div>
+        <div v-else-if="props.column.field === 'rating'">
+          <StarRating :read-only="!isEditable" @update-rating="onRatingChanged" :row-id="props.row.orca_sequence_id" :star-size="20" :rating="props.row.rating" :show-rating="false"></StarRating>
+        </div>
+        <span v-else>
+        {{props.formattedRow[props.column.field]}}
+      </span>
+      </template>
+      <div slot="emptystate">
+        No sequences available
+      </div>
+    </vue-good-table>
+    <div class="allAction" v-if="this.currentSelection.length > 0">
+      <span  title="Download Selected" @click="downloadCommand(-1)">
+        <img class="deleteIcon" src="../assets/download.svg">
+      </span>
+      <span title="Delete Selected" @click="deleteCommand(-1)">
+        <img class="deleteIcon" src="../assets/trash-alt-solid.svg">
+      </span>
+      <span title="Add or remove selected to random player" @click="addRandomPlayerCommand(-1)">
+        <img class="addIcon" src="../assets/plus_icon.svg" alt="">
+      </span>
+    </div>
+  </div>
+</template>
+
+<script>
+import axios from 'axios'
+import StarRating from '../components/StarRating.vue'
+import JSZip from 'jszip'
+import { saveAs } from 'file-saver'
+import { Bus } from '@/main'
+
+export default {
+  name: 'OrganizeSequencesView',
+  components: {
+    StarRating
+  },
+  data () {
+    return {
+      audio: null,
+      panChannel: 0,
+      track: null,
+      stereoNode: null,
+      audioContext: new AudioContext(),
+      isEditable: false,
+      bufferedAudioTapes: {},
+      rowIdPlaying: -1,
+      windowHeight: 250,
+      randomPlayerQueue: ['dummy'],
+      currentSelection: [],
+      columns: [
+        {
+          label: 'Action',
+          field: 'action',
+          sortable: false,
+          filterOptions: {
+            enabled: false // enable filter for this column
+          }
+        },
+        {
+          label: 'Username',
+          field: 'user_name',
+          filterOptions: {
+            enabled: true, // enable filter for this column
+            placeholder: 'Filter users', // placeholder for filter input
+            filterValue: '', // initial populated value for this filter
+            filterDropdownItems: [], // dropdown (with selected values) instead of text input
+            filterFn: function (data, filterString) {
+              const stringData = data.toString()
+              return stringData.includes(filterString)
+            }
+          }
+        },
+        {
+          label: 'Tags',
+          field: 'tags',
+          filterOptions: {
+            enabled: true, // enable filter for this column
+            placeholder: 'Filter tags', // placeholder for filter input
+            filterDropdownItems: [], // dropdown (with selected values) instead of text input
+            filterFn: function (data, filterString) {
+              const stringData = data.toString()
+              return stringData.includes(filterString)
+            }
+          }
+        },
+        {
+          label: 'Rating',
+          field: 'rating',
+          type: 'number',
+          filterOptions: {
+            enabled: true, // enable filter for this column
+            placeholder: 'Filter rating', // placeholder for filter input
+            filterValue: '', // initial populated value for this filter
+            filterDropdownItems: [
+              { value: 1, text: '1 Rated' },
+              { value: 2, text: '2 Rated' },
+              { value: 3, text: '3 Rated' },
+              { value: 4, text: '4 Rated' },
+              { value: 5, text: '5 Rated' }
+            ]
+          }
+        },
+        {
+          label: 'Tape',
+          field: 'tape_name',
+          filterOptions: {
+            enabled: true, // enable filter for this column
+            placeholder: 'Filter tape', // placeholder for filter input
+            filterValue: '', // initial populated value for this filter
+            filterDropdownItems: [], // dropdown (with selected values) instead of text input
+            filterFn: function (data, filterString) {
+              const stringData = data.toString()
+              return stringData.includes(filterString)
+            }
+          }
+        },
+        {
+          label: 'Year',
+          field: 'tape_year',
+          type: 'number',
+          filterOptions: {
+            enabled: true, // enable filter for this column
+            placeholder: 'Filter year', // placeholder for filter input
+            filterValue: '', // initial populated value for this filter
+            filterDropdownItems: [], // dropdown (with selected values) instead of text input
+            filterFn: function (data, filterString) {
+              const stringData = data.toString()
+              return stringData.includes(filterString)
+            }
+          }
+        },
+        {
+          label: 'Duration',
+          field: 'duration',
+          filterOptions: {
+            enabled: true, // enable filter for this column
+            placeholder: 'Filter duration', // placeholder for filter input
+            filterValue: '', // initial populated value for this filter
+            filterDropdownItems: ['< 5 sec.', '5 - 10 sec.', '10 - 20 sec.', '>= 20 sec.'], // dropdown (with selected values) instead of text input
+            filterFn: function (data, filterString) {
+              return (filterString === '< 5 sec.' && data < 5) ||
+                (filterString === '5 - 10 sec.' && data >= 5 && data < 10) ||
+                (filterString === '10 - 20 sec.' && data >= 10 && data < 20) ||
+                (filterString === '>= 20 sec.' && data >= 20)
+            }
+          }
+        },
+        {
+          label: 'Sequence Id',
+          field: 'orca_sequence_id',
+          filterOptions: {
+            enabled: true, // enable filter for this column
+            placeholder: 'Filter id', // placeholder for filter input
+            filterValue: '', // initial populated value for this filter
+            filterDropdownItems: [], // dropdown (with selected values) instead of text input
+            filterFn: function (data, filterString) {
+              const stringData = data.toString()
+              return stringData.includes(filterString)
+            }
+          }
+        },
+        {
+          label: 'Segment Id',
+          field: 'audio_segment',
+          filterOptions: {
+            enabled: true, // enable filter for this column
+            placeholder: 'Filter id', // placeholder for filter input
+            filterValue: '', // initial populated value for this filter
+            filterDropdownItems: [], // dropdown (with selected values) instead of text input
+            filterFn: function (data, filterString) {
+              const stringData = data.toString()
+              return stringData.includes(filterString)
+            }
+          }
+        }
+      ],
+      rows: []
+    }
+  },
+  beforeDestroy () {
+    Bus.$off()
+  },
+  created () {
+    Bus.$on('user-set', () => {
+      this.isEditable = true
+    })
+    this.$eventHub.$on('change-queue-event', (sequences) => {
+      this.randomPlayerQueue = sequences
+    })
+  },
+  async mounted () {
+    if (localStorage.user !== undefined) {
+      this.isEditable = true
+    }
+    window.addEventListener('resize', () => {
+      this.windowHeight = window.innerHeight
+    })
+    try {
+      const response = await axios.get('/api/browse/mark/orca_sequences/')
+      for (let i = 0; i < response.data.length; i++) {
+        const sequenceId = response.data[i]
+        const responseSequence = await axios.get('/api/browse/mark/orca_sequence/' + sequenceId)
+        const sequence = responseSequence.data
+        sequence.orca_sequence_id = sequenceId
+        sequence.duration = ((parseInt(sequence.timestamp_end_ms) - parseInt(sequence.timestamp_start_ms)) / 1000).toFixed(2)
+        const tags = sequence.tags
+        sequence.tags = ''
+
+        if (!(this.columns[6].filterOptions.filterDropdownItems.includes(sequence.user_name))) {
+          this.columns[6].filterOptions.filterDropdownItems.push(sequence.user_name)
+        }
+
+        for (let i = 0; i < tags.length; i++) {
+          sequence.tags += tags[i]
+          if (i < tags.length - 1) {
+            sequence.tags += ','
+          }
+        }
+        console.log(sequence)
+        this.rows.push(sequence)
+      }
+      const responseTags = await axios.get('/api/browse/mark/orca_sequences/tags')
+      this.columns[3].filterOptions.filterDropdownItems = Object.keys(responseTags.data)
+    } catch (error) {
+      console.log(error)
+    }
+    if (localStorage.sequenceQueue !== undefined) {
+      this.randomPlayerQueue = localStorage.sequenceQueue.split(',')
+      console.log('mounted: ' + JSON.stringify(this.randomPlayerQueue))
+    }
+  },
+  methods: {
+    async onRatingChanged (selectedRating, rowId) {
+      await this.updateRating(rowId, selectedRating)
+    },
+    async updateRating (rowId, selectedRating) {
+      try {
+        const uploadSequence = {
+          orca_sequence_id: rowId,
+          rating: selectedRating
+        }
+        await axios.put('/api/orca_sequence/rating/' + uploadSequence.orca_sequence_id, uploadSequence)
+        this.$vs.notify({
+          title: 'Successfully updated',
+          text: 'Sequence ID: ' + uploadSequence.orca_sequence_id,
+          color: 'success',
+          icon: 'verified_user'
+        })
+      } catch (error) {
+        console.log(error)
+        this.$vs.notify({
+          title: 'Update with error',
+          text: error,
+          color: 'warning',
+          icon: 'error'
+        })
+        return false
+      }
+      return true
+    },
+    async playPauseRow (row) {
+      if (this.rowIdPlaying !== row.orca_sequence_id) {
+        this.rowIdPlaying = row.orca_sequence_id
+        if (this.audio !== null) {
+          this.audio.pause()
+        }
+        if (this.bufferedAudioTapes[row.tape_name] === undefined) {
+          // const tapData = row.tape_name.split('_')
+          const orcaPath = '/files/tapes/' + row.tape_year + '/' + row.tape_name + '/' + row.tape_channel + '.mp3'
+          // const orcaPath = require('../assets/audio/001A1.mp3')
+          const config = { url: orcaPath, method: 'get', responseType: 'blob' }
+          const response = await axios.request(config)
+          this.bufferedAudioTapes[row.tape_name] = response.data
+        }
+        const blobAudio = this.bufferedAudioTapes[row.tape_name]
+        const size = blobAudio.size
+        const duration = 48 * 60 * 1000
+        const bytePerMillisecond = size / duration
+        const startBytes = bytePerMillisecond * row.timestamp_start_ms
+        const endBytes = bytePerMillisecond * row.timestamp_end_ms
+        const blobAudioSliced = blobAudio.slice(startBytes, endBytes)
+        const blobURL = window.URL.createObjectURL(blobAudioSliced)
+        this.audio = new Audio(blobURL)
+        this.track = this.audioContext.createMediaElementSource(this.audio)
+        this.panChannel = 0
+        if (localStorage.isLive !== undefined && localStorage.isLive === 'true') {
+          this.panChannel = 1
+        }
+        this.stereoNode = new StereoPannerNode(this.audioContext, { pan: this.panChannel })
+        this.track.connect(this.stereoNode).connect(this.audioContext.destination)
+        this.audio.addEventListener('canplaythrough', (event) => {
+          this.audio.play()
+        })
+        this.audio.addEventListener('ended', (event) => {
+          this.rowIdPlaying = -1
+        })
+      } else {
+        this.rowIdPlaying = -1
+        this.audio.pause()
+      }
+    },
+    selectionChanged (item) {
+      this.showSelectionOptions = true
+      this.currentSelection = []
+      for (let i = 0; i < item.selectedRows.length; i++) {
+        this.currentSelection.push(item.selectedRows[i])
+      }
+    },
+    async downloadCommand (row) {
+      const d = new Date()
+      let metaData = 'Downloaded on ' + d.getDate() + '. ' + d.getMonth() + ' ' + d.getFullYear() + ' at ' + d.getHours() + ':' + d.getMinutes()
+      metaData += '\nFilter options: ' + JSON.stringify(this.$refs.table_ref.columnFilters)
+      if (row !== -1) {
+        this.currentSelection.push(row)
+        console.log(JSON.stringify(this.currentSelection))
+      }
+      const zip = new JSZip()
+      for (let i = 0; i < this.currentSelection.length; i++) {
+        console.log(JSON.stringify(this.currentSelection))
+        metaData += '\n' + JSON.stringify(this.currentSelection[i])
+        const blobAudioSliced = await this.createBlobSequence(this.currentSelection[i])
+        zip.file(this.currentSelection[i].orca_sequence_id + '.mp3', blobAudioSliced)
+      }
+      zip.file('meta_information.txt', metaData)
+      zip.generateAsync({
+        type: 'blob'
+      }).then(function (content) {
+        saveAs(content, 'orca_sequences.zip')
+      })
+    },
+    async createBlobSequence (row) {
+      if (this.bufferedAudioTapes[row.tape_name] === undefined) {
+        const orcaPath = require('../assets/audio/001A1.mp3')
+        const config = { url: orcaPath, method: 'get', responseType: 'blob' }
+        const response = await axios.request(config)
+        this.bufferedAudioTapes[row.tape_name] = response.data
+      }
+      const blobAudio = this.bufferedAudioTapes[row.tape_name]
+      const size = blobAudio.size
+      const duration = 48 * 60 * 1000
+      const bytePerMillisecond = size / duration
+      const startBytes = bytePerMillisecond * row.timestamp_start_ms
+      const endBytes = bytePerMillisecond * row.timestamp_end_ms
+      return blobAudio.slice(startBytes, endBytes)
+    },
+    async deleteCommand (id) {
+      if (!this.isEditable) {
+        return
+      }
+      if (id === -1) {
+        const isExecuted = confirm('Are you sure to delete ' + this.currentSelection.length + ' sequence(s)?')
+        if (!isExecuted) {
+          return
+        }
+        const ids = this.currentSelection
+        for (let i = 0; i < ids.length; i++) {
+          await this.deleteSequence(ids[i].orca_sequence_id)
+        }
+      } else {
+        /* const isExecuted = confirm('Are you sure to delete ' + 1 + ' sequence?')
+        if (!isExecuted) {
+          return
+        } */
+        await this.deleteSequence(id)
+      }
+    },
+    async addRandomPlayerCommand (id) {
+      console.log('Add to player:' + String(id))
+      if (id === -1) {
+        const isExecuted = confirm('Are you sure to add ' + this.currentSelection.length + ' sequence(s) to the orca player?')
+        if (!isExecuted) {
+          return
+        }
+        const ids = this.currentSelection
+        this.$eventHub.$emit('live_set_queue', ids)
+      } else {
+        if (localStorage.sequenceQueue !== undefined) {
+          this.randomPlayerQueue = localStorage.sequenceQueue.split(',')
+        }
+        if (this.randomPlayerQueue.includes(id)) {
+          this.randomPlayerQueue = this.randomPlayerQueue.filter(e => e !== id)
+          this.$eventHub.$emit('live_remove_from_queue', id)
+          console.log('remove from orca player: ' + JSON.stringify(this.randomPlayerQueue))
+        } else {
+          const sequence = this.rows.find(sequence => sequence.orca_sequence_id === id)
+          this.$eventHub.$emit('live_add_to_queue', sequence)
+          this.randomPlayerQueue.push(id)
+        }
+      }
+    },
+    async deleteSequence (sequenceId) {
+      if (!this.isEditable) {
+        return
+      }
+      try {
+        const response = await axios.delete('/api/orca_sequence/' + sequenceId)
+        if (response.status === 200) {
+          this.rows = this.rows.filter(sequence => sequence.orca_sequence_id !== sequenceId)
+          this.randomPlayerQueue = this.randomPlayerQueue.filter(e => e !== sequenceId)
+          Bus.$emit('live_remove_from_queue', sequenceId)
+        }
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+.table {
+  margin-top: 50px;
+  padding-bottom: 20px;
+  padding-left: 25px;
+  margin-right: 25px;
+}
+
+.row {
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+}
+
+.playIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 25px;
+  height: 25px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.deleteIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 25px;
+  height: 25px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.pauseIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 25px;
+  height: 25px;
+  filter: invert(61%) sepia(14%) saturate(1125%) hue-rotate(155deg) brightness(84%) contrast(86%);
+  cursor: pointer;
+}
+
+.addIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 25px;
+  height: 25px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.removeIcon{
+  margin-left: 5px;
+  margin-right: 5px;
+  width: 25px;
+  height: 25px;
+  filter: invert(35%) sepia(25%) saturate(1262%) hue-rotate(151deg) brightness(94%) contrast(85%);
+  cursor: pointer;
+}
+
+.allAction {
+  margin-left: 25px;
+  padding-bottom: 20px;
+}
+
+</style>