changeset 1476:ccf9fd7ff0bd bulkreview

merge with default
author Thomas Junk <thomas.junk@intevation.de>
date Mon, 03 Dec 2018 13:08:24 +0100
parents 2365acde39dc (current diff) 18ddb6935aa6 (diff)
children 5ad79db38ecf
files client/src/assets/application.sass client/src/assets/tooltip.sass client/src/components/map/contextbox/Staging.vue
diffstat 40 files changed, 1956 insertions(+), 1059 deletions(-) [+]
line wrap: on
line diff
--- a/client/Makefile	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/Makefile	Mon Dec 03 13:08:24 2018 +0100
@@ -20,7 +20,7 @@
 OUTPUT_DIR = src
 
 # Available locales for the app.
-LOCALES = de_AT en_GB
+LOCALES = de_AT en_GB sk_SK
 
 # Name of the generated .po files for each available locale.
 LOCALE_FILES ?= $(patsubst %,$(OUTPUT_DIR)/locale/%/LC_MESSAGES/app.po,$(LOCALES))
--- a/client/src/assets/application.sass	Fri Nov 30 12:50:18 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/* This is Free Software under GNU Affero General Public License v >= 3.0
- * without warranty, see README.md and license for details.
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- * License-Filename: LICENSES/AGPL-3.0.txt
- *
- * Copyright (C) 2018 by via donau
- *   – Österreichische Wasserstraßen-Gesellschaft mbH
- * Software engineering by Intevation GmbH
- *
- * Author(s):
- * Thomas Junk <thomas.junk@intevation.de>
- * Markus Kottländer <markus.kottlaender@intevation>
- */
-
-$shadow-xs: 0 0.1rem 0.5rem rgba(0, 0, 0, 0.2)
-$border-radius: 0.25rem
-$icon-height: 2rem
-$icon-width: 2rem
-$large-offset: 2rem
-$offset: 1rem
-$sidebar-width: 15rem
-$slight-transparent: 0.96
-$small-offset: 0.5rem
-$smaller: 0.9rem
-$transition-fast: 0.3s
-$x-large-offset: 3rem
-$xx-large-offset: 5rem
-$color-info: #17a2b8
-
-a
-  color: $color-info
-  &:hover,
-  &:active,
-  &:focus
-    color: darken($color-info, 13)
-
-.w-90
-  width: 90%
-
-.w-95
-  width: 95%
-
-.debug
-  border: 1px solid red
-
-%fully-centered
-  position: absolute
-  top: 50%
-  left: 50%
-  transform: translate(-50%, -50%)
-
-.ui-element
-  pointer-events: auto
-
-.shadow-xs
-  box-shadow: $shadow-xs
-
-.box
-  opacity: $slight-transparent
-  max-height: 0
-  max-width: 0
-  overflow: hidden
-  margin-left: 0
-  margin-right: 0
-  margin-bottom: 0
-  box-shadow: $shadow-xs
-  transition: max-width .4s, max-height .4s, margin-left .4s, margin-right .4s, margin-bottom .4s
-
-.box h6,
-.contextbox h6
-  color: $color-info
-  font-weight: bold
-
-.expanded
-  max-height: 999px
-  max-width: 999px
-  margin-left: 0.5rem
-  margin-right: 0.5rem
-  margin-bottom: 1rem
-
-// needed to fix the whitespace problem of
-//   https://github.com/Polyconseil/vue-gettext/issues/80
-// use like
-//    <a href="..">link</a>
-//    <span v-translate class="fix-trans-space">contributors.</span>
-//
-// done centrally, so we can fix it centrally for better vue-gettext version
-.fix-trans-space
-  &:before
-    content: " "
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/assets/application.scss	Mon Dec 03 13:08:24 2018 +0100
@@ -0,0 +1,114 @@
+/* This is Free Software under GNU Affero General Public License v >= 3.0;
+ * without warranty, see README.md and license for details.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ * License-Filename: LICENSES/AGPL-3.0.txt
+ *
+ * Copyright (C) 2018 by via donau
+ *   – Österreichische Wasserstraßen-Gesellschaft mbH
+ * Software engineering by Intevation GmbH
+ *
+ * Author(s):
+ * Thomas Junk <thomas.junk@intevation.de>
+ * Markus Kottländer <markus.kottlaender@intevation>
+ */
+
+$shadow-xs: 0 0.1rem 0.5rem rgba(0, 0, 0, 0.2);
+$border-radius: 0.25rem;
+$icon-height: 2rem;
+$icon-width: 2rem;
+$large-offset: 2rem;
+$offset: 1rem;
+$sidebar-width: 15rem;
+$slight-transparent: 0.96;
+$small-offset: 0.5rem;
+$smaller: 0.9rem;
+$transition-fast: 0.3s;
+$x-large-offset: 3rem;
+$xx-large-offset: 5rem;
+$color-info: #17a2b8;
+
+a {
+  color: $color-info;
+}
+
+a:hover,
+a:active,
+a:focus {
+  color: darken($color-info, 13);
+}
+
+.w-90 {
+  width: 90%;
+}
+
+.w-95 {
+  width: 95%;
+}
+
+.debug {
+  border: 1px solid red;
+}
+
+%fully-centered {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+
+.ui-element {
+  pointer-events: auto;
+}
+
+.shadow-xs {
+  box-shadow: $shadow-xs;
+}
+
+.box {
+  opacity: $slight-transparent;
+  max-height: 0;
+  max-width: 0;
+  overflow: hidden;
+  margin-left: 0;
+  margin-right: 0;
+  margin-bottom: 0;
+  box-shadow: $shadow-xs;
+  transition: max-width 0.4s, max-height 0.4s, margin-left 0.4s,
+    margin-right 0.4s, margin-bottom 0.4s;
+}
+
+.box h6,
+.contextbox h6 {
+  color: $color-info;
+  font-weight: bold;
+}
+
+.expanded {
+  max-height: 999px;
+  max-width: 999px;
+  margin-left: 0.5rem;
+  margin-right: 0.5rem;
+  margin-bottom: 1rem;
+}
+
+// needed to fix the whitespace problem of
+//   https://github.com/Polyconseil/vue-gettext/issues/80;
+// use like
+//    <a href="..">link</a>
+//    <span v-translate class="fix-trans-space">contributors.</span>
+//
+// done centrally, so we can fix it centrally for better vue-gettext version
+.fix-trans-space,
+.fix-trans-space:before {
+  content: " ";
+}
+
+.closebutton {
+  position: absolute;
+  right: $offset;
+}
+
+.headline {
+  font-weight: bold;
+}
--- a/client/src/assets/tooltip.sass	Fri Nov 30 12:50:18 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/* This is Free Software under GNU Affero General Public License v >= 3.0
- * without warranty, see README.md and license for details.
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- * License-Filename: LICENSES/AGPL-3.0.txt
- *
- * Copyright (C) 2018 by via donau
- *   – Österreichische Wasserstraßen-Gesellschaft mbH
- * Software engineering by Intevation GmbH
- *
- * Author(s):
- * Thomas Junk <thomas.junk@intevation.de>
- */
-.tooltip
-  display: block !important
-  z-index: 10000
-
-  .tooltip-inner
-    background: black
-    color: white
-    border-radius: 16px
-    padding: 5px 10px 4px
-
-  .tooltip-arrow
-    width: 0
-    height: 0
-    border-style: solid
-    position: absolute
-    margin: 5px
-    border-color: black
-    z-index: 1
-
-  &[x-placement^="top"]
-    margin-bottom: 5px
-
-    .tooltip-arrow
-      border-width: 5px 5px 0 5px
-      border-left-color: transparent !important
-      border-right-color: transparent !important
-      border-bottom-color: transparent !important
-      bottom: -5px
-      left: calc(50% - 5px)
-      margin-top: 0
-      margin-bottom: 0
-
-  &[x-placement^="bottom"]
-    margin-top: 5px
-
-    .tooltip-arrow
-      border-width: 0 5px 5px 5px
-      border-left-color: transparent !important
-      border-right-color: transparent !important
-      border-top-color: transparent !important
-      top: -5px
-      left: calc(50% - 5px)
-      margin-top: 0
-      margin-bottom: 0
-
-  &[x-placement^="right"]
-    margin-left: 5px
-
-    .tooltip-arrow
-      border-width: 5px 5px 5px 0
-      border-left-color: transparent !important
-      border-top-color: transparent !important
-      border-bottom-color: transparent !important
-      left: -5px
-      top: calc(50% - 5px)
-      margin-left: 0
-      margin-right: 0
-
-  &[x-placement^="left"]
-    margin-right: 5px
-
-    .tooltip-arrow
-      border-width: 5px 0 5px 5px
-      border-top-color: transparent !important
-      border-right-color: transparent !important
-      border-bottom-color: transparent !important
-      right: -5px
-      top: calc(50% - 5px)
-      margin-left: 0
-      margin-right: 0
-
-  &.popover
-    $color: #f9f9f9
-
-    .popover-inner
-      background: $color
-      color: black
-      padding: 24px
-      border-radius: 5px
-      box-shadow: 0 5px 30px rgba(black, 0.1)
-
-    .popover-arrow
-      border-color: $color
-
-  &[aria-hidden="true"]
-    visibility: hidden
-    opacity: 0
-    transition: opacity 0.15s, visibility 0.15s
-
-  &[aria-hidden="false"]
-    visibility: visible
-    opacity: 1
-    transition: opacity 0.15s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/assets/tooltip.scss	Mon Dec 03 13:08:24 2018 +0100
@@ -0,0 +1,118 @@
+/* This is Free Software under GNU Affero General Public License v >= 3.0
+ * without warranty, see README.md and license for details.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ * License-Filename: LICENSES/AGPL-3.0.txt
+ *
+ * Copyright (C) 2018 by via donau
+ *   – Österreichische Wasserstraßen-Gesellschaft mbH
+ * Software engineering by Intevation GmbH
+ *
+ * Author(s):
+ * Thomas Junk <thomas.junk@intevation.de>
+ */
+.tooltip {
+  display: block !important;
+  z-index: 10000;
+}
+
+.tooltip .tooltip-inner {
+  background: black;
+  color: white;
+  border-radius: 16px;
+  padding: 5px 10px 4px;
+}
+
+.tooltip .tooltip-arrow {
+  width: 0;
+  height: 0;
+  border-style: solid;
+  position: absolute;
+  margin: 5px;
+  border-color: black;
+  z-index: 1;
+}
+
+.tooltip[x-placement^="top"] {
+  margin-bottom: 5px;
+}
+
+.tooltip[x-placement^="top"] .tooltip-arrow {
+  border-width: 5px 5px 0 5px;
+  border-left-color: transparent !important;
+  border-right-color: transparent !important;
+  border-bottom-color: transparent !important;
+  bottom: -5px;
+  left: calc(50% - 5px);
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+.tooltip[x-placement^="bottom"] {
+  margin-top: 5px;
+}
+
+.tooltip[x-placement^="bottom"] .tooltip-arrow {
+  border-width: 0 5px 5px 5px;
+  border-left-color: transparent !important;
+  border-right-color: transparent !important;
+  border-top-color: transparent !important;
+  top: -5px;
+  left: calc(50% - 5px);
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+.tooltip[x-placement^="right"] {
+  margin-left: 5px;
+}
+
+.tooltip[x-placement^="right"] .tooltip-arrow {
+  border-width: 5px 5px 5px 0;
+  border-left-color: transparent !important;
+  border-top-color: transparent !important;
+  border-bottom-color: transparent !important;
+  left: -5px;
+  top: calc(50% - 5px);
+  margin-left: 0;
+  margin-right: 0;
+}
+
+.tooltip[x-placement^="left"] {
+  margin-right: 5px;
+}
+
+.tooltip[x-placement^="left"] .tooltip-arrow {
+  border-width: 5px 0 5px 5px;
+  border-top-color: transparent !important;
+  border-right-color: transparent !important;
+  border-bottom-color: transparent !important;
+  right: -5px;
+  top: calc(50% - 5px);
+  margin-left: 0;
+  margin-right: 0;
+}
+
+.tooltip.popover .popover-inner {
+  background: #f9f9f9;
+  color: black;
+  padding: 24px;
+  border-radius: 5px;
+  box-shadow: 0 5px 30px rgba(black, 0.1);
+}
+
+.tooltip.popover .popover-arrow {
+  border-color: #f9f9f9;
+}
+
+.tooltip[aria-hidden="true"] {
+  visibility: hidden;
+  opacity: 0;
+  transition: opacity 0.15s, visibility 0.15s;
+}
+
+.tooltip[aria-hidden="false"] {
+  visibility: visible;
+  opacity: 1;
+  transition: opacity 0.15s;
+}
--- a/client/src/components/App.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/App.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -34,28 +34,31 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-.userinterface
-  position: absolute
-  top: 0
-  left: 0
-  height: 100vh
-  width: 100vw
-  z-index: 4
-  pointer-events: none
+<style lang="scss" scoped>
+.userinterface {
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 100vh;
+  width: 100vw;
+  z-index: 4;
+  pointer-events: none;
+}
 
-.topbar
-  position: relative
-  z-index: 2
+.topbar {
+  position: relative;
+  z-index: 2;
+}
 
-#app
-  height: 100vh
-  width: 100vw
-  font-family: "Avenir", Helvetica, Arial, sans-serif
-  -webkit-font-smoothing: antialiased
-  -moz-osx-font-smoothing: grayscale
-  text-align: center
-  color: #2c3e50
+#app {
+  height: 100vh;
+  width: 100vw;
+  font-family: "Avenir", Helvetica, Arial, sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-align: center;
+  color: #2c3e50;
+}
 </style>
 
 <script>
--- a/client/src/components/Login.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/Login.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -76,24 +76,29 @@
   </div>
 </template>)
 
-<style lang="sass" scoped>
-.login
-  min-width: 375px
-  min-height: 500px
-  @extend %fully-centered
+<style lang="scss" scoped>
+.login {
+  min-width: 375px;
+  min-height: 500px;
+  @extend %fully-centered;
+}
 
-.loginform
-  max-width: 375px
+.loginform {
+  max-width: 375px;
+}
 
-.alert
-  padding: 0.5rem
+.alert {
+  padding: 0.5rem;
+}
 
-.secondary-logo
-  max-width: 375px
+.secondary-logo {
+  max-width: 375px;
+}
 
 /* avoid IE and Edge show a password reveal as we do our own */
-input[type="password"]::-ms-reveal
-  display: none
+input[type="password"]::-ms-reveal {
+  display: none;
+}
 </style>
 
 <script>
--- a/client/src/components/Sidebar.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/Sidebar.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -136,49 +136,65 @@
 };
 </script>
 
