Move modal frame parts away from modal-content into modal, improve error handling

This commit is contained in:
Henry Jameson 2020-05-26 23:58:55 +03:00
parent 5187b37aca
commit a8e013bd65
10 changed files with 190 additions and 178 deletions

View file

@ -1,19 +1,17 @@
<template>
<div class="error-window panel">
<div class="panel-heading">
<span class="title">
<div class="async-component-error">
<div>
<h4>
{{ $t('general.generic_error') }}
</span>
</div>
<div class="panel-body">
</h4>
<p>
{{ $t('general.error_retry') }}
</p>
<button
class="btn"
@click="closeAllModals"
>
{{ $t('general.close') }}
@click="retry"
>
{{ $t('general.retry') }}
</button>
</div>
</div>
@ -22,9 +20,7 @@
<script>
export default {
methods: {
closeAllModals () {
// TODO make a global hook to close all modals?
this.$store.dispatch('closeSettingsModal')
retry () {
this.$emit('resetAsyncComponent')
}
}
@ -32,7 +28,11 @@ export default {
</script>
<style lang="scss">
.error-window {
.async-component-error {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
.btn {
margin: .5em;
padding: .5em 2em;

View file

@ -1,16 +0,0 @@
<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;
> i {
color: white;
}
}
</style>

View file

@ -0,0 +1,29 @@
<template>
<div class="panel-loading">
<span class="loading-text">
<i class="icon-spin4 animate-spin" />
{{ $t('general.loading') }}
</span>
</div>
</template>
<style lang="scss">
@import 'src/_variables.scss';
.panel-loading {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
font-size: 2em;
color: $fallback--text;
color: var(--text, $fallback--text);
.loading-text i {
font-size: 3em;
line-height: 0;
vertical-align: middle;
color: $fallback--text;
color: var(--text, $fallback--text);
}
}
</style>

View file

@ -1,6 +1,6 @@
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 PanelLoading from 'src/components/panel_loading/panel_loading.vue'
import AsyncComponentError from 'src/components/async_component_error/async_component_error.vue'
import getResettableAsyncComponent from 'src/services/resettable_async_component.js'
const SettingsModal = {
@ -9,12 +9,20 @@ const SettingsModal = {
SettingsModalContent: getResettableAsyncComponent(
() => import('./settings_modal_content.vue'),
{
loading: BigSpinner,
error: ErrorWindow,
loading: PanelLoading,
error: AsyncComponentError,
delay: 0
}
)
},
methods: {
closeModal () {
this.$store.dispatch('closeSettingsModal')
},
peekModal () {
this.$store.dispatch('togglePeekSettingsModal')
}
},
computed: {
modalActivated () {
return this.$store.state.interface.settingsModalState !== 'hidden'

View file

@ -3,7 +3,7 @@
overflow: hidden;
&.peek {
.modal-panel {
.settings-modal-panel {
/* Explanation:
* Modal is positioned vertically centered.
* 100vh - 100% = Distance between modal's top+bottom boundaries and screen
@ -15,4 +15,30 @@
transform: translateY(calc(((100vh - 100%) / 2 + 100%) - 50px));
}
}
.settings-modal-panel {
overflow: hidden;
transition: transform;
transition-timing-function: ease-in-out;
transition-duration: 300ms;
width: 1000px;
max-width: 90vw;
height: 90vh;
@media all and (max-width: 800px) {
max-width: 100vw;
height: 100vh;
}
.panel-body {
height: 100%;
overflow-y: hidden;
.btn {
min-height: 28px;
min-width: 10em;
padding: 0 2em;
}
}
}
}

View file

@ -5,10 +5,47 @@
:class="{ peek: modalPeeked }"
:no-background="modalPeeked"
>
<SettingsModalContent
v-if="modalActivated"
class="modal-panel"
/>
<div class="settings-modal-panel panel">
<div class="panel-heading">
<span class="title">
{{ $t('settings.settings') }}
</span>
<transition name="fade">
<template v-if="currentSaveStateNotice">
<div
v-if="currentSaveStateNotice.error"
class="alert error"
@click.prevent
>
{{ $t('settings.saving_err') }}
</div>
<div
v-if="!currentSaveStateNotice.error"
class="alert transparent"
@click.prevent
>
{{ $t('settings.saving_ok') }}
</div>
</template>
</transition>
<button
class="btn"
@click="peekModal"
>
{{ $t('general.peek') }}
</button>
<button
class="btn"
@click="closeModal"
>
{{ $t('general.close') }}
</button>
</div>
<div class="panel-body">
<SettingsModalContent v-if="modalActivated" />
</div>
</div>
</Modal>
</template>

View file

@ -31,14 +31,6 @@ const SettingsModalContent = {
isLoggedIn () {
return !!this.$store.state.users.currentUser
}
},
methods: {
closeModal () {
this.$store.dispatch('closeSettingsModal')
},
peekModal () {
this.$store.dispatch('togglePeekSettingsModal')
}
}
}

View file

@ -1,32 +1,6 @@
@import 'src/_variables.scss';
.settings-modal-panel {
overflow: hidden;
transition: transform;
transition-timing-function: ease-in-out;
transition-duration: 300ms;
width: 1000px;
max-width: 90vw;
height: 90vh;
@media all and (max-width: 800px) {
max-width: 100vw;
height: 100vh;
}
.settings_tab-switcher {
height: 100%;
}
.panel-body {
height: 100%;
overflow-y: hidden;
.btn {
min-height: 28px;
min-width: 10em;
padding: 0 2em;
}
}
.settings_tab-switcher {
height: 100%;
.full-height {
height: 100%;

View file

@ -1,112 +1,72 @@
<template>
<div class="settings-modal-panel panel">
<div class="panel-heading">
<span class="title">
{{ $t('settings.settings') }}
</span>
<transition name="fade">
<template v-if="currentSaveStateNotice">
<div
v-if="currentSaveStateNotice.error"
class="alert error"
@click.prevent
>
{{ $t('settings.saving_err') }}
</div>
<div
v-if="!currentSaveStateNotice.error"
class="alert transparent"
@click.prevent
>
{{ $t('settings.saving_ok') }}
</div>
</template>
</transition>
<button
class="btn"
@click="peekModal"
<tab-switcher
ref="tabSwitcher"
class="settings_tab-switcher"
:side-tab-bar="true"
:scrollable-tabs="true"
>
<div
:label="$t('settings.general')"
icon="wrench"
>
{{ $t('general.peek') }}
</button>
<button
class="btn"
@click="closeModal"
>
{{ $t('general.close') }}
</button>
<GeneralTab />
</div>
<div class="panel-body">
<tab-switcher
ref="tabSwitcher"
class="settings_tab-switcher"
:side-tab-bar="true"
:scrollable-tabs="true"
<div
v-if="isLoggedIn"
:label="$t('settings.profile_tab')"
icon="user"
>
<div
:label="$t('settings.general')"
icon="wrench"
>
<GeneralTab />
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.profile_tab')"
icon="user"
>
<ProfileTab />
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.security_tab')"
icon="lock"
>
<SecurityTab />
</div>
<div
:label="$t('settings.filtering')"
icon="filter"
>
<FilteringTab />
</div>
<div
:label="$t('settings.theme')"
icon="brush"
>
<ThemeTab />
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.notifications')"
icon="chat"
>
<NotificationsTab />
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.data_import_export_tab')"
icon="download"
>
<DataImportExportTab />
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.mutes_and_blocks')"
:fullHeight="true"
class="full-height"
icon="eye-off"
>
<MutesAndBlocksTab />
</div>
<div
:label="$t('settings.version.title')"
icon="info-circled"
>
<VersionTab />
</div>
</tab-switcher>
<ProfileTab />
</div>
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.security_tab')"
icon="lock"
>
<SecurityTab />
</div>
<div
:label="$t('settings.filtering')"
icon="filter"
>
<FilteringTab />
</div>
<div
:label="$t('settings.theme')"
icon="brush"
>
<ThemeTab />
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.notifications')"
icon="chat"
>
<NotificationsTab />
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.data_import_export_tab')"
icon="download"
>
<DataImportExportTab />
</div>
<div
v-if="isLoggedIn"
:label="$t('settings.mutes_and_blocks')"
:fullHeight="true"
class="full-height"
icon="eye-off"
>
<MutesAndBlocksTab />
</div>
<div
:label="$t('settings.version.title')"
icon="info-circled"
>
<VersionTab />
</div>
</tab-switcher>
</template>
<script src="./settings_modal_content.js"></script>

View file

@ -59,8 +59,10 @@
"apply": "Apply",
"submit": "Submit",
"more": "More",
"loading": "Loading…",
"generic_error": "An error occured",
"error_retry": "Please try again",
"retry": "Try again",
"optional": "optional",
"show_more": "Show more",
"show_less": "Show less",