comparison client/src/components/importoverview/ImportOverview.vue @ 2559:d9e1db955d49

Backed out changeset 91c68153e7b6
author Thomas Junk <thomas.junk@intevation.de>
date Fri, 08 Mar 2019 13:36:24 +0100
parents 91c68153e7b6
children 0d2650dd8f62
comparison
equal deleted inserted replaced
2557:91c68153e7b6 2559:d9e1db955d49
3 <UIBoxHeader 3 <UIBoxHeader
4 icon="clipboard-check" 4 icon="clipboard-check"
5 title="Staging Area" 5 title="Staging Area"
6 :closeCallback="$parent.close" 6 :closeCallback="$parent.close"
7 /> 7 />
8 <div class="imports text-left ml-1 mr-1"> 8 <div class="d-flex flex-row w-100 justify-content-end">
9 <div class="mt-3 d-flex flex-row border-bottom"> 9 <button
10 <div class="icons small condensed">&nbsp;</div> 10 class="btn btn-sm btn-outline-info align-self-start mr-3"
11 <div class="id small condensed">Id</div> 11 @click="refresh"
12 <div class="kind small condensed">Kind</div> 12 >
13 <div class="date small condensed"> 13 <font-awesome-icon icon="redo"></font-awesome-icon>
14 Date 14 </button>
15 </div> 15 </div>
16 <div class="enqueued small condensed"> 16 <div class="d-flex flex-row w-100 border-bottom">
17 Imported 17 <font-awesome-icon
18 </div> 18 class="pointer"
19 <div class="user small condensed">User</div> 19 @click="toggleStaging()"
20 <div class="state small condensed">State</div> 20 v-if="stagingVisible && staging.length > 0"
21 <div class="actions small condensed">&nbsp;</div> 21 icon="angle-up"
22 fixed-width
23 ></font-awesome-icon>
24 <font-awesome-icon
25 class="pointer"
26 @click="toggleStaging()"
27 v-if="!stagingVisible && staging.length > 0"
28 icon="angle-down"
29 fixed-width
30 ></font-awesome-icon>
31 <span style="width:1.25em;" v-if="!(staging.length > 0)"></span>
32 <Staging v-if="stagingVisible && staging.length > 0"></Staging>
33 <div v-else class="d-flex flex-row">
34 <h6>
35 <small><translate>Review</translate></small>
36 </h6>
37 <small class="ml-3" v-if="!(staging.length > 0)"
38 ><translate>Nothing to review</translate></small
39 >
22 </div> 40 </div>
23 <div class="d-flex flex-row" v-for="entry in importQueue" :key="entry.id"> 41 </div>
24 <div class="d-flex flex-column w-100"> 42 <div class="mt-2">
25 <div class="d-flex flex-row"> 43 <div class="d-flex flex-row">
26 <div class="icons"> 44 <font-awesome-icon
27 <font-awesome-icon 45 class="pointer"
28 @click="toggleDetails(entry.id)" 46 @click="toggleLogs()"
29 class="pointer text-info" 47 v-if="logsVisible"
30 v-if="show != entry.id" 48 icon="angle-up"
31 icon="angle-right" 49 fixed-width
32 fixed-width 50 ></font-awesome-icon>
33 ></font-awesome-icon> 51 <font-awesome-icon
34 <font-awesome-icon 52 class="pointer"
35 @click="toggleDetails(entry.id)" 53 @click="toggleLogs()"
36 class="pointer text-info" 54 v-if="!logsVisible"
37 v-if="show == entry.id" 55 icon="angle-down"
38 icon="angle-down" 56 fixed-width
39 fixed-width 57 ></font-awesome-icon>
40 ></font-awesome-icon> 58 <Logs v-if="logsVisible" :reload="reload"></Logs>
41 </div> 59 <div v-else>
42 <div class="id small condensed">{{ entry.id }}</div> 60 <h6>
43 <div class="kind small condensed"> 61 <small><translate>Logs</translate></small>
44 {{ entry.kind.toUpperCase() }} 62 </h6>
45 </div>
46 <div class="date small condensed">
47 {{ entry.summary.date | surveyDate }}
48 </div>
49 <div class="enqueued small condensed">
50 {{ entry.enqueued.split("T")[0] | surveyDate }}
51 </div>
52 <div class="user small condensed">{{ entry.user }}</div>
53 <div class="state small condensed">
54 {{ entry.state }}
55 </div>
56 <div class="actions small condensed">
57 <font-awesome-icon
58 v-if="entry.warnings"
59 class="ml-1 text-warning text-info"
60 icon="exclamation-triangle"
61 fixed-width
62 ></font-awesome-icon>
63 <font-awesome-icon
64 v-if="!entry.warnings"
65 class="ml-1 text-white"
66 icon="exclamation-triangle"
67 fixed-width
68 ></font-awesome-icon>
69 <font-awesome-icon
70 class="ml-1 text-mute"
71 icon="check"
72 fixed-width
73 ></font-awesome-icon>
74 <font-awesome-icon
75 class="ml-1 text-mute"
76 icon="times"
77 fixed-width
78 ></font-awesome-icon>
79 </div>
80 </div>
81 <div class="d-flex flex-row" v-if="show == entry.id">
82 <div class="ml-1 details d-flex flex-column">
83 <div
84 v-if="isApprovedGaugeMeasurement(entry.kind.toUpperCase())"
85 class="d-flex flex-row"
86 >
87 <font-awesome-icon
88 @click="toggleAdditional(entry.id)"
89 class="pointer text-info"
90 v-if="showAdditional != entry.id"
91 icon="angle-right"
92 fixed-width
93 ></font-awesome-icon>
94 <font-awesome-icon
95 @click="toggleAdditional(entry.id)"
96 class="pointer text-info"
97 v-if="showAdditional == entry.id"
98 icon="angle-down"
99 fixed-width
100 ></font-awesome-icon>
101 <small class="condensed">Additional Info</small>
102 </div>
103 <div
104 v-if="showAdditional == entry.id"
105 class="additionalinfo ml-4"
106 >
107 <div v-for="(result, index) in entry.summary" :key="index">
108 <font-awesome-icon
109 @click="toggleDiff(index)"
110 class="pointer text-info"
111 v-if="showDiff != index"
112 icon="angle-right"
113 fixed-width
114 ></font-awesome-icon>
115 <font-awesome-icon
116 @click="toggleDiff(index)"
117 class="pointer text-info"
118 v-if="showDiff == index"
119 icon="angle-down"
120 fixed-width
121 ></font-awesome-icon>
122 <span
123 v-if="result.versions.length == 1"
124 class="agmcode text-left"
125 ><small
126 >{{ result["fk-gauge-id"] }}
127 <translate class="mr-1">( New )</translate></small
128 ></span
129 >
130 <span
131 v-if="result.versions.length == 2"
132 class="agmcode text-left"
133 ><small>{{ result["fk-gauge-id"] }}</small></span
134 >
135 <span class="agmdetail text-left"
136 ><small>{{
137 result["measure-date"] | datetime
138 }}</small></span
139 >
140 <div v-if="showDiff == index" class="ml-1">
141 <div>
142 <div class="d-flex flex-row pl-3 text-left">
143 <div class="header border-bottom agmdetailskeys">
144 <small><translate>Value</translate></small>
145 </div>
146 <div
147 v-if="result.versions.length == 2"
148 class="header border-bottom agmdetailsvalues"
149 >
150 <small><translate>Old</translate></small>
151 </div>
152 <div class="header border-bottom agmdetailsvalues">
153 <small><translate>New</translate></small>
154 </div>
155 </div>
156 <div
157 class="d-flex flex-row pl-3 text-left"
158 v-for="(entry, index) in Object.keys(
159 result.versions[0]
160 )"
161 :key="index"
162 >
163 <div
164 v-if="
165 result.versions.length == 1 ||
166 result.versions[0][entry] !=
167 result.versions[1][entry]
168 "
169 class="agmdetailskeys"
170 >
171 <small>{{ entry }}</small>
172 </div>
173 <div
174 v-if="
175 result.versions.length == 1 ||
176 result.versions[0][entry] !=
177 result.versions[1][entry]
178 "
179 class="agmdetailsvalues"
180 >
181 <small>{{ result.versions[0][entry] }}</small>
182 </div>
183 <div
184 v-if="
185 result.versions.length == 2 &&
186 result.versions[0][entry] !=
187 result.versions[1][entry]
188 "
189 class="agmdetailsvalues"
190 >
191 <small>{{ result.versions[1][entry] }}</small>
192 </div>
193 </div>
194 </div>
195 </div>
196 </div>
197 </div>
198 <div class="d-flex flex-row">
199 <div class="d-flex flex-column">
200 <div class="d-flex flex-row">
201 <font-awesome-icon
202 @click="toggleLogs(entry.id)"
203 class="pointer text-info"
204 v-if="showLogs != entry.id"
205 icon="angle-right"
206 fixed-width
207 ></font-awesome-icon>
208 <font-awesome-icon
209 @click="toggleLogs(entry.id)"
210 class="pointer text-info"
211 v-if="showLogs == entry.id"
212 icon="angle-down"
213 fixed-width
214 ></font-awesome-icon>
215 <small class="condensed">Logs</small>
216 </div>
217 <div v-if="showLogs == entry.id" class="ml-4 logentries">
218 <div
219 v-for="(logentry, index) in logEntries"
220 :key="index"
221 class="d-flex flex-row"
222 >
223 <small
224 :class="[
225 'condensed type',
226 {
227 'text-danger':
228 logentry.kind.toUpperCase() == 'ERROR',
229 'text-warning':
230 logentry.kind.toUpperCase() == 'WARN'
231 }
232 ]"
233 >{{ logentry.kind.toUpperCase() }}</small
234 >
235 <small
236 :class="[
237 'condensed type',
238 {
239 'text-danger':
240 logentry.kind.toUpperCase() == 'ERROR',
241 'text-warning':
242 logentry.kind.toUpperCase() == 'WARN'
243 }
244 ]"
245 >{{ logentry.time }}</small
246 >
247 <small
248 :class="[
249 'condensed type',
250 {
251 'text-danger':
252 logentry.kind.toUpperCase() == 'ERROR',
253 'text-warning':
254 logentry.kind.toUpperCase() == 'WARN'
255 }
256 ]"
257 >{{ logentry.message }}</small
258 >
259 </div>
260 </div>
261 </div>
262 </div>
263 </div>
264 </div>
265 </div> 63 </div>
266 </div> 64 </div>
267 </div> 65 </div>
268 </div> 66 </div>
269 </template> 67 </template>
270 68
271 <script> 69 <script>
70 /* This is Free Software under GNU Affero General Public License v >= 3.0
71 * without warranty, see README.md and license for details.
72 *
73 * SPDX-License-Identifier: AGPL-3.0-or-later
74 * License-Filename: LICENSES/AGPL-3.0.txt
75 *
76 * Copyright (C) 2018 by via donau
77 * – Österreichische Wasserstraßen-Gesellschaft mbH
78 * Software engineering by Intevation GmbH
79 *
80 * Author(s):
81 * Thomas Junk <thomas.junk@intevation.de>
82 */
272 import { displayError } from "@/lib/errors.js"; 83 import { displayError } from "@/lib/errors.js";
273 import { HTTP } from "@/lib/http"; 84 import { mapState } from "vuex";
274
275 //import { mapState } from "vuex";
276
277 const NODETAILS = -1;
278 const NODIFF = -1;
279 85
280 export default { 86 export default {
281 name: "importoverviewalt", 87 name: "importoverview",
282 data() { 88 data() {
283 return { 89 return {
284 showDiff: NODIFF, 90 reload: false
285 importQueue: [],
286 logEntries: [],
287 show: NODETAILS,
288 showAdditional: NODETAILS,
289 showLogs: NODETAILS
290 }; 91 };
291 }, 92 },
93 components: {
94 Staging: () => import("./staging/Staging.vue"),
95 Logs: () => import("./importlogs/Logs.vue")
96 },
97 computed: {
98 ...mapState("imports", ["stagingVisible", "logsVisible", "staging"])
99 },
292 methods: { 100 methods: {
293 isFairwayDimension(kind) { 101 toggleStaging() {
294 return kind === "FD"; 102 this.$store.commit("imports/setStagingVisibility", !this.stagingVisible);
295 }, 103 },
296 isApprovedGaugeMeasurement(kind) { 104 toggleLogs() {
297 return kind === "AGM"; 105 this.$store.commit("imports/setLogsVisibility", !this.logsVisible);
298 },
299 isBottleneck(kind) {
300 return kind === "BN" || kind === "UBN";
301 },
302 isStretch(kind) {
303 return kind === "ST";
304 },
305 toggleAdditional(id) {
306 if (id === this.showAdditional) {
307 this.showAdditional = NODETAILS;
308 return;
309 }
310 this.showAdditional = id;
311 },
312 toggleDiff(id) {
313 if (id === this.showDiff) {
314 this.showDiff = NODIFF;
315 return;
316 }
317 this.showDiff = id;
318 },
319 toggleLogs(id) {
320 if (id === this.showLogs) {
321 this.showLogs = NODETAILS;
322 return;
323 }
324 this.loadLogEntries(id);
325 },
326 toggleDetails(id) {
327 if (id === this.show) {
328 this.show = NODETAILS;
329 this.showAdditional = NODETAILS;
330 this.showLogs = NODETAILS;
331 return;
332 }
333 this.show = id;
334 }, 106 },
335 refresh() { 107 refresh() {
336 this.reload = true; 108 this.reload = true;
337 this.loadImportQueue(); 109 this.loadImportQueue();
338 this.loadLogs(); 110 this.loadLogs();
339 }, 111 },
340 loadLogEntries(id) {
341 HTTP.get("/imports/" + id, {
342 headers: { "X-Gemma-Auth": localStorage.getItem("token") }
343 })
344 .then(response => {
345 const { entries } = response.data;
346 this.logEntries = entries;
347 this.showLogs = id;
348 })
349 .catch(error => {
350 const { status, data } = error.response;
351 displayError({
352 title: this.$gettext("Backend Error"),
353 message: `${status}: ${data.message || data}`
354 });
355 });
356 },
357 loadImportQueue() { 112 loadImportQueue() {
358 HTTP.get("/imports?states=running,pending", { 113 this.$store
359 headers: { "X-Gemma-Auth": localStorage.getItem("token") } 114 .dispatch("imports/getStaging")
360 }) 115 .then(() => {
361 .then(response => { 116 this.reload = false;
362 this.importQueue = response.data.imports;
363 }) 117 })
364 .catch(error => { 118 .catch(error => {
365 const { status, data } = error.response; 119 const { status, data } = error.response;
366 displayError({ 120 displayError({
367 title: "Backend Error", 121 title: "Backend Error",
384 }); 138 });
385 } 139 }
386 }, 140 },
387 mounted() { 141 mounted() {
388 this.refresh(); 142 this.refresh();
389 }, 143 }
390 NODETAILS: NODETAILS
391 }; 144 };
392 </script> 145 </script>
393 146
394 <style lang="scss" scoped> 147 <style lang="scss" scoped>
395 .agmdetailskeys {
396 width: 100px;
397 }
398
399 .agmdetailsvalues {
400 width: 200px;
401 }
402
403 .overview { 148 .overview {
404 max-height: 800px; 149 max-height: 850px;
405 }
406 .logentries {
407 max-height: 400px;
408 max-width: 600px;
409 font-size: smaller;
410 white-space: nowrap;
411 line-height: 1.1em;
412 overflow: auto;
413 }
414
415 .additionalinfo {
416 max-width: 650px;
417 max-height: 350px;
418 overflow-y: auto; 150 overflow-y: auto;
419 } 151 }
420
421 .additionalinfo > div:hover {
422 background: #eee;
423 }
424
425 .logentries > div:hover {
426 background: #eee;
427 }
428
429 .details {
430 width: 100%;
431 padding: 5px;
432 cursor: pointer;
433 }
434
435 .imports {
436 line-height: 1.5rem;
437 }
438
439 .icons {
440 width: 4%;
441 }
442
443 .id {
444 width: 10%;
445 }
446
447 .kind {
448 width: 10%;
449 }
450
451 .date {
452 width: 20%;
453 }
454
455 .enqueued {
456 width: 20%;
457 }
458
459 .user {
460 width: 10%;
461 }
462
463 .state {
464 width: 10%;
465 }
466
467 .actions {
468 width: 16%;
469 }
470 </style> 152 </style>