-<style lang="sass" scoped>
-.menubutton
-  height: $icon-height
-  width: $icon-width
-  top: 0
-  left: 0
-  color: #666
+<style lang="scss" scoped>
+.menubutton {
+  height: 2rem;
+  width: 2rem;
+  top: 0;
+  left: 0;
+  color: #666;
+}
+
+.menu a {
+  display: block;
+  text-align: left;
+  padding: 0.5rem 1rem;
+  color: #333;
+  text-decoration: none;
+}
+
+.menu a svg path {
+  fill: #666;
+}
+
+.menu a:hover {
+  background-color: #f8f8f8;
+}
+
+.menu a.router-link-exact-active {
+  background-color: #17a2b8;
+  color: #fff;
+}
 
-.menu
-  a
-    display: block
-    text-align: left
-    padding: 0.5rem 1rem
-    color: #333
-    text-decoration: none
-    svg path
-      fill: #666
-    &:hover
-      background-color: #f8f8f8
-    &.router-link-exact-active
-      background-color: $color-info
-      color: #fff
-      svg path
-        fill: #fff
-    &.secondary
-      &.active
-        background: lighten($color-info, 55)
-        color: darken($color-info, 15)
-        svg path
-          fill: darken($color-info, 15)
+.menu a.router-link-exact-active svg path {
+  fill: #fff;
+}
+
+.menu a.secondary.active {
+  background: #ebfafd;
+  color: #0f6674;
+}
+
+.menu a.secondary.active svg path {
+  fill: #0f6674;
+}
 
-.sidebar
-  background-color: #ffffff
-  padding-top: $large-offset
-  opacity: $slight-transparent
-  transition: $transition-fast
-  overflow: hidden
+.sidebar {
+  background-color: #ffffff;
+  padding-top: $large-offset;
+  opacity: $slight-transparent;
+  transition: $transition-fast;
+  overflow: hidden;
+}
 
-.sidebarcollapsed
-  max-height: $icon-height
-  max-width: $icon-width
+.sidebarcollapsed {
+  max-height: $icon-height;
+  max-width: $icon-width;
+}
 
-.sidebarextended
-  max-height: 35rem
-  max-width: $sidebar-width
+.sidebarextended {
+  max-height: 35rem;
+  max-width: $sidebar-width;
+  min-width: $sidebar-width;
+}
 </style>
--- a/client/src/components/admin/Importqueue.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/admin/Importqueue.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -1,9 +1,12 @@
 <template>
   <div class="d-flex flex-row">
     <div :class="spacerStyle"></div>
-    <div class="mt-3 mx-auto">
-      <div class="card importqueuecard">
-        <div class="card-header shadow-sm text-white bg-info mb-3"><translate>Importqueue</translate></div>
+    <div class="mt-3">
+      <div class="card importqueuecard shadow-xs">
+        <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center">
+          <font-awesome-icon icon="tasks" class="mr-2"></font-awesome-icon>
+          <translate class="headline">Importqueue</translate>
+        </h6>
         <div class="card-body importcardbody">
           <div class="card-body importcardbody">
             <div class="searchandfilter d-flex flex-row">
@@ -23,20 +26,38 @@
                 >
               </div>
               <div class="filters">
-                <button @click="setFilter('successful')" :class="successfulStyle"><translate>Successful</translate></button>
-                <button @click="setFilter('failed')" :class="failedStyle"><translate>Failed</translate></button>
-                <button @click="setFilter('pending')" :class="pendingStyle"><translate>Pending</translate></button>
-                <button @click="setFilter('rejected')" :class="rejectedStyle"><translate>Rejected</translate></button>
-                <button @click="setFilter('accepted')" :class="acceptedStyle"><translate>Accepted</translate></button>
+                <button @click="setFilter('successful')" :class="successfulStyle">
+                  <translate>Successful</translate>
+                </button>
+                <button @click="setFilter('failed')" :class="failedStyle">
+                  <translate>Failed</translate>
+                </button>
+                <button @click="setFilter('pending')" :class="pendingStyle">
+                  <translate>Pending</translate>
+                </button>
+                <button @click="setFilter('rejected')" :class="rejectedStyle">
+                  <translate>Rejected</translate>
+                </button>
+                <button @click="setFilter('accepted')" :class="acceptedStyle">
+                  <translate>Accepted</translate>
+                </button>
               </div>
             </div>
             <table class="table">
               <thead>
                 <tr>
-                  <th><translate>Enqueued</translate></th>
-                  <th><translate>Kind</translate></th>
-                  <th><translate>User</translate></th>
-                  <th><translate>State</translate></th>
+                  <th>
+                    <translate>Enqueued</translate>
+                  </th>
+                  <th>
+                    <translate>Kind</translate>
+                  </th>
+                  <th>
+                    <translate>User</translate>
+                  </th>
+                  <th>
+                    <translate>State</translate>
+                  </th>
                 </tr>
               </thead>
               <tbody>
@@ -49,7 +70,9 @@
               </tbody>
             </table>
             <div>
-              <button @click="refresh" class="btn btn-info refresh"><translate>Refresh</translate></button>
+              <button @click="refresh" class="btn btn-info refresh">
+                <translate>Refresh</translate>
+              </button>
             </div>
           </div>
         </div>
@@ -201,50 +224,61 @@
 };
 </script>
 
-<style lang="sass" scoped>
-.refresh
-  position: absolute
-  right: $offset
-  bottom: $offset
+<style lang="scss" scoped>
+.refresh {
+  position: absolute;
+  right: $offset;
+  bottom: $offset;
+}
 
-.spacer
-  height: 100vh
+.spacer {
+  height: 100vh;
+}
 
-.spacer-collapsed
-  min-width: $icon-width + $offset
-  transition: $transition-fast
+.spacer-collapsed {
+  min-width: $icon-width + $offset;
+  transition: $transition-fast;
+}
 
-.spacer-expanded
-  min-width: $sidebar-width + $offset
+.spacer-expanded {
+  min-width: $sidebar-width + $offset;
+}
 
-.importqueuecard
-  width: 80vw
-  min-height: 20rem
+.importqueuecard {
+  width: 80vw;
+  min-height: 20rem;
+}
 
-.card-body
-  width: 100%
-  margin-left: auto
-  margin-right: auto
+.card-body {
+  width: 100%;
+  margin-left: auto;
+  margin-right: auto;
+}
 
-.searchandfilter
-  position: relative
-  margin-bottom: $xx-large-offset
+.searchandfilter {
+  position: relative;
+  margin-bottom: $xx-large-offset;
+}
 
-.filters
-  position: absolute
-  right: 0
+.filters {
+  position: absolute;
+  right: 0;
+}
 
-.filters button
-  margin-right: $small-offset
+.filters button {
+  margin-right: $small-offset;
+}
 
 .table td,
-.table th
-  border-top: 0 !important
-  text-align: left
-  padding: $small-offset !important
+.table th {
+  border-top: 0 !important;
+  text-align: left;
+  padding: $small-offset !important;
+}
 
-.searchgroup
-  position: absolute
-  left: 0
-  width: 50%
+.searchgroup {
+  position: absolute;
+  left: 0;
+  width: 50%;
+}
 </style>
--- a/client/src/components/admin/Logs.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/admin/Logs.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -2,7 +2,7 @@
   <div class="main d-flex flex-column">
     <div class="d-flex flex-row">
       <div :class="spacer"></div>
-      <div class="logoutput text-left bg-white shadow mt-3 mx-3">
+      <div class="logoutput text-left bg-white shadow-xs mt-3 mx-3">
         <pre id="code" v-highlightjs="logs"><code class="bash hljs hljs-string"></code></pre>
       </div>
     </div>
@@ -14,65 +14,83 @@
               @click="fetch('system/log/apache2/access.log', 'accesslog')"
               :class="accesslogStyle"
               href="#"
-            ><translate>Accesslog</translate></a>
+            >
+              <translate>Accesslog</translate>
+            </a>
           </li>
           <li class="nav-item">
             <a
               @click="fetch('system/log/apache2/error.log', 'errorlog')"
               :class="errorlogStyle"
               href="#"
-            ><translate>Errorlog</translate></a>
+            >
+              <translate>Errorlog</translate>
+            </a>
           </li>
         </ul>
       </div>
       <div class="statuscontainer d-flex flex-row">
         <div class="statusline ml-3 mt-1 align-self-center">
-          <h3><translate>Last refresh:</translate> {{refreshed}}</h3>
+          <h3>
+            <translate>Last refresh:</translate>
+            {{refreshed}}
+          </h3>
         </div>
         <div class="refresh">
-          <button class="btn btn-dark" @click="fetch(currentFile, currentLog)"><translate>Refresh</translate></button>
+          <button class="btn btn-dark" @click="fetch(currentFile, currentLog)">
+            <translate>Refresh</translate>
+          </button>
         </div>
       </div>
     </div>
   </div>
 </template>
 
-<style lang="sass" scoped>
-.statuscontainer
-  width: 87%
-  position: relative
+<style lang="scss" scoped>
+.statuscontainer {
+  width: 87%;
+  position: relative;
+}
 
-.logmenu
-  margin-left: 5rem
-  min-width: 60vw
+.logmenu {
+  margin-left: 5rem;
+  min-width: 60vw;
+}
 
-#code
-  overflow: auto
+#code {
+  overflow: auto;
+}
 
-.refresh
-  position: absolute
-  right: 0
+.refresh {
+  position: absolute;
+  right: 0;
+}
 
-.logoutput
-  width: 95%
-  height: 85vh
-  overflow: auto
-  transition: $transition-fast
+.logoutput {
+  width: 95%;
+  height: 85vh;
+  overflow: auto;
+  transition: $transition-fast;
+}
 
-.spacer
-  height: 90vh
+.spacer {
+  height: 90vh;
+}
 
-.spacer-collapsed
-  min-width: $icon-width + $offset
-  transition: $transition-fast
+.spacer-collapsed {
+  min-width: $icon-width + $offset;
+  transition: $transition-fast;
+}
 
-.spacer-expanded
-  min-width: $sidebar-width + $offset
+.spacer-expanded {
+  min-width: $sidebar-width + $offset;
+}
 
-.statusline
-  position: absolute
-  right: 0
-  margin-right: 7rem
+.statusline {
+  position: absolute;
+  right: 0;
+  margin-right: 7rem;
+}
 </style>
 
 <script>
--- a/client/src/components/admin/Systemconfiguration.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/admin/Systemconfiguration.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -1,18 +1,28 @@
 <template>
   <div class="d-flex flex-row">
-    <div class="card sysconfig mt-3 mx-auto">
-      <div class="card-header shadow-sm text-white bg-info mb-6"><translate>Systemconfiguration</translate></div>
+    <div :class="spacerStyle"></div>
+    <div class="card sysconfig mt-3 shadow-xs">
+      <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center">
+        <font-awesome-icon icon="wrench" class="mr-2"></font-awesome-icon>
+        <translate class="headline">Systemconfiguration</translate>
+      </h6>
       <div class="card-body config">
         <section class="configsection">
-          <h4 class="card-title"><translate>Bottleneck Areas stroke-color</translate></h4>
+          <h4 class="card-title">
+            <translate>Bottleneck Areas stroke-color</translate>
+          </h4>
           <compact-picker v-model="strokeColor"/>
         </section>
         <section>
-          <h4 class="card-title"><translate>Bottleneck Areas fill-color</translate></h4>
+          <h4 class="card-title">
+            <translate>Bottleneck Areas fill-color</translate>
+          </h4>
           <chrome-picker v-model="fillColor"/>
         </section>
         <div class="sendbutton">
-          <a @click.prevent="submit" class="btn btn-info"><translate>Send</translate></a>
+          <a @click.prevent="submit" class="btn btn-info text-white">
+            <translate>Send</translate>
+          </a>
         </div>
       </div>
       <!-- card-body -->
@@ -20,24 +30,43 @@
   </div>
 </template>
 
-<style scoped lang="sass">
-.config
-  text-align: left
+<style scoped lang="scss">
+.config {
+  text-align: left;
+}
 
-.configsection
-  margin-bottom: $large-offset
+.configsection {
+  margin-bottom: $large-offset;
+}
+
+.sendbutton {
+  position: absolute;
+  right: $offset;
+  bottom: $offset;
+}
 
