|
1 | 1 | <script setup lang="ts"> |
2 | 2 | import Calendar from 'primevue/calendar'; |
3 | 3 | import Button from 'primevue/button'; |
4 | | - import { computed, ComputedRef, Ref, ref } from 'vue'; |
| 4 | + import { computed, ComputedRef, onBeforeMount, onBeforeUnmount, Ref, ref } from 'vue'; |
5 | 5 | import { DropdownOption } from '../../models/Common'; |
6 | 6 | import { ComponentFactory, Observation, Participant } from '@gs'; |
7 | 7 | import { AxiosError, AxiosResponse } from 'axios'; |
|
17 | 17 | import { useGlobalStore } from '../../stores/globalStore'; |
18 | 18 | import MultiSelect from 'primevue/multiselect'; |
19 | 19 | import { DownloadDataFilter } from '../../models/DataDownloadModel'; |
| 20 | + 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); |
20 | 28 |
|
21 | 29 | const { t } = useI18n(); |
22 | 30 | const { componentsApi } = useComponentsApi(); |
|
165 | 173 | .then((response: any) => response.data) |
166 | 174 | .then((rs) => (factories = rs)) |
167 | 175 | .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 | + } |
| 202 | + } |
| 203 | + pendingRoute.value = null |
| 204 | + } |
| 205 | + }) |
| 206 | + } |
| 207 | +
|
| 208 | + onBeforeRouteLeave((to, from, next) => { |
| 209 | + if (isDownloadDataLoading.value) { |
| 210 | + pendingRoute.value = to |
| 211 | + interceptPageNavigation() |
| 212 | + // preventNavigation |
| 213 | + next(false) |
| 214 | + } else { |
| 215 | + // navigate |
| 216 | + next() |
| 217 | + } |
| 218 | + }) |
| 219 | +
|
| 220 | + onBeforeMount(() => { |
| 221 | + window.addEventListener('beforeunload', (e) => { |
| 222 | + if (isDownloadDataLoading.value) e.preventDefault() } |
| 223 | + ) |
| 224 | + }) |
| 225 | + onBeforeUnmount(() => { |
| 226 | + window.removeEventListener('beforeunload', (e) => { |
| 227 | + if (isDownloadDataLoading.value) e.preventDefault() } |
| 228 | + ) |
| 229 | + }) |
168 | 230 | </script> |
169 | 231 |
|
170 | 232 | <template> |
|
259 | 321 | :label="$t('study.studyList.labels.exportStudyData')" |
260 | 322 | :disabled="isDownloadDataLoading" |
261 | 323 | @click="downloadStudyData()" |
262 | | - /> |
| 324 | + > |
| 325 | + <span class="p-button-icon p-button-icon-left pi pi-download"></span> |
| 326 | + <span>{{t('study.studyList.labels.exportStudyData')}}</span> |
| 327 | + <ProgressSpinner |
| 328 | + v-if="isDownloadDataLoading" |
| 329 | + class="!text-white ml-2" |
| 330 | + style="width: 25px; height: 25px" |
| 331 | + stroke-width="6" |
| 332 | + fill="transparent" |
| 333 | + animation-duration=".5s" |
| 334 | + /> |
| 335 | + </Button> |
263 | 336 | </div> |
264 | 337 | </div> |
265 | 338 | </template> |
266 | 339 |
|
267 | | -<style scoped lang="postcss"></style> |
| 340 | +<style scoped lang="postcss"> |
| 341 | + :deep(.p-progress-spinner-circle) { |
| 342 | + stroke: currentColor!important; |
| 343 | + } |
| 344 | +</style> |
0 commit comments