2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-11-27 10:51:33 +00:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2018-11-14 14:00:01 +00:00
|
|
|
<template>
|
2020-09-09 19:25:59 +01:00
|
|
|
<div class="dashboard">
|
2019-04-05 16:08:14 +01:00
|
|
|
<div v-if="isLoading" class="loading-overlay active">
|
2019-10-04 14:22:26 +01:00
|
|
|
<img class="loading-image" src="@/../static/images/register/Loading.gif" alt="Company logo loading gif">
|
2019-04-05 16:08:14 +01:00
|
|
|
</div>
|
2020-08-04 18:36:49 +01:00
|
|
|
<NoPaywallInfoBar v-if="isNoPaywallInfoBarShown && !isLoading"/>
|
2020-09-09 19:25:59 +01:00
|
|
|
<div v-if="!isLoading" class="dashboard__wrap">
|
|
|
|
<DashboardHeader/>
|
|
|
|
<div class="dashboard__wrap__main-area">
|
|
|
|
<NavigationArea class="regular-navigation"/>
|
|
|
|
<div class="dashboard__wrap__main-area__content">
|
|
|
|
<div class="dashboard__wrap__main-area__content__bar-area">
|
2020-03-12 15:32:40 +00:00
|
|
|
<VInfoBar
|
2020-09-04 14:58:50 +01:00
|
|
|
v-if="isBillingInfoBarShown"
|
2020-03-12 15:32:40 +00:00
|
|
|
:first-value="storageRemaining"
|
|
|
|
:second-value="bandwidthRemaining"
|
|
|
|
first-description="of Storage Remaining"
|
|
|
|
second-description="of Bandwidth Remaining"
|
2020-03-18 17:07:29 +00:00
|
|
|
:path="projectDashboardPath"
|
2020-09-04 14:58:50 +01:00
|
|
|
:link="projectLimitsIncreaseRequestURL"
|
2020-03-12 15:32:40 +00:00
|
|
|
link-label="Request Limit Increase ->"
|
2019-12-02 19:27:56 +00:00
|
|
|
/>
|
2020-09-04 14:58:50 +01:00
|
|
|
<VInfoBar
|
|
|
|
v-if="isProjectLimitInfoBarShown"
|
|
|
|
is-blue="true"
|
2020-10-05 18:33:16 +01:00
|
|
|
:first-value="`You have used ${projectsCount}`"
|
2020-09-04 14:58:50 +01:00
|
|
|
first-description="of your"
|
2020-10-05 18:33:16 +01:00
|
|
|
:second-value="projectLimit"
|
2020-09-04 14:58:50 +01:00
|
|
|
second-description="available projects."
|
2020-10-13 11:46:22 +01:00
|
|
|
:link="projectLimitsIncreaseRequestURL"
|
2020-09-04 14:58:50 +01:00
|
|
|
link-label="Request Project Limit Increase"
|
|
|
|
/>
|
2019-12-02 19:27:56 +00:00
|
|
|
</div>
|
2020-09-09 19:25:59 +01:00
|
|
|
<router-view/>
|
2019-03-26 16:56:38 +00:00
|
|
|
</div>
|
2018-12-05 16:39:03 +00:00
|
|
|
</div>
|
2018-11-14 14:00:01 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2019-09-09 11:33:39 +01:00
|
|
|
import { Component, Vue } from 'vue-property-decorator';
|
|
|
|
|
2020-03-12 15:32:40 +00:00
|
|
|
import VInfoBar from '@/components/common/VInfoBar.vue';
|
2019-09-26 14:36:12 +01:00
|
|
|
import DashboardHeader from '@/components/header/HeaderArea.vue';
|
2019-09-09 11:33:39 +01:00
|
|
|
import NavigationArea from '@/components/navigation/NavigationArea.vue';
|
2020-08-04 18:36:49 +01:00
|
|
|
import NoPaywallInfoBar from '@/components/noPaywallInfoBar/NoPaywallInfoBar.vue';
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2019-10-23 18:33:24 +01:00
|
|
|
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
|
2019-09-09 11:33:39 +01:00
|
|
|
import { RouteConfig } from '@/router';
|
2020-11-16 17:35:07 +00:00
|
|
|
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
2020-06-02 17:38:44 +01:00
|
|
|
import { API_KEYS_ACTIONS } from '@/store/modules/apiKeys';
|
2019-09-09 11:33:39 +01:00
|
|
|
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
2019-10-23 18:33:24 +01:00
|
|
|
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
2019-09-09 11:33:39 +01:00
|
|
|
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
|
|
|
import { USER_ACTIONS } from '@/store/modules/users';
|
2020-04-30 21:35:09 +01:00
|
|
|
import { ApiKeysPage } from '@/types/apiKeys';
|
2019-09-09 11:33:39 +01:00
|
|
|
import { Project } from '@/types/projects';
|
2020-04-30 21:35:09 +01:00
|
|
|
import { User } from '@/types/users';
|
2020-03-12 15:32:40 +00:00
|
|
|
import { Size } from '@/utils/bytesSize';
|
2019-09-09 11:33:39 +01:00
|
|
|
import {
|
|
|
|
APP_STATE_ACTIONS,
|
|
|
|
PM_ACTIONS,
|
|
|
|
} from '@/utils/constants/actionNames';
|
|
|
|
import { AppState } from '@/utils/constants/appStateEnum';
|
2020-09-18 12:26:24 +01:00
|
|
|
import { LocalData } from '@/utils/localData';
|
2020-09-04 14:58:50 +01:00
|
|
|
import { MetaUtils } from '@/utils/meta';
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2019-10-23 18:33:24 +01:00
|
|
|
const {
|
2020-07-10 14:05:17 +01:00
|
|
|
GET_PAYWALL_ENABLED_STATUS,
|
2019-10-23 18:33:24 +01:00
|
|
|
SETUP_ACCOUNT,
|
|
|
|
GET_BALANCE,
|
|
|
|
GET_CREDIT_CARDS,
|
2020-05-21 18:01:56 +01:00
|
|
|
GET_PAYMENTS_HISTORY,
|
2020-03-26 13:34:16 +00:00
|
|
|
GET_PROJECT_USAGE_AND_CHARGES_CURRENT_ROLLUP,
|
|
|
|
GET_PROJECT_USAGE_AND_CHARGES_PREVIOUS_ROLLUP,
|
2019-10-23 18:33:24 +01:00
|
|
|
} = PAYMENTS_ACTIONS;
|
|
|
|
|
2019-09-09 11:33:39 +01:00
|
|
|
@Component({
|
|
|
|
components: {
|
|
|
|
NavigationArea,
|
|
|
|
DashboardHeader,
|
2020-03-12 15:32:40 +00:00
|
|
|
VInfoBar,
|
2020-08-04 18:36:49 +01:00
|
|
|
NoPaywallInfoBar,
|
2019-09-13 15:58:18 +01:00
|
|
|
},
|
2019-09-09 11:33:39 +01:00
|
|
|
})
|
2019-09-26 14:36:12 +01:00
|
|
|
export default class DashboardArea extends Vue {
|
2020-11-16 17:35:07 +00:00
|
|
|
private FIRST_PAGE: number = 1;
|
|
|
|
|
2020-03-12 15:32:40 +00:00
|
|
|
/**
|
2020-04-02 13:31:52 +01:00
|
|
|
* Holds router link to project dashboard page.
|
2020-03-12 15:32:40 +00:00
|
|
|
*/
|
2020-03-18 17:07:29 +00:00
|
|
|
public readonly projectDashboardPath: string = RouteConfig.ProjectDashboard.path;
|
2019-12-16 17:13:30 +00:00
|
|
|
|
2020-02-14 15:35:10 +00:00
|
|
|
/**
|
|
|
|
* Lifecycle hook after initial render.
|
|
|
|
* Pre fetches user`s and project information.
|
|
|
|
*/
|
2019-09-27 15:41:04 +01:00
|
|
|
public async mounted(): Promise<void> {
|
2020-04-30 21:35:09 +01:00
|
|
|
let user: User;
|
|
|
|
|
2019-09-27 15:41:04 +01:00
|
|
|
// TODO: combine all project related requests in one
|
|
|
|
try {
|
2020-04-30 21:35:09 +01:00
|
|
|
user = await this.$store.dispatch(USER_ACTIONS.GET);
|
2019-09-27 15:41:04 +01:00
|
|
|
} catch (error) {
|
2020-02-03 16:55:44 +00:00
|
|
|
if (!(error instanceof ErrorUnauthorized)) {
|
|
|
|
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);
|
|
|
|
await this.$notify.error(error.message);
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(async () => await this.$router.push(RouteConfig.Login.path), 1000);
|
2019-09-27 15:41:04 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2020-07-10 14:05:17 +01:00
|
|
|
try {
|
|
|
|
await this.$store.dispatch(GET_PAYWALL_ENABLED_STATUS);
|
|
|
|
} catch (error) {
|
|
|
|
await this.$notify.error(`Unable to get paywall enabled status. ${error.message}`);
|
|
|
|
}
|
|
|
|
|
2019-11-04 10:54:25 +00:00
|
|
|
try {
|
|
|
|
await this.$store.dispatch(SETUP_ACCOUNT);
|
2020-04-22 17:21:12 +01:00
|
|
|
} catch (error) {
|
|
|
|
await this.$notify.error(`Unable to setup account. ${error.message}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
await this.$store.dispatch(GET_BALANCE);
|
|
|
|
} catch (error) {
|
|
|
|
await this.$notify.error(`Unable to get account balance. ${error.message}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
await this.$store.dispatch(GET_CREDIT_CARDS);
|
|
|
|
} catch (error) {
|
|
|
|
await this.$notify.error(`Unable to get credit cards. ${error.message}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2020-05-21 18:01:56 +01:00
|
|
|
await this.$store.dispatch(GET_PAYMENTS_HISTORY);
|
2020-04-22 17:21:12 +01:00
|
|
|
} catch (error) {
|
2020-05-21 18:01:56 +01:00
|
|
|
await this.$notify.error(`Unable to get account payments history. ${error.message}`);
|
2020-04-22 17:21:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2020-03-26 13:34:16 +00:00
|
|
|
await this.$store.dispatch(GET_PROJECT_USAGE_AND_CHARGES_CURRENT_ROLLUP);
|
2019-11-04 10:54:25 +00:00
|
|
|
} catch (error) {
|
2020-04-22 17:21:12 +01:00
|
|
|
await this.$notify.error(`Unable to get usage and charges for current billing period. ${error.message}`);
|
2019-11-04 10:54:25 +00:00
|
|
|
}
|
2019-10-23 18:33:24 +01:00
|
|
|
|
2019-09-27 15:41:04 +01:00
|
|
|
let projects: Project[] = [];
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2019-09-27 15:41:04 +01:00
|
|
|
try {
|
|
|
|
projects = await this.$store.dispatch(PROJECTS_ACTIONS.FETCH);
|
|
|
|
} catch (error) {
|
2019-10-28 17:33:06 +00:00
|
|
|
await this.$notify.error(error.message);
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2019-09-27 15:41:04 +01:00
|
|
|
return;
|
|
|
|
}
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2020-04-22 17:21:12 +01:00
|
|
|
if (!projects.length) {
|
2020-04-30 21:35:09 +01:00
|
|
|
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
|
2020-02-18 15:48:19 +00:00
|
|
|
|
|
|
|
try {
|
2020-04-22 17:21:12 +01:00
|
|
|
await this.$router.push(RouteConfig.OnboardingTour.path);
|
2020-02-18 15:48:19 +00:00
|
|
|
} catch (error) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-18 12:26:24 +01:00
|
|
|
this.selectProject(projects);
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2020-04-30 21:35:09 +01:00
|
|
|
let apiKeysPage: ApiKeysPage = new ApiKeysPage();
|
|
|
|
|
2019-09-27 15:41:04 +01:00
|
|
|
try {
|
2020-11-16 17:35:07 +00:00
|
|
|
apiKeysPage = await this.$store.dispatch(API_KEYS_ACTIONS.FETCH, this.FIRST_PAGE);
|
2019-09-27 15:41:04 +01:00
|
|
|
} catch (error) {
|
2020-04-30 21:35:09 +01:00
|
|
|
await this.$notify.error(`Unable to fetch api keys. ${error.message}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (projects.length === 1 && projects[0].ownerId === user.id && apiKeysPage.apiKeys.length === 0) {
|
|
|
|
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
|
|
|
|
|
|
|
|
try {
|
|
|
|
await this.$router.push(RouteConfig.OnboardingTour.path);
|
|
|
|
} catch (error) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2019-09-27 15:41:04 +01:00
|
|
|
}
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2020-11-16 17:35:07 +00:00
|
|
|
try {
|
|
|
|
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.FETCH, this.FIRST_PAGE);
|
|
|
|
} catch (error) {
|
|
|
|
await this.$notify.error(`Unable to fetch api keys. ${error.message}`);
|
|
|
|
}
|
|
|
|
|
2020-11-17 11:57:57 +00:00
|
|
|
try {
|
|
|
|
await this.$store.dispatch(BUCKET_ACTIONS.FETCH_ALL_BUCKET_NAMES);
|
|
|
|
} catch (error) {
|
|
|
|
await this.$notify.error(`Unable to fetch all bucket names. ${error.message}`);
|
|
|
|
}
|
|
|
|
|
2020-05-15 13:38:00 +01:00
|
|
|
await this.$store.dispatch(PM_ACTIONS.SET_SEARCH_QUERY, '');
|
2020-01-02 14:17:57 +00:00
|
|
|
try {
|
2020-11-16 17:35:07 +00:00
|
|
|
await this.$store.dispatch(PM_ACTIONS.FETCH, this.FIRST_PAGE);
|
2020-01-02 14:17:57 +00:00
|
|
|
} catch (error) {
|
2020-04-30 21:35:09 +01:00
|
|
|
await this.$notify.error(`Unable to fetch project members. ${error.message}`);
|
2020-01-02 14:17:57 +00:00
|
|
|
}
|
|
|
|
|
2019-09-27 15:41:04 +01:00
|
|
|
try {
|
2020-04-30 21:35:09 +01:00
|
|
|
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
2019-09-27 15:41:04 +01:00
|
|
|
} catch (error) {
|
2020-04-30 21:35:09 +01:00
|
|
|
await this.$notify.error(`Unable to fetch project limits. ${error.message}`);
|
2019-09-27 15:41:04 +01:00
|
|
|
}
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2019-09-27 15:41:04 +01:00
|
|
|
try {
|
2020-11-16 17:35:07 +00:00
|
|
|
await this.$store.dispatch(BUCKET_ACTIONS.FETCH, this.FIRST_PAGE);
|
2019-09-27 15:41:04 +01:00
|
|
|
} catch (error) {
|
2019-10-28 17:33:06 +00:00
|
|
|
await this.$notify.error(`Unable to fetch buckets. ${error.message}`);
|
2019-09-27 15:41:04 +01:00
|
|
|
}
|
2019-09-09 11:33:39 +01:00
|
|
|
|
2019-09-27 15:41:04 +01:00
|
|
|
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
|
2019-09-09 11:33:39 +01:00
|
|
|
}
|
2019-09-05 09:41:39 +01:00
|
|
|
|
2020-08-04 18:36:49 +01:00
|
|
|
/**
|
|
|
|
* Indicates if no paywall info bar is shown.
|
|
|
|
*/
|
|
|
|
public get isNoPaywallInfoBarShown(): boolean {
|
2020-12-01 16:53:57 +00:00
|
|
|
const isOnboardingTour: boolean = this.$route.path.includes(RouteConfig.OnboardingTour.path);
|
2020-08-04 18:36:49 +01:00
|
|
|
|
|
|
|
return !this.isPaywallEnabled && !isOnboardingTour &&
|
|
|
|
this.$store.state.paymentsModule.balance.coins === 0 &&
|
|
|
|
this.$store.state.paymentsModule.creditCards.length === 0;
|
|
|
|
}
|
|
|
|
|
2020-02-14 15:35:10 +00:00
|
|
|
/**
|
2020-09-04 14:58:50 +01:00
|
|
|
* Indicates if billing info bar is shown.
|
2020-02-14 15:35:10 +00:00
|
|
|
*/
|
2020-09-04 14:58:50 +01:00
|
|
|
public get isBillingInfoBarShown(): boolean {
|
2020-02-27 18:28:11 +00:00
|
|
|
const isBillingPage = this.$route.name === RouteConfig.Billing.name;
|
2020-02-18 15:48:19 +00:00
|
|
|
|
2020-10-05 18:33:16 +01:00
|
|
|
return isBillingPage && this.projectsCount > 0;
|
2020-09-04 14:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicates if project limit info bar is shown.
|
|
|
|
*/
|
|
|
|
public get isProjectLimitInfoBarShown(): boolean {
|
2020-10-05 18:33:16 +01:00
|
|
|
return this.$route.name === RouteConfig.ProjectDashboard.name;
|
2020-09-04 14:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns user's projects count.
|
|
|
|
*/
|
2020-10-05 18:33:16 +01:00
|
|
|
public get projectsCount(): number {
|
|
|
|
return this.$store.getters.projectsCount;
|
2020-09-04 14:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-10-05 18:33:16 +01:00
|
|
|
* Returns project limit from store.
|
2020-09-04 14:58:50 +01:00
|
|
|
*/
|
2020-10-05 18:33:16 +01:00
|
|
|
public get projectLimit(): number {
|
|
|
|
const projectLimit: number = this.$store.getters.user.projectLimit;
|
|
|
|
if (projectLimit < this.projectsCount) return this.projectsCount;
|
|
|
|
|
|
|
|
return projectLimit;
|
2020-09-04 14:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns project limits increase request url from config.
|
|
|
|
*/
|
|
|
|
public get projectLimitsIncreaseRequestURL(): string {
|
|
|
|
return MetaUtils.getMetaContent('project-limits-increase-request-url');
|
|
|
|
}
|
|
|
|
|
2020-03-12 15:32:40 +00:00
|
|
|
/**
|
|
|
|
* Returns formatted string of remaining storage.
|
|
|
|
*/
|
|
|
|
public get storageRemaining(): string {
|
|
|
|
const storageUsed = this.$store.state.projectsModule.currentLimits.storageUsed;
|
|
|
|
const storageLimit = this.$store.state.projectsModule.currentLimits.storageLimit;
|
2020-03-13 18:14:41 +00:00
|
|
|
|
|
|
|
const difference = storageLimit - storageUsed;
|
|
|
|
if (difference < 0) {
|
|
|
|
return '0 Bytes';
|
|
|
|
}
|
|
|
|
|
|
|
|
const remaining = new Size(difference, 2);
|
2020-03-12 15:32:40 +00:00
|
|
|
|
|
|
|
return `${remaining.formattedBytes}${remaining.label}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns formatted string of remaining bandwidth.
|
|
|
|
*/
|
|
|
|
public get bandwidthRemaining(): string {
|
|
|
|
const bandwidthUsed = this.$store.state.projectsModule.currentLimits.bandwidthUsed;
|
|
|
|
const bandwidthLimit = this.$store.state.projectsModule.currentLimits.bandwidthLimit;
|
2020-03-13 18:14:41 +00:00
|
|
|
|
|
|
|
const difference = bandwidthLimit - bandwidthUsed;
|
|
|
|
if (difference < 0) {
|
|
|
|
return '0 Bytes';
|
|
|
|
}
|
|
|
|
|
|
|
|
const remaining = new Size(difference, 2);
|
2020-03-12 15:32:40 +00:00
|
|
|
|
|
|
|
return `${remaining.formattedBytes}${remaining.label}`;
|
2019-11-27 14:57:56 +00:00
|
|
|
}
|
|
|
|
|
2020-02-14 15:35:10 +00:00
|
|
|
/**
|
|
|
|
* Indicates if loading screen is active.
|
|
|
|
*/
|
2019-09-09 11:33:39 +01:00
|
|
|
public get isLoading(): boolean {
|
|
|
|
return this.$store.state.appStateModule.appState.fetchState === AppState.LOADING;
|
|
|
|
}
|
2020-08-04 18:36:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicates if paywall is enabled.
|
|
|
|
*/
|
|
|
|
private get isPaywallEnabled(): boolean {
|
|
|
|
return this.$store.state.paymentsModule.isPaywallEnabled;
|
|
|
|
}
|
2020-09-18 12:26:24 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if stored project is in fetched projects array and selects it.
|
|
|
|
* Selects first fetched project if check is not successful.
|
|
|
|
* @param fetchedProjects - fetched projects array
|
|
|
|
*/
|
|
|
|
private selectProject(fetchedProjects: Project[]): void {
|
|
|
|
const storedProjectID = LocalData.getSelectedProjectId();
|
|
|
|
const isProjectInFetchedProjects = fetchedProjects.some(project => project.id === storedProjectID);
|
|
|
|
if (storedProjectID && isProjectInFetchedProjects) {
|
|
|
|
this.storeProject(storedProjectID);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Length of fetchedProjects array is checked before selectProject() function call.
|
|
|
|
this.storeProject(fetchedProjects[0].id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores project to vuex store and browser's local storage.
|
|
|
|
* @param projectID - project id string
|
|
|
|
*/
|
|
|
|
private storeProject(projectID: string): void {
|
|
|
|
this.$store.dispatch(PROJECTS_ACTIONS.SELECT, projectID);
|
|
|
|
LocalData.setSelectedProjectId(projectID);
|
|
|
|
}
|
2019-09-09 11:33:39 +01:00
|
|
|
}
|
2018-11-14 14:00:01 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2020-08-20 20:38:17 +01:00
|
|
|
.loading-overlay {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
right: 0;
|
|
|
|
bottom: 0;
|
|
|
|
background-color: rgba(134, 134, 148, 1);
|
|
|
|
visibility: hidden;
|
|
|
|
opacity: 0;
|
|
|
|
-webkit-transition: all 0.5s linear;
|
|
|
|
-moz-transition: all 0.5s linear;
|
|
|
|
-o-transition: all 0.5s linear;
|
|
|
|
transition: all 0.5s linear;
|
|
|
|
}
|
|
|
|
|
|
|
|
.loading-overlay.active {
|
|
|
|
visibility: visible;
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
|
2020-09-09 19:25:59 +01:00
|
|
|
.dashboard {
|
2019-10-28 15:59:19 +00:00
|
|
|
height: 100%;
|
|
|
|
background-color: #f5f6fa;
|
2020-08-20 20:38:17 +01:00
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
2018-11-19 15:32:50 +00:00
|
|
|
|
2018-12-05 16:39:03 +00:00
|
|
|
&__wrap {
|
|
|
|
display: flex;
|
2020-09-09 19:25:59 +01:00
|
|
|
flex-direction: column;
|
2020-08-20 20:38:17 +01:00
|
|
|
height: 100%;
|
2019-03-26 16:56:38 +00:00
|
|
|
|
2020-09-09 19:25:59 +01:00
|
|
|
&__main-area {
|
2019-03-26 16:56:38 +00:00
|
|
|
display: flex;
|
2020-08-20 20:38:17 +01:00
|
|
|
height: 100%;
|
|
|
|
|
2020-09-09 19:25:59 +01:00
|
|
|
&__content {
|
2020-08-20 20:38:17 +01:00
|
|
|
overflow-y: scroll;
|
2020-09-09 19:25:59 +01:00
|
|
|
height: calc(100vh - 62px);
|
|
|
|
width: 100%;
|
2020-08-20 20:38:17 +01:00
|
|
|
|
|
|
|
&__bar-area {
|
2020-09-09 19:25:59 +01:00
|
|
|
position: relative;
|
2020-08-20 20:38:17 +01:00
|
|
|
}
|
|
|
|
}
|
2019-03-26 16:56:38 +00:00
|
|
|
}
|
2018-12-05 16:39:03 +00:00
|
|
|
}
|
2020-08-04 18:36:49 +01:00
|
|
|
}
|
|
|
|
|
2020-02-27 18:28:11 +00:00
|
|
|
@media screen and (max-width: 1280px) {
|
2019-10-28 15:59:19 +00:00
|
|
|
|
2020-09-09 19:25:59 +01:00
|
|
|
.regular-navigation {
|
2019-09-20 11:21:22 +01:00
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
}
|
2019-03-26 16:56:38 +00:00
|
|
|
</style>
|