-.sendbutton
-  position: absolute
-  right: $offset
-  bottom: $offset
+.inputs {
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.sysconfig {
+  width: 30vw;
+  height: 100%;
+}
 
-.inputs
-  margin-left: auto
-  margin-right: auto
+.spacer {
+  height: 100vh;
+}
 
-.sysconfig
-  width: 30vw
+.spacer-collapsed {
+  min-width: $icon-width + $offset;
+  transition: $transition-fast;
+}
+
+.spacer-expanded {
+  min-width: $sidebar-width + $offset;
+}
 </style>
 
 <script>
@@ -60,6 +89,7 @@
 
 import { HTTP } from "../../lib/http";
 import { displayError } from "../../lib/errors.js";
+import { mapState } from "vuex";
 export default {
   name: "systemconfiguration",
   data() {
@@ -70,7 +100,22 @@
       currentConfig: null
     };
   },
-  components: { "chrome-picker": Chrome, "compact-picker": Compact },
+  components: {
+    "chrome-picker": Chrome,
+    "compact-picker": Compact
+  },
+  computed: {
+    ...mapState("application", ["showSidebar"]),
+    spacerStyle() {
+      return [
+        "spacer ml-3",
+        {
+          "spacer-expanded": this.showSidebar,
+          "spacer-collapsed": !this.showSidebar
+        }
+      ];
+    }
+  },
   methods: {
     submit() {
       HTTP.put("/system/style/Bottlenecks/stroke", this.strokeColor.rgba, {
--- a/client/src/components/admin/importschedule/Importschedule.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/admin/importschedule/Importschedule.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -2,10 +2,11 @@
   <div class="d-flex flex-row">
     <div :class="spacerStyle"></div>
     <div class="mt-3">
-      <div class="card schedulecard">
-        <div class="card-header shadow-sm text-white bg-info mb-3">
-          <translate>Importschedule</translate>
-        </div>
+      <div class="card schedulecard shadow-xs">
+        <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center">
+          <font-awesome-icon icon="clock" class="mr-2"></font-awesome-icon>
+          <translate class="headline">Importschedule</translate>
+        </h6>
         <div class="card-body schedulecardbody">
           <div class="card-body schedulecardbody">
             <div class="searchandfilter d-flex flex-row">
@@ -130,28 +131,34 @@
 };
 </script>
 
-<style lang="sass" scoped>
-.spacer
-  height: 100vh
+<style lang="scss" scoped>
+.spacer {
+  height: 100vh;
+}
 
-.spacer-collapsed
-  min-width: $icon-width + $offset
-  transition: $transition-fast
+.spacer-collapsed {
+  min-width: $icon-width + $offset;
+  transition: $transition-fast;
+}
 
-.spacer-expanded
-  min-width: $sidebar-width + $offset
+.spacer-expanded {
+  min-width: $sidebar-width + $offset;
+}
 
-.schedulecard
-  width: 40vw
-  min-height: 20rem
+.schedulecard {
+  width: 40vw;
+  min-height: 20rem;
+}
 
-.schedulecard-body
-  width: 100%
-  margin-left: auto
-  margin-right: aut
+.schedulecard-body {
+  width: 100%;
+  margin-left: auto;
+  margin-right: auto;
+}
 
-.newbutton
-  position:absolute
-  bottom: $offset
-  right: $offset
+.newbutton {
+  position: absolute;
+  bottom: $offset;
+  right: $offset;
+}
 </style>
--- a/client/src/components/admin/importschedule/Importscheduledetail.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/admin/importschedule/Importscheduledetail.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -1,11 +1,12 @@
 <template>
-  <div v-if="importScheduleDetailVisible">
-    <div class="card">
-      <div class="card-header shadow-sm text-white bg-info mb-3">
-        <span @click="closeDetailview" class="pull-right">
+  <div class="importscheduledetails" v-if="importScheduleDetailVisible">
+    <div class="card shadow-xs">
+      <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center">
+        <translate>New import</translate>
+        <span @click="closeDetailview" class="closebutton">
           <font-awesome-icon icon="times"></font-awesome-icon>
         </span>
-      </div>
+      </h6>
       <div class="card-body">
         <h1>lalala</h1>
         <form @submit.prevent="save" class="ml-3"></form>
@@ -31,5 +32,9 @@
 };
 </script>
 
-<style>
+<style lang="scss" scoped>
+.importscheduledetails {
+  margin-top: $offset;
+  margin-left: $offset;
+}
 </style>
--- a/client/src/components/admin/usermanagement/Userdetail.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/admin/usermanagement/Userdetail.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -1,12 +1,12 @@
 <template>
   <div class="userdetails h-100 mt-3 mr-auto shadow fadeIn animated">
     <div class="card">
-      <div class="card-header shadow-sm text-white bg-info mb-3">
+      <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center">
         {{ this.cardHeader }}
-        <span @click="closeDetailview" class="pull-right">
+        <span @click="closeDetailview" class="closebutton">
           <font-awesome-icon icon="times"></font-awesome-icon>
         </span>
-      </div>
+      </h6>
       <div class="card-body">
         <form @submit.prevent="save" class="ml-3">
           <div class="formfields">
@@ -142,18 +142,22 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-.mailbutton
-  width: 12vw
+<style lang="scss" scoped>
+.mailbutton {
+  width: 12vw;
+}
 
-.formfields
-  width: 10vw
+.formfields {
+  width: 10vw;
+}
 
-.userdetails
-  min-width: 40vw
+.userdetails {
+  min-width: 40vw;
+}
 
-form
-  font-size: $smaller
+form {
+  font-size: $smaller;
+}
 </style>
 
 <script>
--- a/client/src/components/admin/usermanagement/Usermanagement.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/admin/usermanagement/Usermanagement.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -5,9 +5,10 @@
       <div class="d-flex flex-row">
         <div :class="userlistStyle">
           <div class="card">
-            <div class="card-header shadow-sm text-white bg-info mb-3">
-              <translate>Users</translate>
-            </div>
+            <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center">
+              <font-awesome-icon icon="users-cog" class="mr-2"></font-awesome-icon>
+              <translate class="headline">Users</translate>
+            </h6>
             <div class="card-body">
               <table id="datatable" :class="tableStyle">
                 <thead>
@@ -80,70 +81,69 @@
   </div>
 </template>
 
-<style scoped lang="sass">
-@import "../../../assets/tooltip.sass"
+<style scoped lang="scss">
+@import "../../../assets/tooltip.scss";
 
-.spacer
-  height: 100vh
-
-.spacer-collapsed
-  min-width: $icon-width + $offset
-  transition: $transition-fast
+.spacer {
+  height: 100vh;
+  margin-left: $offset;
+}
 
-@media screen and (min-width: 600px)
-  .spacer-expanded
-    min-width: $icon-width + $offset
+.spacer-collapsed {
+  min-width: $icon-width + $offset;
+  transition: $transition-fast;
+}
 
-@media screen and (max-width: 1650px)
-  .spacer-expanded
-    min-width: $sidebar-width + $offset
+.spacer-expanded {
+  min-width: $sidebar-width + $offset;
+}
 
-.main
-  height: 100vh
+.main {
+  height: 100vh;
+}
 
-@media screen and (min-width: 600px)
-  .content
-    margin-left: $sidebar-width
-    margin-right: auto
+.icon {
+  font-size: large;
+}
 
-@media screen and (min-width: 1650px)
-  .content
-    margin-left: $sidebar-width
-    margin-right: auto
+.userlist {
+  min-width: 520px;
+  height: 100%;
+}
 
-.icon
-  font-size: large
+.userlistsmall {
+  width: 30vw;
+}
 
-.userlist
-  min-width: 520px
-  height: 100%
-
-.userlistsmall
-  width: 30vw
+.userlistextended {
+  width: 70vw;
+}
 
-.userlistextended
-  width: 70vw
+.table {
+  width: 90% !important;
+  margin: auto;
+}
 
-.table
-  width: 90% !important
-  margin: auto
-
-.table th
-  cursor: pointer
+.table th {
+  cursor: pointer;
+}
 
 .table th,
-td
-  font-size: $smaller
-  border-top: 0px !important
-  text-align: left
-  padding: $small-offset !important
+td {
+  font-size: $smaller;
+  border-top: 0px !important;
+  text-align: left;
+  padding: $small-offset !important;
+}
 
-.table td
-  font-size: $smaller
-  cursor: pointer
+.table td {
+  font-size: $smaller;
+  cursor: pointer;
+}
 
-tr span
-  display: flex
+tr span {
+  display: flex;
+}
 </style>
 
 <script>
@@ -179,13 +179,13 @@
   },
   computed: {
     ...mapGetters("usermanagement", ["isUserDetailsVisible"]),
-    ...mapState("application", ["showSidebar", "showUsermenu"]),
+    ...mapState("application", ["showSidebar"]),
     spacerStyle() {
       return [
-        "spacer ml-3",
+        "spacer",
         {
-          "spacer-expanded": this.showUsermenu && this.showSidebar,
-          "spacer-collapsed": !this.showUsermenu && this.showSidebar
+          "spacer-expanded": this.showSidebar,
+          "spacer-collapsed": !this.showSidebar
         }
       ];
     },
@@ -222,7 +222,7 @@
     },
     userlistStyle() {
       return [
-        "userlist mt-3 mr-3 shadow",
+        "userlist mt-3 mr-3 shadow-xs",
         {
           userlistsmall: this.isUserDetailsVisible,
           userlistextended: !this.isUserDetailsVisible
--- a/client/src/components/map/Identify.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/Identify.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -56,14 +56,16 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-.features
-  max-height: 19rem
-  overflow-y: auto
+<style lang="scss" scoped>
+.features {
+  max-height: 19rem;
+  overflow-y: auto;
+}
 
-.versioninfo
-  font-size: 60%
-  white-space: normal
+.versioninfo {
+  font-size: 60%;
+  white-space: normal;
+}
 </style>
 
 <script>
--- a/client/src/components/map/Maplayer.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/Maplayer.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -2,24 +2,29 @@
   <div id="map" :class="mapStyle"></div>
 </template>
 
-<style lang="sass" scoped>
-.nocursor
-  cursor: none
+<style lang="scss" scoped>
+.nocursor {
+  cursor: none;
+}
 
-.mapsplit
-  height: 50vh
+.mapsplit {
+  height: 50vh;
+}
 
-.mapfull
-  height: 100vh
+.mapfull {
+  height: 100vh;
+}
 
-@media print
-  .mapfull
-    width: 2000px
-    height: 2828px
-
-  .mapsplit
-    width: 2000px
-    height: 2828px
+@media print {
+  .mapfull {
+    width: 2000px;
+    height: 2828px;
+  }
+  .mapsplit {
+    width: 2000px;
+    height: 2828px;
+  }
+}
 </style>
 
 <script>
--- a/client/src/components/map/Search.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/Search.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -5,7 +5,9 @@
         <font-awesome-icon icon="search"></font-awesome-icon>
       </span>
     </div>
-    <div :class="['searchgroup', {'searchgroup-collapsed': !showSearchbar, big: showContextBox && ['bottlenecks', 'staging'].indexOf(contextBoxContent) !== -1 }]">
+    <div
+      :class="['searchgroup', {'searchgroup-collapsed': !showSearchbar, big: showContextBox && ['bottlenecks', 'staging'].indexOf(contextBoxContent) !== -1 }]"
+    >
       <input
         @keyup.enter="takeFirstSearchresult"
         id="search"
@@ -20,9 +22,14 @@
     >
       <div v-for="entry of searchResults" :key="entry.name" class="border-top text-left">
         <a href="#" @click.prevent="moveToSearchResult(entry)" class="p-2 d-block text-nowrap">
-          <font-awesome-icon icon="ship" v-if="entry.type === 'bottleneck'" class="mr-1" fixed-width />
-          <font-awesome-icon icon="water" v-if="entry.type === 'rhm'" class="mr-1" fixed-width />
-          <font-awesome-icon icon="city" v-if="entry.type === 'city'" class="mr-1" fixed-width />
+          <font-awesome-icon
+            icon="ship"
+            v-if="entry.type === 'bottleneck'"
+            class="mr-1"
+            fixed-width
+          />
+          <font-awesome-icon icon="water" v-if="entry.type === 'rhm'" class="mr-1" fixed-width/>
+          <font-awesome-icon icon="city" v-if="entry.type === 'city'" class="mr-1" fixed-width/>
           {{ entry.name }}
         </a>
       </div>
@@ -30,57 +37,75 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-  .searchcontainer
-    opacity: $slight-transparent
-    .searchbar
-      border-top-left-radius: 0 !important
-      border-bottom-left-radius: 0 !important
+<style lang="scss" scoped>
+.searchcontainer {
+  opacity: 0.96;
+}
+
+.searchcontainer .searchbar {
+  border-top-left-radius: 0 !important;
+  border-bottom-left-radius: 0 !important;
+}
+
+.searchgroup {
+  margin-left: -3px;
+  transition: width 0.3s;
+  width: 300px;
+  overflow: hidden;
+}
 
-  .searchgroup
-    margin-left: -3px
-    transition: width 0.3s
-    width: 300px
-    overflow: hidden
-    &.big
-      width: 571px
+.searchgroup.big {
+  width: 571px;
+}
+
+.searchgroup-collapsed {
+  width: 0;
+}
 
-  .searchgroup-collapsed
-    width: 0
+.searchbar {
+  height: 2rem !important;
+  box-shadow: none !important;
+}
 
-  .searchbar
-    height: $icon-height !important
-    box-shadow: none !important
-    &.rounded-top-right
-      border-radius: 0 !important
-      border-top-right-radius: $border-radius !important
+.searchbar.rounded-top-right {
+  border-radius: 0 !important;
+  border-top-right-radius: 0.25rem !important;
+}
 
-  .searchlabel
-    &.rounded-top-left
-      border-radius: 0 !important
-      border-top-left-radius: $border-radius !important
+.searchlabel.rounded-top-left {
+  border-radius: 0 !important;
+  border-top-left-radius: 0.25rem !important;
+}
 
-  .input-group-text
-    height: $icon-height
-    width: $icon-width
+.input-group-text {
+  height: 2rem;
+  width: 2rem;
+}
 
-  .input-group-prepend
-    svg path
-      fill: #666
+.input-group-prepend svg path {
+  fill: #666;
+}
 
-  .searchresults
-    box-shadow: $shadow-xs
-    top: $icon-height
-    left: 0
-    right: 0
-    max-height: 24rem
-    overflow: auto
-    > div:first-child
-      border-top: 0 !important
-    a
-      text-decoration: none
-      &:hover
-        background: #f8f8f8
+.searchresults {
+  box-shadow: 0 0.1rem 0.5rem rgba(0, 0, 0, 0.2);
+  top: 2rem;
+  left: 0;
+  right: 0;
+  max-height: 24rem;
+  overflow: auto;
+}
+
+.searchresults > div:first-child {
+  border-top: 0 !important;
+}
+
+.searchresults a {
+  text-decoration: none;
+}
+
+.searchresults a:hover {
+  background: #f8f8f8;
+}
 </style>
 
 <script>
@@ -203,7 +228,7 @@
         .catch(error => {
           const { status, data } = error.response;
           displayError({
-            title: "Backend Error",
+            title: this.$gettext("Backend Error"),
             message: `${status}: ${data.message || data}`
           });
         });
--- a/client/src/components/map/Zoom.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/Zoom.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -15,18 +15,20 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-.buttoncontainer
-  bottom: 0
-  left: 50%
-  margin-left: -$icon-width
+<style lang="scss" scoped>
+.buttoncontainer {
+  bottom: 0;
+  left: 50%;
+  margin-left: -$icon-width;
+}
 
-.zoomButton
-  min-height: $icon-width
-  min-width: $icon-width
-  z-index: 1
-  outline: none
-  color: #666
+.zoomButton {
+  min-height: $icon-width;
+  min-width: $icon-width;
+  z-index: 1;
+  outline: none;
+  color: #666;
+}
 </style>
 <script>
 /* This is Free Software under GNU Affero General Public License v >= 3.0
--- a/client/src/components/map/contextbox/Bottlenecks.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/contextbox/Bottlenecks.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -1,21 +1,28 @@
 <template>
   <div>
     <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
-      <font-awesome-icon icon="ship" class="mr-2"></font-awesome-icon><translate>Bottlenecks</translate>
+      <font-awesome-icon icon="ship" class="mr-2"></font-awesome-icon>
+      <translate>Bottlenecks</translate>
     </h6>
     <div class="row p-2 text-left small">
       <div class="col-5">
-        <a href="#" @click="sortBy('name')" class="sort-link"><translate>Name</translate></a>
+        <a href="#" @click="sortBy('name')" class="sort-link">
+          <translate>Name</translate>
+        </a>
         <font-awesome-icon :icon="sortIcon" class="ml-1" v-if="sortColumn === 'name'"></font-awesome-icon>
       </div>
       <div class="col-2">
-        <a href="#" @click="sortBy('latestMeasurement')" class="sort-link"><translate>Latest</translate>
-          <br><translate>Measurement</translate>
+        <a href="#" @click="sortBy('latestMeasurement')" class="sort-link">
+          <translate>Latest</translate>
+          <br>
+          <translate>Measurement</translate>
         </a>
         <font-awesome-icon :icon="sortIcon" class="ml-1" v-if="sortColumn === 'latestMeasurement'"></font-awesome-icon>
       </div>
       <div class="col-3">
-        <a href="#" @click="sortBy('chainage')" class="sort-link"><translate>Chainage</translate></a>
+        <a href="#" @click="sortBy('chainage')" class="sort-link">
+          <translate>Chainage</translate>
+        </a>
         <font-awesome-icon :icon="sortIcon" class="ml-1" v-if="sortColumn === 'chainage'"></font-awesome-icon>
       </div>
       <div class="col-2"></div>
@@ -31,17 +38,12 @@
         class="border-top row bottleneck-row mx-0"
       >
         <div class="col-5 py-2 text-left">
-          <a
-            href="#"
-            @click="selectBottleneck(bottleneck)"
-          >{{ bottleneck.properties.name }}</a>
+          <a href="#" @click="selectBottleneck(bottleneck)">{{ bottleneck.properties.name }}</a>
         </div>
-        <div class="col-2 py-2">
-          {{ displayCurrentSurvey(bottleneck.properties.current) }}
-        </div>
-        <div class="col-3 py-2">
-          {{ displayCurrentChainage(bottleneck.properties.from, bottleneck.properties.from) }}
-        </div>
+        <div class="col-2 py-2">{{ displayCurrentSurvey(bottleneck.properties.current) }}</div>
+        <div
+          class="col-3 py-2"
+        >{{ displayCurrentChainage(bottleneck.properties.from, bottleneck.properties.from) }}</div>
         <div class="col-2 pr-0 text-right">
           <button
             type="button"
@@ -49,12 +51,27 @@
             @click="loadSurveys(bottleneck.properties.name)"
             v-if="bottleneck.properties.current"
           >
-            <font-awesome-icon icon="spinner" fixed-width spin v-if="loading === bottleneck.properties.name"></font-awesome-icon>
-            <font-awesome-icon icon="angle-down" fixed-width v-if="loading !== bottleneck.properties.name && openBottleneck !== bottleneck.properties.name"></font-awesome-icon>
-            <font-awesome-icon icon="angle-up" fixed-width v-if="loading !== bottleneck.properties.name && openBottleneck === bottleneck.properties.name"></font-awesome-icon>
+            <font-awesome-icon
+              icon="spinner"
+              fixed-width
+              spin
+              v-if="loading === bottleneck.properties.name"
+            ></font-awesome-icon>
+            <font-awesome-icon
+              icon="angle-down"
+              fixed-width
+              v-if="loading !== bottleneck.properties.name && openBottleneck !== bottleneck.properties.name"
+            ></font-awesome-icon>
+            <font-awesome-icon
+              icon="angle-up"
+              fixed-width
+              v-if="loading !== bottleneck.properties.name && openBottleneck === bottleneck.properties.name"
+            ></font-awesome-icon>
           </button>
         </div>
-        <div :class="['col-12 p-0', 'surveys', {open: openBottleneck === bottleneck.properties.name}]">
+        <div
+          :class="['col-12 p-0', 'surveys', {open: openBottleneck === bottleneck.properties.name}]"
+        >
           <a
             href="#"
             class="d-block px-3 py-2"
@@ -65,7 +82,9 @@
         </div>
       </div>
     </div>
-    <div v-else class="small text-center py-3 border-top"><translate>No results.</translate></div>
+    <div v-else class="small text-center py-3 border-top">
+      <translate>No results.</translate>
+    </div>
   </div>
 </template>
 
@@ -192,9 +211,9 @@
           }
         })
           .then(response => {
-            this.openBottleneckSurveys = response.data.surveys.sort(
-              (a, b) => (a.date_info < b.date_info ? 1 : -1)
-            );
+            this.openBottleneckSurveys = response.data.surveys.sort((a, b) => {
+              return a.date_info < b.date_info ? 1 : -1;
+            });
           })
           .catch(error => {
             const { status, data } = error.response;
@@ -219,28 +238,36 @@
 };
 </script>
 
-<style lang="sass" scoped>
-.bottleneck-list
-  overflow-y: auto
-  .bottleneck-row
-    a
-      text-decoration: none
-    &:hover
-      background: #fbfbfb
+<style lang="scss" scoped>
+.bottleneck-list {
+  overflow-y: auto;
+}
+
+.bottleneck-list .bottleneck-row a {
+  text-decoration: none;
+}
+
+.bottleneck-list .bottleneck-row:hover {
+  background: #fbfbfb;
+}
 
-.surveys
-  max-height: 0
-  min-height: 0
-  overflow: hidden
-  a
-    &:hover
-      background: #f3f3f3
+.surveys {
+  max-height: 0;
+  min-height: 0;
+  overflow: hidden;
+}
+
+.surveys a:hover {
+  background: #f3f3f3;
+}
 
-.surveys.open
-  max-height: 250px
-  overflow: auto
+.surveys.open {
+  max-height: 250px;
+  overflow: auto;
+}
 
-.sort-link
-  color: #444
-  font-weight: bold
+.sort-link {
+  color: #444;
+  font-weight: bold;
+}
 </style>
--- a/client/src/components/map/contextbox/Contextbox.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/contextbox/Contextbox.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -62,30 +62,35 @@
 };
 </script>
 
-<style lang="sass" scoped>
-.contextbox
-  position: relative
-  background-color: #ffffff
-  opacity: $slight-transparent
-  transition: max-width 0.3s, max-height 0.3s
-  overflow: hidden
-  background: #fff
-  > div:last-child
-    width: 600px
+<style lang="scss" scoped>
+.contextbox {
+  position: relative;
+  background-color: #ffffff;
+  opacity: $slight-transparent;
+  transition: max-width 0.3s, max-height 0.3s;
+  overflow: hidden;
+  background: #fff;
+}
+.contextbox > div:last-child {
+  width: 600px;
+}
 
-.contextboxcollapsed
-  max-width: 0
-  max-height: 0
+.contextboxcollapsed {
+  max-width: 0;
+  max-height: 0;
+}
 
-.contextboxextended
-  max-width: 600px
-  max-height: 640px
+.contextboxextended {
+  max-width: 600px;
+  max-height: 640px;
+}
 
-.close-contextbox
-  position: absolute
-  z-index: 2
-  right: 0
-  top: 7px
-  height: $icon-width
-  width: $icon-height
+.close-contextbox {
+  position: absolute;
+  z-index: 2;
+  right: 0;
+  top: 7px;
+  height: $icon-width;
+  width: $icon-height;
+}
 </style>
--- a/client/src/components/map/contextbox/ImportSoundingresults.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/contextbox/ImportSoundingresults.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -55,7 +55,9 @@
             </span>
           </div>
           <div class="mt-1 text-left w-50 mr-2">
-            <small class="text-muted">Date</small>
+            <small class="text-muted">
+              <translate>Date</translate>
+            </small>
             <input
               id="importdate"
               type="date"
@@ -115,7 +117,7 @@
           @click="submit"
           class="btn btn-info"
           type="button"
-        >{{ uploadState ? "Upload" : "Confirm" }}</button>
+        >{{ uploadState ? Upload : Confirm }}</button>
       </div>
     </div>
   </div>
@@ -140,7 +142,6 @@
 import { displayError, displayInfo } from "../../../lib/errors.js";
 import { mapState } from "vuex";
 
-const defaultLabel = "Choose .zip-file";
 const IMPORTSTATE = { UPLOAD: "UPLOAD", EDIT: "EDIT" };
 
 export default {
@@ -152,7 +153,7 @@
       bottleneck: "",
       projection: "",
       importDate: "",
-      uploadLabel: defaultLabel,
+      uploadLabel: this.$gettext("choose .zip- file"),
       uploadFile: null,
       disableUpload: false,
       token: null,
@@ -166,7 +167,7 @@
       this.bottleneck = "";
       this.projection = "";
       this.importDate = "";
-      this.uploadLabel = defaultLabel;
+      this.uploadLabel = this.$gettext("choose .zip- file");
       this.uploadFile = null;
       this.disableUpload = false;
       this.token = null;
@@ -190,7 +191,7 @@
         .catch(error => {
           const { status, data } = error.response;
           displayError({
-            title: "Backend Error",
+            title: this.$gettext("Backend Error"),
             message: `${status}: ${data.message || data}`
           });
         });
@@ -229,7 +230,7 @@
           const { status, data } = error.response;
           const messages = data.messages ? data.messages.join(", ") : "";
           displayError({
-            title: "Backend Error",
+            title: this.$gettext("Backend Error"),
             message: `${status}: ${messages}`
           });
         });
@@ -252,15 +253,15 @@
       })
         .then(() => {
           displayInfo({
-            title: "Import",
-            message: "Starting import for " + this.bottleneck
+            title: this.$gettext("Import"),
+            message: this.$gettext("Starting import for ") + this.bottleneck
           });
           this.initialState();
         })
         .catch(error => {
           const { status, data } = error.response;
           displayError({
-            title: "Backend Error",
+            title: this.$gettext("Backend Error"),
             message: `${status}: ${data.message || data}`
           });
         });
@@ -297,6 +298,12 @@
     uploadState() {
       return this.importState === IMPORTSTATE.UPLOAD;
     },
+    Upload() {
+      return this.$gettext("Upload");
+    },
+    Confirm() {
+      return this.$gettext("Confirm");
+    },
     dataLink() {
       return (
         "data:text/json;charset=utf-8," +
@@ -337,21 +344,26 @@
 };
 </script>
 
-<style lang="sass" scoped>
-.projectionLabel
-  margin-left: $small-offset
+<style lang="scss" scoped>
+.projectionLabel {
+  margin-left: $small-offset;
+}
 
-.depthreferencelabel
-  margin-left: $small-offset
+.depthreferencelabel {
+  margin-left: $small-offset;
+}
 
-.offset-r
-  margin-right: $small-offset
-
-.buttons button
-  margin-left: $offset !important
+.offset-r {
+  margin-right: $small-offset;
+}
 
-.label-text
-  width: 5rem
-  text-align: left
-  line-height: 2.25rem
+.buttons button {
+  margin-left: $offset !important;
+}
+
+.label-text {
+  width: 5rem;
+  text-align: left;
+  line-height: 2.25rem;
+}
 </style>
--- a/client/src/components/map/contextbox/Staging.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/contextbox/Staging.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -193,13 +193,13 @@
 };
 </script>
 
-<style lang="sass" scoped>
-
+<style lang="scss" scoped>
 .table th,
-td
-  font-size: 0.9rem
-  border-top: 0px !important
-  border-bottom-width: 1px
-  text-align: left
-  padding: 0.5rem !important
+td {
+  font-size: 0.9rem;
+  border-top: 0px !important;
+  border-bottom-width: 1px;
+  text-align: left;
+  padding: 0.5rem !important;
+}
 </style>
--- a/client/src/components/map/fairway/Fairwayprofile.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/fairway/Fairwayprofile.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -1,7 +1,5 @@
 <template>
-  <div
-    :class="['position-relative', {show: showSplitscreen}]"
-  >
+  <div :class="['position-relative', {show: showSplitscreen}]">
     <button
       class="rounded-bottom bg-white border-0 position-absolute splitscreen-toggle"
       @click="$store.commit('application/showSplitscreen', false)"
@@ -22,8 +20,11 @@
         v-if="selectedBottleneck && selectedSurvey"
       >{{ selectedBottleneck }} ({{ selectedSurvey.date_info }})</h5>
       <div class="d-flex flex-fill">
-        <div class="loading d-flex justify-content-center align-items-center" v-if="surveysLoading || profileLoading">
-          <font-awesome-icon icon="spinner" spin />
+        <div
+          class="loading d-flex justify-content-center align-items-center"
+          v-if="surveysLoading || profileLoading"
+        >
+          <font-awesome-icon icon="spinner" spin/>
         </div>
         <div class="fairwayprofile m-3 mt-0 bg-white flex-grow-1"></div>
       </div>
@@ -31,43 +32,49 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-.profile
-  width: 100vw
-  height: 0
-  overflow: hidden
-  z-index: 2
-  .headline
-    border-top: solid 3px $color-info
+<style lang="scss" scoped>
+.profile {
+  width: 100vw;
+  height: 0;
+  overflow: hidden;
+  z-index: 2;
+}
 
 .splitscreen-toggle,
-.clear-selection
-  width: $icon-width
-  height: $icon-height
-  margin-top: 8px
-  z-index: 3
-  outline: none
-  svg path
-    fill: #666
+.clear-selection {
+  width: 2rem;
+  height: 2rem;
+  margin-top: 8px;
+  z-index: 3;
+  outline: none;
+}
 
-.splitscreen-toggle
-  right: $small-offset + $icon-width
+.splitscreen-toggle svg path,
+.clear-selection svg path {
+  fill: #666;
+}
+
+.splitscreen-toggle {
+  right: 2.5rem;
+}
 
-.clear-selection
-  right: $small-offset
+.clear-selection {
+  right: 0.5rem;
+}
 
-.show
-  .profile
-    height: 50vh
+.show .profile {
+  height: 50vh;
+}
 
-.loading
-  background: rgba(255, 255, 255, 0.96)
-  position: absolute
-  z-index: 99
-  top: 0
-  right: 0
-  bottom: 0
-  left: 0
+.loading {
+  background: rgba(255, 255, 255, 0.96);
+  position: absolute;
+  z-index: 99;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
 </style>
 
 <script>
--- a/client/src/components/map/fairway/Infobar.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/fairway/Infobar.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -3,7 +3,7 @@
     v-if="Object.keys(currentProfile).length && !showSplitscreen"
     class="ui-element shadow-xs infobar rounded bg-white ml-auto mb-3 mr-3"
   >
-    <div class="d-flex flex-row justify-content-between">
+    <div class="d-flex flex-row justify-content-between h-100">
       <h6 class="my-auto px-2">
         {{ selectedBottleneck }}
         ({{ selectedSurvey.date_info }})
@@ -24,13 +24,15 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-.infobar
-  height: $icon-height + 0.2rem
-  z-index: 2
-  border-top: solid 3px $color-info
-  svg path
-    fill: #666
+<style lang="scss" scoped>
+.infobar {
+  height: 2.2rem;
+  z-index: 2;
+}
+
+.infobar svg path {
+  fill: #666;
+}
 </style>
 
 <script>
--- a/client/src/components/map/fairway/Profiles.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/fairway/Profiles.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -172,28 +172,30 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-  .loading
-    background: rgba(255, 255, 255, 0.9)
-    position: absolute
-    z-index: 99
-    top: 0
-    right: 0
-    bottom: 0
-    left: 0
+<style lang="scss" scoped>
+.loading {
+  background: rgba(255, 255, 255, 0.9);
+  position: absolute;
+  z-index: 99;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
 
-  .input-button-right
-    border-top-right-radius: $border-radius
-    border-bottom-right-radius: $border-radius
-    border-top-left-radius: 0 !important
-    border-bottom-left-radius: 0 !important
+.input-button-right {
+  border-top-right-radius: $border-radius;
+  border-bottom-right-radius: $border-radius;
+  border-top-left-radius: 0 !important;
+  border-bottom-left-radius: 0 !important;
+}
 
-  .rounded-left-only
-    border-top-right-radius: 0 !important
-    border-bottom-right-radius: 0 !important
-    border-top-left-radius: $border-radius
-    border-bottom-left-radius: $border-radius
-
+.rounded-left-only {
+  border-top-right-radius: 0 !important;
+  border-bottom-right-radius: 0 !important;
+  border-top-left-radius: $border-radius;
+  border-bottom-left-radius: $border-radius;
+}
 </style>
 
 <script>
@@ -327,24 +329,15 @@
       }
     },
     toggleCutTool() {
-      if (this.selectedSurvey) {
-        this.cutTool.setActive(!this.cutTool.getActive());
-        this.lineTool.setActive(false);
-        this.polygonTool.setActive(false);
-        this.$store.commit("map/setCurrentMeasurement", null);
-
-        // toggle identifyTool (map events singleclick and dblclick)
-        this.$store.dispatch(
-          this.cutTool.getActive()
-            ? "map/disableIdentifyTool"
-            : "map/enableIdentifyTool"
-        );
-      }
+      this.cutTool.setActive(!this.cutTool.getActive());
+      this.lineTool.setActive(false);
+      this.polygonTool.setActive(false);
+      this.$store.commit("map/setCurrentMeasurement", null);
     },
     onCopyCoordinates() {
       displayInfo({
-        title: "Success",
-        message: "Coordinates copied to clipboard!"
+        title: this.$gettext("Success"),
+        message: this.$gettext("Coordinates copied to clipboard!")
       });
     },
     applyManualCoordinates() {
@@ -378,9 +371,10 @@
         this.$store.dispatch("fairwayprofile/cut", cut);
       } else {
         displayError({
-          title: "Invalid input",
-          message:
+          title: this.$gettext("Invalid input"),
+          message: this.$gettext(
             "Please enter correct coordinates in the format: Lat,Lon,Lat,Lon"
+          )
         });
       }
     },
@@ -403,9 +397,10 @@
 
       this.showLabelInput = false;
       displayInfo({
-        title: "Profile saved!",
-        message:
+        title: this.$gettext("Profile saved!"),
+        message: this.$gettext(
           'You can now select these coordinates from the "Saved cross profiles" menu to restore this cross profile.'
+        )
       });
     },
     deleteSelectedCut() {
@@ -416,7 +411,7 @@
       localStorage.setItem("previousCuts", JSON.stringify(previousCuts));
       this.$store.commit("fairwayprofile/selectedCut", null);
       this.$store.dispatch("fairwayprofile/previousCuts");
-      displayInfo({ title: "Profile deleted!" });
+      displayInfo({ title: this.$gettext("Profile deleted!") });
     },
     moveToBottleneck() {
       const bottleneck = this.bottlenecks.find(
--- a/client/src/components/map/layers/Layerselect.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/layers/Layerselect.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -17,12 +17,13 @@
   </div>
 </template>
 
-<style lang="sass" scoped>
-.selection
-  text-align: left
-
-.layername
-  margin-left: $small-offset
+<style lang="scss" scoped>
+.selection {
+  text-align: left;
+}
+.layername {
+  margin-left: $small-offset;
+}
 </style>
 
 
--- a/client/src/components/map/layers/LegendElement.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/layers/LegendElement.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -116,8 +116,9 @@
 };
 </script>
 
-<style lang="sass" scoped>
-.legendelement
-  max-height: 1.5rem
-  width: 2rem
+<style lang="scss" scoped>
+.legendelement {
+  max-height: 1.5rem;
+  width: 2rem;
+}
 </style>
--- a/client/src/components/map/toolbar/Toolbar.vue	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/components/map/toolbar/Toolbar.vue	Mon Dec 03 13:08:24 2018 +0100
@@ -1,72 +1,90 @@
 <template>
   <div class="ml-2">
     <div :class="'rounded-top toolbar toolbar-' + (expandToolbar ? 'expanded' : 'collapsed')">
-        <Identify></Identify>
-        <Layers></Layers>
-        <Profiles></Profiles>
-        <Linetool></Linetool>
-        <Polygontool></Polygontool>
-        <Pdftool></Pdftool>
+      <Identify></Identify>
+      <Layers></Layers>
+      <Profiles></Profiles>
+      <Linetool></Linetool>
+      <Polygontool></Polygontool>
+      <Pdftool></Pdftool>
     </div>
-    <div @click="$store.commit('application/expandToolbar', !expandToolbar)" class="toolbar-button toolbar-toggle rounded-bottom bg-info text-white">
-        <font-awesome-icon :icon="expandToolbar ? 'angle-up' : 'angle-down'"></font-awesome-icon>
+    <div
+      @click="$store.commit('application/expandToolbar', !expandToolbar)"
+      class="toolbar-button toolbar-toggle rounded-bottom bg-info text-white"
+    >
+      <font-awesome-icon :icon="expandToolbar ? 'angle-up' : 'angle-down'"></font-awesome-icon>
     </div>
   </div>
 </template>
 
-<style lang="sass">
+<style lang="scss">
 // not scoped to affect nested components
 // doen't work when put in application/assets/application.sass... why??? o_O
-.toolbar
-  box-shadow: $shadow-xs
-  overflow: hidden
-  transition: max-height 0.4s
-  margin-bottom: auto
+.toolbar {
+  box-shadow: 0 0.1rem 0.5rem rgba(0, 0, 0, 0.2);
+  overflow: hidden;
+  transition: max-height 0.4s;
+  margin-bottom: auto;
+}
+
+.toolbar-collapsed {
+  max-height: 6rem;
+}
+
+.toolbar-expanded {
+  max-height: 100%;
+}
 
-.toolbar-collapsed
-  max-height: 3 * $icon-height
-
-.toolbar-expanded
-  max-height: 100%
+.toolbar-button {
+  opacity: 0.96;
+  color: #666;
+  height: 2rem;
+  width: 2rem;
+  align-items: center;
+  justify-content: center;
+  display: flex;
+  background: #fff;
+  border-bottom: 1px solid #dee2e6;
+  z-index: 2;
+  pointer-events: auto;
+  position: relative;
+  overflow: hidden;
+}
 
-.toolbar-button
-  opacity: $slight-transparent
-  color: #666
-  height: $icon-width
-  width: $icon-height
-  align-items: center
-  justify-content: center
-  display: flex
-  background: #fff
-  border-bottom: 1px solid #dee2e6
-  z-index: 2
-  pointer-events: auto
-  position: relative
-  overflow: hidden
-  &:last-child
-    border-bottom: none
-  .inverted
-    color: $color-info
-  .grey
-    color: #ddd
-  .indicator
-    color: #fff
-    background: $color-info
-    position: absolute
-    bottom: -14px
-    left: -14px
-    padding: 2px 4px 1px
-    font-size: 11px
-    line-height: 11px
-    border-top-right-radius: $border-radius
-    transition: bottom 0.3s, left 0.3s
-    &.show
-      left: 0
-      bottom: 0
+.toolbar-button:last-child {
+  border-bottom: none;
+}
+
+.toolbar-button .inverted {
+  color: #17a2b8;
+}
+
+.toolbar-button .grey {
+  color: #ddd;
+}
 
-.toolbar-toggle
-  height: 1.2rem
-  border-bottom: none
+.toolbar-button .indicator {
+  color: #fff;
+  background: #17a2b8;
+  position: absolute;
+  bottom: -14px;
+  left: -14px;
+  padding: 2px 4px 1px;
+  font-size: 11px;
+  line-height: 11px;
+  border-top-right-radius: 0.25rem;
+  transition: bottom 0.3s, left 0.3s;
+}
+
+.toolbar-button .indicator.show {
+  left: 0;
+  bottom: 0;
+}
+
+.toolbar-toggle {
+  height: 1.2rem;
+  border-bottom: none;
+}
 </style>
 
 <script>
--- a/client/src/locale/de_AT/LC_MESSAGES/app.po	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/locale/de_AT/LC_MESSAGES/app.po	Mon Dec 03 13:08:24 2018 +0100
@@ -8,21 +8,22 @@
 msgstr ""
 "Project-Id-Version: wamosjs 0.1.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-11-29 17:47+0100\n"
-"PO-Revision-Date: 2018-07-03 17:00+0200\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
+"POT-Creation-Date: 2018-12-03 10:57+0100\n"
+"PO-Revision-Date: 2018-12-03 09:31+0000\n"
+"Last-Translator: Bernhard E. Reiter <bernhard.reiter@intevation.de>\n"
+"Language-Team: Austrian German <https://hosted.weblate.org/projects/gemma/client/de_AT/>\n"
 "Language: de_AT\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 3.3\n"
 
-#: src/components/admin/Importqueue.vue:29
+#: src/components/admin/Importqueue.vue:40
 msgid "Accepted"
-msgstr ""
+msgstr "Akzeptiert"
 
-#: src/components/admin/Logs.vue:16
+#: src/components/admin/Logs.vue:17
 msgid "Accesslog"
 msgstr ""
 
@@ -32,36 +33,49 @@
 
 #: src/components/admin/importschedule/Importschedule.vue:37
 msgid "Author"
-msgstr ""
+msgstr "Autor"
 
 #: src/components/Login.vue:59
 msgid "back to login"
+msgstr "zurück zur Anmeldung"
+
+#: src/components/map/Search.vue:231
+#: src/components/map/contextbox/ImportSoundingresults.vue:194
+#: src/components/map/contextbox/ImportSoundingresults.vue:233
+#: src/components/map/contextbox/ImportSoundingresults.vue:264
+#: src/components/map/contextbox/Staging.vue:99
+msgid "Backend Error"
 msgstr ""
 
 #: src/components/map/contextbox/ImportSoundingresults.vue:11
 msgid "Bottleneck"
-msgstr ""
+msgstr "Engstelle"
 
-#: src/components/admin/Systemconfiguration.vue:10
+#: src/components/admin/Systemconfiguration.vue:15
 msgid "Bottleneck Areas fill-color"
 msgstr ""
 
-#: src/components/admin/Systemconfiguration.vue:6
+#: src/components/admin/Systemconfiguration.vue:9
 msgid "Bottleneck Areas stroke-color"
 msgstr ""
 
 #: src/components/Sidebar.vue:19
-#: src/components/map/contextbox/Bottlenecks.vue:3
+#: src/components/map/contextbox/Bottlenecks.vue:4
 msgid "Bottlenecks"
 msgstr "Engstellen"
 
-#: src/components/map/contextbox/ImportSoundingresults.vue:110
+#: src/components/map/contextbox/ImportSoundingresults.vue:112
 msgid "Cancel Upload"
+msgstr "Hochladen abbrechen"
+
+#: src/components/map/contextbox/Bottlenecks.vue:23
+msgid "Chainage"
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:17
-msgid "Chainage"
-msgstr ""
+#: src/components/map/contextbox/ImportSoundingresults.vue:156
+#: src/components/map/contextbox/ImportSoundingresults.vue:170
+msgid "choose .zip- file"
+msgstr "Wählen Sie eine .zip Datei"
 
 #: src/components/map/Pdftool.vue:12
 msgid "Chose format:"
@@ -75,33 +89,39 @@
 msgid "Configuration"
 msgstr ""
 
+#: src/components/map/contextbox/ImportSoundingresults.vue:305
 #: src/components/map/contextbox/Staging.vue:65
 msgid "Confirm"
-msgstr ""
+msgstr "Bestätigen"
 
 #: src/components/map/Identify.vue:52
 msgid "contributors."
 msgstr ""
 
-#: src/components/admin/usermanagement/Userdetail.vue:33
-msgid "Country"
+#: src/components/map/fairway/Profiles.vue:340
+msgid "Coordinates copied to clipboard!"
 msgstr ""
 
+#: src/components/admin/usermanagement/Userdetail.vue:33
+msgid "Country"
+msgstr "Land"
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:58
 #: src/components/map/contextbox/Staging.vue:16
 msgid "Date"
-msgstr ""
+msgstr "Datum"
 
 #: src/components/map/contextbox/ImportSoundingresults.vue:42
 msgid "Depthreference"
-msgstr ""
+msgstr "Tiefenreferenz"
 
 #: src/components/map/Pdftool.vue:25
 msgid "Download"
 msgstr ""
 
-#: src/components/map/contextbox/ImportSoundingresults.vue:107
+#: src/components/map/contextbox/ImportSoundingresults.vue:109
 msgid "Download Meta.json"
-msgstr ""
+msgstr "Meta.json Herunterladen"
 
 #: src/components/admin/importschedule/Importschedule.vue:43
 msgid "Email"
@@ -109,9 +129,9 @@
 
 #: src/components/admin/usermanagement/Userdetail.vue:58
 msgid "Email address"
-msgstr ""
+msgstr "Email Adresse"
 
-#: src/components/admin/Importqueue.vue:35
+#: src/components/admin/Importqueue.vue:48
 msgid "Enqueued"
 msgstr ""
 
@@ -123,22 +143,22 @@
 msgid "Enter label for cross profile"
 msgstr ""
 
-#: src/components/Login.vue:141
+#: src/components/Login.vue:146
 msgid "Enter passphrase"
 msgstr "Passphrase"
 
-#: src/components/Login.vue:144
+#: src/components/Login.vue:149
 #, fuzzy
 msgid "Enter username"
 msgstr "Passphrase"
 
-#: src/components/admin/Logs.vue:23
+#: src/components/admin/Logs.vue:26
 msgid "Errorlog"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:26
+#: src/components/admin/Importqueue.vue:31
 msgid "Failed"
-msgstr ""
+msgstr "Fehlgeschlagen"
 
 #: src/components/Login.vue:65
 msgid "Forgot password"
@@ -146,13 +166,14 @@
 
 #: src/components/map/Pdftool.vue:4 src/components/map/Pdftool.vue:38
 msgid "Generate PDF"
-msgstr ""
+msgstr "PDF generieren"
 
 #: src/components/map/Identify.vue:5
 msgid "Identified"
 msgstr ""
 
 #: src/components/admin/importschedule/Importschedule.vue:31
+#: src/components/map/contextbox/ImportSoundingresults.vue:256
 msgid "Import"
 msgstr ""
 
@@ -166,9 +187,9 @@
 
 #: src/components/map/contextbox/Staging.vue:19
 msgid "Imported"
-msgstr ""
+msgstr "Importiert"
 
-#: src/components/Sidebar.vue:58 src/components/admin/Importqueue.vue:5
+#: src/components/Sidebar.vue:58 src/components/admin/Importqueue.vue:6
 msgid "Importqueue"
 msgstr ""
 
@@ -177,7 +198,11 @@
 msgid "Importschedule"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:36
+#: src/components/map/fairway/Profiles.vue:374
+msgid "Invalid input"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:51
 msgid "Kind"
 msgstr ""
 
@@ -185,11 +210,11 @@
 msgid "landscape"
 msgstr ""
 
-#: src/components/admin/Logs.vue:29
+#: src/components/admin/Logs.vue:34
 msgid "Last refresh:"
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:11
+#: src/components/map/contextbox/Bottlenecks.vue:15
 msgid "Latest"
 msgstr ""
 
@@ -201,7 +226,7 @@
 msgid "Login"
 msgstr "Login"
 
-#: src/components/Login.vue:135
+#: src/components/Login.vue:140
 msgid "Login failed"
 msgstr "Login fehlgeschlagen"
 
@@ -221,24 +246,24 @@
 msgid "Map"
 msgstr "Karte"
 
-#: src/components/map/contextbox/Bottlenecks.vue:12
+#: src/components/map/contextbox/Bottlenecks.vue:17
 msgid "Measurement"
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:7
+#: src/components/map/contextbox/Bottlenecks.vue:9
 #: src/components/map/contextbox/Staging.vue:10
 msgid "Name"
-msgstr ""
+msgstr "Name"
 
 #: src/components/admin/importschedule/Importschedule.vue:69
 msgid "New Import"
-msgstr ""
+msgstr "Neuer Import"
 
 #: src/components/map/Identify.vue:33
 msgid "No features identified."
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:67
+#: src/components/map/contextbox/Bottlenecks.vue:85
 #: src/components/map/contextbox/Staging.vue:58
 msgid "No results."
 msgstr ""
@@ -249,17 +274,17 @@
 
 #: src/components/map/Pdftool.vue:32
 msgid "Open in new window"
-msgstr ""
+msgstr "In neuem Fenster öffnen"
 
-#: src/components/Login.vue:137
+#: src/components/Login.vue:142
 msgid "Password reset requested!"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:27
+#: src/components/admin/Importqueue.vue:34
 msgid "Pending"
 msgstr ""
 
-#: src/components/map/contextbox/ImportSoundingresults.vue:69
+#: src/components/map/contextbox/ImportSoundingresults.vue:71
 msgid "Please enter a date"
 msgstr ""
 
@@ -271,6 +296,11 @@
 msgid "Please enter a reference"
 msgstr ""
 
+#: src/components/map/fairway/Profiles.vue:375
+#: src/components/map/fairway/Profiles.vue:376
+msgid "Please enter correct coordinates in the format: Lat,Lon,Lat,Lon"
+msgstr ""
+
 #: src/components/map/contextbox/ImportSoundingresults.vue:18
 msgid "Please select a bottleneck"
 msgstr ""
@@ -284,21 +314,29 @@
 msgid "portrait"
 msgstr ""
 
+#: src/components/map/fairway/Profiles.vue:414
+msgid "Profile deleted!"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:400
+msgid "Profile saved!"
+msgstr ""
+
 #: src/components/map/fairway/Profiles.vue:5
 msgid "Profiles"
 msgstr ""
 
 #: src/components/map/contextbox/ImportSoundingresults.vue:24
 msgid "Projection"
-msgstr ""
+msgstr "Projektion"
 
-#: src/components/admin/Importqueue.vue:51 src/components/admin/Logs.vue:32
+#: src/components/admin/Importqueue.vue:72 src/components/admin/Logs.vue:40
 msgid "Refresh"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:28
+#: src/components/admin/Importqueue.vue:37
 msgid "Rejected"
-msgstr ""
+msgstr "Abgelehnt"
 
 #: src/components/Login.vue:55
 msgid "Request password reset!"
@@ -317,17 +355,16 @@
 msgstr ""
 
 #: src/components/map/fairway/Profiles.vue:25
-#, fuzzy
 msgid "Select Bottleneck"
-msgstr "Engstellen"
+msgstr "Wähle Engstelle"
 
-#: src/components/admin/Systemconfiguration.vue:14
+#: src/components/admin/Systemconfiguration.vue:21
 msgid "Send"
 msgstr ""
 
 #: src/components/admin/usermanagement/Userdetail.vue:132
 msgid "Send testmail"
-msgstr ""
+msgstr "Testmail senden"
 
 #: src/components/map/Identify.vue:50
 msgid "Some data"
@@ -346,6 +383,7 @@
 msgstr ""
 
 #: src/components/map/contextbox/Staging.vue:4
+#: src/components/map/contextbox/Staging.vue:125
 msgid "Staging Area"
 msgstr ""
 
@@ -353,7 +391,11 @@
 msgid "Start"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:38
+#: src/components/map/contextbox/ImportSoundingresults.vue:257
+msgid "Starting import for "
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:57
 msgid "State"
 msgstr ""
 
@@ -361,9 +403,13 @@
 msgid "Submit"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:25
+#: src/components/map/fairway/Profiles.vue:339
+msgid "Success"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:28
 msgid "Successful"
-msgstr ""
+msgstr "Erfolgreich"
 
 #: src/components/admin/usermanagement/Userdetail.vue:88
 msgid "Sysadmin"
@@ -373,7 +419,7 @@
 msgid "Systemadministration"
 msgstr ""
 
-#: src/components/admin/Systemconfiguration.vue:3
+#: src/components/admin/Systemconfiguration.vue:4
 msgid "Systemconfiguration"
 msgstr ""
 
@@ -386,7 +432,11 @@
 msgid "Type"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:37
+#: src/components/map/contextbox/ImportSoundingresults.vue:302
+msgid "Upload"
+msgstr "Hochladen"
+
+#: src/components/admin/Importqueue.vue:54
 msgid "User"
 msgstr ""
 
@@ -416,3 +466,8 @@
 #: src/components/map/Identify.vue:41
 msgid "without warranty, see docs for details."
 msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:401
+#: src/components/map/fairway/Profiles.vue:402
+msgid "You can now select these coordinates from the \"Saved cross profiles\" menu to restore this cross profile."
+msgstr ""
--- a/client/src/locale/en_GB/LC_MESSAGES/app.po	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/locale/en_GB/LC_MESSAGES/app.po	Mon Dec 03 13:08:24 2018 +0100
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: wamosjs 0.1.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-11-29 17:47+0100\n"
+"POT-Creation-Date: 2018-12-03 10:57+0100\n"
 "PO-Revision-Date: 2018-07-03 17:18+0200\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -17,11 +17,11 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/components/admin/Importqueue.vue:29
+#: src/components/admin/Importqueue.vue:40
 msgid "Accepted"
 msgstr ""
 
-#: src/components/admin/Logs.vue:16
+#: src/components/admin/Logs.vue:17
 msgid "Accesslog"
 msgstr ""
 
@@ -37,31 +37,44 @@
 msgid "back to login"
 msgstr ""
 
+#: src/components/map/Search.vue:231
+#: src/components/map/contextbox/ImportSoundingresults.vue:194
+#: src/components/map/contextbox/ImportSoundingresults.vue:233
+#: src/components/map/contextbox/ImportSoundingresults.vue:264
+#: src/components/map/contextbox/Staging.vue:99
+msgid "Backend Error"
+msgstr ""
+
 #: src/components/map/contextbox/ImportSoundingresults.vue:11
 msgid "Bottleneck"
 msgstr ""
 
-#: src/components/admin/Systemconfiguration.vue:10
+#: src/components/admin/Systemconfiguration.vue:15
 msgid "Bottleneck Areas fill-color"
 msgstr ""
 
-#: src/components/admin/Systemconfiguration.vue:6
+#: src/components/admin/Systemconfiguration.vue:9
 msgid "Bottleneck Areas stroke-color"
 msgstr ""
 
 #: src/components/Sidebar.vue:19
-#: src/components/map/contextbox/Bottlenecks.vue:3
+#: src/components/map/contextbox/Bottlenecks.vue:4
 msgid "Bottlenecks"
 msgstr ""
 
-#: src/components/map/contextbox/ImportSoundingresults.vue:110
+#: src/components/map/contextbox/ImportSoundingresults.vue:112
 msgid "Cancel Upload"
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:17
+#: src/components/map/contextbox/Bottlenecks.vue:23
 msgid "Chainage"
 msgstr ""
 
+#: src/components/map/contextbox/ImportSoundingresults.vue:156
+#: src/components/map/contextbox/ImportSoundingresults.vue:170
+msgid "choose .zip- file"
+msgstr ""
+
 #: src/components/map/Pdftool.vue:12
 msgid "Chose format:"
 msgstr ""
@@ -74,6 +87,7 @@
 msgid "Configuration"
 msgstr ""
 
+#: src/components/map/contextbox/ImportSoundingresults.vue:305
 #: src/components/map/contextbox/Staging.vue:65
 msgid "Confirm"
 msgstr ""
@@ -82,10 +96,15 @@
 msgid "contributors."
 msgstr ""
 
+#: src/components/map/fairway/Profiles.vue:340
+msgid "Coordinates copied to clipboard!"
+msgstr ""
+
 #: src/components/admin/usermanagement/Userdetail.vue:33
 msgid "Country"
 msgstr ""
 
+#: src/components/map/contextbox/ImportSoundingresults.vue:58
 #: src/components/map/contextbox/Staging.vue:16
 msgid "Date"
 msgstr ""
@@ -98,7 +117,7 @@
 msgid "Download"
 msgstr ""
 
-#: src/components/map/contextbox/ImportSoundingresults.vue:107
+#: src/components/map/contextbox/ImportSoundingresults.vue:109
 msgid "Download Meta.json"
 msgstr ""
 
@@ -110,7 +129,7 @@
 msgid "Email address"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:35
+#: src/components/admin/Importqueue.vue:48
 msgid "Enqueued"
 msgstr ""
 
@@ -122,26 +141,25 @@
 msgid "Enter label for cross profile"
 msgstr ""
 
-#: src/components/Login.vue:141
+#: src/components/Login.vue:146
 msgid "Enter passphrase"
-msgstr "Enter passphrase"
+msgstr ""
 
-#: src/components/Login.vue:144
-#, fuzzy
+#: src/components/Login.vue:149
 msgid "Enter username"
-msgstr "Enter passphrase"
+msgstr ""
 
-#: src/components/admin/Logs.vue:23
+#: src/components/admin/Logs.vue:26
 msgid "Errorlog"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:26
+#: src/components/admin/Importqueue.vue:31
 msgid "Failed"
 msgstr ""
 
 #: src/components/Login.vue:65
 msgid "Forgot password"
-msgstr "Forgot password"
+msgstr ""
 
 #: src/components/map/Pdftool.vue:4 src/components/map/Pdftool.vue:38
 msgid "Generate PDF"
@@ -152,6 +170,7 @@
 msgstr ""
 
 #: src/components/admin/importschedule/Importschedule.vue:31
+#: src/components/map/contextbox/ImportSoundingresults.vue:256
 msgid "Import"
 msgstr ""
 
@@ -167,7 +186,7 @@
 msgid "Imported"
 msgstr ""
 
-#: src/components/Sidebar.vue:58 src/components/admin/Importqueue.vue:5
+#: src/components/Sidebar.vue:58 src/components/admin/Importqueue.vue:6
 msgid "Importqueue"
 msgstr ""
 
@@ -176,7 +195,11 @@
 msgid "Importschedule"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:36
+#: src/components/map/fairway/Profiles.vue:374
+msgid "Invalid input"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:51
 msgid "Kind"
 msgstr ""
 
@@ -184,11 +207,11 @@
 msgid "landscape"
 msgstr ""
 
-#: src/components/admin/Logs.vue:29
+#: src/components/admin/Logs.vue:34
 msgid "Last refresh:"
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:11
+#: src/components/map/contextbox/Bottlenecks.vue:15
 msgid "Latest"
 msgstr ""
 
@@ -198,11 +221,11 @@
 
 #: src/components/Login.vue:51
 msgid "Login"
-msgstr "Login"
+msgstr ""
 
-#: src/components/Login.vue:135
+#: src/components/Login.vue:140
 msgid "Login failed"
-msgstr "Login failed"
+msgstr ""
 
 #: src/components/Sidebar.vue:68
 msgid "Logout"
@@ -220,11 +243,11 @@
 msgid "Map"
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:12
+#: src/components/map/contextbox/Bottlenecks.vue:17
 msgid "Measurement"
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:7
+#: src/components/map/contextbox/Bottlenecks.vue:9
 #: src/components/map/contextbox/Staging.vue:10
 msgid "Name"
 msgstr ""
@@ -237,7 +260,7 @@
 msgid "No features identified."
 msgstr ""
 
-#: src/components/map/contextbox/Bottlenecks.vue:67
+#: src/components/map/contextbox/Bottlenecks.vue:85
 #: src/components/map/contextbox/Staging.vue:58
 msgid "No results."
 msgstr ""
@@ -250,15 +273,15 @@
 msgid "Open in new window"
 msgstr ""
 
-#: src/components/Login.vue:137
+#: src/components/Login.vue:142
 msgid "Password reset requested!"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:27
+#: src/components/admin/Importqueue.vue:34
 msgid "Pending"
 msgstr ""
 
-#: src/components/map/contextbox/ImportSoundingresults.vue:69
+#: src/components/map/contextbox/ImportSoundingresults.vue:71
 msgid "Please enter a date"
 msgstr ""
 
@@ -270,6 +293,11 @@
 msgid "Please enter a reference"
 msgstr ""
 
+#: src/components/map/fairway/Profiles.vue:375
+#: src/components/map/fairway/Profiles.vue:376
+msgid "Please enter correct coordinates in the format: Lat,Lon,Lat,Lon"
+msgstr ""
+
 #: src/components/map/contextbox/ImportSoundingresults.vue:18
 msgid "Please select a bottleneck"
 msgstr ""
@@ -283,6 +311,14 @@
 msgid "portrait"
 msgstr ""
 
+#: src/components/map/fairway/Profiles.vue:414
+msgid "Profile deleted!"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:400
+msgid "Profile saved!"
+msgstr ""
+
 #: src/components/map/fairway/Profiles.vue:5
 msgid "Profiles"
 msgstr ""
@@ -291,11 +327,11 @@
 msgid "Projection"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:51 src/components/admin/Logs.vue:32
+#: src/components/admin/Importqueue.vue:72 src/components/admin/Logs.vue:40
 msgid "Refresh"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:28
+#: src/components/admin/Importqueue.vue:37
 msgid "Rejected"
 msgstr ""
 
@@ -319,7 +355,7 @@
 msgid "Select Bottleneck"
 msgstr ""
 
-#: src/components/admin/Systemconfiguration.vue:14
+#: src/components/admin/Systemconfiguration.vue:21
 msgid "Send"
 msgstr ""
 
@@ -344,6 +380,7 @@
 msgstr ""
 
 #: src/components/map/contextbox/Staging.vue:4
+#: src/components/map/contextbox/Staging.vue:125
 msgid "Staging Area"
 msgstr ""
 
@@ -351,7 +388,11 @@
 msgid "Start"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:38
+#: src/components/map/contextbox/ImportSoundingresults.vue:257
+msgid "Starting import for "
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:57
 msgid "State"
 msgstr ""
 
@@ -359,7 +400,11 @@
 msgid "Submit"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:25
+#: src/components/map/fairway/Profiles.vue:339
+msgid "Success"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:28
 msgid "Successful"
 msgstr ""
 
@@ -371,7 +416,7 @@
 msgid "Systemadministration"
 msgstr ""
 
-#: src/components/admin/Systemconfiguration.vue:3
+#: src/components/admin/Systemconfiguration.vue:4
 msgid "Systemconfiguration"
 msgstr ""
 
@@ -384,15 +429,18 @@
 msgid "Type"
 msgstr ""
 
-#: src/components/admin/Importqueue.vue:37
+#: src/components/map/contextbox/ImportSoundingresults.vue:302
+msgid "Upload"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:54
 msgid "User"
 msgstr ""
 
 #: src/components/admin/usermanagement/Userdetail.vue:14
 #: src/components/map/contextbox/Staging.vue:22
-#, fuzzy
 msgid "Username"
-msgstr "Enter passphrase"
+msgstr ""
 
 #: src/components/Sidebar.vue:44
 #: src/components/admin/usermanagement/Usermanagement.vue:8
@@ -414,3 +462,8 @@
 #: src/components/map/Identify.vue:41
 msgid "without warranty, see docs for details."
 msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:401
+#: src/components/map/fairway/Profiles.vue:402
+msgid "You can now select these coordinates from the \"Saved cross profiles\" menu to restore this cross profile."
+msgstr ""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/locale/sk_SK/LC_MESSAGES/app.po	Mon Dec 03 13:08:24 2018 +0100
@@ -0,0 +1,469 @@
+# English translations for wamosjs package.
+# Copyright (C) 2018 THE wamosjs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the wamosjs package.
+# Automatically generated, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: wamosjs 0.1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-12-03 10:57+0100\n"
+"PO-Revision-Date: 2018-07-03 17:18+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: sk_SK\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/components/admin/Importqueue.vue:40
+msgid "Accepted"
+msgstr ""
+
+#: src/components/admin/Logs.vue:17
+msgid "Accesslog"
+msgstr ""
+
+#: src/components/admin/usermanagement/Usermanagement.vue:71
+msgid "Add User"
+msgstr ""
+
+#: src/components/admin/importschedule/Importschedule.vue:37
+msgid "Author"
+msgstr ""
+
+#: src/components/Login.vue:59
+msgid "back to login"
+msgstr ""
+
+#: src/components/map/Search.vue:231
+#: src/components/map/contextbox/ImportSoundingresults.vue:194
+#: src/components/map/contextbox/ImportSoundingresults.vue:233
+#: src/components/map/contextbox/ImportSoundingresults.vue:264
+#: src/components/map/contextbox/Staging.vue:99
+msgid "Backend Error"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:11
+msgid "Bottleneck"
+msgstr ""
+
+#: src/components/admin/Systemconfiguration.vue:15
+msgid "Bottleneck Areas fill-color"
+msgstr ""
+
+#: src/components/admin/Systemconfiguration.vue:9
+msgid "Bottleneck Areas stroke-color"
+msgstr ""
+
+#: src/components/Sidebar.vue:19
+#: src/components/map/contextbox/Bottlenecks.vue:4
+msgid "Bottlenecks"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:112
+msgid "Cancel Upload"
+msgstr ""
+
+#: src/components/map/contextbox/Bottlenecks.vue:23
+msgid "Chainage"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:156
+#: src/components/map/contextbox/ImportSoundingresults.vue:170
+msgid "choose .zip- file"
+msgstr ""
+
+#: src/components/map/Pdftool.vue:12
+msgid "Chose format:"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:49
+msgid "Compare with"
+msgstr ""
+
+#: src/components/Sidebar.vue:50
+msgid "Configuration"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:305
+#: src/components/map/contextbox/Staging.vue:65
+msgid "Confirm"
+msgstr ""
+
+#: src/components/map/Identify.vue:52
+msgid "contributors."
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:340
+msgid "Coordinates copied to clipboard!"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:33
+msgid "Country"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:58
+#: src/components/map/contextbox/Staging.vue:16
+msgid "Date"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:42
+msgid "Depthreference"
+msgstr ""
+
+#: src/components/map/Pdftool.vue:25
+msgid "Download"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:109
+msgid "Download Meta.json"
+msgstr ""
+
+#: src/components/admin/importschedule/Importschedule.vue:43
+msgid "Email"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:58
+msgid "Email address"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:48
+msgid "Enqueued"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:96
+msgid "Enter coordinates manually"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:154
+msgid "Enter label for cross profile"
+msgstr ""
+
+#: src/components/Login.vue:146
+msgid "Enter passphrase"
+msgstr ""
+
+#: src/components/Login.vue:149
+msgid "Enter username"
+msgstr ""
+
+#: src/components/admin/Logs.vue:26
+msgid "Errorlog"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:31
+msgid "Failed"
+msgstr ""
+
+#: src/components/Login.vue:65
+msgid "Forgot password"
+msgstr ""
+
+#: src/components/map/Pdftool.vue:4 src/components/map/Pdftool.vue:38
+msgid "Generate PDF"
+msgstr ""
+
+#: src/components/map/Identify.vue:5
+msgid "Identified"
+msgstr ""
+
+#: src/components/admin/importschedule/Importschedule.vue:31
+#: src/components/map/contextbox/ImportSoundingresults.vue:256
+msgid "Import"
+msgstr ""
+
+#: src/components/Sidebar.vue:28
+msgid "Import soundingresults"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:4
+msgid "Import Soundingresults"
+msgstr ""
+
+#: src/components/map/contextbox/Staging.vue:19
+msgid "Imported"
+msgstr ""
+
+#: src/components/Sidebar.vue:58 src/components/admin/Importqueue.vue:6
+msgid "Importqueue"
+msgstr ""
+
+#: src/components/Sidebar.vue:62
+#: src/components/admin/importschedule/Importschedule.vue:6
+msgid "Importschedule"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:374
+msgid "Invalid input"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:51
+msgid "Kind"
+msgstr ""
+
+#: src/components/map/Pdftool.vue:14
+msgid "landscape"
+msgstr ""
+
+#: src/components/admin/Logs.vue:34
+msgid "Last refresh:"
+msgstr ""
+
+#: src/components/map/contextbox/Bottlenecks.vue:15
+msgid "Latest"
+msgstr ""
+
+#: src/components/map/layers/Layers.vue:4
+msgid "Layers"
+msgstr ""
+
+#: src/components/Login.vue:51
+msgid "Login"
+msgstr ""
+
+#: src/components/Login.vue:140
+msgid "Login failed"
+msgstr ""
+
+#: src/components/Sidebar.vue:68
+msgid "Logout"
+msgstr ""
+
+#: src/components/Sidebar.vue:54
+msgid "Logs"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:135
+msgid "Mail was sent"
+msgstr ""
+
+#: src/components/Sidebar.vue:11
+msgid "Map"
+msgstr ""
+
+#: src/components/map/contextbox/Bottlenecks.vue:17
+msgid "Measurement"
+msgstr ""
+
+#: src/components/map/contextbox/Bottlenecks.vue:9
+#: src/components/map/contextbox/Staging.vue:10
+msgid "Name"
+msgstr ""
+
+#: src/components/admin/importschedule/Importschedule.vue:69
+msgid "New Import"
+msgstr ""
+
+#: src/components/map/Identify.vue:33
+msgid "No features identified."
+msgstr ""
+
+#: src/components/map/contextbox/Bottlenecks.vue:85
+#: src/components/map/contextbox/Staging.vue:58
+msgid "No results."
+msgstr ""
+
+#: src/components/admin/importschedule/Importschedule.vue:66
+msgid "No schedules"
+msgstr ""
+
+#: src/components/map/Pdftool.vue:32
+msgid "Open in new window"
+msgstr ""
+
+#: src/components/Login.vue:142
+msgid "Password reset requested!"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:34
+msgid "Pending"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:71
+msgid "Please enter a date"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:34
+msgid "Please enter a projection"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:52
+msgid "Please enter a reference"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:375
+#: src/components/map/fairway/Profiles.vue:376
+msgid "Please enter correct coordinates in the format: Lat,Lon,Lat,Lon"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:18
+msgid "Please select a bottleneck"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:41
+#: src/components/admin/usermanagement/Userdetail.vue:85
+msgid "Please select one"
+msgstr ""
+
+#: src/components/map/Pdftool.vue:15
+msgid "portrait"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:414
+msgid "Profile deleted!"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:400
+msgid "Profile saved!"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:5
+msgid "Profiles"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:24
+msgid "Projection"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:72 src/components/admin/Logs.vue:40
+msgid "Refresh"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:37
+msgid "Rejected"
+msgstr ""
+
+#: src/components/Login.vue:55
+msgid "Request password reset!"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:77
+msgid "Role"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:63
+msgid "Saved cross profiles"
+msgstr ""
+
+#: src/components/admin/importschedule/Importschedule.vue:40
+msgid "Schedule"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:25
+msgid "Select Bottleneck"
+msgstr ""
+
+#: src/components/admin/Systemconfiguration.vue:21
+msgid "Send"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:132
+msgid "Send testmail"
+msgstr ""
+
+#: src/components/map/Identify.vue:50
+msgid "Some data"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:37
+msgid "Sounding Result"
+msgstr ""
+
+#: src/components/map/Identify.vue:45
+msgid "source-code"
+msgstr ""
+
+#: src/components/Sidebar.vue:36
+msgid "Staging area"
+msgstr ""
+
+#: src/components/map/contextbox/Staging.vue:4
+#: src/components/map/contextbox/Staging.vue:125
+msgid "Staging Area"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:116
+msgid "Start"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:257
+msgid "Starting import for "
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:57
+msgid "State"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:123
+msgid "Submit"
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:339
+msgid "Success"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:28
+msgid "Successful"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:88
+msgid "Sysadmin"
+msgstr ""
+
+#: src/components/Sidebar.vue:39
+msgid "Systemadministration"
+msgstr ""
+
+#: src/components/admin/Systemconfiguration.vue:4
+msgid "Systemconfiguration"
+msgstr ""
+
+#: src/components/map/Identify.vue:37
+msgid "This app uses"
+msgstr ""
+
+#: src/components/admin/importschedule/Importschedule.vue:34
+#: src/components/map/contextbox/Staging.vue:13
+msgid "Type"
+msgstr ""
+
+#: src/components/map/contextbox/ImportSoundingresults.vue:302
+msgid "Upload"
+msgstr ""
+
+#: src/components/admin/Importqueue.vue:54
+msgid "User"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:14
+#: src/components/map/contextbox/Staging.vue:22
+msgid "Username"
+msgstr ""
+
+#: src/components/Sidebar.vue:44
+#: src/components/admin/usermanagement/Usermanagement.vue:8
+msgid "Users"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:91
+msgid "Waterway Admin"
+msgstr ""
+
+#: src/components/admin/usermanagement/Userdetail.vue:94
+msgid "Waterway User"
+msgstr ""
+
+#: src/components/map/Identify.vue:39
+msgid "which is Free Software under"
+msgstr ""
+
+#: src/components/map/Identify.vue:41
+msgid "without warranty, see docs for details."
+msgstr ""
+
+#: src/components/map/fairway/Profiles.vue:401
+#: src/components/map/fairway/Profiles.vue:402
+msgid "You can now select these coordinates from the \"Saved cross profiles\" menu to restore this cross profile."
+msgstr ""
--- a/client/src/locale/translations.json	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/locale/translations.json	Mon Dec 03 13:08:24 2018 +0100
@@ -1,1 +1,1 @@
-{"de_AT":{"Bottlenecks":"Engstellen","Enter passphrase":"Passphrase","Forgot password":"Passwort vergessen","Login":"Login","Login failed":"Login fehlgeschlagen","Map":"Karte"},"en_GB":{"Enter passphrase":"Enter passphrase","Forgot password":"Forgot password","Login":"Login","Login failed":"Login failed"}}
\ No newline at end of file
+{"de_AT":{"Accepted":"Akzeptiert","Author":"Autor","back to login":"zurück zur Anmeldung","Bottleneck":"Engstelle","Bottlenecks":"Engstellen","Cancel Upload":"Hochladen abbrechen","choose .zip- file":"Wählen Sie eine .zip Datei","Confirm":"Bestätigen","Country":"Land","Date":"Datum","Depthreference":"Tiefenreferenz","Download Meta.json":"Meta.json Herunterladen","Email address":"Email Adresse","Enter passphrase":"Passphrase","Failed":"Fehlgeschlagen","Forgot password":"Passwort vergessen","Generate PDF":"PDF generieren","Imported":"Importiert","Login":"Login","Login failed":"Login fehlgeschlagen","Map":"Karte","Name":"Name","New Import":"Neuer Import","Open in new window":"In neuem Fenster öffnen","Projection":"Projektion","Rejected":"Abgelehnt","Select Bottleneck":"Wähle Engstelle","Send testmail":"Testmail senden","Successful":"Erfolgreich","Upload":"Hochladen"},"en_GB":{},"sk_SK":{}}
\ No newline at end of file
--- a/client/src/main.js	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/main.js	Mon Dec 03 13:08:24 2018 +0100
@@ -138,13 +138,18 @@
 // planned also SK, HU, HR, RS, BiH, BG, RO, UA
 const supportedLanguages = {
   en_GB: "British English",
-  de_AT: "Deutsch"
+  de_AT: "Deutsch",
+  sk_SK: "slovenčina"
 };
 
 if (browserLanguage === "de-DE") {
   browserLanguage = "de-AT"; // map german to austrian variant for now
 }
 
+if (browserLanguage === "sk") {
+  browserLanguage = "sk_SK";
+}
+
 const language = browserLanguage.replace("-", "_");
 const isLanguageAvailable = supportedLanguages[language];
 let defaultLanguage = isLanguageAvailable ? language : "en_GB";
--- a/client/src/store/fairway.js	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/store/fairway.js	Mon Dec 03 13:08:24 2018 +0100
@@ -140,92 +140,103 @@
             headers: { "X-Gemma-Auth": localStorage.getItem("token") }
           })
             .then(response => {
-              commit("profileLoaded", {
-                response: response,
-                surveyDate: survey.date_info
-              });
-              resolve(response);
+              if (response.data.geometry.coordinates.length) {
+                commit("profileLoaded", {
+                  response: response,
+                  surveyDate: survey.date_info
+                });
+                resolve(response);
+              } else {
+                commit("clearCurrentProfile");
+                commit("application/showSplitscreen", false, { root: true });
+                reject({
+                  response: {
+                    status: null,
+                    data: "No intersection with sounding data."
+                  }
+                });
+              }
             })
-            .catch(error => {
-              reject(error);
-            });
+            .catch(error => reject(error));
         });
       }
     },
     cut({ commit, dispatch, rootState, rootGetters }, cut) {
-      const length = getLength(cut.getGeometry());
-      commit(
-        "map/setCurrentMeasurement",
-        {
-          quantity: "Length",
-          unitSymbol: "m",
-          value: Math.round(length * 10) / 10
-        },
-        { root: true }
-      );
+      return new Promise(resolve => {
+        const length = getLength(cut.getGeometry());
+        commit(
+          "map/setCurrentMeasurement",
+          {
+            quantity: "Length",
+            unitSymbol: "m",
+            value: Math.round(length * 10) / 10
+          },
+          { root: true }
+        );
 
-      // if a survey has been selected, request a profile
-      // TODO an improvement could be to check if the line intersects
-      // with the bottleneck area's polygon before trying the server request
-      if (rootState.bottlenecks.selectedSurvey) {
-        const inputLineString = cut.getGeometry().clone();
-        inputLineString.transform("EPSG:3857", "EPSG:4326");
-        const [start, end] = inputLineString
-          .getCoordinates()
-          .map(coords => coords.map(coord => parseFloat(coord.toFixed(8))));
-        commit("setStartPoint", start);
-        commit("setEndPoint", end);
-        const profileLine = new LineString([start, end]);
+        // if a survey has been selected, request a profile
+        // TODO an improvement could be to check if the line intersects
+        // with the bottleneck area's polygon before trying the server request
+        if (rootState.bottlenecks.selectedSurvey) {
+          const inputLineString = cut.getGeometry().clone();
+          inputLineString.transform("EPSG:3857", "EPSG:4326");
+          const [start, end] = inputLineString
+            .getCoordinates()
+            .map(coords => coords.map(coord => parseFloat(coord.toFixed(8))));
+          commit("setStartPoint", start);
+          commit("setEndPoint", end);
+          const profileLine = new LineString([start, end]);
 
-        const profileLoaders = [
-          dispatch("loadProfile", rootState.bottlenecks.selectedSurvey)
-        ];
-        if (rootState.fairwayprofile.additionalSurvey) {
-          profileLoaders.push(
-            dispatch("loadProfile", rootState.fairwayprofile.additionalSurvey)
-          );
-        }
+          const profileLoaders = [
+            dispatch("loadProfile", rootState.bottlenecks.selectedSurvey)
+          ];
+          if (rootState.fairwayprofile.additionalSurvey) {
+            profileLoaders.push(
+              dispatch("loadProfile", rootState.fairwayprofile.additionalSurvey)
+            );
+          }
 
-        commit("profileLoading", true);
-        Promise.all(profileLoaders)
-          .then(() => {
-            dispatch("map/enableIdentifyTool", null, { root: true });
-            rootState.map.cutTool.setActive(false);
-            rootGetters["map/getVSourceByName"](
-              "Fairway Dimensions"
-            ).forEachFeatureIntersectingExtent(
-              // need to use EPSG:3857 which is the proj of vectorSource
-              profileLine
-                .clone()
-                .transform("EPSG:4326", "EPSG:3857")
-                .getExtent(),
-              feature => {
-                // transform back to prepare for usage
-                var intersectingPolygon = feature
-                  .getGeometry()
+          commit("profileLoading", true);
+          Promise.all(profileLoaders)
+            .then(() => {
+              rootState.map.cutTool.setActive(false);
+              rootGetters["map/getVSourceByName"](
+                "Fairway Dimensions"
+              ).forEachFeatureIntersectingExtent(
+                // need to use EPSG:3857 which is the proj of vectorSource
+                profileLine
                   .clone()
-                  .transform("EPSG:3857", "EPSG:4326");
-                const fairwayCoordinates = calculateFairwayCoordinates(
-                  profileLine,
-                  intersectingPolygon,
-                  DEMODATA
-                );
-                commit("setFairwayCoordinates", fairwayCoordinates);
-              }
-            );
-          })
-          .catch(error => {
-            const { status, data } = error.response;
-            displayError({
-              title: "Backend Error",
-              message: `${status}: ${data.message || data}`
+                  .transform("EPSG:4326", "EPSG:3857")
+                  .getExtent(),
+                feature => {
+                  // transform back to prepare for usage
+                  var intersectingPolygon = feature
+                    .getGeometry()
+                    .clone()
+                    .transform("EPSG:3857", "EPSG:4326");
+                  const fairwayCoordinates = calculateFairwayCoordinates(
+                    profileLine,
+                    intersectingPolygon,
+                    DEMODATA
+                  );
+                  commit("setFairwayCoordinates", fairwayCoordinates);
+                  commit("application/showSplitscreen", true, { root: true });
+                  resolve();
+                }
+              );
+            })
+            .catch(error => {
+              const { status, data } = error.response;
+              displayError({
+                title: "Backend Error",
+                message: `${status ? status + ":" : ""} ${data.message || data}`
+              });
+            })
+            .finally(() => {
+              commit("profileLoading", false);
             });
-          })
-          .finally(() => {
-            commit("application/showSplitscreen", true, { root: true });
-            commit("profileLoading", false);
-          });
-      }
+        }
+      });
     },
     previousCuts({ commit, rootState }) {
       const previousCuts =
--- a/client/src/store/map.js	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/src/store/map.js	Mon Dec 03 13:08:24 2018 +0100
@@ -462,11 +462,17 @@
       });
       cutTool.setActive(false);
       cutTool.on("drawstart", () => {
+        dispatch("disableIdentifyTool");
         cutVectorSrc.clear();
       });
       cutTool.on("drawend", event => {
         commit("fairwayprofile/selectedCut", null, { root: true });
-        dispatch("fairwayprofile/cut", event.feature, { root: true });
+        dispatch("fairwayprofile/cut", event.feature, { root: true }).then(() =>
+          // This setTimeout is an ugly workaround. If we would enable the
+          // identifyTool here immediately then the click event from ending the
+          // cut will trigger it. We don't want that.
+          setTimeout(() => dispatch("enableIdentifyTool"), 1000)
+        );
       });
 
       map.addInteraction(lineTool);
@@ -480,70 +486,80 @@
     },
     disableIdentifyTool({ state }) {
       unByKey(state.identifyTool);
+      state.identifyTool = null;
     },
-    enableIdentifyTool({ state, commit, dispatch, getters }) {
-      state.identifyTool = state.openLayersMap.on(
-        ["singleclick", "dblclick"],
-        event => {
-          commit("setIdentifiedFeatures", []);
-          // checking our WFS layers
-          var features = state.openLayersMap.getFeaturesAtPixel(event.pixel);
-          if (features) {
-            commit("setIdentifiedFeatures", features);
+    enableIdentifyTool({ state, rootState, commit, dispatch, getters }) {
+      if (!state.identifyTool) {
+        state.identifyTool = state.openLayersMap.on(
+          ["singleclick", "dblclick"],
+          event => {
+            commit("setIdentifiedFeatures", []);
+            // checking our WFS layers
+            var features = state.openLayersMap.getFeaturesAtPixel(event.pixel);
+            if (features) {
+              commit("setIdentifiedFeatures", features);
 
-            // get selected bottleneck from identified features
-            for (let feature of features) {
-              let id = feature.getId();
-              // RegExp.prototype.test() works with number, str and undefined
-              if (/^bottlenecks\./.test(id)) {
-                dispatch(
-                  "bottlenecks/setSelectedBottleneck",
-                  feature.get("objnam"),
-                  { root: true }
-                );
-                commit("moveMap", {
-                  coordinates: getCenter(
-                    feature
-                      .getGeometry()
-                      .clone()
-                      .transform("EPSG:3857", "EPSG:4326")
-                      .getExtent()
-                  ),
-                  zoom: 17,
-                  preventZoomOut: true
-                });
+              // get selected bottleneck from identified features
+              for (let feature of features) {
+                let id = feature.getId();
+                // RegExp.prototype.test() works with number, str and undefined
+                if (/^bottlenecks\./.test(id)) {
+                  if (
+                    rootState.bottlenecks.selectedBottleneck !=
+                    feature.get("objnam")
+                  ) {
+                    dispatch(
+                      "bottlenecks/setSelectedBottleneck",
+                      feature.get("objnam"),
+                      { root: true }
+                    );
+                    commit("moveMap", {
+                      coordinates: getCenter(
+                        feature
+                          .getGeometry()
+                          .clone()
+                          .transform("EPSG:3857", "EPSG:4326")
+                          .getExtent()
+                      ),
+                      zoom: 17,
+                      preventZoomOut: true
+                    });
+                  }
+                }
               }
             }
-          }
+
+            // DEBUG output and example how to remove the GeometryName
+            /*
+            for (let feature of features) {
+              console.log("Identified:", feature.getId());
+              for (let key of feature.getKeys()) {
+                if (key != feature.getGeometryName()) {
+                  console.log(key, feature.get(key));
+                }
+              }
+            }
+            */
 
-          // DEBUG output and example how to remove the GeometryName
-          /*
-          for (let feature of features) {
-            console.log("Identified:", feature.getId());
-            for (let key of feature.getKeys()) {
-              if (key != feature.getGeometryName()) {
-                console.log(key, feature.get(key));
-              }
+            // trying the GetFeatureInfo way for WMS
+            var wmsSource = getters.getVSourceByName(
+              "Inland ECDIS chart Danube"
+            );
+            var url = wmsSource.getGetFeatureInfoUrl(
+              event.coordinate,
+              100 /* resolution */,
+              "EPSG:3857",
+              // { INFO_FORMAT: "application/vnd.ogc.gml" } // not allowed by d4d
+              { INFO_FORMAT: "text/plain" }
+            );
+
+            if (url) {
+              // cannot directly query here because of SOP
+              console.log("GetFeatureInfo url:", url);
             }
           }
-          */
-
-          // trying the GetFeatureInfo way for WMS
-          var wmsSource = getters.getVSourceByName("Inland ECDIS chart Danube");
-          var url = wmsSource.getGetFeatureInfoUrl(
-            event.coordinate,
-            100 /* resolution */,
-            "EPSG:3857",
-            // { INFO_FORMAT: "application/vnd.ogc.gml" } // not allowed by d4d
-            { INFO_FORMAT: "text/plain" }
-          );
-
-          if (url) {
-            // cannot directly query here because of SOP
-            console.log("GetFeatureInfo url:", url);
-          }
-        }
-      );
+        );
+      }
     }
   }
 };
