web/satellite: fix billing history table styling
This change fixes an issue where the billing history will not display properly see: https://github.com/storj/storj/issues/5097 Change-Id: Iac9a1f3038d4fdebf38448cccd1084ddc830402a
This commit is contained in:
parent
0e99f7a8cf
commit
d6c7aa9290
@ -2,13 +2,23 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<BillingHistoryHeader />
|
||||
<VList
|
||||
:data-set="historyItems"
|
||||
:item-component="billingHistoryStructure"
|
||||
/>
|
||||
<router-view />
|
||||
<div class="billing-history">
|
||||
<h1 class="billing-history__title">
|
||||
Billing History
|
||||
</h1>
|
||||
|
||||
<v-table class="billing-history__table">
|
||||
<template #head>
|
||||
<BillingHistoryHeader />
|
||||
</template>
|
||||
<template #body>
|
||||
<BillingHistoryItem
|
||||
v-for="item in historyItems"
|
||||
:key="item.id"
|
||||
:item="item"
|
||||
/>
|
||||
</template>
|
||||
</v-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -17,14 +27,15 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PaymentsHistoryItem, PaymentsHistoryItemType } from '@/types/payments';
|
||||
|
||||
import VList from '@/components/common/VList.vue';
|
||||
import BillingHistoryHeader from '@/components/account/billing/billingTabs/BillingHistoryHeader.vue';
|
||||
import BillingHistoryShape from '@/components/account/billing/billingTabs/BillingHistoryShape.vue';
|
||||
import BillingHistoryItem from '@/components/account/billing/billingTabs/BillingHistoryItem.vue';
|
||||
import VTable from '@/components/common/VTable.vue';
|
||||
|
||||
// @vue/component
|
||||
@Component({
|
||||
components: {
|
||||
VList,
|
||||
BillingHistoryItem,
|
||||
VTable,
|
||||
BillingHistoryHeader,
|
||||
},
|
||||
})
|
||||
@ -36,22 +47,20 @@ export default class BillingArea extends Vue {
|
||||
return item.type === PaymentsHistoryItemType.Invoice || item.type === PaymentsHistoryItemType.Charge;
|
||||
});
|
||||
}
|
||||
|
||||
public get billingHistoryStructure() {
|
||||
return BillingHistoryShape;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.billing_history2 {
|
||||
position: relative;
|
||||
.billing-history {
|
||||
margin-top: 2rem;
|
||||
|
||||
&__content {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
&__title {
|
||||
font-family: sans-serif;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
&__table {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,150 +2,24 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="sort-header-container">
|
||||
<div class="sort-header-container__date-item">
|
||||
<p class="sort-header-container__date-item__title">DATE</p>
|
||||
</div>
|
||||
<div class="sort-header-container__status-item">
|
||||
<p class="sort-header-container__status-item__title creation-date">STATUS</p>
|
||||
</div>
|
||||
<div class="sort-header-container__amount-item">
|
||||
<p class="sort-header-container__amount-item__title creation-date">AMOUNT</p>
|
||||
</div>
|
||||
<div class="sort-header-container__download-item">
|
||||
<p class="sort-header-container__download-item__title creation-date">DOWNLOAD</p>
|
||||
</div>
|
||||
</div>
|
||||
<fragment>
|
||||
<th class="align-left">DATE</th>
|
||||
<th class="align-left">STATUS</th>
|
||||
<th class="align-left">AMOUNT</th>
|
||||
<th class="align-left">DOWNLOAD</th>
|
||||
</fragment>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { AccessGrantsOrderBy, OnHeaderClickCallback } from '@/types/accessGrants';
|
||||
import { SortDirection } from '@/types/common';
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import { Fragment } from 'vue-fragment';
|
||||
|
||||
// @vue/component
|
||||
@Component({
|
||||
components: {
|
||||
Fragment,
|
||||
},
|
||||
})
|
||||
export default class BillingHistoryHeader extends Vue {
|
||||
@Prop({ default: () => () => new Promise(() => false) })
|
||||
private readonly onHeaderClickCallback: OnHeaderClickCallback;
|
||||
|
||||
public AccessGrantsOrderBy = AccessGrantsOrderBy;
|
||||
|
||||
public sortBy: AccessGrantsOrderBy = AccessGrantsOrderBy.NAME;
|
||||
public sortDirection: SortDirection = SortDirection.ASCENDING;
|
||||
|
||||
/**
|
||||
* Used for arrow styling.
|
||||
*/
|
||||
public get getSortDirection(): SortDirection {
|
||||
return this.sortDirection === SortDirection.DESCENDING ? SortDirection.ASCENDING : SortDirection.DESCENDING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets sorting kind if different from current.
|
||||
* If same, changes sort direction.
|
||||
* @param sortBy
|
||||
*/
|
||||
|
||||
public get areAccessGrantsSortedByName(): boolean {
|
||||
return this.sortBy === AccessGrantsOrderBy.NAME;
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.sort-header-container {
|
||||
display: flex;
|
||||
height: 40px;
|
||||
background-color: #fff;
|
||||
margin-top: 31px;
|
||||
padding: 16px 16px 0;
|
||||
border-radius: 8px 8px 0 0;
|
||||
|
||||
&__name-item,
|
||||
&__status-item {
|
||||
padding-bottom: 13px;
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: #6b7280;
|
||||
width: 20%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__amount-item {
|
||||
padding-bottom: 13px;
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: #6b7280;
|
||||
width: 20%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__download-item {
|
||||
padding-bottom: 13px;
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
margin-left: 0 0 0 53px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: #6b7280;
|
||||
width: 24%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&__title {
|
||||
margin-left: 46px;
|
||||
}
|
||||
}
|
||||
|
||||
&__date-item {
|
||||
padding-bottom: 13px;
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: #6b7280;
|
||||
width: 30%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
|
||||
.sort-header-container__status-item__title,
|
||||
.sort-header-container__status-item {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,133 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<tr @click="downloadInvoice">
|
||||
<th class="align-left data mobile">
|
||||
<div class="few-items">
|
||||
<p class="array-val date">
|
||||
<span><Calendar /></span>
|
||||
<span>{{ item.formattedStart }}</span>
|
||||
</p>
|
||||
<p class="array-val status">
|
||||
<span v-if="item.status === 'paid'"> <CheckIcon class="checkmark" /> </span>
|
||||
<span>{{ item.formattedStatus }}</span>
|
||||
</p>
|
||||
<p class="array-val">
|
||||
{{ item.amount | centsToDollars }}
|
||||
</p>
|
||||
</div>
|
||||
</th>
|
||||
<fragment>
|
||||
<th class="align-left data tablet-laptop">
|
||||
<p class="date">
|
||||
<span><Calendar /></span>
|
||||
<span>{{ item.formattedStart }}</span>
|
||||
</p>
|
||||
</th>
|
||||
<th class="align-left data tablet-laptop">
|
||||
<p class="status">
|
||||
<span v-if="item.status === 'paid'"> <CheckIcon class="checkmark" /> </span>
|
||||
<span>{{ item.formattedStatus }}</span>
|
||||
</p>
|
||||
</th>
|
||||
<th class="align-left data tablet-laptop">
|
||||
<p>
|
||||
{{ item.amount | centsToDollars }}
|
||||
</p>
|
||||
</th>
|
||||
<th class="align-left data tablet-laptop">
|
||||
<a :href="item.link" download>Invoice PDF</a>
|
||||
</th>
|
||||
</fragment>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop } from 'vue-property-decorator';
|
||||
import { Fragment } from 'vue-fragment';
|
||||
|
||||
import { PaymentsHistoryItem } from '@/types/payments';
|
||||
|
||||
import Resizable from '@/components/common/Resizable.vue';
|
||||
|
||||
import CheckIcon from '@/../static/images/billing/check-green-circle.svg';
|
||||
import Calendar from '@/../static/images/billing/calendar.svg';
|
||||
|
||||
// @vue/component
|
||||
@Component({
|
||||
components: {
|
||||
Calendar,
|
||||
CheckIcon,
|
||||
Fragment,
|
||||
},
|
||||
})
|
||||
export default class BillingHistoryItem extends Resizable {
|
||||
@Prop({ default: new PaymentsHistoryItem('', '', 0, 0, '', '', new Date(), new Date(), 0, 0) })
|
||||
private readonly item: PaymentsHistoryItem;
|
||||
|
||||
public downloadInvoice() {
|
||||
if (this.isMobile || this.isTablet)
|
||||
window.open(this.item.link, '_blank', 'noreferrer');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
a {
|
||||
color: #0149ff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.date {
|
||||
display: flex;
|
||||
gap: 0.7rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: flex;
|
||||
gap: 0.7rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.few-items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.array-val {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.25rem;
|
||||
|
||||
&:first-of-type {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 425px) {
|
||||
|
||||
.mobile {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.tablet-laptop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 426px) {
|
||||
|
||||
.tablet-laptop {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,228 +0,0 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="billing-history">
|
||||
<div class="billing-history__common-info">
|
||||
<span class="name-container" :title="historyItem.start">
|
||||
<Calendar />
|
||||
<p class="name_date">{{ historyItem.start }}</p>
|
||||
</span>
|
||||
</div>
|
||||
<div class="billing-history__common-info">
|
||||
<span class="name-container" :title="historyItem.status">
|
||||
<CheckIcon class="checkmark" />
|
||||
<p class="name_status">{{ historyItem.status }}</p>
|
||||
</span>
|
||||
</div>
|
||||
<div class="billing-history__common-info">
|
||||
<div class="name-container" :title="historyItem.amount">
|
||||
<p class="name_amount">{{ historyItem.amount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="historyItem.link" class="billing-history__common-info">
|
||||
<a href="historyItem.link" download>
|
||||
<div class="name-container" :title="historyItem.link">
|
||||
<p class="name_download">Invoice PDF</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PaymentsHistoryItem } from '@/types/payments';
|
||||
import { AccessGrant } from '@/types/accessGrants';
|
||||
|
||||
import CheckIcon from '@/../static/images/billing/check-green-circle.svg';
|
||||
import Calendar from '@/../static/images/billing/calendar.svg';
|
||||
|
||||
// @vue/component
|
||||
@Component({
|
||||
components: {
|
||||
Calendar,
|
||||
CheckIcon,
|
||||
},
|
||||
})
|
||||
export default class BillingHistoryShape extends Vue {
|
||||
@Prop({ default: new PaymentsHistoryItem('', '', 0, 0, '', '', new Date(), new Date(), 0, 0) })
|
||||
@Prop({ default: new AccessGrant('', '', new Date(), '') })
|
||||
private readonly historyItem: PaymentsHistoryItem;
|
||||
private popupVisible = false;
|
||||
|
||||
public togglePopupVisibility(): void {
|
||||
this.popupVisible = !this.popupVisible;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@mixin popup-menu-button {
|
||||
padding: 0 15px;
|
||||
height: 50%;
|
||||
line-height: 55px;
|
||||
text-align: left;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
color: #1b2533;
|
||||
transition: 100ms;
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
margin-top: 3px;
|
||||
margin-left: 37px;
|
||||
}
|
||||
|
||||
.billing-history {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
height: 64px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-bottom: 0;
|
||||
width: 78%;
|
||||
|
||||
&__common-info {
|
||||
margin-left: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-container {
|
||||
margin-left: 28px;
|
||||
min-width: 21px;
|
||||
min-height: 21px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #1b2533;
|
||||
|
||||
&__image {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.name-container {
|
||||
// max-width: calc(100% - 131px);
|
||||
display: flex;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.name_date {
|
||||
margin-top: 6px;
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
color: #354049;
|
||||
margin-left: 15px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.name_status {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #111827;
|
||||
margin-left: 6px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.name_amount {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #111827;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
.name_downloaod {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
color: #354049;
|
||||
margin-left: 5px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
color: #354049;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ellipses {
|
||||
margin: 0 auto 20px;
|
||||
font-size: 30px;
|
||||
font-weight: 1000;
|
||||
color: #7c8794;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.popup-menu {
|
||||
width: 160px;
|
||||
height: 100px;
|
||||
position: absolute;
|
||||
right: 70px;
|
||||
bottom: -90px;
|
||||
z-index: 1;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 20px 34px rgb(10 27 44 / 28%);
|
||||
|
||||
&__popup-details {
|
||||
@include popup-menu-button;
|
||||
|
||||
border-radius: 10px 10px 0 0;
|
||||
|
||||
&:hover {
|
||||
background-color: #354049;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&__popup-divider {
|
||||
height: 1px;
|
||||
background-color: #e5e7eb;
|
||||
}
|
||||
|
||||
&__popup-delete {
|
||||
@include popup-menu-button;
|
||||
|
||||
border-radius: 0 0 10px 10px;
|
||||
|
||||
&:hover {
|
||||
background-color: #b53737;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.date-item-container {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.menu-item-container {
|
||||
width: 10%;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
@ -161,6 +161,10 @@ export class PaymentsHistoryItem {
|
||||
return this.status.charAt(0).toUpperCase() + this.status.substring(1);
|
||||
}
|
||||
|
||||
public get formattedStart(): string {
|
||||
return this.start.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
|
||||
}
|
||||
|
||||
public get hasExpiration(): boolean {
|
||||
// Go's zero date is passed in if the coupon does not expire
|
||||
// Go's zero date is 0001-01-01 00:00:00 +0000 UTC
|
||||
|
Loading…
Reference in New Issue
Block a user