changeset 2387:f185503ef35a

client: unified box's header styles by creating a reusable component The clients html/css and resulting look and feel of the app is partially very inconsistent. By moving code to more small and reusable components consistency will hopefully be increased.
author Markus Kottlaender <markus@intevation.de>
date Mon, 25 Feb 2019 15:02:34 +0100
parents 24e3e86b8cb6
children f27b005db9f5
files client/src/components/Bottlenecks.vue client/src/components/Contextbox.vue client/src/components/ImportApprovedGaugeMeasurement.vue client/src/components/ImportSoundingresults.vue client/src/components/ImportStretches.vue client/src/components/ImportWaterwayProfiles.vue client/src/components/Logs.vue client/src/components/Pdftool.vue client/src/components/Popup.vue client/src/components/fairway/Profiles.vue client/src/components/identify/Identify.vue client/src/components/importqueue/Importqueue.vue client/src/components/importschedule/Importschedule.vue client/src/components/importschedule/Importscheduledetail.vue client/src/components/layers/Layers.vue client/src/components/staging/Staging.vue client/src/components/systemconfiguration/Systemconfiguration.vue client/src/components/ui/box/Header.vue client/src/components/usermanagement/Userdetail.vue client/src/components/usermanagement/Usermanagement.vue client/src/main.js
diffstat 21 files changed, 119 insertions(+), 170 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Bottlenecks.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/Bottlenecks.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -1,9 +1,10 @@
 <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>
-    </h6>
+    <UIBoxHeader
+      icon="ship"
+      title="Bottlenecks"
+      :closeCallback="$parent.close"
+    />
     <div class="row p-2 text-left small">
       <div class="col-5">
         <a href="#" @click="sortBy('name')" class="sort-link">
--- a/client/src/components/Contextbox.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/Contextbox.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -1,8 +1,5 @@
 <template>
   <div :class="style">
-    <div @click="close" class="ui-element close-contextbox text-muted">
-      <font-awesome-icon icon="times" class="pointer"></font-awesome-icon>
-    </div>
     <Bottlenecks v-if="contextBoxContent === 'bottlenecks'"></Bottlenecks>
     <Staging v-if="contextBoxContent === 'staging'"></Staging>
     <Stretches v-if="contextBoxContent === 'stretches'"></Stretches>
--- a/client/src/components/ImportApprovedGaugeMeasurement.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/ImportApprovedGaugeMeasurement.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -2,14 +2,7 @@
   <div class="d-flex flex-row">
     <Spacer></Spacer>
     <div class="card sysconfig mt-3 shadow-xs w-100 h-100 mr-3">
-      <h6
-        class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center"
-      >
-        <font-awesome-icon icon="upload" class="mr-2"></font-awesome-icon>
-        <translate class="headline"
-          >Import approved gaugemeasurements</translate
-        >
-      </h6>
+      <UIBoxHeader icon="upload" title="Import approved gaugemeasurements" />
       <div class="card-body stretches-card">
         <div class="w-95 ml-auto mr-auto mt-4 mb-4">
           <div class="d-flex flex-column text-left w-25">
--- a/client/src/components/ImportSoundingresults.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/ImportSoundingresults.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -3,12 +3,7 @@
     <div class="d-flex flex-row">
       <Spacer></Spacer>
       <div class="card shadow-xs mt-3 mr-3 w-100 importsoundingresultscard">
-        <h6
-          class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center"
-        >
-          <font-awesome-icon icon="upload" class="mr-2"></font-awesome-icon>
-          <translate class="headline">Import Soundingresults</translate>
-        </h6>
+        <UIBoxHeader icon="upload" title="Import Soundingresults" />
         <div v-if="editState" class="ml-auto mr-auto mt-4 w-95">
           <div class="d-flex flex-column">
             <div class="d-flex flex-row">
--- a/client/src/components/ImportStretches.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/ImportStretches.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -1,9 +1,10 @@
 <template>
   <div class="d-flex flex-column mb-3">
-    <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
-      <font-awesome-icon icon="road" class="mr-2"></font-awesome-icon>
-      <translate>Define stretches</translate>
-    </h6>
+    <UIBoxHeader
+      icon="road"
+      title="Define Stretches"
+      :closeCallback="$parent.close"
+    />
     <div v-if="!edit" class="mb-3 mr-3 ml-3 text-left">
       <table v-if="stretches.length > 0" class="table">
         <thead>
