diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/big_spinner/big_spinner.vue | 13 | ||||
| -rw-r--r-- | src/components/error_window/error_window.vue | 41 | ||||
| -rw-r--r-- | src/components/settings_modal/settings_modal.js | 13 | ||||
| -rw-r--r-- | src/i18n/en.json | 1 | ||||
| -rw-r--r-- | src/services/resettable_async_component.js | 32 |
5 files changed, 99 insertions, 1 deletions
diff --git a/src/components/big_spinner/big_spinner.vue b/src/components/big_spinner/big_spinner.vue new file mode 100644 index 00000000..cda28de5 --- /dev/null +++ b/src/components/big_spinner/big_spinner.vue @@ -0,0 +1,13 @@ +<template> + <div class="big-spinner"> + <i class="icon-spin4 animate-spin" /> + </div> +</template> + +<style lang="scss"> +.big-spinner { + font-size: 15em; + line-height: 0; + opacity: .6; +} +</style> diff --git a/src/components/error_window/error_window.vue b/src/components/error_window/error_window.vue new file mode 100644 index 00000000..ddb4ba00 --- /dev/null +++ b/src/components/error_window/error_window.vue @@ -0,0 +1,41 @@ +<template> + <div class="error-window panel"> + <div class="panel-heading"> + <span class="title"> + {{ $t('general.generic_error') }} + </span> + </div> + <div class="panel-body"> + <p> + {{ $t('general.error_retry') }} + </p> + <button + class="btn" + @click="closeAllModals" + > + {{ $t('general.close') }} + </button> + </div> + </div> +</template> + +<script> +export default { + methods: { + closeAllModals () { + // TODO make a global hook to close all modals? + this.$store.dispatch('closeSettingsModal') + this.$emit('resetAsyncComponent') + } + } +} +</script> + +<style lang="scss"> +.error-window { + .btn { + margin: .5em; + padding: .5em 2em; + } +} +</style> diff --git a/src/components/settings_modal/settings_modal.js b/src/components/settings_modal/settings_modal.js index d38c5751..60d14649 100644 --- a/src/components/settings_modal/settings_modal.js +++ b/src/components/settings_modal/settings_modal.js @@ -1,9 +1,20 @@ import Modal from 'src/components/modal/modal.vue' +import BigSpinner from 'src/components/big_spinner/big_spinner.vue' +import ErrorWindow from 'src/components/error_window/error_window.vue' +import getResettableAsyncComponent from 'src/services/resettable_async_component.js' const SettingsModal = { components: { Modal, - SettingsModalContent: () => import('./settings_modal_content.vue') + SettingsModalContent: getResettableAsyncComponent( + () => import('./settings_modal_content.vue'), + { + loading: BigSpinner, + error: ErrorWindow, + delay: 0, + timeout: 3000 + } + ) }, computed: { modalActivated () { diff --git a/src/i18n/en.json b/src/i18n/en.json index ad9c22bd..e3dc75d7 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -60,6 +60,7 @@ "submit": "Submit", "more": "More", "generic_error": "An error occured", + "error_retry": "Please try again", "optional": "optional", "show_more": "Show more", "show_less": "Show less", diff --git a/src/services/resettable_async_component.js b/src/services/resettable_async_component.js new file mode 100644 index 00000000..517bbd88 --- /dev/null +++ b/src/services/resettable_async_component.js @@ -0,0 +1,32 @@ +import Vue from 'vue' + +/* By default async components don't have any way to recover, if component is + * failed, it is failed forever. This helper tries to remedy that by recreating + * async component when retry is requested (by user). You need to emit the + * `resetAsyncComponent` event from child to reset the component. Generally, + * this should be done from error component but could be done from loading or + * actual target component itself if needs to be. + */ +function getResettableAsyncComponent (asyncComponent, options) { + const asyncComponentFactory = () => () => ({ + component: asyncComponent(), + ...options + }) + + const observe = Vue.observable({ c: asyncComponentFactory() }) + + return { + functional: true, + render (createElement, { data, children }) { + // emit event resetAsyncComponent to reloading + data.on = {} + data.on.resetAsyncComponent = () => { + observe.c = asyncComponentFactory() + // parent.$forceUpdate() + } + return createElement(observe.c, data, children) + } + } +} + +export default getResettableAsyncComponent |
