aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/big_spinner/big_spinner.vue13
-rw-r--r--src/components/error_window/error_window.vue41
-rw-r--r--src/components/settings_modal/settings_modal.js13
-rw-r--r--src/i18n/en.json1
-rw-r--r--src/services/resettable_async_component.js32
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