--- a/client/vue.config.js	Fri Nov 30 12:50:18 2018 +0100
+++ b/client/vue.config.js	Mon Dec 03 13:08:24 2018 +0100
@@ -1,7 +1,4 @@
 const CopyWebpackPlugin = require("copy-webpack-plugin");
-const PurgecssPlugin = require("purgecss-webpack-plugin");
-const glob = require("glob-all");
-const path = require("path");
 
 module.exports = {
   outputDir: "../web",
@@ -13,22 +10,13 @@
       .use(CopyWebpackPlugin, [[{ from: vendorImgPath, to: "img" }]], {
         copyUnmodified: true
       });
-    config.plugin("PurgecssPlugin").use(PurgecssPlugin, [
-      {
-        paths: glob.sync([
-          path.join(__dirname, "./src/index.html"),
-          path.join(__dirname, "./**/*.vue"),
-          path.join(__dirname, "./src/**/*.js")
-        ])
-      }
-    ]);
   },
   css: {
     loaderOptions: {
       // pass options to sass-loader
       sass: {
         // @/ is an alias to src/
-        data: `@import "@/assets/application.sass";`
+        data: `@import "@/assets/application.scss";`
       }
     }
   },
--- a/docker/Dockerfile.spa	Fri Nov 30 12:50:18 2018 +0100
+++ b/docker/Dockerfile.spa	Mon Dec 03 13:08:24 2018 +0100
@@ -6,7 +6,7 @@
 RUN sed -i 's/\(deb.*\)$/\1 universe/' /etc/apt/sources.list
 
 RUN apt-get update &&\