--- a/client/src/components/ImportWaterwayProfiles.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/ImportWaterwayProfiles.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -2,12 +2,7 @@
   <div class="d-flex flex-row">
     <Spacer></Spacer>
     <div class="card sysconfig mt-3 shadow-xs w-100 h-100 mr-3">
-      <h6
-        class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center"
-      >
-        <font-awesome-icon icon="upload" class="mr-2"></font-awesome-icon>
-        <translate class="headline">Import Waterwayprofiles</translate>
-      </h6>
+      <UIBoxHeader icon="upload" title="Import Waterway Profiles" />
       <div class="card-body stretches-card">
         <div class="w-95 ml-auto mr-auto mt-4 mb-4">
           <div class="mb-4">
--- a/client/src/components/Logs.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/Logs.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -3,12 +3,7 @@
     <div class="d-flex flex-row">
       <Spacer></Spacer>
       <div class="card logs shadow-xs mt-3 mr-3">
-        <h6
-          class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center"
-        >
-          <font-awesome-icon class="mr-2 fa-fw" icon="book"></font-awesome-icon>
-          <translate class="headline">Logs</translate>
-        </h6>
+        <UIBoxHeader icon="book" title="Logs" />
         <div class="logoutput text-left bg-white">
           <pre id="code" v-highlightjs="logs">
           <code class="bash hljs hljs-string"></code>
--- a/client/src/components/Pdftool.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/Pdftool.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -6,15 +6,11 @@
     ]"
   >
     <div style="width: 18rem">
-      <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
-        <font-awesome-icon icon="file-pdf" class="mr-2"></font-awesome-icon>
-        <translate>Generate PDF</translate>
-        <font-awesome-icon
-          icon="times"
-          class="ml-auto text-muted pointer"
-          @click="$store.commit('application/showPdfTool', false)"
-        ></font-awesome-icon>
-      </h6>
+      <UIBoxHeader
+        icon="file-pdf"
+        title="Generate PDF"
+        :closeCallback="close"
+      />
       <div class="p-3 text-left">
         <select
           @change="applyTemplateToForm"
@@ -199,6 +195,9 @@
     }
   },
   methods: {
+    close() {
+      this.$store.commit("application/showPdfTool", false);
+    },
     // When a template is chosen from the dropdown, its propoerties are
     // applied to the rest of the form.
     applyTemplateToForm() {
--- a/client/src/components/Popup.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/Popup.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -5,15 +5,11 @@
       v-if="popup"
     >
       <div class="popup">
-        <h6 class="popup-header">
-          <span class="popup-title">
-            <font-awesome-icon :icon="popup.icon" class="popup-icon" />
-            {{ popup.title }}
-          </span>
-          <span class="popup-close" @click="close()">
-            <font-awesome-icon icon="times" />
-          </span>
-        </h6>
+        <UIBoxHeader
+          :icon="popup.icon"
+          :title="popup.title"
+          :closeCallback="close"
+        />
         <div class="popup-content" v-html="popup.content"></div>
         <div class="popup-footer" v-if="popup.cancel || popup.confirm">
           <button
--- a/client/src/components/fairway/Profiles.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/fairway/Profiles.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -6,15 +6,7 @@
     ]"
   >
     <div style="width: 18rem">
-      <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
-        <font-awesome-icon icon="chart-area" class="mr-2"></font-awesome-icon>
-        <translate>Profiles</translate>
-        <font-awesome-icon
-          icon="times"
-          class="ml-auto text-muted pointer"
-          @click="$store.commit('application/showProfiles', false)"
-        ></font-awesome-icon>
-      </h6>
+      <UIBoxHeader icon="chart-area" title="Profiles" :closeCallback="close" />
       <div
         class="d-flex flex-column p-3 flex-grow-1 text-left position-relative"
       >
@@ -358,6 +350,9 @@
     }
   },
   methods: {
+    close() {
+      this.$store.commit("application/showProfiles", false);
+    },
     formatSurveyDate(date) {
       return formatSurveyDate(date);
     },
--- a/client/src/components/identify/Identify.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/identify/Identify.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -6,15 +6,7 @@
     ]"
   >
     <div style="width: 18rem">
-      <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
-        <font-awesome-icon icon="info" class="mr-2"></font-awesome-icon>
-        <translate>Identified</translate>
-        <font-awesome-icon
-          icon="times"
-          class="ml-auto text-muted"
-          @click="$store.commit('application/showIdentify', false)"
-        ></font-awesome-icon>
-      </h6>
+      <UIBoxHeader icon="info" title="Identified" :closeCallback="close" />
       <div class="features flex-grow-1 text-left">
         <div v-if="currentMeasurement">
           <small class="d-block bg-dark text-light text-center px-2 py-1">
