/
ErrorPage.vue
152 lines (134 loc) · 3.84 KB
/
ErrorPage.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="error-area d-flex flex-column justify-center">
<div class="error-area__logo-wrapper d-flex justify-center">
<v-img
v-if="theme.global.current.value.dark"
class="error-area__logo-wrapper__logo"
src="@poc/assets/logo-dark.svg"
width="120"
alt="Storj Logo"
@click="goToHomepage"
/>
<v-img
v-else
class="error-area__logo-wrapper__logo"
src="@poc/assets/logo.svg"
width="120"
alt="Storj Logo"
@click="goToHomepage"
/>
</div>
<div class="d-flex flex-column align-center text-center">
<h3 class="text-h3">{{ statusCode }}</h3>
<h4 class="text-h4 mb-5">{{ message }}</h4>
<v-btn
@click="onButtonClick"
>
{{ 'Go ' + (isFatal ? 'to homepage' : 'back') }}
</v-btn>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { VBtn, VImg } from 'vuetify/components';
import { useTheme } from 'vuetify';
import { useAppStore } from '@poc/store/appStore';
import { useConfigStore } from '@/store/modules/configStore';
const appStore = useAppStore();
const configStore = useConfigStore();
const router = useRouter();
const route = useRoute();
const theme = useTheme();
const messages = new Map<number, string>([
[404, 'Oops, page not found.'],
[500, 'Internal server error.'],
]);
/**
* Retrieves the error's status code from the store.
*/
const statusCode = computed((): number => {
return appStore.state.error.statusCode;
});
/**
* Retrieves the message corresponding to the error's status code.
*/
const message = computed((): string => {
return messages.get(statusCode.value) || 'An error occurred.';
});
/**
* Indicates whether the error is unrecoverable.
*/
const isFatal = computed((): boolean => {
return appStore.state.error.fatal;
});
/**
* Navigates to the homepage.
*/
function goToHomepage(): void {
window.location.href = configStore.state.config.homepageURL || 'https://www.storj.io';
}
/**
* Navigates to the homepage if fatal or the previous route otherwise.
*/
function onButtonClick(): void {
if (isFatal.value) {
goToHomepage();
return;
}
if (!route.redirectedFrom) {
router.replace('/');
return;
}
router.back();
}
/**
* Lifecycle hook after initial render. Sets page title.
*/
onMounted(() => {
const satName = configStore.state.config.satelliteName;
document.title = statusCode.value.toString() + (satName ? ' | ' + satName : '');
});
</script>
<style scoped lang="scss">
.error-area {
position: fixed;
inset: 0;
padding: 52px 24px;
box-sizing: border-box;
overflow-y: auto;
&:before {
content: '';
position: fixed;
inset: 0;
background: url('../../../static/images/errors/world.svg') no-repeat center;
background-size: auto 75%;
z-index: -1;
opacity: 0.15;
}
&__logo-wrapper {
height: 30.89px;
position: absolute;
top: 52px;
left: 0;
right: 0;
margin-bottom: 52px;
&__logo {
height: 100%;
width: auto;
cursor: pointer;
}
}
}
@media screen and (height <= 500px) {
.error-area {
justify-content: flex-start;
&__logo-wrapper {
position: unset;
}
}
}
</style>