comparison client/src/components/Bottlenecks.vue @ 1558:0ded4c56978e

refac: component filestructure. remove admin/map hierarchy
author Thomas Junk <thomas.junk@intevation.de>
date Wed, 12 Dec 2018 09:22:20 +0100
parents client/src/components/map/contextbox/Bottlenecks.vue@276df8dadc14
children 70421380142d
comparison
equal deleted inserted replaced
1557:62171cd9a42b 1558:0ded4c56978e
1 <template>
2 <div>
3 <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
4 <font-awesome-icon icon="ship" class="mr-2"></font-awesome-icon>
5 <translate>Bottlenecks</translate>
6 </h6>
7 <div class="row p-2 text-left small">
8 <div class="col-5">
9 <a href="#" @click="sortBy('name')" class="sort-link">
10 <translate>Name</translate>
11 </a>
12 <font-awesome-icon
13 :icon="sortIcon"
14 class="ml-1"
15 v-if="sortColumn === 'name'"
16 ></font-awesome-icon>
17 </div>
18 <div class="col-2">
19 <a href="#" @click="sortBy('latestMeasurement')" class="sort-link">
20 <translate>Latest</translate> <br />
21 <translate>Measurement</translate>
22 </a>
23 <font-awesome-icon
24 :icon="sortIcon"
25 class="ml-1"
26 v-if="sortColumn === 'latestMeasurement'"
27 ></font-awesome-icon>
28 </div>
29 <div class="col-3">
30 <a href="#" @click="sortBy('chainage')" class="sort-link">
31 <translate>Chainage</translate>
32 </a>
33 <font-awesome-icon
34 :icon="sortIcon"
35 class="ml-1"
36 v-if="sortColumn === 'chainage'"
37 ></font-awesome-icon>
38 </div>
39 <div class="col-2"></div>
40 </div>
41 <div
42 class="bottleneck-list small text-left"
43 :style="'max-height: ' + (showSplitscreen ? 18 : 35) + 'rem'"
44 v-if="filteredAndSortedBottlenecks().length"
45 >
46 <div
47 v-for="bottleneck in filteredAndSortedBottlenecks()"
48 :key="bottleneck.properties.name"
49 class="border-top row bottleneck-row mx-0"
50 >
51 <div class="col-5 py-2 text-left">
52 <a href="#" @click="selectBottleneck(bottleneck)">{{
53 bottleneck.properties.name
54 }}</a>
55 </div>
56 <div class="col-2 py-2">
57 {{ formatSurveyDate(bottleneck.properties.current) }}
58 </div>
59 <div class="col-3 py-2">
60 {{
61 displayCurrentChainage(
62 bottleneck.properties.from,
63 bottleneck.properties.to
64 )
65 }}
66 </div>
67 <div class="col-2 pr-0 text-right">
68 <button
69 type="button"
70 class="btn btn-sm btn-info rounded-0 h-100"
71 @click="loadSurveys(bottleneck.properties.name)"
72 v-if="bottleneck.properties.current"
73 >
74 <font-awesome-icon
75 icon="spinner"
76 fixed-width
77 spin
78 v-if="loading === bottleneck.properties.name"
79 ></font-awesome-icon>
80 <font-awesome-icon
81 icon="angle-down"
82 fixed-width
83 v-if="
84 loading !== bottleneck.properties.name &&
85 openBottleneck !== bottleneck.properties.name
86 "
87 ></font-awesome-icon>
88 <font-awesome-icon
89 icon="angle-up"
90 fixed-width
91 v-if="
92 loading !== bottleneck.properties.name &&
93 openBottleneck === bottleneck.properties.name
94 "
95 ></font-awesome-icon>
96 </button>
97 </div>
98 <div
99 :class="[
100 'col-12 p-0',
101 'surveys',
102 { open: openBottleneck === bottleneck.properties.name }
103 ]"
104 >
105 <a
106 href="#"
107 class="d-block px-3 py-2"
108 v-for="(survey, index) in openBottleneckSurveys"
109 :key="index"
110 @click="selectSurvey(survey, bottleneck)"
111 >{{ formatSurveyDate(survey.date_info) }}</a
112 >
113 </div>
114 </div>
115 </div>
116 <div v-else class="small text-center py-3 border-top">
117 <translate>No results.</translate>
118 </div>
119 </div>
120 </template>
121
122 <script>
123 /* This is Free Software under GNU Affero General Public License v >= 3.0
124 * without warranty, see README.md and license for details.
125 *
126 * SPDX-License-Identifier: AGPL-3.0-or-later
127 * License-Filename: LICENSES/AGPL-3.0.txt
128 *
129 * Copyright (C) 2018 by via donau
130 * – Österreichische Wasserstraßen-Gesellschaft mbH
131 * Software engineering by Intevation GmbH
132 *
133 * Author(s):
134 * Markus Kottländer <markus.kottlaender@intevation.de>
135 */
136 import { mapState } from "vuex";
137 import { HTTP } from "../lib/http";
138 import { displayError } from "../lib/errors.js";
139 import { formatSurveyDate } from "../lib/date.js";
140
141 export default {
142 name: "bottlenecks",
143 data() {
144 return {
145 sortColumn: "name",
146 sortDirection: "ASC",
147 openBottleneck: null,
148 openBottleneckSurveys: null,
149 loading: null
150 };
151 },
152 computed: {
153 ...mapState("application", [
154 "searchQuery",
155 "showSearchbarLastState",
156 "showSplitscreen"
157 ]),
158 ...mapState("bottlenecks", ["bottlenecks"]),
159 sortIcon() {
160 return this.sortDirection === "ASC"
161 ? "sort-amount-down"
162 : "sort-amount-up";
163 }
164 },
165 methods: {
166 formatSurveyDate(date) {
167 return formatSurveyDate(date);
168 },
169 filteredAndSortedBottlenecks() {
170 return this.bottlenecks
171 .filter(bn => {
172 return bn.properties.name
173 .toLowerCase()
174 .includes(this.searchQuery.toLowerCase());
175 })
176 .sort((bnA, bnB) => {
177 switch (this.sortColumn) {
178 case "name":
179 if (
180 bnA.properties.name.toLowerCase() <
181 bnB.properties.name.toLowerCase()
182 )
183 return this.sortDirection === "ASC" ? -1 : 1;
184 if (
185 bnA.properties.name.toLowerCase() >
186 bnB.properties.name.toLowerCase()
187 )
188 return this.sortDirection === "ASC" ? 1 : -1;
189 return 0;
190
191 case "latestMeasurement": {
192 if (
193 (bnA.properties.current || "") < (bnB.properties.current || "")
194 )
195 return this.sortDirection === "ASC" ? -1 : 1;
196 if (
197 (bnA.properties.current || "") > (bnB.properties.current || "")
198 )
199 return this.sortDirection === "ASC" ? 1 : -1;
200 return 0;
201 }
202
203 case "chainage":
204 if (bnA.properties.from < bnB.properties.from)
205 return this.sortDirection === "ASC" ? -1 : 1;
206 if (bnA.properties.from > bnB.properties.from)
207 return this.sortDirection === "ASC" ? 1 : -1;
208 return 0;
209
210 default:
211 return 0;
212 }
213 });
214 },
215 selectSurvey(survey, bottleneck) {
216 this.$store
217 .dispatch(
218 "bottlenecks/setSelectedBottleneck",
219 bottleneck.properties.name
220 )
221 .then(() => {
222 this.$store.commit("bottlenecks/selectedSurvey", survey);
223 })
224 .then(() => {
225 this.$store.commit("map/moveMap", {
226 coordinates: bottleneck.geometry.coordinates,
227 zoom: 17,
228 preventZoomOut: true
229 });
230 });
231 },
232 selectBottleneck(bottleneck) {
233 this.$store
234 .dispatch(
235 "bottlenecks/setSelectedBottleneck",
236 bottleneck.properties.name
237 )
238 .then(() => {
239 this.$store.commit("bottlenecks/setFirstSurveySelected");
240 })
241 .then(() => {
242 this.$store.commit("map/moveMap", {
243 coordinates: bottleneck.geometry.coordinates,
244 zoom: 17,
245 preventZoomOut: true
246 });
247 });
248 },
249 sortBy(column) {
250 this.sortColumn = column;
251 this.sortDirection = this.sortDirection === "ASC" ? "DESC" : "ASC";
252 },
253 loadSurveys(name) {
254 this.openBottleneckSurveys = null;
255 if (name === this.openBottleneck) {
256 this.openBottleneck = null;
257 } else {
258 this.openBottleneck = name;
259 this.loading = name;
260
261 HTTP.get("/surveys/" + name, {
262 headers: {
263 "X-Gemma-Auth": localStorage.getItem("token"),
264 "Content-type": "text/xml; charset=UTF-8"
265 }
266 })
267 .then(response => {
268 this.openBottleneckSurveys = response.data.surveys.sort((a, b) => {
269 return a.date_info < b.date_info ? 1 : -1;
270 });
271 })
272 .catch(error => {
273 const { status, data } = error.response;
274 displayError({
275 title: this.$gettext("Backend Error"),
276 message: `${status}: ${data.message || data}`
277 });
278 })
279 .finally(() => (this.loading = null));
280 }
281 },
282 displayCurrentChainage(from, to) {
283 return from / 10 + " - " + to / 10;
284 }
285 },
286 mounted() {
287 this.$store.dispatch("bottlenecks/loadBottlenecks");
288 }
289 };
290 </script>
291
292 <style lang="scss" scoped>
293 .bottleneck-list {
294 overflow-y: auto;
295 }
296
297 .bottleneck-list .bottleneck-row a {
298 text-decoration: none;
299 }
300
301 .bottleneck-list .bottleneck-row:hover {
302 background: #fbfbfb;
303 }
304
305 .surveys {
306 max-height: 0;
307 min-height: 0;
308 overflow: hidden;
309 }
310
311 .surveys a:hover {
312 background: #f3f3f3;
313 }
314
315 .surveys.open {
316 max-height: 250px;
317 overflow: auto;
318 }
319
320 .sort-link {
321 color: #444;
322 font-weight: bold;
323 }
324 </style>