web/satellite: router refactoring (#2846)

This commit is contained in:
Yehor Butko 2019-08-22 13:44:08 +03:00 committed by GitHub
parent 1b9d163c95
commit 7c6fdd09d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 199 additions and 1394 deletions

View File

@ -15,6 +15,7 @@
import { Component, Vue } from 'vue-property-decorator';
import TabNavigation from '@/components/navigation/TabNavigation.vue';
import { NavigationLink } from '@/types/navigation';
import { RouteConfig } from '@/router';
@Component({
components: {
@ -23,14 +24,10 @@
})
export default class AccountArea extends Vue {
public navigation: NavigationLink[] = [
new NavigationLink('/account/profile', 'Profile'),
new NavigationLink('/account/payment-methods', 'Payment Methods'),
new NavigationLink('/account/billing-history', 'Billing History'),
RouteConfig.Account.with(RouteConfig.Profile),
RouteConfig.Account.with(RouteConfig.PaymentMethods),
RouteConfig.Account.with(RouteConfig.BillingHistory),
];
public mounted(): void {
this.$router.push(this.navigation[0].path);
}
}
</script>

View File

@ -69,7 +69,7 @@
import HeaderedInput from '@/components/common/HeaderedInput.vue';
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
import { AuthToken } from '@/utils/authToken';
import ROUTES from '@/utils/constants/routerConstants';
import { RouteConfig } from '@/router';
@Component({
components: {
@ -102,7 +102,7 @@
AuthToken.remove();
this.isLoading = false;
this.$router.push(ROUTES.LOGIN.path);
this.$router.push(RouteConfig.Login.path);
} catch (error) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, error.message);
this.isLoading = false;

View File

@ -7,7 +7,7 @@
import { Component, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
import ROUTES from '@/utils/constants/routerConstants';
import { RouteConfig } from '@/router';
import { AuthApi } from '@/api/auth';
import { getUserId } from '@/utils/consoleLocalStorage';
@ -48,7 +48,7 @@
public onCloseClick(): void {
this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS);
this.$router.push(ROUTES.LOGIN.path);
this.$router.push(RouteConfig.Login.path);
}
public get isPopupShown(): boolean {

View File

@ -29,7 +29,7 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { AuthToken } from '@/utils/authToken';
import ROUTES from '@/utils/constants/routerConstants';
import { RouteConfig } from '@/router';
import {
APP_STATE_ACTIONS,
PROJETS_ACTIONS,
@ -47,14 +47,14 @@
}
public onAccountSettingsClick(): void {
this.$router.push(ROUTES.ACCOUNT_SETTINGS.path + '/' + ROUTES.PROFILE.path);
this.$router.push(RouteConfig.Account.with(RouteConfig.Profile).path);
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_ACCOUNT);
}
public onLogoutClick(): void {
AuthToken.remove();
this.$router.push(ROUTES.LOGIN.path);
this.$router.push(RouteConfig.Login.path);
this.$store.dispatch(PM_ACTIONS.CLEAR);
this.$store.dispatch(PROJETS_ACTIONS.CLEAR);
this.$store.dispatch(USER_ACTIONS.CLEAR);

View File

@ -5,9 +5,10 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import NAVIGATION_ITEMS from '@/utils/constants/navigationLinks';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import AddUserPopup from '@/components/team/AddUserPopup.vue';
import { NavigationLink } from '@/types/navigation';
import { RouteConfig } from '@/router';
@Component({
components: {
@ -15,8 +16,46 @@
}
})
export default class NavigationArea extends Vue {
// TODO: create types for navigation items
public readonly navigation: any = NAVIGATION_ITEMS;
// TODO: Use SvgLoaderComponent to reduce markup lines
public readonly navigation: NavigationLink[] = [
RouteConfig.ProjectOverview.with(RouteConfig.ProjectDetails).withIcon(
`<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.073 5.3913C21.8382 5.15652 21.5252 5 21.2121 5H6.89038C6.26429 5 5.71647 5.54783 5.79473 6.09565L2.19473 6.01739C1.80342 6.09565 1.49038 6.17391 1.2556 6.48696C1.09908 6.72174 0.942555 7.03478 1.02082 7.42609L3.13386 18.4609C3.21212 19.0087 3.68169 19.4 4.22951 19.4H19.0991C19.6469 19.4 20.1165 19.0087 20.1947 18.4609L22.3078 6.33043C22.386 6.01739 22.3078 5.62609 22.073 5.3913ZM19.6469 14.7826L18.7078 9.38261C18.6295 8.75652 18.0034 8.28696 17.3773 8.28696H8.4556C8.37734 8.28696 8.29908 8.2087 8.29908 8.13043L8.14256 7.34783C8.14256 6.8 7.75125 6.33043 7.28169 6.17391L21.2121 6.09565L19.6469 14.7826Z" fill="#363840"/>
</svg>`),
RouteConfig.Team.withIcon(
`<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M19.6621 11.1388C19.8233 10.8971 19.9039 10.6553 19.9845 10.333C20.5485 10.0913 20.8709 9.52718 20.9515 8.72136C21.032 7.99612 20.7097 7.43204 20.3068 7.10971C20.2262 5.01456 19.5816 3 16.6 3C13.6184 3 12.9738 5.01456 12.8126 7.10971C12.4097 7.43204 12.0874 8.0767 12.168 8.72136C12.2485 9.4466 12.6515 10.0913 13.135 10.333C13.2155 10.5748 13.3767 10.8971 13.4573 11.1388C12.9738 11.3 12.4903 11.4612 12.0874 11.6223C11.6845 11.4612 11.201 11.2194 10.7175 11.1388C10.8786 10.8971 10.9592 10.6553 11.0398 10.333C11.6039 10.0913 11.9262 9.52718 12.0068 8.72136C12.0874 7.99612 11.765 7.43204 11.3621 7.10971C11.201 5.01456 10.6369 3 7.57476 3C4.5932 3 3.94854 5.01456 3.78738 7.10971C3.38447 7.43204 3.06214 8.0767 3.14272 8.72136C3.2233 9.4466 3.62621 10.0913 4.10971 10.333C4.19029 10.5748 4.35146 10.8971 4.43204 11.1388C1.53107 11.9447 0 13.6369 0 16.2155C0 16.4573 0.161165 16.6184 0.32233 16.699C2.09515 17.5049 4.75437 17.9883 7.49418 17.9883C9.10583 17.9883 10.6369 17.8272 12.0068 17.5049C13.3767 17.8272 14.9078 17.9883 16.5194 17.9883C19.2592 17.9883 21.9184 17.5049 23.6913 16.699C23.8524 16.6184 24.0136 16.3767 24.0136 16.2155C24.0942 13.6369 22.5631 11.9447 19.6621 11.1388Z" fill="#354049"/>
<path d="M13.7532 12.8937C13.1891 13.1354 12.5445 13.2966 11.8192 13.4577C11.094 13.2966 10.4493 13.1354 9.88525 12.8937C9.96584 11.6043 10.6105 10.5568 11.8192 9.91211C13.1086 10.5568 13.6726 11.5238 13.7532 12.8937Z" fill="#2683FF"/>
<path class="white" d="M14.3174 13.832C17.0572 14.4767 19.0717 15.8466 19.0717 18.7476C17.1378 19.634 14.3174 20.0369 11.8193 20.0369C9.32126 20.0369 6.42029 19.634 4.56689 18.7476C4.56689 15.8466 6.50087 14.4767 9.32126 13.832" fill="white"/>
<path d="M11.7389 20.6001C8.8379 20.6001 6.01751 20.1166 4.24469 19.2302C4.08353 19.2302 3.92236 18.9884 3.92236 18.8273C3.92236 16.0069 5.6146 14.1535 9.07964 13.3477L9.32139 14.3952C6.58159 15.0399 5.21168 16.3292 5.05052 18.4244C6.74275 19.1496 9.24081 19.5525 11.8195 19.5525C14.3981 19.5525 16.8156 19.1496 18.5884 18.4244C18.4272 16.3292 17.0573 15.0399 14.3175 14.3952L14.5593 13.3477C17.9437 14.1535 19.7165 16.0069 19.7165 18.8273C19.7165 19.069 19.5554 19.2302 19.3942 19.3108C17.4602 20.1166 14.6398 20.6001 11.7389 20.6001Z" fill="#354049"/>
<path class="white" d="M11.7388 15.3628C10.5301 15.3628 9.16018 13.9929 8.5961 12.1395C8.11261 12.1395 7.79028 11.5754 7.7097 10.9308C7.62911 10.2861 7.95144 9.72205 8.35436 9.56088C8.43494 6.98224 9.16018 5.45117 11.7388 5.45117C14.3175 5.45117 15.0427 6.98224 15.1233 9.56088C15.5262 9.64146 15.8485 10.2055 15.7679 10.8502C15.6874 11.4949 15.365 12.0589 14.8815 12.0589C14.398 13.9929 12.9476 15.3628 11.7388 15.3628Z" fill="white"/>
<path d="M11.7387 15.926C10.2882 15.926 8.83776 14.5561 8.11251 12.6221C7.54844 12.3804 7.14552 11.7357 7.06494 11.0105C7.06494 10.2047 7.38727 9.56 7.79018 9.23767C7.95135 7.06194 8.59601 4.9668 11.7387 4.9668C14.8814 4.9668 15.5261 7.06194 15.6873 9.23767C16.1708 9.56 16.4125 10.2047 16.3319 10.9299C16.2513 11.7357 15.8484 12.3804 15.2844 12.5416C14.7203 14.4755 13.1892 15.926 11.7387 15.926ZM11.7387 6.01437C9.72416 6.01437 8.99892 6.98136 8.83776 9.56C8.83776 9.80175 8.67659 10.0435 8.43484 10.0435C8.35426 10.0435 8.1931 10.3658 8.1931 10.7687C8.1931 11.2522 8.43484 11.494 8.51543 11.494C8.75717 11.494 8.99892 11.6551 8.99892 11.8969C9.48242 13.6697 10.7717 14.7173 11.6581 14.7173C12.5446 14.7173 13.7533 13.6697 14.3174 11.8969C14.398 11.6551 14.5591 11.494 14.8009 11.494C14.8814 11.494 15.1232 11.2522 15.1232 10.7687C15.1232 10.2852 14.962 10.0435 14.8814 10.0435C14.6397 9.96291 14.4785 9.80175 14.4785 9.56C14.4785 6.98136 13.7533 6.01437 11.7387 6.01437Z" fill="#354049"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>`),
RouteConfig.ApiKeys.withIcon(
`<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M18.6059 9.10806C18.6059 8.85201 18.6912 8.51062 18.6912 8.25458C18.6912 4.24322 15.3626 1 11.3513 1C7.33993 1 4.0967 4.24322 4.0967 8.25458C4.0967 8.51062 4.0967 8.85201 4.18205 9.10806C1.87766 9.27875 0 11.1564 0 13.5462C0 16.0212 1.963 17.9842 4.4381 17.9842H7.76667V21.9103L6.82784 21.0568C6.57179 20.8007 6.14506 20.8007 5.88901 21.0568C5.63297 21.3128 5.63297 21.7396 5.88901 21.9956L8.27875 24.2147L10.6685 21.9956C10.9245 21.7396 10.9245 21.3128 10.6685 21.0568C10.4125 20.8007 9.98571 20.8007 9.72967 21.0568L8.79084 21.9103V17.9842H13.3143V12.0952L12.3755 12.9487C12.1194 13.2048 11.6927 13.2048 11.4366 12.9487C11.1806 12.6927 11.1806 12.2659 11.4366 12.0099L13.8264 9.79084L16.2161 12.0099C16.4722 12.2659 16.4722 12.6927 16.2161 12.9487C16.1308 13.1194 15.8747 13.1194 15.704 13.1194C15.5333 13.1194 15.3626 13.0341 15.2773 12.9487L14.3385 12.0952V17.9842H17.8377C17.9231 17.9842 18.0084 17.9842 18.0084 17.8989C20.2275 17.6429 22.0198 15.7652 22.0198 13.4608C22.6172 11.2418 20.8249 9.3641 18.6059 9.10806Z" fill="#354049"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>`),
RouteConfig.Buckets.withIcon(
`<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 12.4548V20.273C1 21.273 1.81116 22.0003 2.71245 22.0003H20.1974C21.1888 22.0003 21.9099 21.1821 21.9099 20.273V12.4548C21.9099 11.4548 21.0987 10.7275 20.1974 10.7275H2.71245C1.81116 10.7275 1 11.4548 1 12.4548ZM14.97 14.0912H7.75966C7.30901 14.0912 6.85837 13.7275 6.85837 13.1821C6.85837 12.7275 7.21888 12.273 7.75966 12.273H14.97C15.4206 12.273 15.8712 12.6366 15.8712 13.1821C15.8712 13.7275 15.5107 14.0912 14.97 14.0912Z" fill="#354049"/>
<path d="M2.53227 9.81792C2.17175 9.81792 1.90137 9.54519 1.90137 9.18155V5.90882C1.90137 5.54519 2.17175 5.27246 2.53227 5.27246H20.4679C20.8284 5.27246 21.0988 5.54519 21.0988 5.90882V8.99973C21.0988 9.36337 20.8284 9.6361 20.4679 9.6361C20.1074 9.6361 19.837 9.36337 19.837 8.99973V6.54519H3.16317V9.18155C3.16317 9.54519 2.89278 9.81792 2.53227 9.81792Z" fill="#354049"/>
<path d="M20.4679 4.27273H2.53227C2.17175 4.27273 1.90137 4 1.90137 3.63636C1.90137 3.27273 2.17175 3 2.53227 3H20.4679C20.8284 3 21.0988 3.27273 21.0988 3.63636C21.0988 4 20.8284 4.27273 20.4679 4.27273Z" fill="#354049"/>
</svg>`),
];
public togglePopup(): void {
if (!this.$store.getters.selectedProject.id) return;

File diff suppressed because one or more lines are too long

View File

@ -52,7 +52,7 @@
import { Component, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import ROUTES from '@/utils/constants/routerConstants';
import { RouteConfig } from '@/router';
@Component({
components: {
@ -65,7 +65,7 @@
}
public onCreateAPIKeyClick(): void {
this.$router.push(ROUTES.API_KEYS.path);
this.$router.push(RouteConfig.ApiKeys.path);
this.onCloseClick();
}

View File

@ -53,7 +53,7 @@
import Checkbox from '@/components/common/Checkbox.vue';
import EmptyState from '@/components/common/EmptyStateArea.vue';
import { PROJETS_ACTIONS, APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
import ROUTES from '@/utils/constants/routerConstants';
import { RouteConfig } from '@/router';
import DeleteProjectPopup from '@/components/project/DeleteProjectPopup.vue';
@Component({
@ -114,7 +114,7 @@
}
public onMoreClick(): void {
this.$router.push(ROUTES.USAGE_REPORT);
this.$router.push(RouteConfig.UsageReport.path);
}
private toggleEditing(): void {

View File

@ -29,19 +29,13 @@
TabNavigation,
}
})
export default class ProjectDetailsArea extends Vue {
export default class ProjectOverviewArea extends Vue {
// TODO: make type for project routes
public navigation: NavigationLink[] = [
new NavigationLink('/project-overview/details', 'Details'),
new NavigationLink('/project-overview/payment-methods', 'Payment Methods'),
new NavigationLink('/project-overview/billing-history', 'Billing History'),
new NavigationLink('/project-overview/usage-report', 'Report'),
];
public mounted(): void {
this.$router.push(this.navigation[0].path);
}
public get isProjectSelected(): boolean {
return this.$store.getters.selectedProject.id !== '';
}

View File

@ -58,7 +58,7 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import ROUTES from '@/utils/constants/routerConstants';
import { RouteConfig } from '@/router';
import Datepicker from '@/components/project/DatePicker.vue';
import { NOTIFICATION_ACTIONS, PROJECT_USAGE_ACTIONS } from '@/utils/constants/actionNames';
import { toUnixTimestamp } from '@/utils/time';
@ -124,7 +124,7 @@
}
public onBackClick(): void {
this.$router.push(ROUTES.PROJECT_OVERVIEW);
this.$router.push(RouteConfig.ProjectOverview.path);
}
public async onCurrentRollupClick(event: any): Promise<void> {

View File

@ -1,113 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div>
<div v-if="billing > 0" class="billing-overflow">
<div class="billing-header">
<p>Billing</p>
</div>
<div class="billing-container">
<div class="billing-container__table-holder">
<table class="billing-container__table">
<SortingHeader />
<BillingItem />
</table>
</div>
<PaginationArea />
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import EmptyState from '@/components/common/EmptyStateArea.vue';
import BillingItem from '@/components/project/billing/BillingItem.vue';
import PaginationArea from '@/components/project/billing/PaginationArea.vue';
import SortingHeader from '@/components/project/billing/SortingHeader.vue';
@Component({
components: {
EmptyState,
SortingHeader,
BillingItem,
PaginationArea,
}
})
export default class BillingArea extends Vue {
public billing: number = 1;
}
</script>
<style scoped lang="scss">
.billing-header {
display: flex;
align-items: center;
justify-content: flex-start;
p {
font-family: 'font_bold';
font-size: 24px;
line-height: 29px;
color: #384B65;
margin-right: 50px;
margin-block-start: 0.5em;
margin-block-end: 0.5em;
}
}
.billing-container {
&__table-holder {
margin-top: 20px;
}
&__table {
margin-top: 20px;
width: 100%;
}
}
.table-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 90px 0 40px;
&:last-child {
padding-left: 20px;
}
}
@media screen and (max-height: 900px) {
.billing-container__table-holder {
overflow-y: scroll;
height: 555px;
&::-webkit-scrollbar,
&::-webkit-scrollbar-track,
&::-webkit-scrollbar-thumb {
visibility: hidden;
}
}
}
@media screen and (max-height: 860px) {
.billing-container__table-holder {
height: 535px;
}
}
@media screen and (max-height: 835px) {
.billing-container__table-holder {
height: 495px;
}
}
@media screen and (max-height: 795px) {
.billing-container__table-holder {
height: 475px;
}
}
</style>

View File

@ -1,121 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<tr class="container">
<td class="container__item bold">test</td>
<td class="container__item">test</td>
<td class="container__item">
<div class="row justify-start">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 7.26316V3.87134C20 3.40351 19.7938 2.93567 19.4845 2.5848C19.1753 2.23392 18.7629 2 18.3505 2H1.64948C1.23711 2 0.824742 2.23392 0.515464 2.5848C0.206186 2.93567 0 3.40351 0 3.87134V7.26316H20Z" fill="#2683FF"/>
<path d="M0 9.36816V16.1852C0 16.5862 0.206186 16.9872 0.515464 17.288C0.824742 17.5887 1.23711 17.7892 1.64948 17.7892H18.3505C18.7629 17.7892 19.1753 17.5887 19.4845 17.288C19.7938 16.9872 20 16.5862 20 16.1852V9.36816H0ZM5.36083 15.1827H2.68041V13.8794H5.36083V15.1827ZM10.7217 15.1827H6.70103V13.8794H10.7217V15.1827Z" fill="#2683FF"/>
</svg>
<p>test</p>
</div>
</td>
<td class="container__item">
<div class="row justify-start">
<svg width="16" height="12" viewBox="0 0 16 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.3333 0H2.66667C1.19418 0 0 1.15147 0 2.57131V9.42869C0 10.8485 1.19418 12 2.66667 12H13.3333C14.8058 12 16 10.8485 16 9.42869V2.57131C16 1.15147 14.8058 0 13.3333 0ZM11.1383 8.1165C11.2642 8.23703 11.335 8.40095 11.335 8.57209C11.335 8.74244 11.265 8.90636 11.14 9.02769C11.0142 9.14822 10.8442 9.21571 10.6675 9.21571C10.49 9.21571 10.32 9.14742 10.195 9.02608L8.00004 6.90876L5.80506 9.02608C5.54422 9.27517 5.12339 9.27437 4.86338 9.02448C4.60423 8.77376 4.60337 8.36799 4.86172 8.11647L7.05756 5.99997L4.86172 3.88348C4.60339 3.63196 4.60422 3.22619 4.86338 2.97547C5.12339 2.72558 5.54422 2.72476 5.80506 2.97387L8.00004 5.09119L10.195 2.97469V2.97389C10.4559 2.7248 10.8767 2.7256 11.1367 2.97549C11.3959 3.22621 11.3967 3.63198 11.1384 3.8835L8.94253 5.99999L11.1383 8.1165Z" fill="#EB001B"/>
</svg>
<p>test</p>
</div>
</td>
<td class="container__item bold">
<div class="row">
<p>test</p>
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect class="background" width="40" height="40" rx="4" fill="#E2ECF7"/>
<path class="blue" d="M25.6491 19.2809L21.2192 23.5281C20.891 23.8427 20.3988 24 20.0707 24C19.7425 24 19.2503 23.8427 19.0862 23.5281L14.4922 19.2809C13.8359 18.6517 13.8359 17.8652 14.4922 17.236C14.8204 16.9213 15.1485 16.9213 15.6407 16.9213C15.9689 16.9213 16.4611 17.0787 16.6252 17.3933L18.594 19.1236L18.594 11.4157C18.594 10.6292 19.2503 10 20.0707 10C20.891 10 21.5473 10.6292 21.5473 11.4157L21.5473 19.1236L23.5162 17.236C23.6803 16.9213 24.1725 16.9213 24.5006 16.9213C24.8288 16.9213 25.321 17.0787 25.4851 17.3933C26.1414 17.8652 26.1414 18.809 25.6491 19.2809Z" fill="#2683FF"/>
<rect class="blue" x="11" y="28" width="18" height="2" rx="1" fill="#2683FF"/>
</svg>
</div>
</td>
</tr>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class BillingItem extends Vue {}
</script>
<style scoped lang="scss">
.container {
transition: box-shadow .2s ease-out;
padding: 35px 0px 35px 70px;
transition: all .2s ease;
margin-bottom: 10px;
border-radius: 6px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
outline: none;
&:hover {
background: #fff;
box-shadow: 0px 4px 4px rgba(231, 232, 238, 0.6);
}
&__item {
width: 20%;
height: 80px;
padding-left: 30px;
font-family: 'font_medium';
font-size: 16px;
margin: 0;
svg {
cursor: pointer;
}
svg:hover {
.background {
fill: #2683FF !important;
}
.blue {
fill: white !important;
}
}
}
&:first-of-type {
font-weight: bold;
}
}
.row {
display: flex;
justify-content: space-between;
align-items: center;
padding-right: 36px;
}
.justify-start {
justify-content: flex-start;
svg {
cursor: default;
}
p {
margin-left: 7px;
}
}
.bold {
font-family: 'font_bold';
}
@media screen and (max-width: 1600px) {
.container {
grid-template-columns: 2% 20% 30% 20% 15% 13%;
padding: 20px 0px 20px 70px;
}
}
</style>

View File

@ -1,121 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="pagination-container">
<div class="pagination-container__pages">
<div v-html="arrowLeft" class="pagination-container__button"></div>
<div class="pagination-container__items">
<span class="selected">1</span>
<span>2</span>
</div>
<div v-html="arrowRight" class="pagination-container__button"></div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
@Component
export default class PaginationArea extends Vue {
public arrowLeft: string = EMPTY_STATE_IMAGES.ARROW_LEFT;
public arrowRight: string = EMPTY_STATE_IMAGES.ARROW_RIGHT;
}
</script>
<style scoped lang="scss">
.pagination-container {
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 25px;
margin-top: 25px;
&__pages {
display: flex;
align-items: center;
}
&__counter {
p {
font-family: 'font_medium';
font-size: 16px;
color: #AFB7C1;
}
}
&__button {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: 1px solid #AFB7C1;
border-radius: 6px;
width: 30px;
height: 30px;
&:hover {
svg {
path {
fill: #fff !important;
}
}
}
}
&__items {
margin: 0 20px;
display: flex;
.selected {
color: #2379EC;
font-family: 'font_bold';
&:after {
content: '';
display: block;
position: absolute;
bottom: -4px;
left: 0;
width: 10px;
height: 2px;
background-color: #2379EC;
}
}
span {
font-family: 'font_medium';
font-size: 16px;
margin-right: 15px;
cursor: pointer;
display: block;
position: relative;
transition: all .2s ease;
&:hover {
color: #2379EC;
&:after {
content: '';
display: block;
position: absolute;
bottom: -4px;
left: 0;
width: 100%;
height: 2px;
background-color: #2379EC;
}
}
&:last-child {
margin-right: 0;
}
}
}
}
</style>

View File

@ -1,114 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<tr class="sort-header-container">
<th class="sort-header-container__item">
<div class="row">
<p>Invoice</p>
<div class="sort-header-container__item__arrows">
<span v-html="arrowUp"></span>
<span class="selected" v-html="arrowDown"></span>
</div>
</div>
</th>
<th class="sort-header-container__item">
<div class="row">
<p>Billing Period</p>
<div class="sort-header-container__item__arrows">
<span v-html="arrowUp"></span>
<span v-html="arrowDown"></span>
</div>
</div>
</th>
<th class="sort-header-container__item">
<div class="row">
<p>Payment method</p>
</div>
</th>
<th class="sort-header-container__item">
<div class="row">
<p>Status</p>
</div>
</th>
<th class="sort-header-container__item">
<div class="row">
<p>Amount</p>
<div class="sort-header-container__item__arrows">
<span v-html="arrowUp"></span>
<span v-html="arrowDown"></span>
</div>
</div>
</th>
</tr>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
@Component
export default class SortProjectBillingHeader extends Vue {
public arrowUp: string = EMPTY_STATE_IMAGES.ARROW_UP;
public arrowDown: string = EMPTY_STATE_IMAGES.ARROW_DOWN;
}
</script>
<style scoped lang="scss">
.sort-header-container {
height: 80px;
&__item {
margin: 0;
cursor: pointer;
text-align: left;
padding-left: 30px;
&__arrows {
display: flex;
flex-direction: column;
justify-content: flex-start;
padding-bottom: 12px;
margin-left: 10px;
span.selected {
svg {
path {
fill: #2683FF !important;
}
}
}
span {
height: 10px;
}
}
p {
font-family: 'font_medium';
font-size: 16px;
line-height: 23px;
color: #AFB7C1;
}
&:nth-child(1) {
margin-left: 0px;
}
}
}
.row {
display: flex;
flex-direction: row;
align-items: center;
}
@media screen and (max-width: 1600px) {
.sort-header-container {
grid-template-columns: 25% 28% 19% 15% 14%;
height: 65px;
}
}
</style>

View File

@ -1,215 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="payment-methods-container__card-container">
<div class="payment-methods-container__card-container__info-area">
<img class="payment-methods-container__card-container__info-area__card-logo" src="@/../static/images/Logo.svg">
<div class="payment-methods-container__card-container__info-area__info-container">
<h1>xxxx {{paymentMethod.lastFour}}</h1>
</div>
<div class="payment-methods-container__card-container__info-area__expire-container">
<h2>Expires</h2>
<h1>{{paymentMethod.expMonth}}/{{paymentMethod.expYear}}</h1>
</div>
<h3 class="payment-methods-container__card-container__info-area__added-text">Added on {{formatDate(paymentMethod.addedAt)}}</h3>
</div>
<div class="payment-methods-container__card-container__default-button" v-if="paymentMethod.isDefault">
<p class="payment-methods-container__card-container__default-button__label">Default</p>
</div>
<div class="payment-methods-container__card-container__make-default-container" v-if="!paymentMethod.isDefault">
<div class="payment-methods-container__card-container__make-default-container__make-button" v-on:click="onMakeDefaultClick(paymentMethod.id)" id="makeDefaultPaymentMethodButton">
<p class="payment-methods-container__card-container__make-default-container__make-button__label">Make Default</p>
</div>
<MakeDefaultPaymentMethodDialog :paymentMethodID="paymentMethod.id" v-if="isSetDefaultPaymentMethodPopupShown"/>
</div>
<div class="payment-methods-container__card-container__delete-button-container">
<div class="payment-methods-container__card-container__delete-button-container__delete-button" v-on:click="onDeletePaymentMethodClick" id="deletePaymentMethodButton">
<svg width="34"
height="34"
viewBox="0 0 34 34"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<rect width="34" height="34" rx="17" fill="#EB5757"/>
<path d="M19.7834 11.9727V11.409C19.7834 10.6576 19.1215 10 18.2706 10H16.0014C15.1504 10 14.4886 10.6576 14.4886 11.409V11.9727H10.7065V13.1938H12.0302V22.3057C12.0302 23.5269 12.9758 24.4662 14.0158 24.4662H20.1616C21.2962 24.4662 22.1471 23.5269 22.1471 22.3057V13.1938H23.4709V11.9727H19.7834ZM16.6632 22.3057H15.3395V14.2271H16.6632V22.3057ZM18.9324 22.3057H17.6087V14.2271H18.9324V22.3057Z" fill="white"/>
</svg>
</div>
<DeletePaymentMethodDialog :paymentMethodID="paymentMethod.id" v-if="isDeletePaymentMethodPopupShown"/>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import { APP_STATE_ACTIONS, } from '@/utils/constants/actionNames';
import DeletePaymentMethodDialog from '@/components/project/paymentMethods/DeletePaymentMethodDialog.vue';
import MakeDefaultPaymentMethodDialog from '@/components/project/paymentMethods/MakeDefaultPaymentMethodDialog.vue';
@Component({
components: {
MakeDefaultPaymentMethodDialog,
Button,
DeletePaymentMethodDialog,
}
})
export default class CardComponent extends Vue {
@Prop({default: {}})
private readonly paymentMethod: PaymentMethod;
public formatDate(d: string): string {
return new Date(d).toLocaleDateString('en-US', {timeZone: 'UTC'});
}
public async onMakeDefaultClick(): Promise<void> {
if (this.getSetDefaultPaymentMethodID == this.paymentMethod.id) {
this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS);
return;
}
this.$store.dispatch(APP_STATE_ACTIONS.SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP, this.paymentMethod.id);
}
public async onDeletePaymentMethodClick(): Promise<void> {
if (this.getDeletePaymentMethodID == this.paymentMethod.id) {
this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS);
return;
}
this.$store.dispatch(APP_STATE_ACTIONS.SHOW_DELETE_PAYMENT_METHOD_POPUP, this.paymentMethod.id);
}
public get getDeletePaymentMethodID(): string {
return this.$store.state.appStateModule.appState.deletePaymentMethodID;
}
public get getSetDefaultPaymentMethodID(): string {
return this.$store.state.appStateModule.appState.setDefaultPaymentMethodID;
}
public get isDeletePaymentMethodPopupShown(): boolean {
return this.$store.state.appStateModule.appState.deletePaymentMethodID == this.paymentMethod.id;
}
public get isSetDefaultPaymentMethodPopupShown(): boolean {
return this.$store.state.appStateModule.appState.setDefaultPaymentMethodID == this.paymentMethod.id;
}
}
</script>
<style scoped lang="scss">
h1 {
font-family: 'font_bold';
font-size: 16px;
line-height: 21px;
color: #61666B;
margin-block-start: 0.5em;
margin-block-end: 0.5em;
}
h2 {
font-family: 'font_regular';
font-size: 16px;
line-height: 21px;
color: #61666B;
margin-right: 5px;
}
.payment-methods-container__card-container {
width: calc(100% - 80px);
margin-top: 24px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 25px 40px 25px 40px;
background-color: white;
border-radius: 6px;
&__info-area {
width: 75%;
display: flex;
align-items: center;
justify-content: space-between;
&__card-logo {
height: 70px;
width: 85px;
}
&__info-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: auto;
}
&__expire-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: auto;
}
&__added-text {
font-family: 'font_regular';
font-size: 16px;
line-height: 21px;
color: #61666B;
}
}
&__default-button {
width: 100px;
height: 34px;
border-radius: 6px;
background-color: #F5F6FA;
display: flex;
justify-content: center;
align-items: center;
&__label {
font-family: 'font_medium';
font-size: 16px;
line-height: 23px;
color: #AFB7C1;
}
}
&__make-default-container {
position: relative;
&__make-button {
width: 134px;
height: 34px;
border-radius: 6px;
background-color: #DFEDFF;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
&__label {
font-family: 'font_medium';
font-size: 16px;
line-height: 23px;
color: #2683FF;
}
}
}
&__delete-button-container {
position: relative;
&__delete-button {
svg {
cursor: pointer;
}
}
}
}
</style>

View File

@ -1,105 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="dialog-container" id="deletePaymentMethodDialog">
<div class="delete-container">
<h1>Confirm Delete Card</h1>
<h2>Are you sure you want to remove your card?</h2>
<div class="button-container">
<Button height="48px" width="128px" label="Cancel" isWhite="true" :onPress="onCancelClick"/>
<Button class="delete-button" height="48px" width="128px" label="Delete" :onPress="onDeleteClick"/>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import {
APP_STATE_ACTIONS,
NOTIFICATION_ACTIONS,
PROJECT_PAYMENT_METHODS_ACTIONS
} from '@/utils/constants/actionNames';
@Component({
components: {
Button,
}
})
export default class DeletePaymentMethodDialog extends Vue {
@Prop({default: ''})
private readonly paymentMethodID: string;
public onCancelClick(): void {
this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS);
}
public async onDeleteClick(): Promise<void> {
const response = await this.$store.dispatch(PROJECT_PAYMENT_METHODS_ACTIONS.DELETE, this.paymentMethodID);
if (!response.isSuccess) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
}
const paymentMethodsResponse = await this.$store.dispatch(PROJECT_PAYMENT_METHODS_ACTIONS.FETCH);
if (!paymentMethodsResponse.isSuccess) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch payment methods: ${paymentMethodsResponse.errorMessage}`);
}
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Payment method deleted successfully');
}
}
</script>
<style scoped lang="scss">
.dialog-container {
background-image: url('../../../../static/images/container.png');
background-size: 340px 240px;
z-index: 1;
position: absolute;
bottom: 40px;
right: -17px;
height: 240px;
width: 340px;
}
h1 {
font-family: 'font_bold';
font-size: 16px;
line-height: 21px;
color: #384B65;
}
h2 {
font-family: 'font_regular';
font-size: 12px;
color: #384B65;
margin-top: 20px;
}
.delete-container {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 25px 32px 33px 32px;
box-shadow: 0px 4px 20px rgba(204, 208, 214, 0.25);
}
.button-container {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 35px;
}
.delete-button {
background-color: #EB5757;
color: white;
&:hover {
box-shadow: none;
background-color: #d24949;
}
}
</style>

View File

@ -1,97 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="dialog-container" id="makeDefaultPaymentDialog">
<div class="delete-container">
<h1>Update Default Card</h1>
<h2>We will automatically charge your default card at the close of the current billing period</h2>
<div class="button-container">
<Button height="48px" width="128px" label="Cancel" isWhite="true" :onPress="onCancelClick"/>
<Button class="delete-button" height="48px" width="128px" label="Update" :onPress="onUpdateClick"/>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import {
APP_STATE_ACTIONS,
NOTIFICATION_ACTIONS,
PROJECT_PAYMENT_METHODS_ACTIONS
} from '@/utils/constants/actionNames';
@Component({
components: {
Button,
}
})
export default class MakeDefaultPaymentMethodDialog extends Vue {
@Prop({default: ''})
private readonly paymentMethodID: string;
public onCancelClick(): void {
this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS);
}
public async onUpdateClick(): Promise<void> {
const result = await this.$store.dispatch(PROJECT_PAYMENT_METHODS_ACTIONS.SET_DEFAULT, this.paymentMethodID);
if (!result.isSuccess) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, result.errorMessage);
return;
}
const paymentMethodsResponse = await this.$store.dispatch(PROJECT_PAYMENT_METHODS_ACTIONS.FETCH);
if (!paymentMethodsResponse.isSuccess) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch payment methods: ${paymentMethodsResponse.errorMessage}`);
}
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Default payment method set successfully');
}
}
</script>
<style scoped lang="scss">
.dialog-container {
background-image: url('../../../../static/images/ContainerCentered.png');
background-size: 340px 240px;
z-index: 1;
position: absolute;
left: 50%;
bottom: 40px;
transform: translate(-50%);
height: 240px;
width: 340px;
}
h1 {
font-family: 'font_bold';
font-size: 16px;
line-height: 21px;
color: #384B65;
}
h2 {
font-family: 'font_regular';
font-size: 12px;
color: #384B65;
}
.delete-container {
display: flex;
flex-direction: column;
padding: 25px 32px 33px 32px;
box-shadow: 0px 4px 20px rgba(204, 208, 214, 0.25);
margin-top: 4px;
}
.button-container {
display: flex;
flex-direction: row;
margin-top: 25px;
justify-content: space-between;
}
</style>

View File

@ -1,228 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="add-payment-popup-overflow" v-on:keyup.enter="onDoneClick" v-on:keyup.esc="onCloseClick">
<div class="add-payment-popup-container">
<div class="card-form-input">
<img src="../../../../static/images/Card.svg"/>
<form id="payment-form">
<div class="form-row">
<div id="card-element">
<!-- A Stripe Element will be inserted here. -->
</div>
<!-- Used to display form errors. -->
<div id="card-errors" role="alert"></div>
</div>
<div class="checkbox-container" v-if="projectPaymentMethodsCount > 0">
<Checkbox @setData="toggleMakeDefault"/>
<h2>Make Default</h2>
</div>
<Button
label="Save"
width="135px"
height="48px"
:on-press="onSaveClick"/>
</form>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import {
NOTIFICATION_ACTIONS,
PROJECT_PAYMENT_METHODS_ACTIONS
} from '@/utils/constants/actionNames';
import Checkbox from '@/components/common/Checkbox.vue';
@Component(
{
data: function () {
return {
makeDefault: false,
};
},
mounted: function () {
if (!window['Stripe']) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Stripe library not loaded');
return;
}
const stripe = window['Stripe'](process.env.VUE_APP_STRIPE_PUBLIC_KEY);
if (!stripe) {
console.error('Unable to initialize stripe');
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Unable to initialize stripe');
return;
}
const elements = stripe.elements();
if (!elements) {
console.error('Unable to instantiate elements');
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Unable to instantiate elements');
return;
}
const card = elements.create('card');
if (!card) {
console.error('Unable to create card');
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Unable to create card');
return;
}
card.mount('#card-element');
card.addEventListener('change', function (event) {
const displayError = document.getElementById('card-errors') as HTMLElement;
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
const form = document.getElementById('payment-form') as HTMLElement;
let self = this;
form.addEventListener('submit', function (event) {
event.preventDefault();
stripe.createToken(card).then(async function (result: any) {
if (result.token.card.funding == 'prepaid') {
self.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Prepaid cards not supported');
return;
}
const input = {
token: result.token.id,
makeDefault: self.$data.makeDefault} as AddPaymentMethodInput;
const response = await self.$store.dispatch(PROJECT_PAYMENT_METHODS_ACTIONS.ADD, input);
if (!response.isSuccess) {
self.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.error);
}
await self.$store.dispatch(PROJECT_PAYMENT_METHODS_ACTIONS.FETCH);
self.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Card successfully added');
card.clear();
});
});
},
computed: {
projectPaymentMethodsCount: function () {
if (this.$store.state.projectPaymentsMethodsModule.paymentMethods) {
return this.$store.state.projectPaymentsMethodsModule.paymentMethods.length;
} else {
return 0;
}
}
},
methods: {
toggleMakeDefault: function (value: boolean) {
this.$data.makeDefault = value;
},
onSaveClick: function () {
const form = document.getElementById('payment-form') as HTMLElement;
const saveEvent = new CustomEvent('submit', {'bubbles': true});
form.dispatchEvent(saveEvent);
}
},
components: {
Button,
Checkbox,
}
}
)
export default class AddNewPaymentMethodPopup extends Vue {
}
</script>
<style scoped lang="scss">
.StripeElement {
box-sizing: border-box;
width: 484px;
padding: 13px 12px;
border: 1px solid transparent;
border-radius: 4px;
background-color: white;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
.StripeElement--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
border-color: #fa755a;
}
.StripeElement--webkit-autofill {
background-color: #fefde5 !important;
}
.card-form-input {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
form {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}
img {
margin-top: 7px;
margin-right: 25px;
margin-left: -20px;
}
}
.checkbox-container {
display: flex;
justify-content: center;
align-items: center;
h2 {
font-family: 'font_regular';
font-size: 12px;
line-height: 18px;
color: #384B65;
}
}
.add-payment-popup-overflow {
margin-top: 37px;
}
.add-payment-popup-container {
width: calc(100% - 80px);
display: flex;
align-items: center;
justify-content: space-between;
padding: 25px 40px 25px 40px;
background-color: white;
border-radius: 6px;
}
</style>

View File

@ -71,7 +71,7 @@
import Button from '@/components/common/Button.vue';
import { EmailInput } from '@/types/EmailInput';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
import ROUTES from '@/utils/constants/routerConstants';
import { RouteConfig } from '@/router';
import { validateEmail } from '@/utils/validation';
@Component({
@ -197,7 +197,7 @@
}
public get registerPath(): string {
return location.host + ROUTES.REGISTER.path;
return location.host + RouteConfig.Register.path;
}
private resetFormErrors(index): void {

View File

@ -13,129 +13,123 @@ import ForgotPassword from '@/views/forgotPassword/ForgotPassword.vue';
import Login from '@/views/login/Login.vue';
import Page404 from '@/components/errors/Page404.vue';
import Profile from '@/components/account/Profile.vue';
import ProjectBillingHistory from '@/components/project/billing/BillingArea.vue';
import ProjectDetails from '@/components/project/ProjectDetails.vue';
import ProjectMembersArea from '@/components/team/ProjectMembersArea.vue';
import ProjectOverviewArea from '@/components/project/ProjectOverviewArea.vue';
import ProjectPaymentMethods from '@/components/project/ProjectPaymentMethods.vue';
import Register from '@/views/register/Register.vue';
import Router from 'vue-router';
import ROUTES from '@/utils/constants/routerConstants';
import store from '@/store';
import Router, { RouteRecord } from 'vue-router';
import UsageReport from '@/components/project/UsageReport.vue';
import { NavigationLink } from '@/types/navigation';
Vue.use(Router);
let router = new Router({
export abstract class RouteConfig {
// root paths
public static Root = new NavigationLink('/', 'Root');
public static Login = new NavigationLink('/login', 'Login');
public static Register = new NavigationLink('/register', 'Register');
public static ForgotPassword = new NavigationLink('/forgot-password', 'Forgot Password');
public static Account = new NavigationLink('/account', 'Account');
public static ProjectOverview = new NavigationLink('/project-overview', 'Overview');
public static Team = new NavigationLink('/project-members', 'Team');
public static ApiKeys = new NavigationLink('/api-keys', 'API Keys');
public static Buckets = new NavigationLink('/buckets', 'Buckets');
// child paths
public static ProjectDetails = new NavigationLink('details', 'Project Details');
public static BillingHistory = new NavigationLink('billing-history', 'Billing History');
public static UsageReport = new NavigationLink('usage-report', 'Usage Report');
public static PaymentMethods = new NavigationLink('payment-methods', 'Payment Methods');
public static Profile = new NavigationLink('profile', 'Profile');
// not in project yet
// public static Referral = new NavigationLink('//ref/:ids', 'Referral');
}
const router = new Router({
mode: 'history',
routes: [
{
path: ROUTES.LOGIN.path,
name: ROUTES.LOGIN.name,
path: RouteConfig.Login.path,
name: RouteConfig.Login.name,
component: Login
},
{
path: ROUTES.REGISTER.path,
name: ROUTES.REGISTER.name,
path: RouteConfig.Register.path,
name: RouteConfig.Register.name,
component: Register
},
{
path: ROUTES.REFERRAL.path,
name: ROUTES.REFERRAL.name,
component: Register
},
{
path: ROUTES.FORGOT_PASSWORD.path,
name: ROUTES.FORGOT_PASSWORD.name,
path: RouteConfig.ForgotPassword.path,
name: RouteConfig.ForgotPassword.name,
component: ForgotPassword
},
{
path: ROUTES.DASHBOARD.path,
path: RouteConfig.Root.path,
meta: {
requiresAuth: true
},
component: Dashboard,
children: [
{
path: ROUTES.ACCOUNT_SETTINGS.path,
name: ROUTES.ACCOUNT_SETTINGS.name,
path: RouteConfig.Account.path,
name: RouteConfig.Account.name,
component: AccountArea,
children: [
{
path: ROUTES.PROFILE.path,
name: ROUTES.PROFILE.name,
path: RouteConfig.Profile.path,
name: RouteConfig.Profile.name,
component: Profile,
},
{
path: ROUTES.PAYMENT_METHODS.path,
name: ROUTES.PAYMENT_METHODS.name,
path: RouteConfig.PaymentMethods.path,
name: RouteConfig.PaymentMethods.name,
component: AccountPaymentMethods,
},
{
path: ROUTES.BILLING_HISTORY.path,
name: ROUTES.BILLING_HISTORY.name,
path: RouteConfig.BillingHistory.path,
name: RouteConfig.BillingHistory.name,
component: AccountBillingHistory,
},
]
},
{
path: ROUTES.PROJECT_OVERVIEW.path,
name: ROUTES.PROJECT_OVERVIEW.name,
path: RouteConfig.ProjectOverview.path,
name: RouteConfig.ProjectOverview.name,
component: ProjectOverviewArea,
children: [
{
path: ROUTES.USAGE_REPORT.path,
name: ROUTES.USAGE_REPORT.name,
path: RouteConfig.UsageReport.path,
name: RouteConfig.UsageReport.name,
component: UsageReport,
},
{
path: ROUTES.PROJECT_DETAILS.path,
name: ROUTES.PROJECT_DETAILS.name,
path: RouteConfig.ProjectDetails.path,
name: RouteConfig.ProjectDetails.name,
component: ProjectDetails
},
{
path: ROUTES.BILLING_HISTORY.path,
name: ROUTES.BILLING_HISTORY.name,
component: ProjectBillingHistory
},
{
path: ROUTES.PAYMENT_METHODS.path,
name: ROUTES.PAYMENT_METHODS.name,
component: ProjectPaymentMethods
},
]
},
// Remove when dashboard will be created
{
path: '/',
path: RouteConfig.Root.path,
name: 'default',
component: ProjectOverviewArea
},
{
path: ROUTES.TEAM.path,
name: ROUTES.TEAM.name,
path: RouteConfig.Team.path,
name: RouteConfig.Team.name,
component: ProjectMembersArea
},
{
path: ROUTES.API_KEYS.path,
name: ROUTES.API_KEYS.name,
path: RouteConfig.ApiKeys.path,
name: RouteConfig.ApiKeys.name,
component: ApiKeysArea
},
{
path: ROUTES.BUCKETS.path,
name: ROUTES.BUCKETS.name,
path: RouteConfig.Buckets.path,
name: RouteConfig.Buckets.name,
component: BucketArea
},
// {
// path: ROUTES.BUCKETS.path,
// name: ROUTES.BUCKETS.name,
// component: BucketArea
// },
// {
// path: '/',
// name: 'dashboardArea',
// component: DashboardArea
// },
]
},
{
@ -146,34 +140,40 @@ let router = new Router({
]
});
// Makes check that Token exist at session storage before any route except Login and Register
// and if we are able to navigate to page without existing project
router.beforeEach((to, from, next) => {
if (isUnavailablePageWithoutProject(to.name as string)) {
next(ROUTES.PROJECT_OVERVIEW.path + '/' + ROUTES.PROJECT_DETAILS.path);
return;
}
if (to.matched.some(route => route.meta.requiresAuth)) {
if (!AuthToken.get()) {
next(ROUTES.LOGIN);
next(RouteConfig.Login.path);
return;
}
}
if (navigateToFirstSubTab(to.matched, RouteConfig.Account, RouteConfig.Profile)) {
next(RouteConfig.Account.with(RouteConfig.Profile).path);
return;
}
if (navigateToFirstSubTab(to.matched, RouteConfig.ProjectOverview, RouteConfig.ProjectDetails)) {
next(RouteConfig.ProjectOverview.with(RouteConfig.ProjectDetails).path);
return;
}
next();
});
// isUnavailablePageWithoutProject checks if we are able to navigate to page without existing project
function isUnavailablePageWithoutProject(pageName: string): boolean {
let unavailablePages: string[] = [ROUTES.TEAM.name, ROUTES.API_KEYS.name, ROUTES.BUCKETS.name];
const state = store.state as any;
let isProjectSelected = state.projectsModule.selectedProject.id !== '';
return unavailablePages.includes(pageName) && !isProjectSelected;
/**
* if our route is a tab and has no sub tab route - we will navigate to default subtab.
* F.E. /account/ -> /account/profile/; /project-overview/ -> /project-overview/details/
* @param routes - array of RouteRecord from vue-router
* @param next - callback to process next route
* @param tabRoute - tabNavigator route
* @param subTabRoute - default sub route of the tabNavigator
*/
function navigateToFirstSubTab(routes: RouteRecord[], tabRoute: NavigationLink, subTabRoute: NavigationLink): boolean {
return routes.length == 2 && (routes[1].name as string) === tabRoute.name;
}
export default router;

View File

@ -2,12 +2,40 @@
// See LICENSE for copying information.
export class NavigationLink {
public path: string;
public name: string;
private _path: string;
private _name: string;
private _icon: string;
public constructor(path: string, name: string) {
this.path = path;
this.name = name;
public constructor(path: string, name: string, icon: string = '') {
this._path = path;
this._name = name;
this._icon = icon;
}
public get path(): string {
return this._path;
}
public get name(): string {
return this._name;
}
public get icon(): string {
return this._icon;
}
public isChild(): boolean {
return this._path[0] !== '/';
}
public withIcon(icon: string): NavigationLink {
return new NavigationLink(this._path, this._name, icon);
}
public with(child: NavigationLink): NavigationLink {
if (!child.isChild()) {
// TODO: better error message
throw new Error('child root is not child');
}
return new NavigationLink(`${this.path}/${child.path}`, child.name);
}
}

View File

@ -1,72 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import ROUTES from '@/utils/constants/routerConstants';
const NAVIGATION_ITEMS = {
// DASHBOARD: {
// label: 'Dashboard',
// path: '/',
// svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
// <g clip-path="url(#clip0)">
// <path fill-rule="evenodd" clip-rule="evenodd" d="M22.9535 4.1849C23.1974 3.94097 23.604 3.94097 23.8479 4.1849C24.0918 4.42882 24.0918 4.83536 23.8479 4.99798L19.8638 9.22602V7.43723L22.9535 4.1849ZM3.52035 14.0232C3.60165 14.1045 3.76427 14.1858 3.92689 14.1858C4.08951 14.1858 4.25212 14.1045 4.25212 14.0232L8.8867 9.38865C9.04932 9.22603 9.29324 9.14472 9.45586 9.14472C9.69979 9.14472 9.8624 9.22603 10.025 9.38865L13.3587 12.8849C13.7652 13.2914 14.2531 13.5354 14.8222 13.5354C15.3914 13.5354 15.8792 13.2914 16.2858 12.8849L19.7822 9.23804V15.4056C19.8636 16.1374 19.2131 16.7879 18.4813 16.7879H2.38224C1.56916 16.7879 1 16.1374 1 15.4056V5.6486C1 4.83552 1.65047 4.26636 2.38224 4.26636H18.4C19.2131 4.26636 19.7822 4.91682 19.7822 5.6486V7.51567L15.4727 12.1531C15.3101 12.3157 15.1474 12.3971 14.9035 12.3971C14.6596 12.3971 14.497 12.3157 14.3344 12.1531L11.0007 8.65687C10.5942 8.25033 10.1063 8.0064 9.53717 8.0064C9.04932 8.0064 8.48016 8.16902 8.15493 8.49425L3.52035 13.1288C3.27642 13.3728 3.27642 13.7793 3.52035 14.0232ZM15.5543 21.341H5.2281C4.90287 21.341 4.57764 21.097 4.57764 20.6905C4.57764 20.284 4.82156 20.04 5.2281 20.04H15.5543C15.8795 20.04 16.2047 20.284 16.2047 20.6905C16.2047 21.097 15.8795 21.341 15.5543 21.341Z" fill="#354049"/>
// </g>
// <defs>
// <clipPath id="clip0">
// <rect width="24" height="24" fill="white"/>
// </clipPath>
// </defs>
// </svg>`
// },
PROJECT_OVERVIEW: {
label: 'Overview',
path: ROUTES.PROJECT_OVERVIEW.path + '/' + ROUTES.PROJECT_DETAILS.path,
svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.073 5.3913C21.8382 5.15652 21.5252 5 21.2121 5H6.89038C6.26429 5 5.71647 5.54783 5.79473 6.09565L2.19473 6.01739C1.80342 6.09565 1.49038 6.17391 1.2556 6.48696C1.09908 6.72174 0.942555 7.03478 1.02082 7.42609L3.13386 18.4609C3.21212 19.0087 3.68169 19.4 4.22951 19.4H19.0991C19.6469 19.4 20.1165 19.0087 20.1947 18.4609L22.3078 6.33043C22.386 6.01739 22.3078 5.62609 22.073 5.3913ZM19.6469 14.7826L18.7078 9.38261C18.6295 8.75652 18.0034 8.28696 17.3773 8.28696H8.4556C8.37734 8.28696 8.29908 8.2087 8.29908 8.13043L8.14256 7.34783C8.14256 6.8 7.75125 6.33043 7.28169 6.17391L21.2121 6.09565L19.6469 14.7826Z" fill="#363840"/>
</svg>`
},
TEAM: {
label: 'Team',
path: ROUTES.TEAM.path,
svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M19.6621 11.1388C19.8233 10.8971 19.9039 10.6553 19.9845 10.333C20.5485 10.0913 20.8709 9.52718 20.9515 8.72136C21.032 7.99612 20.7097 7.43204 20.3068 7.10971C20.2262 5.01456 19.5816 3 16.6 3C13.6184 3 12.9738 5.01456 12.8126 7.10971C12.4097 7.43204 12.0874 8.0767 12.168 8.72136C12.2485 9.4466 12.6515 10.0913 13.135 10.333C13.2155 10.5748 13.3767 10.8971 13.4573 11.1388C12.9738 11.3 12.4903 11.4612 12.0874 11.6223C11.6845 11.4612 11.201 11.2194 10.7175 11.1388C10.8786 10.8971 10.9592 10.6553 11.0398 10.333C11.6039 10.0913 11.9262 9.52718 12.0068 8.72136C12.0874 7.99612 11.765 7.43204 11.3621 7.10971C11.201 5.01456 10.6369 3 7.57476 3C4.5932 3 3.94854 5.01456 3.78738 7.10971C3.38447 7.43204 3.06214 8.0767 3.14272 8.72136C3.2233 9.4466 3.62621 10.0913 4.10971 10.333C4.19029 10.5748 4.35146 10.8971 4.43204 11.1388C1.53107 11.9447 0 13.6369 0 16.2155C0 16.4573 0.161165 16.6184 0.32233 16.699C2.09515 17.5049 4.75437 17.9883 7.49418 17.9883C9.10583 17.9883 10.6369 17.8272 12.0068 17.5049C13.3767 17.8272 14.9078 17.9883 16.5194 17.9883C19.2592 17.9883 21.9184 17.5049 23.6913 16.699C23.8524 16.6184 24.0136 16.3767 24.0136 16.2155C24.0942 13.6369 22.5631 11.9447 19.6621 11.1388Z" fill="#354049"/>
<path d="M13.7532 12.8937C13.1891 13.1354 12.5445 13.2966 11.8192 13.4577C11.094 13.2966 10.4493 13.1354 9.88525 12.8937C9.96584 11.6043 10.6105 10.5568 11.8192 9.91211C13.1086 10.5568 13.6726 11.5238 13.7532 12.8937Z" fill="#2683FF"/>
<path class="white" d="M14.3174 13.832C17.0572 14.4767 19.0717 15.8466 19.0717 18.7476C17.1378 19.634 14.3174 20.0369 11.8193 20.0369C9.32126 20.0369 6.42029 19.634 4.56689 18.7476C4.56689 15.8466 6.50087 14.4767 9.32126 13.832" fill="white"/>
<path d="M11.7389 20.6001C8.8379 20.6001 6.01751 20.1166 4.24469 19.2302C4.08353 19.2302 3.92236 18.9884 3.92236 18.8273C3.92236 16.0069 5.6146 14.1535 9.07964 13.3477L9.32139 14.3952C6.58159 15.0399 5.21168 16.3292 5.05052 18.4244C6.74275 19.1496 9.24081 19.5525 11.8195 19.5525C14.3981 19.5525 16.8156 19.1496 18.5884 18.4244C18.4272 16.3292 17.0573 15.0399 14.3175 14.3952L14.5593 13.3477C17.9437 14.1535 19.7165 16.0069 19.7165 18.8273C19.7165 19.069 19.5554 19.2302 19.3942 19.3108C17.4602 20.1166 14.6398 20.6001 11.7389 20.6001Z" fill="#354049"/>
<path class="white" d="M11.7388 15.3628C10.5301 15.3628 9.16018 13.9929 8.5961 12.1395C8.11261 12.1395 7.79028 11.5754 7.7097 10.9308C7.62911 10.2861 7.95144 9.72205 8.35436 9.56088C8.43494 6.98224 9.16018 5.45117 11.7388 5.45117C14.3175 5.45117 15.0427 6.98224 15.1233 9.56088C15.5262 9.64146 15.8485 10.2055 15.7679 10.8502C15.6874 11.4949 15.365 12.0589 14.8815 12.0589C14.398 13.9929 12.9476 15.3628 11.7388 15.3628Z" fill="white"/>
<path d="M11.7387 15.926C10.2882 15.926 8.83776 14.5561 8.11251 12.6221C7.54844 12.3804 7.14552 11.7357 7.06494 11.0105C7.06494 10.2047 7.38727 9.56 7.79018 9.23767C7.95135 7.06194 8.59601 4.9668 11.7387 4.9668C14.8814 4.9668 15.5261 7.06194 15.6873 9.23767C16.1708 9.56 16.4125 10.2047 16.3319 10.9299C16.2513 11.7357 15.8484 12.3804 15.2844 12.5416C14.7203 14.4755 13.1892 15.926 11.7387 15.926ZM11.7387 6.01437C9.72416 6.01437 8.99892 6.98136 8.83776 9.56C8.83776 9.80175 8.67659 10.0435 8.43484 10.0435C8.35426 10.0435 8.1931 10.3658 8.1931 10.7687C8.1931 11.2522 8.43484 11.494 8.51543 11.494C8.75717 11.494 8.99892 11.6551 8.99892 11.8969C9.48242 13.6697 10.7717 14.7173 11.6581 14.7173C12.5446 14.7173 13.7533 13.6697 14.3174 11.8969C14.398 11.6551 14.5591 11.494 14.8009 11.494C14.8814 11.494 15.1232 11.2522 15.1232 10.7687C15.1232 10.2852 14.962 10.0435 14.8814 10.0435C14.6397 9.96291 14.4785 9.80175 14.4785 9.56C14.4785 6.98136 13.7533 6.01437 11.7387 6.01437Z" fill="#354049"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>`
},
API_KEYS: {
label: 'API Keys',
path: ROUTES.API_KEYS.path,
svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M18.6059 9.10806C18.6059 8.85201 18.6912 8.51062 18.6912 8.25458C18.6912 4.24322 15.3626 1 11.3513 1C7.33993 1 4.0967 4.24322 4.0967 8.25458C4.0967 8.51062 4.0967 8.85201 4.18205 9.10806C1.87766 9.27875 0 11.1564 0 13.5462C0 16.0212 1.963 17.9842 4.4381 17.9842H7.76667V21.9103L6.82784 21.0568C6.57179 20.8007 6.14506 20.8007 5.88901 21.0568C5.63297 21.3128 5.63297 21.7396 5.88901 21.9956L8.27875 24.2147L10.6685 21.9956C10.9245 21.7396 10.9245 21.3128 10.6685 21.0568C10.4125 20.8007 9.98571 20.8007 9.72967 21.0568L8.79084 21.9103V17.9842H13.3143V12.0952L12.3755 12.9487C12.1194 13.2048 11.6927 13.2048 11.4366 12.9487C11.1806 12.6927 11.1806 12.2659 11.4366 12.0099L13.8264 9.79084L16.2161 12.0099C16.4722 12.2659 16.4722 12.6927 16.2161 12.9487C16.1308 13.1194 15.8747 13.1194 15.704 13.1194C15.5333 13.1194 15.3626 13.0341 15.2773 12.9487L14.3385 12.0952V17.9842H17.8377C17.9231 17.9842 18.0084 17.9842 18.0084 17.8989C20.2275 17.6429 22.0198 15.7652 22.0198 13.4608C22.6172 11.2418 20.8249 9.3641 18.6059 9.10806Z" fill="#354049"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>`
},
BUCKETS: {
label: 'Buckets',
path: ROUTES.BUCKETS.path,
svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 12.4548V20.273C1 21.273 1.81116 22.0003 2.71245 22.0003H20.1974C21.1888 22.0003 21.9099 21.1821 21.9099 20.273V12.4548C21.9099 11.4548 21.0987 10.7275 20.1974 10.7275H2.71245C1.81116 10.7275 1 11.4548 1 12.4548ZM14.97 14.0912H7.75966C7.30901 14.0912 6.85837 13.7275 6.85837 13.1821C6.85837 12.7275 7.21888 12.273 7.75966 12.273H14.97C15.4206 12.273 15.8712 12.6366 15.8712 13.1821C15.8712 13.7275 15.5107 14.0912 14.97 14.0912Z" fill="#354049"/>
<path d="M2.53227 9.81792C2.17175 9.81792 1.90137 9.54519 1.90137 9.18155V5.90882C1.90137 5.54519 2.17175 5.27246 2.53227 5.27246H20.4679C20.8284 5.27246 21.0988 5.54519 21.0988 5.90882V8.99973C21.0988 9.36337 20.8284 9.6361 20.4679 9.6361C20.1074 9.6361 19.837 9.36337 19.837 8.99973V6.54519H3.16317V9.18155C3.16317 9.54519 2.89278 9.81792 2.53227 9.81792Z" fill="#354049"/>
<path d="M20.4679 4.27273H2.53227C2.17175 4.27273 1.90137 4 1.90137 3.63636C1.90137 3.27273 2.17175 3 2.53227 3H20.4679C20.8284 3 21.0988 3.27273 21.0988 3.63636C21.0988 4 20.8284 4.27273 20.4679 4.27273Z" fill="#354049"/>
</svg>`
},
};
export default NAVIGATION_ITEMS;

View File

@ -1,67 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
const ROUTES = {
LOGIN: {
path: '/login',
name: 'Login'
},
REGISTER: {
path: '/register',
name: 'Register'
},
FORGOT_PASSWORD: {
path: '/forgot-password',
name: 'ForgotPassword'
},
DASHBOARD: {
path: '/',
name: 'Dashboard'
},
ACCOUNT_SETTINGS: {
path: '/account',
name: 'Account'
},
PROJECT_OVERVIEW: {
path: '/project-overview',
name: 'ProjectOverview'
},
TEAM: {
path: '/projectMembers',
name: 'Team'
},
API_KEYS: {
path: '/api-keys',
name: 'ApiKeys'
},
USAGE_REPORT: {
path: 'usage-report',
name: 'UsageReport'
},
BILLING_HISTORY: {
path: 'billing-history',
name: 'BillingHistory'
},
PROJECT_DETAILS: {
path: 'details',
name: 'ProjectDetails'
},
PAYMENT_METHODS: {
path: 'payment-methods',
name: 'ProjectPaymentMethods.vue'
},
BUCKETS: {
path: '/buckets',
name: 'Buckets'
},
PROFILE: {
path: 'profile',
name: 'Profile'
},
REFERRAL: {
path: '/ref/:ids',
name: 'Referral'
},
};
export default ROUTES;

View File

@ -37,9 +37,9 @@
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
import { AppState } from '@/utils/constants/appStateEnum';
import { AuthToken } from '@/utils/authToken';
import ROUTES from '@/utils/constants/routerConstants';
import { Project } from '@/types/projects';
import { RequestResponse } from '@/types/response';
import router, { RouteConfig } from '@/router';
import { User } from '@/types/users';
@Component({
@ -52,7 +52,7 @@
} catch (error) {
this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, error.message);
this.$router.push(ROUTES.LOGIN);
this.$router.push(RouteConfig.Login);
AuthToken.remove();
return;
@ -61,6 +61,7 @@
let getProjectsResponse: RequestResponse<Project[]> = await this.$store.dispatch(PROJETS_ACTIONS.FETCH);
if (!getProjectsResponse.isSuccess || getProjectsResponse.data.length < 1) {
this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED_EMPTY);
this.$router.push(RouteConfig.ProjectOverview.with(RouteConfig.ProjectDetails).path);
return;
}

View File

@ -8,7 +8,7 @@
import HeaderlessInput from '@/components/common/HeaderlessInput.vue';
import { LOADING_CLASSES } from '@/utils/constants/classConstants';
import { NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
import ROUTES from '@/utils/constants/routerConstants';
import { RouteConfig } from '@/router';
import { validateEmail } from '@/utils/validation';
import EVENTS from '@/utils/constants/analyticsEventNames';
import { AuthApi } from '@/api/auth';
@ -47,7 +47,7 @@
public onBackToLoginClick(): void {
this.$segment.track(EVENTS.CLICKED_BACK_TO_LOGIN);
this.$router.push(ROUTES.LOGIN.path);
this.$router.push(RouteConfig.Login.path);
}
public onLogoClick(): void {

View File

@ -8,13 +8,13 @@
import HeaderlessInput from '@/components/common/HeaderlessInput.vue';
import Button from '@/components/common/Button.vue';
import { AuthToken } from '@/utils/authToken';
import ROUTES from '@/utils/constants/routerConstants';
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
import { AuthApi } from '@/api/auth';
import { LOADING_CLASSES } from '@/utils/constants/classConstants';
import { AppState } from '@/utils/constants/appStateEnum';
import { validateEmail, validatePassword } from '@/utils/validation';
import EVENTS from '../../utils/constants/analyticsEventNames';
import EVENTS from '@/utils/constants/analyticsEventNames';
import { RouteConfig } from '@/router';
@Component({
components: {
@ -27,7 +27,7 @@
private password: string = '';
private authToken: string = '';
public forgotPasswordRouterPath: string = ROUTES.FORGOT_PASSWORD.path;
private readonly forgotPasswordPath: string = RouteConfig.ForgotPassword.path;
private loadingClassName: string = LOADING_CLASSES.LOADING_OVERLAY;
private loadingLogoClassName: string = LOADING_CLASSES.LOADING_LOGO;
private emailError: string = '';
@ -50,7 +50,7 @@
}
public onSignUpClick(): void {
this.$router.push(ROUTES.REGISTER.path);
this.$router.push(RouteConfig.Register.path);
}
public async onLogin(): Promise<void> {
@ -74,7 +74,7 @@
setTimeout(() => {
AuthToken.set(this.authToken);
this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADING);
this.$router.push(ROUTES.PROJECT_OVERVIEW.path + '/' + ROUTES.PROJECT_DETAILS.path);
this.$router.push(RouteConfig.ProjectOverview.with(RouteConfig.ProjectDetails).path);
}, 2000);
}

View File

@ -35,7 +35,7 @@
isPassword="true">
</HeaderlessInput>
<div class="login-area__submit-area">
<router-link :to="forgotPasswordRouterPath" class="login-area__navigation-area__nav-link" exact>
<router-link :to="forgotPasswordPath" class="login-area__navigation-area__nav-link" exact>
<h3><strong>Forgot password?</strong></h3>
</router-link>
<div class="login-area__submit-area__login-button" @click.prevent="onLogin">

View File

@ -5,17 +5,17 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HeaderlessInput from '../../components/common/HeaderlessInput.vue';
import RegistrationSuccessPopup from '../../components/common/RegistrationSuccessPopup.vue';
import { validateEmail, validatePassword } from '../../utils/validation';
import ROUTES from '../../utils/constants/routerConstants';
import EVENTS from '../../utils/constants/analyticsEventNames';
import { LOADING_CLASSES } from '../../utils/constants/classConstants';
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '../../utils/constants/actionNames';
import { AuthApi } from '../../api/auth';
import HeaderlessInput from '@/components/common/HeaderlessInput.vue';
import RegistrationSuccessPopup from '@/components/common/RegistrationSuccessPopup.vue';
import { validateEmail, validatePassword } from '@/utils/validation';
import { RouteConfig } from '@/router';
import EVENTS from '@/utils/constants/analyticsEventNames';
import { LOADING_CLASSES } from '@/utils/constants/classConstants';
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
import { AuthApi } from '@/api/auth';
import { setUserId } from '@/utils/consoleLocalStorage';
import { User } from '../../types/users';
import InfoComponent from '../../components/common/InfoComponent.vue';
import { User } from '@/types/users';
import InfoComponent from '@/components/common/InfoComponent.vue';
@Component({
components: {
@ -42,7 +42,6 @@
private repeatedPasswordError: string = '';
private isTermsAcceptedError: boolean = false;
private loadingClassName: string = LOADING_CLASSES.LOADING_OVERLAY;
private readonly auth: AuthApi = new AuthApi();
@ -86,7 +85,7 @@
}
public onLoginClick(): void {
this.$segment.track(EVENTS.CLICKED_LOGIN);
this.$router.push(ROUTES.LOGIN.path);
this.$router.push(RouteConfig.Login.path);
}
public setEmail(value: string): void {
this.user.email = value.trim();