web/satellite: fix bottom spacing for all pages

Fixed bottom spacing for all pages. Basically removed bottom padding override in dashboard wrapper.
Removed a couple of unused components and icons.
Made pagination size changer dropdown to appear on top of selector to not extend page height.

This change fixes pagination issue on Team page:
https://github.com/storj/storj/issues/6012

Change-Id: I707dd1bf9d61b05742b7f97a757a2a8f5f9f93fd
This commit is contained in:
Vitalii 2023-07-06 12:44:17 +03:00 committed by Storj Robot
parent a85c080509
commit ece0cc5785
17 changed files with 15 additions and 959 deletions

View File

@ -360,7 +360,6 @@ onBeforeUnmount(() => {
.access-grants {
position: relative;
height: calc(100% - 95px);
padding: 40px 30px 55px;
font-family: 'font_regular', sans-serif;
@ -458,7 +457,6 @@ onBeforeUnmount(() => {
}
.access-grants-items {
padding-bottom: 55px;
&__content {
margin-top: 20px;

View File

@ -213,6 +213,7 @@ onMounted(() => {
<style scoped lang="scss">
.settings {
padding-bottom: 35px;
&__title {
font-family: 'font_bold', sans-serif;

View File

@ -1,419 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="settings">
<h1 class="settings__title" aria-roledescription="title">Account Settings</h1>
<div class="settings__edit-profile">
<div class="settings__edit-profile__row">
<div class="settings__edit-profile__avatar">
<h1 class="settings__edit-profile__avatar__letter">{{ avatarLetter }}</h1>
</div>
<div class="settings__edit-profile__text">
<h2 class="profile-bold-text">Edit Profile</h2>
<h3 class="profile-regular-text">This information will be visible to all users</h3>
</div>
</div>
<EditIcon
class="edit-svg"
@click="toggleEditProfileModal"
/>
</div>
<div class="settings__secondary-container">
<div class="settings__secondary-container__change-password">
<div class="settings__edit-profile__row">
<ChangePasswordIcon class="settings__secondary-container__change-password__img" />
<div class="settings__secondary-container__change-password__text-container">
<h2 class="profile-bold-text">Change Password</h2>
<h3 class="profile-regular-text">6 or more characters</h3>
</div>
</div>
<EditIcon
class="edit-svg"
@click="toggleChangePasswordModal"
/>
</div>
<div class="settings__secondary-container__email-container">
<div class="settings__secondary-container__email-container__row">
<EmailIcon class="settings__secondary-container__img" />
<div class="settings__secondary-container__email-container__text-container">
<h2 class="profile-bold-text email">{{ user.email }}</h2>
</div>
</div>
</div>
</div>
<div class="settings__mfa">
<h2 class="profile-bold-text">Two-Factor Authentication</h2>
<p v-if="!user.isMFAEnabled" class="profile-regular-text">
To increase your account security, we strongly recommend enabling 2FA on your account.
</p>
<p v-else class="profile-regular-text">
2FA is enabled.
</p>
<div class="settings__mfa__buttons">
<VButton
v-if="!user.isMFAEnabled"
label="Enable 2FA"
width="173px"
height="44px"
:on-press="enableMFA"
:is-disabled="isLoading"
/>
<div v-else class="settings__mfa__buttons__row">
<VButton
class="margin-right"
label="Disable 2FA"
width="173px"
height="44px"
:on-press="toggleDisableMFAModal"
:is-deletion="true"
/>
<VButton
label="Regenerate Recovery Codes"
width="240px"
height="44px"
:on-press="generateNewMFARecoveryCodes"
:is-blue-white="true"
:is-disabled="isLoading"
/>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted } from 'vue';
import { User } from '@/types/users';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { useNotify } from '@/utils/hooks';
import { useLoading } from '@/composables/useLoading';
import { useUsersStore } from '@/store/modules/usersStore';
import { useAppStore } from '@/store/modules/appStore';
import VButton from '@/components/common/VButton.vue';
import ChangePasswordIcon from '@/../static/images/account/profile/changePassword.svg';
import EmailIcon from '@/../static/images/account/profile/email.svg';
import EditIcon from '@/../static/images/common/edit.svg';
const appStore = useAppStore();
const usersStore = useUsersStore();
const notify = useNotify();
const { isLoading, withLoading } = useLoading();
/**
* Returns user info from store.
*/
const user = computed((): User => {
return usersStore.state.user;
});
/**
* Returns first letter of user name.
*/
const avatarLetter = computed((): string => {
return usersStore.userName.slice(0, 1).toUpperCase();
});
/**
* Toggles enable MFA modal visibility.
*/
function toggleEnableMFAModal(): void {
appStore.updateActiveModal(MODALS.enableMFA);
}
/**
* Toggles disable MFA modal visibility.
*/
function toggleDisableMFAModal(): void {
appStore.updateActiveModal(MODALS.disableMFA);
}
/**
* Toggles MFA recovery codes modal visibility.
*/
function toggleMFACodesModal(): void {
appStore.updateActiveModal(MODALS.mfaRecovery);
}
/**
* Opens change password popup.
*/
function toggleChangePasswordModal(): void {
appStore.updateActiveModal(MODALS.changePassword);
}
/**
* Opens edit account info modal.
*/
function toggleEditProfileModal(): void {
appStore.updateActiveModal(MODALS.editProfile);
}
/**
* Generates user's MFA secret and opens popup.
*/
async function enableMFA(): Promise<void> {
await withLoading(async () => {
try {
await usersStore.generateUserMFASecret();
toggleEnableMFAModal();
} catch (error) {
await notify.error(error.message, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
}
});
}
/**
* Toggles generate new MFA recovery codes popup visibility.
*/
async function generateNewMFARecoveryCodes(): Promise<void> {
await withLoading(async () => {
try {
await usersStore.generateUserMFARecoveryCodes();
toggleMFACodesModal();
} catch (error) {
await notify.error(error.message, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
}
});
}
/**
* Lifecycle hook after initial render where user info is fetching.
*/
onMounted(() => {
usersStore.getUser();
});
</script>
<style scoped lang="scss">
h3 {
margin-block-start: 0;
margin-block-end: 0;
}
.settings {
position: relative;
font-family: 'font_regular', sans-serif;
padding-bottom: 70px;
&__title {
font-family: 'font_bold', sans-serif;
font-size: 32px;
line-height: 39px;
color: #263549;
margin: 40px 0 25px;
}
&__edit-profile {
height: 137px;
box-sizing: border-box;
width: 100%;
border-radius: 6px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 37px 40px;
background-color: #fff;
&__row {
display: flex;
justify-content: flex-start;
align-items: center;
max-width: calc(100% - 40px);
}
&__avatar {
width: 60px;
height: 60px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
background: #e8eaf2;
margin-right: 32px;
&__letter {
font-family: 'font_medium', sans-serif;
font-size: 16px;
line-height: 23px;
color: #354049;
}
}
}
&__secondary-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 40px;
&__change-password {
height: 137px;
border-radius: 6px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 37px 40px;
background-color: #fff;
width: 48%;
box-sizing: border-box;
&__text-container {
margin-left: 32px;
}
}
&__email-container {
height: 137px;
border-radius: 6px;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 37px 40px;
background-color: #fff;
width: 48%;
box-sizing: border-box;
&__row {
display: flex;
justify-content: flex-start;
align-items: center;
width: 100%;
}
&__text-container {
margin-left: 32px;
}
}
&__img {
min-width: 60px;
min-height: 60px;
}
}
&__mfa {
margin-top: 40px;
padding: 40px;
border-radius: 6px;
background-color: #fff;
&__buttons {
margin-top: 20px;
&__row {
display: flex;
align-items: center;
}
}
}
}
.margin-right {
margin-right: 15px;
}
.edit-svg {
cursor: pointer;
&:hover {
.edit-svg__rect {
fill: #2683ff;
}
.edit-svg__path {
fill: white;
}
}
}
.input-container.full-input,
.input-wrap.full-input {
width: 100%;
}
.profile-bold-text {
font-family: 'font_bold', sans-serif;
color: #354049;
font-size: 18px;
line-height: 27px;
}
.profile-regular-text {
margin: 10px 0;
color: #afb7c1;
font-size: 16px;
line-height: 21px;
}
.email {
word-break: break-all;
}
@media screen and (width <= 1300px) {
.settings {
&__secondary-container {
flex-direction: column;
justify-content: center;
&__change-password,
&__email-container {
height: auto;
width: 100%;
}
&__email-container {
margin-top: 40px;
}
}
}
}
@media screen and (height <= 825px) {
.settings {
height: 535px;
overflow-y: scroll;
&__secondary-container {
margin-top: 20px;
&__email-container {
margin-top: 20px;
}
}
&__button-area {
margin-top: 20px;
}
}
}
@media screen and (width <= 650px) {
.settings__secondary-container__change-password__text-container {
margin: 0;
}
.settings__edit-profile__avatar,
.settings__secondary-container__change-password__img {
display: none;
}
}
@media screen and (width <= 460px) {
.settings__edit-profile,
.settings__secondary-container__change-password,
.settings__secondary-container__email-container {
padding: 25px;
}
}
</style>

View File

@ -57,7 +57,12 @@
</div>
<div v-else class="pagination-container__pages-placeholder" />
<table-size-changer v-if="limit && totalPageCount && totalItemsCount > 10" :item-count="totalItemsCount" class="table-footer__sizer" :selected="pageSize" @change="sizeChanged">Size Changer</table-size-changer>
<table-size-changer
v-if="limit && totalPageCount && totalItemsCount > 10"
:item-count="totalItemsCount"
:selected="pageSize"
@change="sizeChanged"
/>
</div>
</template>

View File

@ -153,7 +153,7 @@ function toggleSelector() {
&__dropdown {
position: absolute;
top: 35px;
top: -190px;
background: var(--c-white);
z-index: 999;
box-sizing: border-box;

View File

@ -1,279 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="pagination-container">
<div class="pagination-container__pages">
<div class="pagination-container__button" @click="prevPage">
<PaginationLeftIcon class="pagination-container__button__image" />
</div>
<div class="pagination-container__items">
<PagesBlock
:pages="firstBlockPages"
:is-selected="isSelected"
/>
<span v-if="isFirstDotsShown" class="pages-divider">...</span>
<PagesBlock
:pages="middleBlockPages"
:is-selected="isSelected"
/>
<span v-if="isSecondDotsShown" class="pages-divider">...</span>
<PagesBlock
:pages="lastBlockPages"
:is-selected="isSelected"
/>
</div>
<div class="pagination-container__button" @click="nextPage">
<PaginationRightIcon class="pagination-container__button__image" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { OnPageClickCallback, Page } from '@/types/pagination';
import { useLoading } from '@/composables/useLoading';
import PagesBlock from '@/components/common/PagesBlock.vue';
import PaginationLeftIcon from '@/../static/images/common/paginationLeft.svg';
import PaginationRightIcon from '@/../static/images/common/paginationRight.svg';
const MAX_PAGES_PER_BLOCK = 3;
const MAX_PAGES_OFF_BLOCKS = 6;
const props = withDefaults(defineProps<{
onPageClickCallback?: OnPageClickCallback;
totalPageCount?: number;
}>(), {
totalPageCount: 0,
onPageClickCallback: () => (_: number) => Promise.resolve(),
});
const { withLoading } = useLoading();
const currentPageNumber = ref<number>(1);
const pagesArray = ref<Page[]>([]);
const firstBlockPages = ref<Page[]>([]);
const middleBlockPages = ref<Page[]>([]);
const lastBlockPages = ref<Page[]>([]);
/**
* Indicates if current page is first.
*/
const isFirstPage = computed((): boolean => {
return currentPageNumber.value === 1;
});
/**
* Indicates if current page is last.
*/
const isLastPage = computed((): boolean => {
return currentPageNumber.value === props.totalPageCount;
});
/**
* Indicates if dots after first pages block should appear.
*/
const isFirstDotsShown = computed((): boolean => {
return middleBlockPages.value.length <= MAX_PAGES_PER_BLOCK
&& pagesArray.value.length > MAX_PAGES_OFF_BLOCKS;
});
/**
* Indicates if dots after middle pages block should appear.
*/
const isSecondDotsShown = computed((): boolean => {
return !!middleBlockPages.value.length;
});
const isCurrentInFirstBlock = computed((): boolean => {
return currentPageNumber.value < MAX_PAGES_PER_BLOCK;
});
const isCurrentInLastBlock = computed((): boolean => {
return props.totalPageCount - currentPageNumber.value < MAX_PAGES_PER_BLOCK - 1;
});
const isPagesTotalOffBlocks = computed((): boolean => {
return props.totalPageCount <= MAX_PAGES_OFF_BLOCKS;
});
/**
* Indicates page is current and should appear in different styling.
*/
function isSelected(page: number): boolean {
return page === currentPageNumber.value;
}
/**
* Creates pages blocks and pages depends of total page count.
*/
function populatePagesArray(): void {
if (!props.totalPageCount) {
return;
}
for (let i = 1; i <= props.totalPageCount; i++) {
pagesArray.value.push(new Page(i, onPageClick));
}
if (isPagesTotalOffBlocks.value) {
firstBlockPages.value = pagesArray.value.slice();
middleBlockPages.value = [];
lastBlockPages.value = [];
return;
}
reorganizePageBlocks();
}
function setBlocksIfCurrentInFirstBlock(): void {
firstBlockPages.value = pagesArray.value.slice(0, 3);
middleBlockPages.value = [];
lastBlockPages.value = pagesArray.value.slice(-1);
}
function setBlocksIfCurrentInMiddleBlock(): void {
firstBlockPages.value = pagesArray.value.slice(0, 1);
middleBlockPages.value = pagesArray.value.slice(currentPageNumber.value - 2, currentPageNumber.value + 1);
lastBlockPages.value = pagesArray.value.slice(-1);
}
function setBlocksIfCurrentInLastBlock(): void {
firstBlockPages.value = pagesArray.value.slice(0, 1);
middleBlockPages.value = [];
lastBlockPages.value = pagesArray.value.slice(-3);
}
function incrementCurrentPage(): void {
currentPageNumber.value++;
}
function decrementCurrentPage(): void {
currentPageNumber.value--;
}
function setCurrentPage(pageNumber: number): void {
currentPageNumber.value = pageNumber;
}
/**
* onPageClick fires after concrete page click.
*/
async function onPageClick(page: number): Promise<void> {
await withLoading(async () => {
await props.onPageClickCallback(page);
setCurrentPage(page);
reorganizePageBlocks();
});
}
/**
* nextPage fires after 'next' arrow click.
*/
async function nextPage(): Promise<void> {
await withLoading(async () => {
if (isLastPage.value) {
return;
}
await props.onPageClickCallback(currentPageNumber.value + 1);
incrementCurrentPage();
reorganizePageBlocks();
});
}
/**
* prevPage fires after 'previous' arrow click.
*/
async function prevPage(): Promise<void> {
await withLoading(async () => {
if (isFirstPage.value) {
return;
}
await props.onPageClickCallback(currentPageNumber.value - 1);
decrementCurrentPage();
reorganizePageBlocks();
});
}
/**
* reorganizePageBlocks changes pages blocks organization depends of
* current selected page index.
*/
function reorganizePageBlocks(): void {
if (isPagesTotalOffBlocks.value) {
return;
}
if (isCurrentInFirstBlock.value) {
setBlocksIfCurrentInFirstBlock();
return;
}
if (!isCurrentInFirstBlock.value && !isCurrentInLastBlock.value) {
setBlocksIfCurrentInMiddleBlock();
return;
}
if (isCurrentInLastBlock.value) {
setBlocksIfCurrentInLastBlock();
}
}
/**
* Component initialization.
*/
onMounted((): void => {
populatePagesArray();
});
</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;
}
&__button {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: 1px solid #afb7c1;
border-radius: 6px;
width: 30px;
height: 30px;
&:hover {
.pagination-svg-path {
fill: #fff !important;
}
}
}
&__items {
margin: 0 20px;
display: flex;
.pages-divider {
margin: 0 20px;
}
}
}
</style>

View File

@ -34,6 +34,6 @@ onMounted(async (): Promise<void> => {
<style scoped lang="scss">
.objects-area {
padding: 20px 45px;
padding-bottom: 55px;
}
</style>

View File

@ -541,13 +541,13 @@ onBeforeUnmount((): void => {
<style scoped lang="scss">
.project-dashboard {
max-width: calc(100vw - 280px - 95px);
background-origin: content-box;
background-image: url('../../../../static/images/project/background.png');
background-position: top right;
background-size: 70%;
background-repeat: no-repeat;
font-family: 'font_regular', sans-serif;
padding-bottom: 55px;
&__heading {
display: flex;

View File

@ -10,14 +10,13 @@
/>
<VLoader v-if="areMembersFetching" width="100px" height="100px" />
<div v-if="isEmptySearchResultShown" class="team-area__empty-search-result-area">
<div v-if="isEmptySearchResultShown && !areMembersFetching" class="team-area__empty-search-result-area">
<h1 class="team-area__empty-search-result-area__title">No results found</h1>
<EmptySearchResultIcon class="team-area__empty-search-result-area__image" />
</div>
<v-table
v-if="!areMembersFetching && !isEmptySearchResultShown"
class="team-area__table"
items-label="project members"
:selectable="true"
:limit="projectMemberLimit"
@ -198,7 +197,6 @@ onMounted(async (): Promise<void> => {
<style scoped lang="scss">
.team-area {
padding: 40px 30px 55px;
height: calc(100% - 95px);
font-family: 'font_regular', sans-serif;
&__header {
@ -219,7 +217,6 @@ onMounted(async (): Promise<void> => {
font-family: 'font_bold', sans-serif;
font-size: 32px;
line-height: 39px;
margin-top: 100px;
}
&__image {

View File

@ -163,7 +163,6 @@ import MobileNavigation from '@/components/navigation/MobileNavigation.vue';
import LimitWarningModal from '@/components/modals/LimitWarningModal.vue';
import VBanner from '@/components/common/VBanner.vue';
import UpgradeNotification from '@/components/notifications/UpgradeNotification.vue';
import ProjectLimitBanner from '@/components/notifications/ProjectLimitBanner.vue';
import ProjectInvitationBanner from '@/components/notifications/ProjectInvitationBanner.vue';
import BrandedLoader from '@/components/common/BrandedLoader.vue';
import ObjectsUploadingModal from '@/components/modals/objectUpload/ObjectsUploadingModal.vue';
@ -335,16 +334,6 @@ const isNavigationHidden = computed((): boolean => {
return isOnboardingTour.value || isCreateProjectPage.value;
});
/**
* Returns whether the user has reached project limits.
*/
const hasReachedProjectLimit = computed((): boolean => {
const projectLimit: number = usersStore.state.user.projectLimit;
const projectsCount: number = projectsStore.projectsCount(usersStore.state.user.id);
return projectsCount === projectLimit;
});
/* whether the paid tier banner should be shown */
const isPaidTierBannerShown = computed((): boolean => {
return !usersStore.state.user.paidTier
@ -361,13 +350,6 @@ const joinedWhileAgo = computed((): boolean => {
return ((Date.now() - createdAt.getTime()) / millisPerDay) > 7;
});
/**
* Indicates if current route is projects list page.
*/
const isProjectListPage = computed((): boolean => {
return route.name === RouteConfig.ProjectsList.name;
});
/**
* Indicates if current route is onboarding tour.
*/
@ -845,7 +827,9 @@ onBeforeUnmount(() => {
&__content {
max-width: 1200px;
padding: 48px 48px 0;
padding-top: 48px;
padding-left: 48px;
padding-right: 48px;
box-sizing: border-box;
width: 100%;
@ -870,6 +854,7 @@ onBeforeUnmount(() => {
&:empty {
padding-top: 0;
padding-bottom: 0;
}
}
}

View File

@ -1,4 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 8.33398V10.834C9.63365 10.8346 9.27773 10.956 8.98727 11.1792C8.69681 11.4025 8.488 11.7152 8.39313 12.0691C8.29827 12.4229 8.32263 12.7982 8.46245 13.1368C8.60228 13.4754 8.84978 13.7585 9.16667 13.9423V15.0007C9.16667 15.2217 9.25446 15.4336 9.41074 15.5899C9.56702 15.7462 9.77899 15.834 10 15.834V18.334H4.16667C3.72464 18.334 3.30072 18.1584 2.98816 17.8458C2.67559 17.5333 2.5 17.1093 2.5 16.6673V10.0007C2.5 9.08398 3.25 8.33398 4.16667 8.33398H10Z" fill="#3F3F3F"/>
<path d="M9.9987 15.8337C10.2197 15.8337 10.4317 15.7459 10.588 15.5896C10.7442 15.4333 10.832 15.2213 10.832 15.0003V13.942C11.1489 13.7582 11.3964 13.4751 11.5362 13.1364C11.6761 12.7978 11.7004 12.4226 11.6056 12.0687C11.5107 11.7149 11.3019 11.4021 11.0114 11.1789C10.721 10.9556 10.365 10.8343 9.9987 10.8337V8.33366H12.4987V5.83366C12.4987 5.17062 12.2353 4.53473 11.7665 4.06589C11.2976 3.59705 10.6617 3.33366 9.9987 3.33366C9.33566 3.33366 8.69977 3.59705 8.23093 4.06589C7.76209 4.53473 7.4987 5.17062 7.4987 5.83366V8.33366H5.83203V5.83366C5.83203 4.72859 6.27102 3.66878 7.05242 2.88738C7.83382 2.10598 8.89363 1.66699 9.9987 1.66699C11.1038 1.66699 12.1636 2.10598 12.945 2.88738C13.7264 3.66878 14.1654 4.72859 14.1654 5.83366V8.33366H15.832C16.2741 8.33366 16.698 8.50925 17.0105 8.82181C17.3231 9.13438 17.4987 9.5583 17.4987 10.0003V16.667C17.4987 17.109 17.3231 17.5329 17.0105 17.8455C16.698 18.1581 16.2741 18.3337 15.832 18.3337H9.9987V15.8337Z" fill="#3F3F3F"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,5 +0,0 @@
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 60C46.5685 60 60 46.5685 60 30C60 13.4315 46.5685 0 30 0C13.4315 0 0 13.4315 0 30C0 46.5685 13.4315 60 30 60Z" fill="#E8EAF2"/>
<path d="M29.5001 34.5196C30.1001 34.5196 30.5865 34.0452 30.5865 33.46C30.5865 32.8748 30.1001 32.4004 29.5001 32.4004C28.9 32.4004 28.4136 32.8748 28.4136 33.46C28.4136 34.0452 28.9 34.5196 29.5001 34.5196Z" fill="#354049"/>
<path d="M39.9405 40.2152C40.1781 40 40.3139 39.6854 40.3139 39.3709V25.5464C40.3139 24.9007 39.7707 24.3709 39.1086 24.3709H35.7473V21.0927C35.7473 17.7318 32.9462 15 29.5 15C26.0538 15 23.2527 17.7318 23.2527 21.0927V24.3709H19.8914C19.2293 24.3709 18.686 24.9007 18.686 25.5464V39.3709C18.686 39.6854 18.8218 40 19.0595 40.2152L23.7959 44.6689C24.0166 44.8841 24.3222 45 24.6278 45H34.3552C34.6608 45 34.9664 44.8841 35.1871 44.6689L39.9405 40.2152ZM30.7053 36.6391V38.1291C30.7053 38.7748 30.1621 39.3046 29.5 39.3046C28.8379 39.3046 28.2947 38.7748 28.2947 38.1291V36.6391C26.9705 36.1589 26.0198 34.9172 26.0198 33.4437C26.0198 31.5728 27.5817 30.0497 29.5 30.0497C31.4183 30.0497 32.9801 31.5728 32.9801 33.4437C32.9801 34.9172 32.0295 36.1589 30.7053 36.6391ZM33.3367 24.3709H25.6464V21.0927C25.6464 19.0232 27.3779 17.351 29.483 17.351C31.5881 17.351 33.3197 19.0397 33.3197 21.0927V24.3709H33.3367Z" fill="#354049"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,4 +0,0 @@
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 60C46.5685 60 60 46.5685 60 30C60 13.4315 46.5685 0 30 0C13.4315 0 0 13.4315 0 30C0 46.5685 13.4315 60 30 60Z" fill="#E8EAF2"/>
<path d="M29.9998 16.7598C25.7965 16.7641 21.8459 18.7646 19.3534 22.1498C16.8607 25.535 16.1236 29.9013 17.3671 33.9162C18.6096 37.9314 21.6853 41.1186 25.6546 42.5032C29.6238 43.8868 34.014 43.305 37.4846 40.9348L35.9861 38.7538C33.3633 40.552 30.0711 41.0781 27.0174 40.1856C23.9649 39.2931 21.4732 37.077 20.2319 34.1482C18.9905 31.2203 19.1294 27.8888 20.6104 25.0734C22.0924 22.2591 24.7588 20.2577 27.8761 19.6232C30.9922 18.9878 34.2296 19.7862 36.6938 21.7976C39.1581 23.809 40.5898 26.8202 40.592 30.0007V31.0365C40.592 32.8762 39.8001 33.9732 38.4723 33.9732V33.995L38.4734 33.9961C38.3892 33.9819 38.305 33.9743 38.2208 33.9743H37.9408C37.1959 33.9743 36.0868 32.8903 36.0868 32.1597V30.0007C36.0989 28.1019 35.2293 26.3038 33.7331 25.1345C32.2358 23.9653 30.2824 23.5563 28.4417 24.0277C26.602 24.498 25.085 25.7963 24.3335 27.5408C23.5832 29.2854 23.6838 31.2794 24.6069 32.9395C25.529 34.5987 27.1696 35.7373 29.0475 36.0206C30.9254 36.3039 32.8286 35.6991 34.2 34.3855C35.0597 35.6542 36.521 36.6255 37.9386 36.6255V36.6025C38.0228 36.6178 38.1092 36.6255 38.1956 36.6255H38.4756C41.326 36.6255 43.2356 34.3855 43.2356 31.042V30.0007C43.2312 26.4909 41.8356 23.1265 39.3551 20.6448C36.8734 18.1631 33.5101 16.7654 30.0003 16.7598L29.9998 16.7598ZM29.9998 33.4416C28.6075 33.4416 27.353 32.6038 26.8204 31.3176C26.2878 30.0313 26.582 28.5515 27.5664 27.567C28.5508 26.5824 30.0306 26.2884 31.317 26.821C32.6032 27.3537 33.441 28.6082 33.441 30.0004C33.441 31.9014 31.901 33.4413 30.0001 33.4413L29.9998 33.4416Z" fill="#354049"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,4 +0,0 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect class="edit-svg__rect" width="40" height="40" rx="4" fill="#E2ECF7"/>
<path class="edit-svg__path" d="M19.0901 21.4605C19.3416 21.7259 19.6695 21.8576 19.9995 21.8576C20.3295 21.8576 20.6574 21.7259 20.9089 21.4605L28.6228 13.3181C29.1257 12.7871 29.1257 11.9291 28.6228 11.3982C28.1198 10.8673 27.3069 10.8673 26.8039 11.3982L19.0901 19.5406C18.5891 20.0715 18.5891 20.9295 19.0901 21.4605ZM27.7134 19.1435C27.0031 19.1435 26.4277 19.7509 26.4277 20.5005V27.2859H13.5713V13.7152H19.9995C20.7097 13.7152 21.2851 13.1078 21.2851 12.3581C21.2851 11.6085 20.7097 11.0011 19.9995 11.0011H13.5713C12.1508 11.0011 11 12.2158 11 13.7152V27.2859C11 28.7852 12.1508 30 13.5713 30H26.4277C27.8482 30 28.999 28.7852 28.999 27.2859V20.5005C28.999 19.7509 28.4236 19.1435 27.7134 19.1435Z" fill="#2683FF"/>
</svg>

Before

Width:  |  Height:  |  Size: 911 B

View File

@ -1,3 +0,0 @@
<svg width="6" height="9" viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="pagination-svg-path" d="M2.80077e-07 4.26316L6 0L6 9L2.80077e-07 4.26316Z" fill="#354049"/>
</svg>

Before

Width:  |  Height:  |  Size: 208 B

View File

@ -1,3 +0,0 @@
<svg width="6" height="9" viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="pagination-svg-path" d="M6 4.73684L0 9L1.20219e-06 -9.53674e-07L6 4.73684Z" fill="#354049"/>
</svg>

Before

Width:  |  Height:  |  Size: 209 B

View File

@ -1,209 +0,0 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import { mount, shallowMount } from '@vue/test-utils';
import Pagination from '@/components/common/VPagination.vue';
describe('Pagination.vue', () => {
it('renders correctly', () => {
const wrapper = shallowMount(Pagination);
expect(wrapper).toMatchSnapshot();
});
it('renders correctly with props', () => {
const wrapper = shallowMount(Pagination, {
propsData: {
totalPageCount: 10,
onPageClickCallback: () => new Promise(() => false),
},
});
expect(wrapper).toMatchSnapshot();
});
it('inits correctly with totalPageCount equals 10 and current pageNumber in first block', async () => {
const wrapper = mount(Pagination, {
propsData: {
totalPageCount: 10,
onPageClickCallback: () => new Promise(() => false),
},
});
const wrapperData = await wrapper.vm.$data;
expect(wrapperData.currentPageNumber).toBe(1);
expect(wrapperData.pagesArray.length).toBe(10);
expect(wrapperData.firstBlockPages.length).toBe(3);
expect(wrapperData.middleBlockPages.length).toBe(0);
expect(wrapperData.lastBlockPages.length).toBe(1);
expect(wrapper.findAll('span').at(0)?.classes().includes('selected')).toBe(true);
});
it('inits correctly with totalPageCount equals 4', () => {
const wrapper = shallowMount(Pagination, {
propsData: {
totalPageCount: 4,
onPageClickCallback: () => new Promise(() => false),
},
});
const wrapperData = wrapper.vm.$data;
expect(wrapperData.currentPageNumber).toBe(1);
expect(wrapperData.pagesArray.length).toBe(4);
expect(wrapperData.firstBlockPages.length).toBe(4);
expect(wrapperData.middleBlockPages.length).toBe(0);
expect(wrapperData.lastBlockPages.length).toBe(0);
});
it('behaves correctly on page click', async () => {
const callbackSpy = jest.fn();
const wrapper = mount(Pagination, {
propsData: {
totalPageCount: 9,
onPageClickCallback: callbackSpy,
},
});
const wrapperData = await wrapper.vm.$data;
await wrapper.findAll('span').at(2)?.trigger('click');
await expect(callbackSpy).toHaveBeenCalledTimes(1);
expect(wrapperData.currentPageNumber).toBe(3);
expect(wrapperData.firstBlockPages.length).toBe(1);
expect(wrapperData.middleBlockPages.length).toBe(3);
expect(wrapperData.lastBlockPages.length).toBe(1);
});
it('behaves correctly on next page button click', async () => {
const callbackSpy = jest.fn();
const wrapper = mount(Pagination, {
propsData: {
totalPageCount: 9,
onPageClickCallback: callbackSpy,
},
});
const wrapperData = wrapper.vm.$data;
wrapper.findAll('.pagination-container__button').at(1)?.trigger('click');
await expect(callbackSpy).toHaveBeenCalledTimes(1);
expect(wrapperData.currentPageNumber).toBe(2);
expect(wrapperData.firstBlockPages.length).toBe(3);
expect(wrapperData.middleBlockPages.length).toBe(0);
expect(wrapperData.lastBlockPages.length).toBe(1);
});
it('behaves correctly on previous page button click', async () => {
const callbackSpy = jest.fn();
const wrapper = mount(Pagination, {
propsData: {
totalPageCount: 9,
onPageClickCallback: callbackSpy,
},
});
await wrapper.vm.onPageClick(8);
const wrapperData = wrapper.vm.$data;
wrapper.findAll('.pagination-container__button').at(0)?.trigger('click');
await expect(callbackSpy).toHaveBeenCalledTimes(2);
expect(wrapperData.currentPageNumber).toBe(7);
expect(wrapperData.firstBlockPages.length).toBe(1);
expect(wrapperData.middleBlockPages.length).toBe(3);
expect(wrapperData.lastBlockPages.length).toBe(1);
});
it('behaves correctly on previous page button click when current is 1', async () => {
const callbackSpy = jest.fn();
const wrapper = mount(Pagination, {
propsData: {
totalPageCount: 9,
onPageClickCallback: callbackSpy,
},
});
const wrapperData = wrapper.vm.$data;
wrapper.findAll('.pagination-container__button').at(0)?.trigger('click');
await expect(callbackSpy).toHaveBeenCalledTimes(0);
expect(wrapperData.currentPageNumber).toBe(1);
expect(wrapperData.firstBlockPages.length).toBe(3);
expect(wrapperData.middleBlockPages.length).toBe(0);
expect(wrapperData.lastBlockPages.length).toBe(1);
});
it('behaves correctly on next page button click when current is last', async () => {
const callbackSpy = jest.fn();
const wrapper = mount(Pagination, {
propsData: {
totalPageCount: 9,
onPageClickCallback: callbackSpy,
},
});
const wrapperData = wrapper.vm.$data;
await wrapper.vm.onPageClick(9);
wrapper.findAll('.pagination-container__button').at(1)?.trigger('click');
await expect(callbackSpy).toHaveBeenCalledTimes(1);
expect(wrapperData.currentPageNumber).toBe(9);
expect(wrapperData.firstBlockPages.length).toBe(1);
expect(wrapperData.middleBlockPages.length).toBe(0);
expect(wrapperData.lastBlockPages.length).toBe(3);
});
it('should reset current page index to 1', async () => {
const wrapper = shallowMount(Pagination, {
propsData: {
totalPageCount: 4,
onPageClickCallback: () => Promise.resolve({}),
},
});
await wrapper.vm.nextPage();
expect(wrapper.vm.$data.currentPageNumber).toBe(2);
wrapper.vm.resetPageIndex();
const wrapperData = wrapper.vm.$data;
expect(wrapperData.currentPageNumber).toBe(1);
expect(wrapperData.pagesArray.length).toBe(4);
});
it('should completely reinitialize Pagination on totalPageCount change', async () => {
const wrapper = shallowMount(Pagination, {
propsData: {
totalPageCount: 4,
onPageClickCallback: () => Promise.resolve({}),
},
});
await wrapper.vm.nextPage();
expect(wrapper.vm.$data.currentPageNumber).toBe(2);
await wrapper.setProps({ totalPageCount: 7 });
const wrapperData = wrapper.vm.$data;
expect(wrapperData.currentPageNumber).toBe(1);
expect(wrapperData.pagesArray.length).toBe(7);
});
});