web/storagenode: loading screen added
Change-Id: I7d966d2dfba1c275d98259eb7b368297559f9f2d
This commit is contained in:
parent
9dbd511396
commit
6c5d948b82
@ -10,12 +10,14 @@
|
|||||||
<SNOFooter />
|
<SNOFooter />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<LoadingScreen v-if="isLoading" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
|
import LoadingScreen from '@/app/components/LoadingScreen.vue';
|
||||||
import SNOFooter from '@/app/components/SNOFooter.vue';
|
import SNOFooter from '@/app/components/SNOFooter.vue';
|
||||||
import SNOHeader from '@/app/components/SNOHeader.vue';
|
import SNOHeader from '@/app/components/SNOHeader.vue';
|
||||||
|
|
||||||
@ -42,15 +44,30 @@ const elementsClassesToRemoveOnScroll: string[] = [
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
LoadingScreen,
|
||||||
SNOHeader,
|
SNOHeader,
|
||||||
SNOFooter,
|
SNOFooter,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class App extends Vue {
|
export default class App extends Vue {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if loading screen is active.
|
||||||
|
*/
|
||||||
|
public get isLoading(): boolean {
|
||||||
|
return this.$store.state.appStateModule.isLoading;
|
||||||
|
}
|
||||||
|
|
||||||
public async beforeCreate(): Promise<void> {
|
public async beforeCreate(): Promise<void> {
|
||||||
|
document.body.classList.add('js-loading');
|
||||||
|
window.onload = () => {
|
||||||
|
document.body.classList.remove('js-loading');
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: place key to server config.
|
// TODO: place key to server config.
|
||||||
await this.$telemetry.init('DTEcoJRlUAN2VylCWMiLrqoknW800GNO');
|
await this.$telemetry.init('DTEcoJRlUAN2VylCWMiLrqoknW800GNO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public onScroll(): void {
|
public onScroll(): void {
|
||||||
elementsIdsToRemoveOnScroll.forEach(id => {
|
elementsIdsToRemoveOnScroll.forEach(id => {
|
||||||
this.removeElementById(id);
|
this.removeElementById(id);
|
||||||
@ -120,6 +137,12 @@ export default class App extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.js-loading *,
|
||||||
|
.js-loading *:before,
|
||||||
|
.js-loading *:after {
|
||||||
|
animation-play-state: paused !important;
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-family: 'font_regular';
|
font-family: 'font_regular';
|
||||||
|
110
web/storagenode/src/app/components/LoadingScreen.vue
Normal file
110
web/storagenode/src/app/components/LoadingScreen.vue
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright (C) 2020 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<transition name="fade" mode="in-out">
|
||||||
|
<div class="loading-screen">
|
||||||
|
<StorjLogo class="logo"/>
|
||||||
|
<svg height="100" width="100" class="loader">
|
||||||
|
<circle cx="50" cy="50" r="40" class="background" />
|
||||||
|
<circle cx="50" cy="50" r="40" class="circle" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
|
import StorjLogo from '@/../static/images/LogoWithoutText.svg';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
StorjLogo,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class LoadingScreen extends Vue {}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.loading-screen {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 100vh;
|
||||||
|
z-index: 99999;
|
||||||
|
background-color: var(--loading-screen-background-color);
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
position: absolute;
|
||||||
|
top: 80px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.storj-logo {
|
||||||
|
|
||||||
|
path {
|
||||||
|
fill: var(--loader-logo-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
fill: none;
|
||||||
|
stroke: #c4c4c4;
|
||||||
|
stroke-width: 20;
|
||||||
|
stroke-dasharray: 250;
|
||||||
|
stroke-dashoffset: 250;
|
||||||
|
stroke-linecap: round;
|
||||||
|
animation: rotate 2s linear infinite, fill 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.background {
|
||||||
|
fill: none;
|
||||||
|
stroke: rgba(206, 206, 206, 0.2);
|
||||||
|
stroke-width: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate {
|
||||||
|
|
||||||
|
50% {
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
stroke-dashoffset: -250;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fill {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
stroke: #c4c4c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
stroke: var(--loader-fill-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -151,6 +151,8 @@ export default class SNOHeader extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async onRefresh(): Promise<void> {
|
public async onRefresh(): Promise<void> {
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, true);
|
||||||
|
|
||||||
const selectedSatellite = this.$store.state.node.selectedSatellite.id;
|
const selectedSatellite = this.$store.state.node.selectedSatellite.id;
|
||||||
await this.$store.dispatch(APPSTATE_ACTIONS.SET_NO_PAYOUT_DATA, false);
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_NO_PAYOUT_DATA, false);
|
||||||
|
|
||||||
@ -161,6 +163,8 @@ export default class SNOHeader extends Vue {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`${error.message} satellite data.`);
|
console.error(`${error.message} satellite data.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -78,6 +78,8 @@ export default class SatelliteSelectionDropdown extends Vue {
|
|||||||
* Fires on satellite click and selects it.
|
* Fires on satellite click and selects it.
|
||||||
*/
|
*/
|
||||||
public async onSatelliteClick(id: string): Promise<void> {
|
public async onSatelliteClick(id: string): Promise<void> {
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch(APPSTATE_ACTIONS.TOGGLE_SATELLITE_SELECTION);
|
await this.$store.dispatch(APPSTATE_ACTIONS.TOGGLE_SATELLITE_SELECTION);
|
||||||
await this.$store.dispatch(NODE_ACTIONS.SELECT_SATELLITE, id);
|
await this.$store.dispatch(NODE_ACTIONS.SELECT_SATELLITE, id);
|
||||||
@ -85,12 +87,16 @@ export default class SatelliteSelectionDropdown extends Vue {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error.message);
|
console.error(error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fires on all satellites click and sets selected satellite id to null.
|
* Fires on all satellites click and sets selected satellite id to null.
|
||||||
*/
|
*/
|
||||||
public async onAllSatellitesClick(): Promise<void> {
|
public async onAllSatellitesClick(): Promise<void> {
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch(APPSTATE_ACTIONS.TOGGLE_SATELLITE_SELECTION);
|
await this.$store.dispatch(APPSTATE_ACTIONS.TOGGLE_SATELLITE_SELECTION);
|
||||||
await this.$store.dispatch(NODE_ACTIONS.SELECT_SATELLITE, null);
|
await this.$store.dispatch(NODE_ACTIONS.SELECT_SATELLITE, null);
|
||||||
@ -98,6 +104,8 @@ export default class SatelliteSelectionDropdown extends Vue {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error.message);
|
console.error(error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,7 @@ export const APPSTATE_MUTATIONS = {
|
|||||||
CLOSE_ALL_POPUPS: 'CLOSE_ALL_POPUPS',
|
CLOSE_ALL_POPUPS: 'CLOSE_ALL_POPUPS',
|
||||||
SET_DARK: 'SET_DARK',
|
SET_DARK: 'SET_DARK',
|
||||||
SET_NO_PAYOUT_INFO: 'SET_NO_PAYOUT_INFO',
|
SET_NO_PAYOUT_INFO: 'SET_NO_PAYOUT_INFO',
|
||||||
|
SET_LOADING_STATE: 'SET_LOADING_STATE',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const APPSTATE_ACTIONS = {
|
export const APPSTATE_ACTIONS = {
|
||||||
@ -23,6 +24,7 @@ export const APPSTATE_ACTIONS = {
|
|||||||
CLOSE_ALL_POPUPS: 'CLOSE_ALL_POPUPS',
|
CLOSE_ALL_POPUPS: 'CLOSE_ALL_POPUPS',
|
||||||
SET_DARK_MODE: 'SET_DARK_MODE',
|
SET_DARK_MODE: 'SET_DARK_MODE',
|
||||||
SET_NO_PAYOUT_DATA: 'SET_NO_PAYOUT_DATA',
|
SET_NO_PAYOUT_DATA: 'SET_NO_PAYOUT_DATA',
|
||||||
|
SET_LOADING: 'SET_LOADING',
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -44,6 +46,7 @@ export const appStateModule = {
|
|||||||
isPayoutCalendarShown: false,
|
isPayoutCalendarShown: false,
|
||||||
isDarkMode: false,
|
isDarkMode: false,
|
||||||
isNoPayoutData: false,
|
isNoPayoutData: false,
|
||||||
|
isLoading: true,
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
[TOGGLE_SATELLITE_SELECTION](state: any): void {
|
[TOGGLE_SATELLITE_SELECTION](state: any): void {
|
||||||
@ -72,6 +75,9 @@ export const appStateModule = {
|
|||||||
[APPSTATE_MUTATIONS.SET_NO_PAYOUT_INFO](state: any, value): void {
|
[APPSTATE_MUTATIONS.SET_NO_PAYOUT_INFO](state: any, value): void {
|
||||||
state.isNoPayoutData = value;
|
state.isNoPayoutData = value;
|
||||||
},
|
},
|
||||||
|
[APPSTATE_MUTATIONS.SET_LOADING_STATE](state: any, value): void {
|
||||||
|
state.isLoading = value;
|
||||||
|
},
|
||||||
[CLOSE_ALL_POPUPS](state: any): void {
|
[CLOSE_ALL_POPUPS](state: any): void {
|
||||||
state.isSatelliteSelectionShown = false;
|
state.isSatelliteSelectionShown = false;
|
||||||
},
|
},
|
||||||
@ -117,6 +123,10 @@ export const appStateModule = {
|
|||||||
[APPSTATE_ACTIONS.SET_NO_PAYOUT_DATA]: function ({commit}: any, value: boolean): void {
|
[APPSTATE_ACTIONS.SET_NO_PAYOUT_DATA]: function ({commit}: any, value: boolean): void {
|
||||||
commit(APPSTATE_MUTATIONS.SET_NO_PAYOUT_INFO, value);
|
commit(APPSTATE_MUTATIONS.SET_NO_PAYOUT_INFO, value);
|
||||||
},
|
},
|
||||||
|
[APPSTATE_ACTIONS.SET_LOADING]: function ({commit}: any, value: boolean): void {
|
||||||
|
value ? commit(APPSTATE_MUTATIONS.SET_LOADING_STATE, value) :
|
||||||
|
setTimeout(() => { commit(APPSTATE_MUTATIONS.SET_LOADING_STATE, value); }, 1000);
|
||||||
|
},
|
||||||
[APPSTATE_ACTIONS.CLOSE_ADDITIONAL_CHARTS]: function ({commit}: any): void {
|
[APPSTATE_ACTIONS.CLOSE_ADDITIONAL_CHARTS]: function ({commit}: any): void {
|
||||||
commit(APPSTATE_MUTATIONS.CLOSE_ADDITIONAL_CHARTS);
|
commit(APPSTATE_MUTATIONS.CLOSE_ADDITIONAL_CHARTS);
|
||||||
},
|
},
|
||||||
|
@ -16,6 +16,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
|||||||
import SNOContentFilling from '@/app/components/SNOContentFilling.vue';
|
import SNOContentFilling from '@/app/components/SNOContentFilling.vue';
|
||||||
import SNOContentTitle from '@/app/components/SNOContentTitle.vue';
|
import SNOContentTitle from '@/app/components/SNOContentTitle.vue';
|
||||||
|
|
||||||
|
import { APPSTATE_ACTIONS } from '@/app/store/modules/appState';
|
||||||
import { NODE_ACTIONS } from '@/app/store/modules/node';
|
import { NODE_ACTIONS } from '@/app/store/modules/node';
|
||||||
import { NOTIFICATIONS_ACTIONS } from '@/app/store/modules/notifications';
|
import { NOTIFICATIONS_ACTIONS } from '@/app/store/modules/notifications';
|
||||||
import { PAYOUT_ACTIONS } from '@/app/store/modules/payout';
|
import { PAYOUT_ACTIONS } from '@/app/store/modules/payout';
|
||||||
@ -34,6 +35,8 @@ export default class Dashboard extends Vue {
|
|||||||
* Fetches notifications and total payout information for all satellites.
|
* Fetches notifications and total payout information for all satellites.
|
||||||
*/
|
*/
|
||||||
public async mounted(): Promise<void> {
|
public async mounted(): Promise<void> {
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch(NODE_ACTIONS.SELECT_SATELLITE, null);
|
await this.$store.dispatch(NODE_ACTIONS.SELECT_SATELLITE, null);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -52,6 +55,8 @@ export default class Dashboard extends Vue {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, false);
|
||||||
|
|
||||||
this.$telemetry.identify(this.$store.state.node.info.id);
|
this.$telemetry.identify(this.$store.state.node.info.id);
|
||||||
this.$telemetry.view(TelemetryViews.MainPage);
|
this.$telemetry.view(TelemetryViews.MainPage);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ import SatelliteSelection from '@/app/components/SatelliteSelection.vue';
|
|||||||
|
|
||||||
import BackArrowIcon from '@/../static/images/notifications/backArrow.svg';
|
import BackArrowIcon from '@/../static/images/notifications/backArrow.svg';
|
||||||
|
|
||||||
|
import { APPSTATE_ACTIONS } from '@/app/store/modules/appState';
|
||||||
import { NODE_ACTIONS } from '@/app/store/modules/node';
|
import { NODE_ACTIONS } from '@/app/store/modules/node';
|
||||||
import { NOTIFICATIONS_ACTIONS } from '@/app/store/modules/notifications';
|
import { NOTIFICATIONS_ACTIONS } from '@/app/store/modules/notifications';
|
||||||
import { PAYOUT_ACTIONS } from '@/app/store/modules/payout';
|
import { PAYOUT_ACTIONS } from '@/app/store/modules/payout';
|
||||||
@ -70,6 +71,8 @@ export default class PayoutArea extends Vue {
|
|||||||
* Fetches payout information.
|
* Fetches payout information.
|
||||||
*/
|
*/
|
||||||
public async mounted(): Promise<any> {
|
public async mounted(): Promise<any> {
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch(NODE_ACTIONS.SELECT_SATELLITE, null);
|
await this.$store.dispatch(NODE_ACTIONS.SELECT_SATELLITE, null);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -87,6 +90,8 @@ export default class PayoutArea extends Vue {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get totalHeld(): number {
|
public get totalHeld(): number {
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
--egress-tooltip-info-background-color: rgba(211, 242, 204, 0.3);
|
--egress-tooltip-info-background-color: rgba(211, 242, 204, 0.3);
|
||||||
--disk-stat-chart-text-color: #657284;
|
--disk-stat-chart-text-color: #657284;
|
||||||
--expand-button-background-color: rgba(226, 236, 247, 0.45);
|
--expand-button-background-color: rgba(226, 236, 247, 0.45);
|
||||||
|
--loading-screen-background-color: #e9ecf2;
|
||||||
|
--loader-fill-color: #133e9c;
|
||||||
|
--loader-logo-color: #929baf;
|
||||||
--tooltip-background-path: url('../../static/images/tooltipBack.png');
|
--tooltip-background-path: url('../../static/images/tooltipBack.png');
|
||||||
--tooltip-arrow-path: url('../../static/images/tooltipArrow.png');
|
--tooltip-arrow-path: url('../../static/images/tooltipArrow.png');
|
||||||
--info-image-arrow-middle-path: url('../../static/images/Message.png');
|
--info-image-arrow-middle-path: url('../../static/images/Message.png');
|
||||||
@ -92,6 +95,9 @@
|
|||||||
--egress-tooltip-info-background-color: #212329;
|
--egress-tooltip-info-background-color: #212329;
|
||||||
--disk-stat-chart-text-color: white;
|
--disk-stat-chart-text-color: white;
|
||||||
--expand-button-background-color: #31343d;
|
--expand-button-background-color: #31343d;
|
||||||
|
--loading-screen-background-color: #1e1e26;
|
||||||
|
--loader-fill-color: #4f97f7;
|
||||||
|
--loader-logo-color: #414148;
|
||||||
--tooltip-background-path: url('../../static/images/tooltipBackDark.png');
|
--tooltip-background-path: url('../../static/images/tooltipBackDark.png');
|
||||||
--tooltip-arrow-path: url('../../static/images/tooltipArrowDark.png');
|
--tooltip-arrow-path: url('../../static/images/tooltipArrowDark.png');
|
||||||
--info-image-arrow-middle-path: url('../../static/images/MessageDark.png');
|
--info-image-arrow-middle-path: url('../../static/images/MessageDark.png');
|
||||||
|
14
web/storagenode/tests/unit/components/LoadingScreen.spec.ts
Normal file
14
web/storagenode/tests/unit/components/LoadingScreen.spec.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (C) 2020 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
import LoadingScreen from '@/app/components/LoadingScreen.vue';
|
||||||
|
|
||||||
|
import { shallowMount } from '@vue/test-utils';
|
||||||
|
|
||||||
|
describe('LoadingScreen', (): void => {
|
||||||
|
it('renders correctly', (): void => {
|
||||||
|
const wrapper = shallowMount(LoadingScreen);
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,12 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`LoadingScreen renders correctly 1`] = `
|
||||||
|
<transition-stub name="fade" mode="in-out">
|
||||||
|
<div class="loading-screen">
|
||||||
|
<storjlogo-stub class="logo"></storjlogo-stub> <svg height="100" width="100" class="loader">
|
||||||
|
<circle cx="50" cy="50" r="40" class="background"></circle>
|
||||||
|
<circle cx="50" cy="50" r="40" class="circle"></circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</transition-stub>
|
||||||
|
`;
|
Loading…
Reference in New Issue
Block a user