-    apt-get -y install --no-install-recommends curl gnupg nodejs make
+    apt-get -y install --no-install-recommends curl gnupg nodejs make mercurial
 
 # Install yarn
 RUN curl https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - &&\
@@ -15,9 +15,10 @@
     apt-get update &&\
     apt-get -y install yarn
 
-COPY ./client /opt/gemma_spa
+COPY ./client /opt/gemma/client
+COPY ./.hg /opt/gemma/.hg
 
-WORKDIR /opt/gemma_spa
+WORKDIR /opt/gemma/client
 
 EXPOSE 8080
 
--- a/pkg/geoserver/boot.go	Fri Nov 30 12:50:18 2018 +0100
+++ b/pkg/geoserver/boot.go	Mon Dec 03 13:08:24 2018 +0100
@@ -29,10 +29,11 @@
 )
 
 const (
-	workspaceName  = "gemma"
-	datastoreName  = "gemma"
-	databaseScheme = "waterway"
-	databaseType   = "postgis"
+	workspaceName         = "gemma"
+	datastoreName         = "gemma"
+	databaseScheme        = "waterway"
+	databaseType          = "postgis"
+	primaryKeyMetadataTbl = "waterway.gt_pk_metadata"
 )
 
 const (
@@ -168,6 +169,7 @@
 					{"user", config.DBUser()},
 					{"passwd", config.DBPassword()},
 					{"dbtype", databaseType},
+					{"Primary key metadata table", primaryKeyMetadataTbl},
 					{"Session startup SQL", startupSQL},
 					{"Session close-up SQL", closeupSQL},
 				},
