Skip to content

Commit d960dbf

Browse files
committed
617: add comfirmation dialog for studydata downlaod, if user navigates to different page
1 parent 419363d commit d960dbf

File tree

7 files changed

+175
-19
lines changed

7 files changed

+175
-19
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<script setup lang="ts">
2+
/* Copyright LBI-DHP and/or licensed to LBI-DHP under one or more contributor
3+
license agreements (LBI-DHP: Ludwig Boltzmann Institute for Digital Health and
4+
Prevention -- A research institute of the Ludwig Boltzmann Gesellschaft,
5+
Oesterreichische Vereinigung zur Foerderung der wissenschaftlichen Forschung).
6+
Licensed under the Elastic License 2.0. */
7+
8+
import { inject } from 'vue';
9+
import Button from 'primevue/button';
10+
import ExclamationIcon from '../shared/ExclamationIcon.vue';
11+
12+
const dialogRef: any = inject('dialogRef');
13+
14+
const message: string = dialogRef.value?.data?.message ?? 'Möchten Sie die Seite wirklich verlassen?';
15+
const cancelBtn: string = dialogRef.value?.data?.cancelBtn ?? 'Abbrechen';
16+
const approveBtn: string = dialogRef.value?.data?.approveBtn ?? 'Bestätigen';
17+
18+
function closeDialog(navigate: boolean): void {
19+
dialogRef.value.close(navigate)
20+
}
21+
22+
</script>
23+
24+
<template>
25+
26+
<div class="text-base">
27+
<div class="mb-8 grid grid-cols-12 place-items-center gap-4">
28+
<div class="col-span-2">
29+
<ExclamationIcon id="exclamation" />
30+
</div>
31+
<div class="col-span-10">
32+
{{message}}
33+
</div>
34+
</div>
35+
<div class="flex flex-row items-center justify-between">
36+
<Button
37+
type="button"
38+
class="p-button btn-important"
39+
:label="approveBtn"
40+
@click="closeDialog(true)"
41+
/>
42+
<Button
43+
type="button"
44+
class="btn-primary"
45+
:label="cancelBtn"
46+
@click="closeDialog(false)"/>
47+
</div>
48+
</div>
49+
50+
51+
</template>

src/components/dialog/InfoDialog.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
/* Copyright LBI-DHP and/or licensed to LBI-DHP under one or more contributor
2-
license agreements (LBI-DHP: Ludwig Boltzmann Institute for Digital Health and
3-
Prevention -- A research institute of the Ludwig Boltzmann Gesellschaft,
4-
Oesterreichische Vereinigung zur Foerderung der wissenschaftlichen Forschung).
5-
Licensed under the Elastic License 2.0. */
61
<script setup lang="ts">
2+
/* Copyright LBI-DHP and/or licensed to LBI-DHP under one or more contributor
3+
license agreements (LBI-DHP: Ludwig Boltzmann Institute for Digital Health and
4+
Prevention -- A research institute of the Ludwig Boltzmann Gesellschaft,
5+
Oesterreichische Vereinigung zur Foerderung der wissenschaftlichen Forschung).
6+
Licensed under the Elastic License 2.0. */
77
import { inject } from 'vue';
88
import Button from 'primevue/button';
99