@@ -129,6 +121,9 @@
     ...mapState("map", ["currentMeasurement"])
   },
   methods: {
+    close() {
+      this.$store.commit("application/showIdentify", false);
+    },
     featureId(feature) {
       // cut away everything from the last . to the end
       return feature.getId().replace(/[.][^.]*$/, "");
--- a/client/src/components/importqueue/Importqueue.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/importqueue/Importqueue.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -3,12 +3,7 @@
     <Spacer></Spacer>
     <div class="mt-3 importqueuecard flex-grow-1">
       <div class="card 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>
+        <UIBoxHeader icon="tasks" title="Importqueue" />
         <div class="card-body importcardbody">
           <div class="card-body importcardbody">
             <div class="searchandfilter d-flex flex-row">
--- a/client/src/components/importschedule/Importschedule.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/importschedule/Importschedule.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -3,12 +3,7 @@
     <Spacer></Spacer>
     <div class="mt-3 w-100">
       <div class="card flex-grow-1 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">Imports</translate>
-        </h6>
+        <UIBoxHeader icon="clock" title="Imports" />
         <div class="card-body schedulecardbody">
           <div class="card-body schedulecardbody">
             <div class="searchandfilter mb-3  w-50 d-flex flex-row">
--- a/client/src/components/importschedule/Importscheduledetail.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/importschedule/Importscheduledetail.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -4,14 +4,7 @@
     v-if="importScheduleDetailVisible"
   >
     <div class="card shadow-xs importscheduledetailscard pb-5">
-      <h6
-        class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center"
-      >
-        {{ dialogLabel }}
-        <span @click="closeDetailview" class="closebutton">
-          <font-awesome-icon icon="times" class="pointer"></font-awesome-icon>
-        </span>
-      </h6>
+      <UIBoxHeader :title="dialogLabel" :closeCallback="closeDetailview" />
       <div class="card-body">
         <form @submit.prevent="save" class="ml-2 mr-2">
           <div class="d-flex flex-row">
--- a/client/src/components/layers/Layers.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/layers/Layers.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -6,15 +6,7 @@
     ]"
   >
     <div style="width: 18rem">
-      <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
-        <font-awesome-icon icon="layer-group" class="mr-2"></font-awesome-icon
-        ><translate>Layers</translate>
-        <font-awesome-icon
-          icon="times"
-          class="ml-auto text-muted pointer"
-          @click="$store.commit('application/showLayers', false)"
-        ></font-awesome-icon>
-      </h6>
+      <UIBoxHeader icon="layer-group" title="Layers" :closeCallback="close" />
       <div class="d-flex flex-column p-3 small">
         <Layerselect
           v-for="(layer, index) in layersForLegend"
@@ -55,6 +47,9 @@
     ...mapState("application", ["showLayers"])
   },
   methods: {
+    close() {
+      this.$store.commit("application/showLayers", false);
+    },
     visibilityToggled(layer) {
       this.$store.commit("map/toggleVisibility", layer);
     }
--- a/client/src/components/staging/Staging.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/staging/Staging.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -1,12 +1,10 @@
 <template>
   <div class="w-90 stagingcard">
-    <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
-      <font-awesome-icon
-        class="mr-2"
-        icon="clipboard-check"
-      ></font-awesome-icon>
-      <translate>Staging Area</translate>
-    </h6>
+    <UIBoxHeader
+      icon="clipboard-check"
+      title="Staging Area"
+      :closeCallback="$parent.close"
+    />
     <div class="mt-3 pl-3 pr-3">
       <div class="mt-3 text-left flex-row d-flex border-bottom">
         <div class="header text-left name"><translate>Name</translate></div>
--- a/client/src/components/systemconfiguration/Systemconfiguration.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/systemconfiguration/Systemconfiguration.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -2,12 +2,7 @@
   <div class="d-flex flex-row">
     <Spacer></Spacer>
     <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>
+      <UIBoxHeader icon="wrench" title="Systemconfiguration" />
       <div class="card-body text-left">
         <PDFTemplates />
         <ColorSettings v-if="isSysAdmin" />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/ui/box/Header.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -0,0 +1,63 @@
+<template>
+  <h6 class="popup-header">
+    <span class="popup-title">
+      <font-awesome-icon
+        :icon="icon"
+        class="popup-icon"
+        v-if="icon"
+        fixed-width
+      />
+      {{ $gettext(title) }}
+    </span>
+    <span class="popup-close" @click="closeCallback" v-if="closeCallback">
+      <font-awesome-icon icon="times" />
+    </span>
+  </h6>
+</template>
+
+<style lang="sass">
+.popup-header
+  display: flex
+  justify-content: space-between
+  align-items: center
+  min-height: 35px
+  padding-left: .5rem
+  border-bottom: 1px solid #dee2e6
+  color: $color-info
+  margin-bottom: 0
+  padding: 0.25rem
+  font-weight: bold
+  .popup-title
+    padding-left: 0.25rem
+    .popup-icon
+      margin-right: 0.25rem
+  .popup-close
+    color: #888
+    padding: 3px 7px
+    border-radius: 0.25rem
+    cursor: pointer
+    transition: background-color 0.3s, color 0.3s
+    &:hover
+      color: #666
+      background-color: #eee
+</style>
+
+<script>
+/* 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):
+ * Markus Kottländer <markus.kottlaender@intevation.de>
+ */
+
+export default {
+  props: ["icon", "title", "closeCallback"]
+};
+</script>
--- a/client/src/components/usermanagement/Userdetail.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/usermanagement/Userdetail.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -1,13 +1,10 @@
 <template>
   <div class="userdetails shadow-xs fadeIn animated card">
-    <h6
-      class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center"
-    >
-      {{ this.cardHeader }}
-      <span @click="closeDetailview" class="closebutton">
-        <font-awesome-icon icon="times" class="pointer"></font-awesome-icon>
-      </span>
-    </h6>
+    <UIBoxHeader
+      icon="user"
+      :title="this.cardHeader"
+      :closeCallback="closeDetailview"
+    />
     <div class="card-body">
       <form @submit.prevent="save" class="ml-3">
         <div class="formfields">
--- a/client/src/components/usermanagement/Usermanagement.vue	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/components/usermanagement/Usermanagement.vue	Mon Feb 25 15:02:34 2019 +0100
@@ -4,15 +4,7 @@
     <div class="d-flex content py-3">
       <div :class="userlistStyle">
         <div class="card shadow-xs">
-          <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 fa-fw"
-            ></font-awesome-icon>
-            <translate class="headline">Users</translate>
-          </h6>
+          <UIBoxHeader icon="users-cog" title="Users" />
           <div class="card-body">
             <table id="datatable" :class="tableStyle">
               <thead>
@@ -115,44 +107,6 @@
       </div>
       <Userdetail v-if="isUserDetailsVisible"></Userdetail>
     </div>
-
-    <div
-      :class="[
-        'box popup ui-element rounded bg-white',
-        { show: showDeleteUserPrompt }
-      ]"
-    >
-      <div>
-        <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
-          <font-awesome-icon icon="trash" class="mr-2"></font-awesome-icon>
-          <translate>Delete user</translate>
-          <font-awesome-icon
-            icon="times"
-            class="ml-auto text-muted pointer"
-            @click="showDeleteUserPrompt = false"
-          ></font-awesome-icon>
-        </h6>
-        <div class="p-3 text-left">
-          <translate class="text-center d-block"
-            >Do you really want to delete the following user account:</translate
-          >
-          <h5 class="mt-3 text-center">{{ userToDelete }}</h5>
-        </div>
-        <div
-          class="py-2 px-3 border-top d-flex align-items-center justify-content-between"
-        >
-          <button
-            class="btn btn-sm btn-warning"
-            @click="showDeleteUserPrompt = false"
-          >
-            no
-          </button>
-          <button class="btn btn-sm btn-info" @click="deleteUser(userToDelete)">
-            yes
-          </button>
-        </div>
-      </div>
-    </div>
   </div>
 </template>
 
--- a/client/src/main.js	Mon Feb 25 14:30:31 2019 +0100
+++ b/client/src/main.js	Mon Feb 25 15:02:34 2019 +0100
@@ -29,6 +29,7 @@
 import store from "./store";
 import translations from "./locale/translations.json";
 import { supportedLanguages, defaultLanguage } from "./locale/languages.js";
+import Header from "@/components/ui/box/Header";
 
 // styles
 import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
@@ -153,6 +154,7 @@
 
 // register global components
 Vue.component("font-awesome-icon", FontAwesomeIcon);
+Vue.component("UIBoxHeader", Header);
 
 // global vue config
 Vue.config.productionTip = false;