--- a/schema/gemma.sql	Fri Nov 30 12:50:18 2018 +0100
+++ b/schema/gemma.sql	Mon Dec 03 13:08:24 2018 +0100
@@ -327,6 +327,23 @@
                (location_code).hectometre
             FROM waterway.distance_marks_virtual
 
+    -- We need to configure primary keys for the views used by
+    -- geoserver for wfs, otherwise it will generate ids on the fly,
+    -- which will change for the same feature...
+    -- See
+    -- https://docs.geoserver.org/stable/en/user/data/database/primarykey.html
+    -- for details.
+    CREATE TABLE gt_pk_metadata (
+        table_schema VARCHAR(32) NOT NULL,
+        table_name VARCHAR(32) NOT NULL,
+        pk_column VARCHAR(32) NOT NULL,
+        pk_column_idx INTEGER,
+        pk_policy VARCHAR(32),
+        pk_sequence VARCHAR(64),
+        unique (table_schema, table_name, pk_column),
+        check (pk_policy in ('sequence', 'assigned', 'autogenerated'))
+    )
+
     CREATE TABLE sections_stretches (
         id varchar PRIMARY KEY,
         is_section boolean NOT NULL, -- maps 'function' from interface
@@ -526,6 +543,12 @@
     ORDER BY objnam
 ;
 
+-- Configure primary keys for geoserver views
+INSERT INTO waterway.gt_pk_metadata VALUES ('waterway',
+                                            'distance_marks_geoserver',
+                                            'location_code');
+
+
 --
 -- Import queue and respective logging
 --