src/components/subComponents/AuditLogDownload.vue

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<script setup lang="ts">
22
import { useI18n } from 'vue-i18n';
3-
import { watch, computed } from 'vue';
3+
import { watch, computed, ref } from 'vue';
44
import { useStudyStore } from '../../stores/studyStore';
55
import Button from 'primevue/button';
6+
import ProgressSpinner from 'primevue/progressspinner';
67
78
const { t } = useI18n();
89
const studyStore = useStudyStore();
10+
const isLoading = ref<boolean>(false);
911
1012
const props = defineProps({
1113
studyId: {
@@ -28,11 +30,15 @@
2830
}, {immediate: true})
2931
3032
async function getAuditlogMetadata(): Promise<void> {
31-
await studyStore.getAuditLogMetadata(studyStore.studyId);
33+
34+
await studyStore.getAuditLogMetadata(studyStore.studyId)
35+
3236
}
3337
3438
function downloadCurrentAuditlog(): void {
39+
isLoading.value = true
3540
studyStore.exportAuditLog(studyStore.studyId)
41+
.then(() => isLoading.value = false);
3642
}
3743
</script>
3844

@@ -52,10 +58,23 @@
5258
class="mt-8"
5359
:label="$t('data.auditLogDownload.btnLabel')"
5460
@click="downloadCurrentAuditlog()"
55-
/>
61+
>
62+
<span class="p-button-icon p-button-icon-left pi pi-download"></span>
63+
<span>{{t('data.auditLogDownload.btnLabel')}}</span>
64+
<ProgressSpinner
65+
v-if="isLoading"
66+
class="!text-white ml-2"
67+
style="width: 25px; height: 25px"
68+
stroke-width="6"
69+
fill="transparent"
70+
animation-duration=".5s"
71+
/>
72+
</Button>
5673
</div>
5774
</template>
5875

59-
<style scoped lang="scss">
60-
76+
<style scoped lang="postcss">
77+
:deep(.p-progress-spinner-circle) {
78+
stroke: currentColor!important;
79+
}
6180
</style>

src/components/subComponents/DataDownload.vue

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import Calendar from 'primevue/calendar';
33
import Button from 'primevue/button';
4-
import { computed, ComputedRef, Ref, ref } from 'vue';
4+
import { computed, ComputedRef, onBeforeMount, onBeforeUnmount, Ref, ref } from 'vue';
55
import { DropdownOption } from '../../models/Common';
66
import { ComponentFactory, Observation, Participant } from '@gs';
77
import { AxiosError, AxiosResponse } from 'axios';
@@ -18,6 +18,13 @@
1818
import MultiSelect from 'primevue/multiselect';
1919
import { DownloadDataFilter } from '../../models/DataDownloadModel';
2020
import ProgressSpinner from 'primevue/progressspinner';
21+
import { useDialog } from 'primevue/usedialog';
22+
import ConfirmationDialog from '../dialog/ConfirmationDialog.vue';
23+
import { onBeforeRouteLeave, useRouter } from 'vue-router';
24+
25+
const dialog = useDialog();
26+
const router = useRouter();
27+
const pendingRoute = ref<any>(null);
2128
2229
const { t } = useI18n();
2330
const { componentsApi } = useComponentsApi();
@@ -166,6 +173,62 @@
166173
.then((response: any) => response.data)
167174
.then((rs) => (factories = rs))
168175
.then(loadData);
176+
177+
function interceptPageNavigation(): void {
178+
dialog.open(ConfirmationDialog, {
179+
data: {
180+
message: t('monitoringData.dialog.msg.downloadStudyData'),
181+
cancelBtn: t('monitoringData.dialog.waitForDownload'),
182+
approveBtn: t('monitoringData.dialog.navigatePage')
183+
},
184+
props: {
185+
header: t('monitoringData.dialog.header.downloadStudyData'),
186+
style: {
187+
width: '50vw',
188+
},
189+
breakpoints: {
190+
'960px': '75vw',
191+
'640px': '90vw',
192+
},
193+
modal: true,
194+
draggable: false,
195+
},
196+
onClose: (options) =>{
197+
if (options?.data) {
198+
if (pendingRoute.value) {
199+
isDownloadDataLoading.value = false
200+
router.push(pendingRoute.value)
201+
pendingRoute.value = null
202+
}
203+
} else {
204+
pendingRoute.value = null
205+
}
206+
}
207+
})
208+
}
209+
210+
onBeforeRouteLeave((to, from, next) => {
211+
if (isDownloadDataLoading.value) {
212+
pendingRoute.value = to
213+
interceptPageNavigation()
214+
// preventNavigation
215+
next(false)
216+
} else {
217+
// navigate
218+
next()
219+
}
220+
})
221+
222+
onBeforeMount(() => {
223+
window.addEventListener('beforeunload', (e) => {
224+
if (isDownloadDataLoading.value) e.preventDefault() }
225+
)
226+
})
227+
onBeforeUnmount(() => {
228+
window.removeEventListener('beforeunload', (e) => {
229+
if (isDownloadDataLoading.value) e.preventDefault() }
230+
)
231+
})
169232
</script>
170233

171234
<template>
@@ -278,6 +341,6 @@
278341

279342
<style scoped lang="postcss">
280343
:deep(.p-progress-spinner-circle) {
281-
stroke: currentColor!important; /* nimmt dann die text-red-600 aus Tailwind */
344+
stroke: currentColor!important;
282345
}
283346
</style>

src/i18n/de.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,17 @@
392392
"dataDownload": "Studiendaten herunterladen",
393393
"lastDataPoints": "Letzte Datenpunkte",
394394
"recordedObservation": "Erhobene Daten",
395-
"auditLog": "AuditLog herunterladen"
395+
"auditLog": "Auditlog herunterladen"
396+
},
397+
"dialog": {
398+
"waitForDownload": "Auf Download warten",
399+
"navigatePage": "Seite verlassen",
400+
"msg": {
401+
"downloadStudyData": "Der Daten-Download läuft noch. Sie können die Seite trotzdem verlassen – der Vorgang wird im Hintergrund gebuffert und der Download öffnet sich automatisch in einem neuen Tab, sobald er bereitsteht. Änderungen, die Sie ab jetzt vornehmen, sind darin nicht enthalten."
402+
},
403+
"header": {
404+
"downloadStudyData": "Seite navigieren"
405+
}
396406
}
397407
},
398408
"moreTable": {

src/i18n/en.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"title": "Download study data"
6464
},
6565
"auditLogDownload": {
66-
"title": "Download AuditLog",
66+
"title": "Download Audit log",
6767
"description": "The number of the current audit log entries is: {length}.",
6868
"btnLabel": "Download current audit log",
6969
"notStartedInfo": "Audit log data is only recorded when a study is active.",
@@ -393,6 +393,16 @@
393393
"lastDataPoints": "Latest Data Points",
394394
"recordedObservation": "Recorded Observations",
395395
"auditLog": "Download AuditLog"
396+
},
397+
"dialog": {
398+
"navigatePage": "Leave page",
399+
"waitForDownload": "Wait for download",
400+
"msg": {
401+
"downloadStudyData": "The data download is still in progress. You may leave the page – the process will be buffered in the background and the download will automatically open in a new tab once it is ready. Any changes you make from now on will not be included in this download."
402+
},
403+
"header": {
404+
"downloadStudyData": "Navigate page"
405+
}
396406
}
397407
},
398408
"moreTable": {

src/main.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,22 @@
99
import { createApp } from 'vue';
1010
import App from './App.vue';
1111
import './index.pcss';
12+
13+
// Tailwind + deine Overrides -> set theme and ovverride with brand colors -> flexibility to switch themes later
14+
// animations and optimization run over the theme since the last update, so we need a basic theme before overriding it with our brand colors
15+
import 'primevue/resources/themes/lara-light-blue/theme.css';
16+
import "primevue/resources/primevue.min.css";
17+
import '../src/styles/more-light/theme.pcss';
1218
import '../src/style.pcss';
19+
1320
// PrimeVue
1421
import PrimeVue from 'primevue/config';
1522
import Tooltip from 'primevue/tooltip';
1623
import ConfirmationService from 'primevue/confirmationservice';
1724
import DialogService from 'primevue/dialogservice';
1825
import ToastService from 'primevue/toastservice';
1926

20-
// Tailwind + deine Overrides -> set theme and ovverride with brand colors -> flexibility to switch themes later
21-
// animations and optimization run over the theme since the last update, so we need a basic theme before overriding it with our brand colors
22-
import 'primevue/resources/themes/lara-light-blue/theme.css';
23-
import "primevue/resources/primevue.min.css";
24-
import '../src/styles/more-light/theme.pcss';
27+
2528

2629
// Router
2730
import { Router } from './router';

0 commit comments

Comments
 (0)