web/satellite: logic removed from template (#3136)

This commit is contained in:
Vitalii Shpital 2019-10-02 12:42:12 +03:00 committed by Nikolay Yurchenko
parent 4f2f8ae11b
commit 6a1203ea46
56 changed files with 534 additions and 298 deletions

View File

@ -6,7 +6,8 @@
<h1 class="account-area-container__title">Account</h1> <h1 class="account-area-container__title">Account</h1>
<TabNavigation <TabNavigation
class="account-area-container__navigation" class="account-area-container__navigation"
:navigation="navigation"/> :navigation="navigation"
/>
<router-view/> <router-view/>
</div> </div>
</template> </template>

View File

@ -39,7 +39,8 @@
label="Add Card" label="Add Card"
width="140px" width="140px"
height="48px" height="48px"
is-disabled="true"/> is-disabled="true"
/>
</div> </div>
</template> </template>

View File

@ -21,7 +21,8 @@
is-password="true" is-password="true"
ref="oldPasswordInput" ref="oldPasswordInput"
:error="oldPasswordError" :error="oldPasswordError"
@setData="setOldPassword" /> @setData="setOldPassword"
/>
<HeaderlessInput <HeaderlessInput
class="full-input mt" class="full-input mt"
label="New Password" label="New Password"
@ -30,7 +31,8 @@
ref="newPasswordInput" ref="newPasswordInput"
is-password="true" is-password="true"
:error="newPasswordError" :error="newPasswordError"
@setData="setNewPassword" /> @setData="setNewPassword"
/>
<HeaderlessInput <HeaderlessInput
class="full-input mt" class="full-input mt"
label="Confirm password" label="Confirm password"
@ -39,19 +41,22 @@
ref="confirmPasswordInput" ref="confirmPasswordInput"
is-password="true" is-password="true"
:error="confirmationPasswordError" :error="confirmationPasswordError"
@setData="setPasswordConfirmation" /> @setData="setPasswordConfirmation"
/>
<div class="change-password-popup__form-container__button-container"> <div class="change-password-popup__form-container__button-container">
<VButton <VButton
label="Cancel" label="Cancel"
width="205px" width="205px"
height="48px" height="48px"
:on-press="onCloseClick" :on-press="onCloseClick"
is-white="true" /> is-white="true"
/>
<VButton <VButton
label="Update" label="Update"
width="205px" width="205px"
height="48px" height="48px"
:on-press="onUpdateClick" /> :on-press="onUpdateClick"
/>
</div> </div>
</div> </div>
<div class="change-password-popup__close-cross-container" @click="onCloseClick"> <div class="change-password-popup__close-cross-container" @click="onCloseClick">

View File

@ -46,20 +46,22 @@
width='100%' width='100%'
is-password="true" is-password="true"
:error='passwordError' :error='passwordError'
@setData='setPassword'> @setData='setPassword'
</HeaderedInput> />
<div class='delete-account__form-container__button-container'> <div class='delete-account__form-container__button-container'>
<VButton <VButton
label='Cancel' label='Cancel'
width='205px' height='48px' width='205px' height='48px'
:on-press='onCloseClick' :on-press='onCloseClick'
is-white="true"/> is-white="true"
/>
<VButton <VButton
label='Delete' label='Delete'
width='205px' width='205px'
height='48px' height='48px'
class='red' class='red'
:on-press='onDeleteAccountClick'/> :on-press='onDeleteAccountClick'
/>
</div> </div>
</div> </div>
<div class='delete-account__close-cross-container' @click='onCloseClick'> <div class='delete-account__close-cross-container' @click='onCloseClick'>

View File

@ -19,7 +19,8 @@
ref="fullNameInput" ref="fullNameInput"
:error="fullNameError" :error="fullNameError"
:init-value="userInfo.fullName" :init-value="userInfo.fullName"
@setData="setFullName" /> @setData="setFullName"
/>
<HeaderedInput <HeaderedInput
class="full-input" class="full-input"
label="Nickname" label="Nickname"
@ -27,19 +28,22 @@
width="100%" width="100%"
ref="shortNameInput" ref="shortNameInput"
:init-value="userInfo.shortName" :init-value="userInfo.shortName"
@setData="setShortName"/> @setData="setShortName"
/>
<div class="edit-profile-popup__form-container__button-container"> <div class="edit-profile-popup__form-container__button-container">
<VButton <VButton
label="Cancel" label="Cancel"
width="205px" width="205px"
height="48px" height="48px"
:on-press="onCloseClick" :on-press="onCloseClick"
is-white="true" /> is-white="true"
/>
<VButton <VButton
label="Update" label="Update"
width="205px" width="205px"
height="48px" height="48px"
:on-press="onUpdateClick" /> :on-press="onUpdateClick"
/>
</div> </div>
</div> </div>
<div class="edit-profile-popup__close-cross-container" @click="onCloseClick"> <div class="edit-profile-popup__close-cross-container" @click="onCloseClick">

View File

@ -59,7 +59,8 @@
width="210px" width="210px"
height="56px" height="56px"
:on-press="toggleDeleteAccountPopup" :on-press="toggleDeleteAccountPopup"
is-deletion="true"/> is-deletion="true"
/>
</div> </div>
<ChangePasswordPopup v-if="isChangePasswordPopupShown"/> <ChangePasswordPopup v-if="isChangePasswordPopupShown"/>
<EditProfilePopup v-if="isEditProfilePopupShown"/> <EditProfilePopup v-if="isEditProfilePopupShown"/>

View File

@ -21,7 +21,8 @@
label="Earn Credits" label="Earn Credits"
width="153px" width="153px"
height="48px" height="48px"
:on-press="onEarnCredits"/> :on-press="onEarnCredits"
/>
</div> </div>
</div> </div>
</template> </template>

View File

@ -13,7 +13,8 @@
<VButton <VButton
label="Earn Credits" label="Earn Credits"
width="153px" width="153px"
height="48px"/> height="48px"
/>
</div> </div>
</div> </div>
<div class="current-month-area__content"> <div class="current-month-area__content">

View File

@ -8,40 +8,45 @@
<ApiKeysCreationPopup <ApiKeysCreationPopup
@closePopup="closeNewApiKeyPopup" @closePopup="closeNewApiKeyPopup"
@showCopyPopup="showCopyApiKeyPopup" @showCopyPopup="showCopyApiKeyPopup"
:is-popup-shown="isNewApiKeyPopupShown"/> :is-popup-shown="isNewApiKeyPopupShown"
/>
<ApiKeysCopyPopup <ApiKeysCopyPopup
:is-popup-shown="isCopyApiKeyPopupShown" :is-popup-shown="isCopyApiKeyPopupShown"
:api-key-secret="apiKeySecret" :api-key-secret="apiKeySecret"
@closePopup="closeCopyNewApiKeyPopup"/> @closePopup="closeCopyNewApiKeyPopup"
<div v-if="!isEmpty || hasSearchQuery" class="api-keys-header"> />
<div v-if="isHeaderShown" class="api-keys-header">
<VHeader <VHeader
ref="headerComponent" ref="headerComponent"
placeholder="API Key" placeholder="API Key"
:search="onSearchQueryCallback"> :search="onSearchQueryCallback">
<div class="header-default-state" v-if="headerState === 0"> <div class="header-default-state" v-if="isDefaultHeaderState">
<VButton <VButton
class="button" class="button"
label="+Create API Key" label="+Create API Key"
width="180px" width="180px"
height="48px" height="48px"
:on-press="onCreateApiKeyClick"/> :on-press="onCreateApiKeyClick"
/>
</div> </div>
<div class="header-selected-api-keys" v-if="headerState === 1 && !isDeleteClicked"> <div class="header-selected-api-keys" v-if="areApiKeysSelected">
<VButton <VButton
class="button deletion" class="button deletion"
label="Delete" label="Delete"
width="122px" width="122px"
height="48px" height="48px"
:on-press="onFirstDeleteClick"/> :on-press="onFirstDeleteClick"
/>
<VButton <VButton
class="button" class="button"
label="Cancel" label="Cancel"
width="122px" width="122px"
height="48px" height="48px"
is-white="true" is-white="true"
:on-press="onClearSelection"/> :on-press="onClearSelection"
/>
</div> </div>
<div class="header-after-delete-click" v-if="headerState === 1 && isDeleteClicked"> <div class="header-after-delete-click" v-if="areSelectedApiKeysBeingDeleted">
<span class="header-after-delete-click__confirmation-label">Are you sure you want to delete {{selectedAPIKeysCount}} {{apiKeyCountTitle}} ?</span> <span class="header-after-delete-click__confirmation-label">Are you sure you want to delete {{selectedAPIKeysCount}} {{apiKeyCountTitle}} ?</span>
<div class="header-after-delete-click__button-area"> <div class="header-after-delete-click__button-area">
<VButton <VButton
@ -49,14 +54,16 @@
label="Delete" label="Delete"
width="122px" width="122px"
height="48px" height="48px"
:on-press="onDelete"/> :on-press="onDelete"
/>
<VButton <VButton
class="button" class="button"
label="Cancel" label="Cancel"
width="122px" width="122px"
height="48px" height="48px"
is-white="true" is-white="true"
:on-press="onClearSelection"/> :on-press="onClearSelection"
/>
</div> </div>
</div> </div>
</VHeader> </VHeader>
@ -69,17 +76,19 @@
<VList <VList
:data-set="apiKeyList" :data-set="apiKeyList"
:item-component="itemComponent" :item-component="itemComponent"
:on-item-click="toggleSelection"/> :on-item-click="toggleSelection"
/>
</div> </div>
<VPagination <VPagination
v-if="totalPageCount > 1" v-if="totalPageCount > 1"
class="pagination-area" class="pagination-area"
ref="pagination" ref="pagination"
:total-page-count="totalPageCount" :total-page-count="totalPageCount"
:on-page-click-callback="onPageClick"/> :on-page-click-callback="onPageClick"
/>
<p class="api-keys-items__additional-info">Want to give limited access? <b>Use API Keys.</b></p> <p class="api-keys-items__additional-info">Want to give limited access? <b>Use API Keys.</b></p>
</div> </div>
<div class="empty-search-result-area" v-if="(isEmpty && hasSearchQuery)"> <div class="empty-search-result-area" v-if="isEmptySearchResultShown">
<h1 class="empty-search-result-area__title">No results found</h1> <h1 class="empty-search-result-area__title">No results found</h1>
<svg class="empty-search-result-area__image" width="254" height="195" viewBox="0 0 380 295" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="empty-search-result-area__image" width="254" height="195" viewBox="0 0 380 295" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M168 295C246.997 295 311 231.2 311 152.5C311 73.8 246.997 10 168 10C89.0028 10 25 73.8 25 152.5C25 231.2 89.0028 295 168 295Z" fill="#E8EAF2"/> <path d="M168 295C246.997 295 311 231.2 311 152.5C311 73.8 246.997 10 168 10C89.0028 10 25 73.8 25 152.5C25 231.2 89.0028 295 168 295Z" fill="#E8EAF2"/>
@ -114,12 +123,13 @@
</div> </div>
<EmptyState <EmptyState
:on-button-click="onCreateApiKeyClick" :on-button-click="onCreateApiKeyClick"
v-if="isEmpty && !isNewApiKeyPopupShown && !hasSearchQuery" v-if="isEmptyStateShown"
main-title="Let's create your first API Key" main-title="Let's create your first API Key"
additional-text="<p>API keys give access to the project allowing you to create buckets, upload files, and read them. Once youve created an API key, youre ready to interact with the network through our Uplink CLI.</p>" additional-text="<p>API keys give access to the project allowing you to create buckets, upload files, and read them. Once youve created an API key, youre ready to interact with the network through our Uplink CLI.</p>"
:image-source="emptyImage" :image-source="emptyImage"
button-label="Create an API Key" button-label="Create an API Key"
is-button-shown="true" /> is-button-shown="true"
/>
</div> </div>
</div> </div>
</template> </template>
@ -162,6 +172,10 @@ const {
SET_SORT_DIRECTION, SET_SORT_DIRECTION,
} = API_KEYS_ACTIONS; } = API_KEYS_ACTIONS;
declare interface ResetPagination {
resetPageIndex(): void;
}
@Component({ @Component({
components: { components: {
VList, VList,
@ -183,17 +197,16 @@ export default class ApiKeysArea extends Vue {
private isCopyApiKeyPopupShown: boolean = false; private isCopyApiKeyPopupShown: boolean = false;
private apiKeySecret: string = ''; private apiKeySecret: string = '';
public $refs!: {
pagination: HTMLElement & ResetPagination;
};
public mounted(): void { public mounted(): void {
this.$store.dispatch(FETCH, this.FIRST_PAGE); this.$store.dispatch(FETCH, this.FIRST_PAGE);
} }
public async beforeDestroy(): Promise<void> { public async beforeDestroy(): Promise<void> {
await this.$store.dispatch(API_KEYS_ACTIONS.CLEAR); await this.$store.dispatch(API_KEYS_ACTIONS.CLEAR);
try {
await this.$store.dispatch(API_KEYS_ACTIONS.FETCH, this.FIRST_PAGE);
} catch (error) {
await this.notifyFetchError(error);
}
} }
public async toggleSelection(apiKey: ApiKey): Promise<void> { public async toggleSelection(apiKey: ApiKey): Promise<void> {
@ -244,6 +257,10 @@ export default class ApiKeysArea extends Vue {
} }
this.isDeleteClicked = false; this.isDeleteClicked = false;
if (this.totalPageCount > 1) {
this.$refs.pagination.resetPageIndex();
}
} }
public get itemComponent() { public get itemComponent() {
@ -290,6 +307,30 @@ export default class ApiKeysArea extends Vue {
return HeaderState.DEFAULT; return HeaderState.DEFAULT;
} }
public get isHeaderShown(): boolean {
return !this.isEmpty || this.hasSearchQuery;
}
public get isDefaultHeaderState(): boolean {
return this.headerState === 0;
}
public get areApiKeysSelected(): boolean {
return this.headerState === 1 && !this.isDeleteClicked;
}
public get areSelectedApiKeysBeingDeleted(): boolean {
return this.headerState === 1 && this.isDeleteClicked;
}
public get isEmptySearchResultShown(): boolean {
return this.isEmpty && this.hasSearchQuery;
}
public get isEmptyStateShown(): boolean {
return this.isEmpty && !this.isNewApiKeyPopupShown && !this.hasSearchQuery;
}
public async onPageClick(index: number): Promise<void> { public async onPageClick(index: number): Promise<void> {
try { try {
await this.$store.dispatch(FETCH, index); await this.$store.dispatch(FETCH, index);
@ -307,7 +348,9 @@ export default class ApiKeysArea extends Vue {
await this.notifyFetchError(error); await this.notifyFetchError(error);
} }
(this.$refs.pagination as VPagination).resetPageIndex(); if (this.totalPageCount > 1) {
this.$refs.pagination.resetPageIndex();
}
} }
public async onSearchQueryCallback(query: string): Promise<void> { public async onSearchQueryCallback(query: string): Promise<void> {
@ -318,7 +361,9 @@ export default class ApiKeysArea extends Vue {
await this.notifyFetchError(error); await this.notifyFetchError(error);
} }
(this.$refs.pagination as VPagination).resetPageIndex(); if (this.totalPageCount > 1) {
this.$refs.pagination.resetPageIndex();
}
} }
public async notifyFetchError(error: Error): Promise<void> { public async notifyFetchError(error: Error): Promise<void> {

View File

@ -54,7 +54,7 @@ export default class ApiKeysCopyPopup extends Vue {
@Prop({default: ''}) @Prop({default: ''})
private readonly apiKeySecret: string; private readonly apiKeySecret: string;
private isCopiedButtonShown: boolean = false; public isCopiedButtonShown: boolean = false;
public onCloseClick(): void { public onCloseClick(): void {
this.isCopiedButtonShown = false; this.isCopiedButtonShown = false;

View File

@ -9,13 +9,15 @@
:error="errorMessage" :error="errorMessage"
placeholder="Enter API Key Name" placeholder="Enter API Key Name"
class="full-input" class="full-input"
width="100%" /> width="100%"
/>
<VButton <VButton
class="next-button" class="next-button"
label="Next >" label="Next >"
width="128px" width="128px"
height="48px" height="48px"
:on-press="onNextClick" /> :on-press="onNextClick"
/>
<div class="new-api-key__close-cross-container" @click="onCloseClick"> <div class="new-api-key__close-cross-container" @click="onCloseClick">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="close-cross-svg-path" d="M15.7071 1.70711C16.0976 1.31658 16.0976 0.683417 15.7071 0.292893C15.3166 -0.0976311 14.6834 -0.0976311 14.2929 0.292893L15.7071 1.70711ZM0.292893 14.2929C-0.0976311 14.6834 -0.0976311 15.3166 0.292893 15.7071C0.683417 16.0976 1.31658 16.0976 1.70711 15.7071L0.292893 14.2929ZM1.70711 0.292893C1.31658 -0.0976311 0.683417 -0.0976311 0.292893 0.292893C-0.0976311 0.683417 -0.0976311 1.31658 0.292893 1.70711L1.70711 0.292893ZM14.2929 15.7071C14.6834 16.0976 15.3166 16.0976 15.7071 15.7071C16.0976 15.3166 16.0976 14.6834 15.7071 14.2929L14.2929 15.7071ZM14.2929 0.292893L0.292893 14.2929L1.70711 15.7071L15.7071 1.70711L14.2929 0.292893ZM0.292893 1.70711L14.2929 15.7071L15.7071 14.2929L1.70711 0.292893L0.292893 1.70711Z" fill="#384B65"/> <path class="close-cross-svg-path" d="M15.7071 1.70711C16.0976 1.31658 16.0976 0.683417 15.7071 0.292893C15.3166 -0.0976311 14.6834 -0.0976311 14.2929 0.292893L15.7071 1.70711ZM0.292893 14.2929C-0.0976311 14.6834 -0.0976311 15.3166 0.292893 15.7071C0.683417 16.0976 1.31658 16.0976 1.70711 15.7071L0.292893 14.2929ZM1.70711 0.292893C1.31658 -0.0976311 0.683417 -0.0976311 0.292893 0.292893C-0.0976311 0.683417 -0.0976311 1.31658 0.292893 1.70711L1.70711 0.292893ZM14.2929 15.7071C14.6834 16.0976 15.3166 16.0976 15.7071 15.7071C16.0976 15.3166 16.0976 14.6834 15.7071 14.2929L14.2929 15.7071ZM14.2929 0.292893L0.292893 14.2929L1.70711 15.7071L15.7071 1.70711L14.2929 0.292893ZM0.292893 1.70711L14.2929 15.7071L15.7071 14.2929L1.70711 0.292893L0.292893 1.70711Z" fill="#384B65"/>

View File

@ -17,9 +17,9 @@
<path d="M10.7756 14.334C10.4108 14.334 10.1226 14.6283 10.1226 15.0007C10.1226 15.3731 10.4108 15.6673 10.7756 15.6673C11.1404 15.6673 11.4287 15.3731 11.4287 15.0007C11.4287 14.6283 11.1404 14.334 10.7756 14.334Z" fill="#2683FF"/> <path d="M10.7756 14.334C10.4108 14.334 10.1226 14.6283 10.1226 15.0007C10.1226 15.3731 10.4108 15.6673 10.7756 15.6673C11.1404 15.6673 11.4287 15.3731 11.4287 15.0007C11.4287 14.6283 11.1404 14.334 10.7756 14.334Z" fill="#2683FF"/>
</svg> </svg>
</div> </div>
<p class="name">{{ itemData.formattedName() }}</p> <p class="name">{{getItemName}}</p>
</div> </div>
<p class="date">{{ itemData.getDate() }}</p> <p class="date">{{getItemDate}}</p>
</div> </div>
</template> </template>
@ -32,6 +32,14 @@ import { ApiKey } from '@/types/apiKeys';
export default class ApiKeysItem extends Vue { export default class ApiKeysItem extends Vue {
@Prop({default: () => new ApiKey('', '', '', '')}) @Prop({default: () => new ApiKey('', '', '', '')})
private readonly itemData: ApiKey; private readonly itemData: ApiKey;
public get getItemName(): string {
return this.itemData.formattedName();
}
public get getItemDate(): string {
return this.itemData.getDate();
}
} }
</script> </script>

View File

@ -6,14 +6,16 @@
<div class="sort-header-container__name-item" @click="onHeaderItemClick(ApiKeyOrderBy.NAME)"> <div class="sort-header-container__name-item" @click="onHeaderItemClick(ApiKeyOrderBy.NAME)">
<p class="sort-header-container__name-item__title">Key Name</p> <p class="sort-header-container__name-item__title">Key Name</p>
<VerticalArrows <VerticalArrows
:isActive="getSortBy === ApiKeyOrderBy.NAME" :isActive="areApiKeysSortedByName"
:direction="getSortDirection"></VerticalArrows> :direction="getSortDirection"
/>
</div> </div>
<div class="sort-header-container__date-item" @click="onHeaderItemClick(ApiKeyOrderBy.CREATED_AT)"> <div class="sort-header-container__date-item" @click="onHeaderItemClick(ApiKeyOrderBy.CREATED_AT)">
<p class="sort-header-container__date-item__title">Created</p> <p class="sort-header-container__date-item__title">Created</p>
<VerticalArrows <VerticalArrows
:isActive="getSortBy === ApiKeyOrderBy.CREATED_AT" :isActive="areApiKeysSortedByDate"
:direction="getSortDirection"></VerticalArrows> :direction="getSortDirection"
/>
</div> </div>
</div> </div>
</template> </template>
@ -48,8 +50,12 @@ export default class SortApiKeysHeader extends Vue {
return SortDirection.DESCENDING; return SortDirection.DESCENDING;
} }
public get getSortBy(): ApiKeyOrderBy { public get areApiKeysSortedByName(): boolean {
return this.sortBy; return this.sortBy === ApiKeyOrderBy.NAME;
}
public get areApiKeysSortedByDate(): boolean {
return this.sortBy === ApiKeyOrderBy.CREATED_AT;
} }
public async onHeaderItemClick(sortBy: ApiKeyOrderBy): Promise<void> { public async onHeaderItemClick(sortBy: ApiKeyOrderBy): Promise<void> {

View File

@ -3,14 +3,15 @@
<template> <template>
<div> <div>
<NoBucketArea v-if="!totalCount && !search" /> <NoBucketArea v-if="isNoBucketAreaShown"/>
<div class="buckets-overflow" v-else> <div class="buckets-overflow" v-else>
<div class="buckets-header"> <div class="buckets-header">
<p class="buckets-header__title">Buckets</p> <p class="buckets-header__title">Buckets</p>
<VHeader <VHeader
class="buckets-header-component" class="buckets-header-component"
placeholder="Buckets" placeholder="Buckets"
:search="fetch"/> :search="fetch"
/>
</div> </div>
<div class="buckets-notification-container"> <div class="buckets-notification-container">
<div class="buckets-notification"> <div class="buckets-notification">
@ -26,17 +27,20 @@
<VList <VList
:data-set="buckets" :data-set="buckets"
:item-component="itemComponent" :item-component="itemComponent"
:on-item-click="doNothing"/> :on-item-click="doNothing"
/>
<VPagination <VPagination
v-if="totalPageCount > 1" v-if="isPaginationShown"
:total-page-count="totalPageCount" :total-page-count="totalPageCount"
:on-page-click-callback="onPageClick" /> :on-page-click-callback="onPageClick"
/>
</div> </div>
<EmptyState <EmptyState
class="empty-container" class="empty-container"
v-if="!totalPageCount && search" v-if="isEmptySearchResultShown"
main-title="Nothing found :(" main-title="Nothing found :("
:image-source="emptyImage" /> :image-source="emptyImage"
/>
</div> </div>
</div> </div>
</template> </template>
@ -104,6 +108,18 @@ export default class BucketArea extends Vue {
return this.$store.getters.cursor.search; return this.$store.getters.cursor.search;
} }
public get isNoBucketAreaShown(): boolean {
return !this.totalCount && !this.search;
}
public get isPaginationShown(): boolean {
return this.totalPageCount > 1;
}
public get isEmptySearchResultShown(): boolean {
return !!(!this.totalPageCount && this.search);
}
public async fetch(searchQuery: string): Promise<void> { public async fetch(searchQuery: string): Promise<void> {
await this.$store.dispatch(SET_SEARCH, searchQuery); await this.$store.dispatch(SET_SEARCH, searchQuery);

View File

@ -27,7 +27,7 @@
</div> </div>
</a> </a>
</div> </div>
<img src="../../../static/images/buckets/uplink.svg"> <img src="@/../static/images/buckets/uplink.svg">
</div> </div>
<p class="no-buckets-area__s3-link">Familiar with AWS S3? <a class="s3-gateway-link" href="https://github.com/storj/storj/wiki/S3-Gateway" target="_blank">Try our S3 Gateway</a></p> <p class="no-buckets-area__s3-link">Familiar with AWS S3? <a class="s3-gateway-link" href="https://github.com/storj/storj/wiki/S3-Gateway" target="_blank">Try our S3 Gateway</a></p>
<div class="no-buckets-area__next-step-area"> <div class="no-buckets-area__next-step-area">

View File

@ -11,7 +11,8 @@
:on-press="onButtonClick" :on-press="onButtonClick"
:label="buttonLabel" :label="buttonLabel"
width="190px" width="190px"
height="50px"/> height="50px"
/>
</div> </div>
<div class="empty-state__wrap__img" v-html="imageSource"></div> <div class="empty-state__wrap__img" v-html="imageSource"></div>
</div> </div>

View File

@ -35,7 +35,8 @@
@input="onInput" @input="onInput"
@change="onInput" @change="onInput"
v-model="value" v-model="value"
:style="style.inputStyle"/> :style="style.inputStyle"
/>
</div> </div>
</template> </template>

View File

@ -4,8 +4,8 @@
<template> <template>
<div class="input-wrap"> <div class="input-wrap">
<div class="label-container"> <div class="label-container">
<img v-if="error" src="../../../static/images/register/ErrorInfo.svg"/> <img v-if="error" src="@/../static/images/register/ErrorInfo.svg"/>
<h3 class="label-container__label" v-if="!error && label" :style="style.labelStyle">{{label}}</h3> <h3 class="label-container__label" v-if="isLabelShown" :style="style.labelStyle">{{label}}</h3>
<h3 class="label-container__error" v-if="error" :style="style.errorStyle">{{error}}</h3> <h3 class="label-container__error" v-if="error" :style="style.errorStyle">{{error}}</h3>
</div> </div>
<input <input
@ -16,13 +16,14 @@
v-model="value" v-model="value"
:placeholder="placeholder" :placeholder="placeholder"
:type="type" :type="type"
:style="style.inputStyle"/> :style="style.inputStyle"
/>
<!--2 conditions of eye image (crossed or not) --> <!--2 conditions of eye image (crossed or not) -->
<svg class="input-wrap__image" v-if="isPassword && !isPasswordShown" @click="changeVision" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="input-wrap__image" v-if="isPasswordHiddenState" @click="changeVision" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="input-wrap__image__path" d="M10 4C4.70642 4 1 10 1 10C1 10 3.6999 16 10 16C16.3527 16 19 10 19 10C19 10 15.3472 4 10 4ZM10 13.8176C7.93537 13.8176 6.2946 12.1271 6.2946 10C6.2946 7.87285 7.93537 6.18239 10 6.18239C12.0646 6.18239 13.7054 7.87285 13.7054 10C13.7054 12.1271 12.0646 13.8176 10 13.8176Z" fill="#AFB7C1"/> <path class="input-wrap__image__path" d="M10 4C4.70642 4 1 10 1 10C1 10 3.6999 16 10 16C16.3527 16 19 10 19 10C19 10 15.3472 4 10 4ZM10 13.8176C7.93537 13.8176 6.2946 12.1271 6.2946 10C6.2946 7.87285 7.93537 6.18239 10 6.18239C12.0646 6.18239 13.7054 7.87285 13.7054 10C13.7054 12.1271 12.0646 13.8176 10 13.8176Z" fill="#AFB7C1"/>
<path d="M11.6116 9.96328C11.6116 10.8473 10.8956 11.5633 10.0116 11.5633C9.12763 11.5633 8.41162 10.8473 8.41162 9.96328C8.41162 9.07929 9.12763 8.36328 10.0116 8.36328C10.8956 8.36328 11.6116 9.07929 11.6116 9.96328Z" fill="#AFB7C1"/> <path d="M11.6116 9.96328C11.6116 10.8473 10.8956 11.5633 10.0116 11.5633C9.12763 11.5633 8.41162 10.8473 8.41162 9.96328C8.41162 9.07929 9.12763 8.36328 10.0116 8.36328C10.8956 8.36328 11.6116 9.07929 11.6116 9.96328Z" fill="#AFB7C1"/>
</svg> </svg>
<svg class="input-wrap__image" v-if="isPassword && isPasswordShown" @click="changeVision" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="input-wrap__image" v-if="isPasswordShownState" @click="changeVision" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="input-wrap__image__path" d="M10 4C4.70642 4 1 10 1 10C1 10 3.6999 16 10 16C16.3527 16 19 10 19 10C19 10 15.3472 4 10 4ZM10 13.8176C7.93537 13.8176 6.2946 12.1271 6.2946 10C6.2946 7.87285 7.93537 6.18239 10 6.18239C12.0646 6.18239 13.7054 7.87285 13.7054 10C13.7054 12.1271 12.0646 13.8176 10 13.8176Z" fill="#AFB7C1"/> <path class="input-wrap__image__path" d="M10 4C4.70642 4 1 10 1 10C1 10 3.6999 16 10 16C16.3527 16 19 10 19 10C19 10 15.3472 4 10 4ZM10 13.8176C7.93537 13.8176 6.2946 12.1271 6.2946 10C6.2946 7.87285 7.93537 6.18239 10 6.18239C12.0646 6.18239 13.7054 7.87285 13.7054 10C13.7054 12.1271 12.0646 13.8176 10 13.8176Z" fill="#AFB7C1"/>
<path d="M11.6121 9.96328C11.6121 10.8473 10.8961 11.5633 10.0121 11.5633C9.12812 11.5633 8.41211 10.8473 8.41211 9.96328C8.41211 9.07929 9.12812 8.36328 10.0121 8.36328C10.8961 8.36328 11.6121 9.07929 11.6121 9.96328Z" fill="#AFB7C1"/> <path d="M11.6121 9.96328C11.6121 10.8473 10.8961 11.5633 10.0121 11.5633C9.12812 11.5633 8.41211 10.8473 8.41211 9.96328C8.41211 9.07929 9.12812 8.36328 10.0121 8.36328C10.8961 8.36328 11.6121 9.07929 11.6121 9.96328Z" fill="#AFB7C1"/>
<mask id="path-3-inside-1" fill="white"> <mask id="path-3-inside-1" fill="white">
@ -101,6 +102,18 @@ export default class HeaderlessInput extends Vue {
this.type = this.passwordType; this.type = this.passwordType;
} }
public get isLabelShown(): boolean {
return !!(!this.error && this.label);
}
public get isPasswordHiddenState(): boolean {
return this.isPassword && !this.isPasswordShown;
}
public get isPasswordShownState(): boolean {
return this.isPassword && this.isPasswordShown;
}
protected get style(): object { protected get style(): object {
return { return {
inputStyle: { inputStyle: {

View File

@ -9,7 +9,8 @@
<VSearch <VSearch
ref="search" ref="search"
:placeholder="placeholder" :placeholder="placeholder"
:search="search"/> :search="search"
/>
</div> </div>
</template> </template>

View File

@ -18,13 +18,13 @@ import { Component, Prop, Vue } from 'vue-property-decorator';
@Component @Component
export default class VInfo extends Vue { export default class VInfo extends Vue {
private isVisible: boolean = false;
@Prop({default: ''}) @Prop({default: ''})
private readonly text: String; private readonly text: String;
@Prop({default: ''}) @Prop({default: ''})
private readonly boldText: String; private readonly boldText: String;
private isVisible: boolean = false;
public toggleVisibility(): void { public toggleVisibility(): void {
this.isVisible = !this.isVisible; this.isVisible = !this.isVisible;
} }

View File

@ -4,13 +4,14 @@
<template> <template>
<div class="item-component"> <div class="item-component">
<component <component
v-for="item in dataSet" v-for="(item, key) in dataSet"
class="item-component__item" class="item-component__item"
:is="itemComponent" :is="itemComponent"
:item-data="item" :item-data="item"
@click.native="onItemClick(item)" @click.native="onItemClick(item)"
:class="{ selected: item.isSelected }" :class="{ selected: item.isSelected }"
:key="item.name"/> :key="key"
/>
</div> </div>
</template> </template>

View File

@ -12,15 +12,18 @@
<div class="pagination-container__items"> <div class="pagination-container__items">
<PagesBlock <PagesBlock
:pages="firstBlockPages" :pages="firstBlockPages"
:is-selected="isSelected"/> :is-selected="isSelected"
/>
<span class="pages-divider" v-if="isFirstDotsShown">...</span> <span class="pages-divider" v-if="isFirstDotsShown">...</span>
<PagesBlock <PagesBlock
:pages="middleBlockPages" :pages="middleBlockPages"
:is-selected="isSelected"/> :is-selected="isSelected"
/>
<span class="pages-divider" v-if="isSecondDotsShown">...</span> <span class="pages-divider" v-if="isSecondDotsShown">...</span>
<PagesBlock <PagesBlock
:pages="lastBlockPages" :pages="lastBlockPages"
:is-selected="isSelected"/> :is-selected="isSelected"
/>
</div> </div>
<div class="pagination-container__button" @click="nextPage"> <div class="pagination-container__button" @click="nextPage">
<svg class="pagination-container__button__image" width="6" height="9" viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="pagination-container__button__image" width="6" height="9" viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg">
@ -37,7 +40,6 @@ import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import PagesBlock from '@/components/common/PagesBlock.vue'; import PagesBlock from '@/components/common/PagesBlock.vue';
import { Page } from '@/types/pagination'; import { Page } from '@/types/pagination';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
@Component({ @Component({
components: { components: {

View File

@ -12,7 +12,8 @@
:placeholder="`Search ${placeholder}`" :placeholder="`Search ${placeholder}`"
:style="style" :style="style"
type="text" type="text"
autocomplete="off"> autocomplete="off"
/>
</template> </template>
<script lang="ts"> <script lang="ts">

View File

@ -24,7 +24,8 @@
width="450px" width="450px"
height="50px" height="50px"
:on-press="onResendEmailButtonClick" :on-press="onResendEmailButtonClick"
:is-disabled="isResendEmailButtonDisabled"/> :is-disabled="isResendEmailButtonDisabled"
/>
</div> </div>
</div> </div>
<div class="register-success-popup__close-cross-container" @click="onCloseClick"> <div class="register-success-popup__close-cross-container" @click="onCloseClick">

View File

@ -5,7 +5,8 @@
<VList <VList
:data-set="dataSetItems" :data-set="dataSetItems"
:item-component="getItemComponent" :item-component="getItemComponent"
:on-item-click="onItemClick"/> :on-item-click="onItemClick"
/>
</template> </template>
<script lang="ts"> <script lang="ts">

View File

@ -5,7 +5,8 @@
<div> <div>
<EmptyState <EmptyState
main-title="Create your first new project" main-title="Create your first new project"
:image-source="emptyImage" /> :image-source="emptyImage"
/>
</div> </div>
</template> </template>

View File

@ -12,8 +12,8 @@
</div> </div>
<h1 class="account-button-toggle-container__user-name">{{userName}}</h1> <h1 class="account-button-toggle-container__user-name">{{userName}}</h1>
<div class="account-button-toggle-container__expander-area"> <div class="account-button-toggle-container__expander-area">
<img v-if="!isDropdownShown" src="../../../static/images/register/BlueExpand.svg" alt="expand settings" /> <img v-if="!isDropdownShown" src="@/../static/images/register/BlueExpand.svg" alt="expand settings"/>
<img v-if="isDropdownShown" src="../../../static/images/register/BlueHide.svg" alt="hide settings" /> <img v-if="isDropdownShown" src="@/../static/images/register/BlueHide.svg" alt="hide settings"/>
</div> </div>
</div> </div>
<AccountDropdown v-if="isDropdownShown"/> <AccountDropdown v-if="isDropdownShown"/>

View File

@ -36,6 +36,7 @@
<ProjectCreationSuccessPopup/> <ProjectCreationSuccessPopup/>
<NavigationArea <NavigationArea
class="adapted-navigation" class="adapted-navigation"
v-if="isNavigationVisible" /> v-if="isNavigationVisible"
/>
<div class="navigation-blur" v-if="isNavigationVisible"></div> <div class="navigation-blur" v-if="isNavigationVisible"></div>
</div> </div>

View File

@ -7,8 +7,8 @@
<div class="project-selection-toggle-container" @click="toggleSelection" v-if="hasProjects"> <div class="project-selection-toggle-container" @click="toggleSelection" v-if="hasProjects">
<h1 class="project-selection-toggle-container__name">{{name}}</h1> <h1 class="project-selection-toggle-container__name">{{name}}</h1>
<div class="project-selection-toggle-container__expander-area"> <div class="project-selection-toggle-container__expander-area">
<img v-if="!isDropdownShown" src="../../../../static/images/register/BlueExpand.svg" alt="expand project list" /> <img v-if="!isDropdownShown" src="@/../static/images/register/BlueExpand.svg" alt="expand project list"/>
<img v-if="isDropdownShown" src="../../../../static/images/register/BlueHide.svg" alt="hide project list" /> <img v-if="isDropdownShown" src="@/../static/images/register/BlueHide.svg" alt="hide project list"/>
</div> </div>
</div> </div>
<ProjectSelectionDropdown v-if="isDropdownShown"/> <ProjectSelectionDropdown v-if="isDropdownShown"/>

View File

@ -78,6 +78,22 @@ export default class NavigationArea extends Vue {
public get isProjectNotSelected(): boolean { public get isProjectNotSelected(): boolean {
return this.$store.state.projectsModule.selectedProject.id === ''; return this.$store.state.projectsModule.selectedProject.id === '';
} }
public get isResourcesDisplayingButtonShown(): boolean {
return !this.areResourceItemsShown && this.isResourceButtonShown;
}
public get isResourcesHidingButtonShown(): boolean {
return this.areResourceItemsShown && this.isResourceButtonShown;
}
public get isAccountItemsDisplayingButtonShown(): boolean {
return !this.areAccountItemsShown && this.isAccountButtonShown;
}
public get isAccountItemsHidingButtonShown(): boolean {
return this.areAccountItemsShown && this.isAccountButtonShown;
}
} }
</script> </script>

View File

@ -32,8 +32,8 @@
</router-link> </router-link>
<div class="navigation-area__resources-title" :class="{ custom: areResourceItemsShown }" @mouseenter="toggleResourceButtonVisibility" @mouseleave="toggleResourceButtonVisibility"> <div class="navigation-area__resources-title" :class="{ custom: areResourceItemsShown }" @mouseenter="toggleResourceButtonVisibility" @mouseleave="toggleResourceButtonVisibility">
<p class="navigation-area__resources-title__title">RESOURCES</p> <p class="navigation-area__resources-title__title">RESOURCES</p>
<p v-if="!areResourceItemsShown && isResourceButtonShown" @click="toggleResourceItemsVisibility" class="navigation-area__resources-title__button">Show</p> <p v-if="isResourcesDisplayingButtonShown" @click="toggleResourceItemsVisibility" class="navigation-area__resources-title__button">Show</p>
<p v-if="areResourceItemsShown && isResourceButtonShown" @click="toggleResourceItemsVisibility" class="navigation-area__resources-title__button">Hide</p> <p v-if="isResourcesHidingButtonShown" @click="toggleResourceItemsVisibility" class="navigation-area__resources-title__button">Hide</p>
</div> </div>
<a v-if="areResourceItemsShown" class="navigation-area__item-container" href="https://github.com/storj/docs/blob/master/Vanguard-Release-Setup-Instructions.md" target="_blank"> <a v-if="areResourceItemsShown" class="navigation-area__item-container" href="https://github.com/storj/docs/blob/master/Vanguard-Release-Setup-Instructions.md" target="_blank">
<div class="navigation-area__item-container__link-container"> <div class="navigation-area__item-container__link-container">
@ -57,14 +57,16 @@
</a> </a>
<div class="navigation-area__account-title" :class="{custom: areAccountItemsShown}" @mouseenter="toggleAccountButtonVisibility" @mouseleave="toggleAccountButtonVisibility"> <div class="navigation-area__account-title" :class="{custom: areAccountItemsShown}" @mouseenter="toggleAccountButtonVisibility" @mouseleave="toggleAccountButtonVisibility">
<p class="navigation-area__account-title__title">ACCOUNT</p> <p class="navigation-area__account-title__title">ACCOUNT</p>
<p v-if="!areAccountItemsShown && isAccountButtonShown" @click="toggleAccountItemsVisibility" class="navigation-area__account-title__button">Show</p> <p v-if="isAccountItemsDisplayingButtonShown" @click="toggleAccountItemsVisibility" class="navigation-area__account-title__button">Show</p>
<p v-if="areAccountItemsShown && isAccountButtonShown" @click="toggleAccountItemsVisibility" class="navigation-area__account-title__button">Hide</p> <p v-if="isAccountItemsHidingButtonShown" @click="toggleAccountItemsVisibility" class="navigation-area__account-title__button">Hide</p>
</div> </div>
<router-link v-if="areAccountItemsShown" class="navigation-area__item-container account-item" v-for="navItem in accountNavigation" :key="navItem.name" :to="navItem.path"> <div v-if="areAccountItemsShown" class="navigation-area__account-area">
<router-link class="navigation-area__item-container account-item" v-for="navItem in accountNavigation" :key="navItem.name" :to="navItem.path">
<div class="navigation-area__item-container__link-container" > <div class="navigation-area__item-container__link-container" >
<h1 class="navigation-area__item-container__link-container__title account-item">{{navItem.name}}</h1> <h1 class="navigation-area__item-container__link-container__title account-item">{{navItem.name}}</h1>
</div> </div>
</router-link> </router-link>
</div>
<div class="divider" :class="{'custom-divider': areAccountItemsShown}"></div> <div class="divider" :class="{'custom-divider': areAccountItemsShown}"></div>
</div> </div>
</div> </div>

View File

@ -2,11 +2,12 @@
// See LICENSE for copying information. // See LICENSE for copying information.
<template> <template>
<div id="notificationArea" class="notification-container" v-if="notifications.length > 0" > <div id="notificationArea" class="notification-container" v-if="doNotificationsExist">
<NotificationItem <NotificationItem
v-for="notification in notifications" v-for="notification in notifications"
:notification="notification" :notification="notification"
:key="notification.id" /> :key="notification.id"
/>
</div> </div>
</template> </template>
@ -26,6 +27,10 @@ export default class NotificationArea extends Vue {
public get notifications(): DelayedNotification[] { public get notifications(): DelayedNotification[] {
return this.$store.state.notificationsModule.notificationQueue; return this.$store.state.notificationsModule.notificationQueue;
} }
public get doNotificationsExist(): boolean {
return this.notifications.length > 0;
}
} }
</script> </script>

View File

@ -52,7 +52,8 @@
<VButton <VButton
label="Save Card" label="Save Card"
height="48px" height="48px"
width="100%"/> width="100%"
/>
<div class="add-stripe-card-popup-container__close-cross-container"> <div class="add-stripe-card-popup-container__close-cross-container">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" > <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" >
<path d="M15.7071 1.70711C16.0976 1.31658 16.0976 0.683417 15.7071 0.292893C15.3166 -0.0976311 14.6834 -0.0976311 14.2929 0.292893L15.7071 1.70711ZM0.292893 14.2929C-0.0976311 14.6834 -0.0976311 15.3166 0.292893 15.7071C0.683417 16.0976 1.31658 16.0976 1.70711 15.7071L0.292893 14.2929ZM1.70711 0.292893C1.31658 -0.0976311 0.683417 -0.0976311 0.292893 0.292893C-0.0976311 0.683417 -0.0976311 1.31658 0.292893 1.70711L1.70711 0.292893ZM14.2929 15.7071C14.6834 16.0976 15.3166 16.0976 15.7071 15.7071C16.0976 15.3166 16.0976 14.6834 15.7071 14.2929L14.2929 15.7071ZM14.2929 0.292893L0.292893 14.2929L1.70711 15.7071L15.7071 1.70711L14.2929 0.292893ZM0.292893 1.70711L14.2929 15.7071L15.7071 14.2929L1.70711 0.292893L0.292893 1.70711Z" fill="#384B65"/> <path d="M15.7071 1.70711C16.0976 1.31658 16.0976 0.683417 15.7071 0.292893C15.3166 -0.0976311 14.6834 -0.0976311 14.2929 0.292893L15.7071 1.70711ZM0.292893 14.2929C-0.0976311 14.6834 -0.0976311 15.3166 0.292893 15.7071C0.683417 16.0976 1.31658 16.0976 1.70711 15.7071L0.292893 14.2929ZM1.70711 0.292893C1.31658 -0.0976311 0.683417 -0.0976311 0.292893 0.292893C-0.0976311 0.683417 -0.0976311 1.31658 0.292893 1.70711L1.70711 0.292893ZM14.2929 15.7071C14.6834 16.0976 15.3166 16.0976 15.7071 15.7071C16.0976 15.3166 16.0976 14.6834 15.7071 14.2929L14.2929 15.7071ZM14.2929 0.292893L0.292893 14.2929L1.70711 15.7071L15.7071 1.70711L14.2929 0.292893ZM0.292893 1.70711L14.2929 15.7071L15.7071 14.2929L1.70711 0.292893L0.292893 1.70711Z" fill="#384B65"/>

View File

@ -57,7 +57,8 @@
type="text" type="text"
placeholder="Enter Project Name" placeholder="Enter Project Name"
v-model="projectName" v-model="projectName"
@keyup="resetError" > @keyup="resetError"
/>
</div> </div>
<div class="delete-project-popup__form-container__button-container"> <div class="delete-project-popup__form-container__button-container">
<VButton <VButton
@ -65,14 +66,16 @@
width="205px" width="205px"
height="48px" height="48px"
:on-press="onCloseClick" :on-press="onCloseClick"
is-white="true"/> is-white="true"
/>
<VButton <VButton
label="Delete" label="Delete"
width="205px" width="205px"
height="48px" height="48px"
class="red" class="red"
:on-press="onDeleteProjectClick" :on-press="onDeleteProjectClick"
:is-disabled="isDeleteButtonDisabled" /> :is-disabled="isDeleteButtonDisabled"
/>
</div> </div>
</div> </div>
<div class="delete-project-popup__close-cross-container" @click="onCloseClick"> <div class="delete-project-popup__close-cross-container" @click="onCloseClick">

View File

@ -17,8 +17,8 @@
width="100%" width="100%"
max-symbols="20" max-symbols="20"
:error="nameError" :error="nameError"
@setData="setProjectName"> @setData="setProjectName"
</HeaderedInput> />
<HeaderedInput <HeaderedInput
label="Description" label="Description"
placeholder="Enter Project Description" placeholder="Enter Project Description"
@ -27,20 +27,22 @@
is-multiline="true" is-multiline="true"
height="100px" height="100px"
width="100%" width="100%"
@setData="setProjectDescription"> @setData="setProjectDescription"
</HeaderedInput> />
<div class="new-project-popup__form-container__button-container"> <div class="new-project-popup__form-container__button-container">
<VButton <VButton
label="Cancel" label="Cancel"
width="205px" width="205px"
height="48px" height="48px"
:on-press="onCloseClick" :on-press="onCloseClick"
is-white="true"/> is-white="true"
/>
<VButton <VButton
label="Next" label="Next"
width="205px" width="205px"
height="48px" height="48px"
:on-press="createProjectClick"/> :on-press="createProjectClick"
/>
</div> </div>
</div> </div>
<div class="new-project-popup__close-cross-container" @click="onCloseClick"> <div class="new-project-popup__close-cross-container" @click="onCloseClick">

View File

@ -40,12 +40,14 @@
width="214px" width="214px"
height="50px" height="50px"
:on-press="onCloseClick" :on-press="onCloseClick"
is-white="true" /> is-white="true"
/>
<VButton <VButton
label="Create first API Key" label="Create first API Key"
width="214px" width="214px"
height="50px" height="50px"
:on-press="onCreateAPIKeyClick" /> :on-press="onCreateAPIKeyClick"
/>
</div> </div>
</div> </div>
<div class="project-creation-success-popup__close-cross-container" @click="onCloseClick"> <div class="project-creation-success-popup__close-cross-container" @click="onCloseClick">
@ -71,7 +73,7 @@ import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
}, },
}) })
export default class ProjectCreationSuccessPopup extends Vue { export default class ProjectCreationSuccessPopup extends Vue {
private onCloseClick(): void { public onCloseClick(): void {
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_PROJECT_CREATION_POPUP); this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_PROJECT_CREATION_POPUP);
} }

View File

@ -32,19 +32,22 @@
height="10vh" height="10vh"
is-multiline="true" is-multiline="true"
:init-value="storedDescription" :init-value="storedDescription"
@setData="setNewDescription" /> @setData="setNewDescription"
/>
<div class="project-details-info-container__description-container__buttons-area"> <div class="project-details-info-container__description-container__buttons-area">
<VButton <VButton
label="Cancel" label="Cancel"
width="180px" width="180px"
height="48px" height="48px"
:on-press="toggleEditing" :on-press="toggleEditing"
is-white="true"/> is-white="true"
/>
<VButton <VButton
label="Save" label="Save"
width="180px" width="180px"
height="48px" height="48px"
:on-press="onSaveButtonClick"/> :on-press="onSaveButtonClick"
/>
</div> </div>
</div> </div>
</div> </div>
@ -55,7 +58,8 @@
width="180px" width="180px"
height="48px" height="48px"
:on-press="toggleDeleteDialog" :on-press="toggleDeleteDialog"
is-deletion="true"/> is-deletion="true"
/>
</div> </div>
</div> </div>
<DeleteProjectPopup v-if="isPopupShown"/> <DeleteProjectPopup v-if="isPopupShown"/>

View File

@ -6,13 +6,15 @@
<TabNavigation <TabNavigation
v-if="isProjectSelected" v-if="isProjectSelected"
class="project-overview__navigation" class="project-overview__navigation"
:navigation="navigation"/> :navigation="navigation"
/>
<router-view v-if="isProjectSelected"/> <router-view v-if="isProjectSelected"/>
<EmptyState <EmptyState
v-if="!isProjectSelected" v-if="!isProjectSelected"
main-title="Create your first project" main-title="Create your first project"
additional-text='<p>Please click the button <b>"New Project"</b> in the right corner</p>' additional-text='<p>Please click the button <b>"New Project"</b> in the right corner</p>'
:image-source="emptyImage" /> :image-source="emptyImage"
/>
</div> </div>
</template> </template>

View File

@ -18,7 +18,8 @@
<Datepicker <Datepicker
ref="datePicker" ref="datePicker"
:date="startTime" :date="startTime"
@change="getDates"/> @change="getDates"
/>
<svg class="usage-report-container__options-area__option__image" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" @click.prevent.self="onCustomDateClick"> <svg class="usage-report-container__options-area__option__image" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" @click.prevent.self="onCustomDateClick">
<path class="usage-report-svg-path" d="M16.3213 2.28026H14.8009V1.50058C14.8009 1.10058 14.4806 0.760742 14.0611 0.760742C13.6611 0.760742 13.3213 1.08106 13.3213 1.50058V2.28026H6.66106V1.50058C6.66106 1.10058 6.34074 0.760742 5.92122 0.760742C5.5009 0.760742 5.2009 1.10058 5.2009 1.50058V2.28026H3.68058C1.92042 2.28026 0.500977 3.70058 0.500977 5.45986V16.0599C0.500977 17.82 1.9213 19.2395 3.68058 19.2395H16.3204C18.0805 19.2395 19.5 17.8191 19.5 16.0599V5.45986C19.5008 3.70048 18.0804 2.28026 16.321 2.28026H16.3213ZM3.68066 3.74042H5.20098V4.5201C5.20098 4.9201 5.5213 5.25994 5.94082 5.25994C6.36114 5.25994 6.68066 4.93962 6.68066 4.5201V3.74042H13.3603V4.5201C13.3603 4.9201 13.6806 5.25994 14.1001 5.25994C14.5001 5.25994 14.8399 4.93962 14.8399 4.5201V3.74042H16.3603C17.3001 3.74042 18.0806 4.50058 18.0806 5.46074V7.06074H1.96098V5.46074C1.96098 4.5209 2.74066 3.74042 3.68052 3.74042H3.68066ZM9.62126 14.2006H10.4009C11.0213 14.2006 11.5213 14.7006 11.5213 15.3209C11.5213 15.9413 11.0213 16.4413 10.4009 16.4413H9.62126C9.00094 16.4413 8.50094 15.9413 8.50094 15.3209C8.50094 14.7006 9.00094 14.2006 9.62126 14.2006ZM8.50094 10.8404C8.50094 10.2201 9.00094 9.7201 9.62126 9.7201L10.4009 9.72088C11.0213 9.72088 11.5213 10.2209 11.5213 10.8412C11.5213 11.4615 11.0213 11.9615 10.4009 11.9615H9.62126C9.00094 11.9607 8.50094 11.4607 8.50094 10.8404V10.8404ZM14.8407 14.2006H15.6204C16.2407 14.2006 16.7407 14.7006 16.7407 15.3209C16.7407 15.9413 16.2407 16.4413 15.6204 16.4413H14.8407C14.2204 16.4413 13.7204 15.9413 13.7204 15.3209C13.7212 14.7006 14.2212 14.2006 14.8407 14.2006ZM13.7212 10.8404C13.7212 10.2201 14.2212 9.7201 14.8415 9.7201H15.6212C16.2415 9.7201 16.7415 10.2201 16.7415 10.8404C16.7415 11.4607 16.2415 11.9607 15.6212 11.9607H14.8415C14.2212 11.9607 13.7212 11.4607 13.7212 10.8404ZM6.2806 10.8404C6.2806 11.4607 5.7806 11.9607 5.16028 11.9607H4.3806C3.76028 11.9607 3.26028 11.4607 3.26028 10.8404C3.26028 10.2201 3.76028 9.7201 4.3806 9.7201H5.16028C5.7806 9.72088 6.2806 10.2209 6.2806 10.8404ZM4.3806 14.2006H5.16028C5.7806 14.2006 6.2806 14.7006 6.2806 15.3209C6.2806 15.9413 5.7806 16.4413 5.16028 16.4413H4.3806C3.76028 16.4413 3.26028 15.9413 3.26028 15.3209C3.26106 14.7006 3.76106 14.2006 4.3806 14.2006Z" fill="#2683FF"/> <path class="usage-report-svg-path" d="M16.3213 2.28026H14.8009V1.50058C14.8009 1.10058 14.4806 0.760742 14.0611 0.760742C13.6611 0.760742 13.3213 1.08106 13.3213 1.50058V2.28026H6.66106V1.50058C6.66106 1.10058 6.34074 0.760742 5.92122 0.760742C5.5009 0.760742 5.2009 1.10058 5.2009 1.50058V2.28026H3.68058C1.92042 2.28026 0.500977 3.70058 0.500977 5.45986V16.0599C0.500977 17.82 1.9213 19.2395 3.68058 19.2395H16.3204C18.0805 19.2395 19.5 17.8191 19.5 16.0599V5.45986C19.5008 3.70048 18.0804 2.28026 16.321 2.28026H16.3213ZM3.68066 3.74042H5.20098V4.5201C5.20098 4.9201 5.5213 5.25994 5.94082 5.25994C6.36114 5.25994 6.68066 4.93962 6.68066 4.5201V3.74042H13.3603V4.5201C13.3603 4.9201 13.6806 5.25994 14.1001 5.25994C14.5001 5.25994 14.8399 4.93962 14.8399 4.5201V3.74042H16.3603C17.3001 3.74042 18.0806 4.50058 18.0806 5.46074V7.06074H1.96098V5.46074C1.96098 4.5209 2.74066 3.74042 3.68052 3.74042H3.68066ZM9.62126 14.2006H10.4009C11.0213 14.2006 11.5213 14.7006 11.5213 15.3209C11.5213 15.9413 11.0213 16.4413 10.4009 16.4413H9.62126C9.00094 16.4413 8.50094 15.9413 8.50094 15.3209C8.50094 14.7006 9.00094 14.2006 9.62126 14.2006ZM8.50094 10.8404C8.50094 10.2201 9.00094 9.7201 9.62126 9.7201L10.4009 9.72088C11.0213 9.72088 11.5213 10.2209 11.5213 10.8412C11.5213 11.4615 11.0213 11.9615 10.4009 11.9615H9.62126C9.00094 11.9607 8.50094 11.4607 8.50094 10.8404V10.8404ZM14.8407 14.2006H15.6204C16.2407 14.2006 16.7407 14.7006 16.7407 15.3209C16.7407 15.9413 16.2407 16.4413 15.6204 16.4413H14.8407C14.2204 16.4413 13.7204 15.9413 13.7204 15.3209C13.7212 14.7006 14.2212 14.2006 14.8407 14.2006ZM13.7212 10.8404C13.7212 10.2201 14.2212 9.7201 14.8415 9.7201H15.6212C16.2415 9.7201 16.7415 10.2201 16.7415 10.8404C16.7415 11.4607 16.2415 11.9607 15.6212 11.9607H14.8415C14.2212 11.9607 13.7212 11.4607 13.7212 10.8404ZM6.2806 10.8404C6.2806 11.4607 5.7806 11.9607 5.16028 11.9607H4.3806C3.76028 11.9607 3.26028 11.4607 3.26028 10.8404C3.26028 10.2201 3.76028 9.7201 4.3806 9.7201H5.16028C5.7806 9.72088 6.2806 10.2209 6.2806 10.8404ZM4.3806 14.2006H5.16028C5.7806 14.2006 6.2806 14.7006 6.2806 15.3209C6.2806 15.9413 5.7806 16.4413 5.16028 16.4413H4.3806C3.76028 16.4413 3.26028 15.9413 3.26028 15.3209C3.26106 14.7006 3.76106 14.2006 4.3806 14.2006Z" fill="#2683FF"/>
</svg> </svg>
@ -74,6 +75,7 @@ export default class UsageReport extends Vue {
public startTime: any = { public startTime: any = {
time: '', time: '',
}; };
private readonly dateRange: any; private readonly dateRange: any;
public constructor() { public constructor() {

View File

@ -15,7 +15,7 @@
<img src="../../../static/images/register/ErrorInfo.svg"/> <img src="../../../static/images/register/ErrorInfo.svg"/>
<p class="add-user__form-container__label__error">{{formError}}</p> <p class="add-user__form-container__label__error">{{formError}}</p>
</div> </div>
<div class="add-user__form-container__inputs-group" :class="{ 'scrollable': inputs.length > 4 }"> <div class="add-user__form-container__inputs-group" :class="{ 'scrollable': isInputsGroupScrollable }">
<div v-for="(input, index) in inputs" <div v-for="(input, index) in inputs"
class="add-user__form-container__inputs-group__item" class="add-user__form-container__inputs-group__item"
:key="index" > :key="index" >
@ -24,7 +24,8 @@
v-model="input.value" v-model="input.value"
class="no-error-input" class="no-error-input"
:class="{ 'error-input': input.error }" :class="{ 'error-input': input.error }"
@keyup="resetFormErrors(index)" /> @keyup="resetFormErrors(index)"
/>
<svg class="add-user__form-container__inputs-group__item__image" @click="deleteInput(index)" width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="add-user__form-container__inputs-group__item__image" @click="deleteInput(index)" width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="delete-input-svg-path" d="M11.7803 1.28033C12.0732 0.987437 12.0732 0.512563 11.7803 0.21967C11.4874 -0.0732233 11.0126 -0.0732233 10.7197 0.21967L11.7803 1.28033ZM0.21967 10.7197C-0.0732233 11.0126 -0.0732233 11.4874 0.21967 11.7803C0.512563 12.0732 0.987437 12.0732 1.28033 11.7803L0.21967 10.7197ZM1.28033 0.21967C0.987437 -0.0732233 0.512563 -0.0732233 0.21967 0.21967C-0.0732233 0.512563 -0.0732233 0.987437 0.21967 1.28033L1.28033 0.21967ZM10.7197 11.7803C11.0126 12.0732 11.4874 12.0732 11.7803 11.7803C12.0732 11.4874 12.0732 11.0126 11.7803 10.7197L10.7197 11.7803ZM10.7197 0.21967L0.21967 10.7197L1.28033 11.7803L11.7803 1.28033L10.7197 0.21967ZM0.21967 1.28033L10.7197 11.7803L11.7803 10.7197L1.28033 0.21967L0.21967 1.28033Z" fill="#AFB7C1"/> <path class="delete-input-svg-path" d="M11.7803 1.28033C12.0732 0.987437 12.0732 0.512563 11.7803 0.21967C11.4874 -0.0732233 11.0126 -0.0732233 10.7197 0.21967L11.7803 1.28033ZM0.21967 10.7197C-0.0732233 11.0126 -0.0732233 11.4874 0.21967 11.7803C0.512563 12.0732 0.987437 12.0732 1.28033 11.7803L0.21967 10.7197ZM1.28033 0.21967C0.987437 -0.0732233 0.512563 -0.0732233 0.21967 0.21967C-0.0732233 0.512563 -0.0732233 0.987437 0.21967 1.28033L1.28033 0.21967ZM10.7197 11.7803C11.0126 12.0732 11.4874 12.0732 11.7803 11.7803C12.0732 11.4874 12.0732 11.0126 11.7803 10.7197L10.7197 11.7803ZM10.7197 0.21967L0.21967 10.7197L1.28033 11.7803L11.7803 1.28033L10.7197 0.21967ZM0.21967 1.28033L10.7197 11.7803L11.7803 10.7197L1.28033 0.21967L0.21967 1.28033Z" fill="#AFB7C1"/>
</svg> </svg>
@ -47,13 +48,15 @@
width='205px' width='205px'
height='48px' height='48px'
:on-press="onClose" :on-press="onClose"
is-white="true"/> is-white="true"
/>
<VButton <VButton
label='Add Team Members' label='Add Team Members'
width='205px' width='205px'
height='48px' height='48px'
:on-press="onAddUsersClick" :on-press="onAddUsersClick"
:is-disabled="!isButtonActive"/> :is-disabled="!isButtonActive"
/>
</div> </div>
</div> </div>
<div class='add-user__close-cross-container' @click='onClose'> <div class='add-user__close-cross-container' @click='onClose'>
@ -159,8 +162,8 @@ export default class AddUserPopup extends Vue {
try { try {
await this.$store.dispatch(PM_ACTIONS.ADD, emailArray); await this.$store.dispatch(PM_ACTIONS.ADD, emailArray);
} catch (err) { } catch (error) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Error during adding project members. ${err.message}`); this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Error during adding project members. ${error.message}`);
this.isLoading = false; this.isLoading = false;
return; return;
@ -219,6 +222,10 @@ export default class AddUserPopup extends Vue {
return location.host + RouteConfig.Register.path; return location.host + RouteConfig.Register.path;
} }
public get isInputsGroupScrollable(): boolean {
return this.inputs.length > 4;
}
private resetFormErrors(index): void { private resetFormErrors(index): void {
this.inputs[index].setError(false); this.inputs[index].setError(false);
if (!this.hasInputError()) { if (!this.hasInputError()) {

View File

@ -9,31 +9,34 @@
ref="headerComponent" ref="headerComponent"
placeholder="Team Members" placeholder="Team Members"
:search="processSearchQuery"> :search="processSearchQuery">
<div class="header-default-state" v-if="headerState === 0"> <div class="header-default-state" v-if="isDefaultState">
<span class="header-default-state__info-text">The only project role currently available is Admin, which gives <b>full access</b> to the project.</span> <span class="header-default-state__info-text">The only project role currently available is Admin, which gives <b>full access</b> to the project.</span>
<VButton <VButton
class="button" class="button"
label="+Add" label="+Add"
width="122px" width="122px"
height="48px" height="48px"
:on-press="onAddUsersClick"/> :on-press="onAddUsersClick"
/>
</div> </div>
<div class="header-selected-members" v-if="headerState === 1 && !isDeleteClicked"> <div class="header-selected-members" v-if="areProjectMembersSelected">
<VButton <VButton
class="button deletion" class="button deletion"
label="Delete" label="Delete"
width="122px" width="122px"
height="48px" height="48px"
:on-press="onFirstDeleteClick"/> :on-press="onFirstDeleteClick"
/>
<VButton <VButton
class="button" class="button"
label="Cancel" label="Cancel"
width="122px" width="122px"
height="48px" height="48px"
is-white="true" is-white="true"
:on-press="onClearSelection"/> :on-press="onClearSelection"
/>
</div> </div>
<div class="header-after-delete-click" v-if="headerState === 1 && isDeleteClicked"> <div class="header-after-delete-click" v-if="areSelectedProjectMembersBeingDeleted">
<span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete {{selectedProjectMembersCount}} {{userCountTitle}}?</span> <span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete {{selectedProjectMembersCount}} {{userCountTitle}}?</span>
<div class="header-after-delete-click__button-area"> <div class="header-after-delete-click__button-area">
<VButton <VButton
@ -41,14 +44,16 @@
label="Delete" label="Delete"
width="122px" width="122px"
height="48px" height="48px"
:on-press="onDelete"/> :on-press="onDelete"
/>
<VButton <VButton
class="button" class="button"
label="Cancel" label="Cancel"
width="122px" width="122px"
height="48px" height="48px"
is-white="true" is-white="true"
:on-press="onClearSelection"/> :on-press="onClearSelection"
/>
</div> </div>
</div> </div>
</VHeader> </VHeader>
@ -124,8 +129,8 @@ export default class HeaderArea extends Vue {
try { try {
await this.$store.dispatch(PM_ACTIONS.DELETE, projectMemberEmails); await this.$store.dispatch(PM_ACTIONS.DELETE, projectMemberEmails);
} catch (err) { } catch (error) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Error while deleting users from projectMembers. ${err.message}`); this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Error while deleting users from projectMembers. ${error.message}`);
return; return;
} }
@ -140,14 +145,26 @@ export default class HeaderArea extends Vue {
this.$store.dispatch(PM_ACTIONS.SET_SEARCH_QUERY, search); this.$store.dispatch(PM_ACTIONS.SET_SEARCH_QUERY, search);
try { try {
await this.$store.dispatch(PM_ACTIONS.FETCH, this.FIRST_PAGE); await this.$store.dispatch(PM_ACTIONS.FETCH, this.FIRST_PAGE);
} catch (err) { } catch (error) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch project members. ${err.message}`); this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch project members. ${error.message}`);
} }
} }
public get isAddTeamMembersPopupShown(): boolean { public get isAddTeamMembersPopupShown(): boolean {
return this.$store.state.appStateModule.appState.isAddTeamMembersPopupShown; return this.$store.state.appStateModule.appState.isAddTeamMembersPopupShown;
} }
public get isDefaultState(): boolean {
return this.headerState === 0;
}
public get areProjectMembersSelected(): boolean {
return this.headerState === 1 && !this.isDeleteClicked;
}
public get areSelectedProjectMembersBeingDeleted(): boolean {
return this.headerState === 1 && this.isDeleteClicked;
}
} }
</script> </script>

View File

@ -8,10 +8,10 @@
<div class="user-container__base-info__avatar" :style="avatarData.style"> <div class="user-container__base-info__avatar" :style="avatarData.style">
<h1 class="user-container__base-info__avatar__letter">{{avatarData.letter}}</h1> <h1 class="user-container__base-info__avatar__letter">{{avatarData.letter}}</h1>
</div> </div>
<p class="user-container__base-info__user-name">{{this.itemData.formattedFullName()}}</p> <p class="user-container__base-info__user-name">{{itemName}}</p>
</div> </div>
<p class="user-container__date">{{this.itemData.joinedAtLocal()}}</p> <p class="user-container__date">{{itemDate}}</p>
<p class="user-container__user-email">{{this.itemData.formattedEmail()}}</p> <p class="user-container__user-email">{{itemEmail}}</p>
</div> </div>
</template> </template>
@ -40,6 +40,18 @@ export default class ProjectMemberListItem extends Vue {
style, style,
}; };
} }
public get itemName(): string {
return this.itemData.formattedFullName();
}
public get itemDate(): string {
return this.itemData.joinedAtLocal();
}
public get itemEmail(): string {
return this.itemData.formattedEmail();
}
} }
</script> </script>

View File

@ -6,24 +6,27 @@
<div class="team-area__header"> <div class="team-area__header">
<HeaderArea <HeaderArea
:header-state="headerState" :header-state="headerState"
:selected-project-members-count="selectedProjectMembers.length"/> :selected-project-members-count="selectedProjectMembers.length"
/>
</div> </div>
<div class="team-area__container" id="team-container" v-if="projectMembersCount > 0 || projectMembersTotalCount > 0"> <div class="team-area__container" id="team-container" v-if="isTeamAreaShown">
<SortingListHeader :on-header-click-callback="onHeaderSectionClickCallback"/> <SortingListHeader :on-header-click-callback="onHeaderSectionClickCallback"/>
<div class="team-area__container__content"> <div class="team-area__container__content">
<VList <VList
:data-set="projectMembers" :data-set="projectMembers"
:item-component="getItemComponent" :item-component="getItemComponent"
:on-item-click="onMemberClick"/> :on-item-click="onMemberClick"
/>
</div> </div>
<VPagination <VPagination
v-if="totalPageCount > 1" v-if="totalPageCount > 1"
class="pagination-area" class="pagination-area"
ref="pagination" ref="pagination"
:total-page-count="totalPageCount" :total-page-count="totalPageCount"
:on-page-click-callback="onPageClick"/> :on-page-click-callback="onPageClick"
/>
</div> </div>
<div class="team-area__empty-search-result-area" v-if="(projectMembersCount === 0 && projectMembersTotalCount === 0)"> <div class="team-area__empty-search-result-area" v-if="isEmptySearchResultShown">
<h1 class="team-area__empty-search-result-area__title">No results found</h1> <h1 class="team-area__empty-search-result-area__title">No results found</h1>
<svg class="team-area__empty-search-result-area__image" width="380" height="295" viewBox="0 0 380 295" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="team-area__empty-search-result-area__image" width="380" height="295" viewBox="0 0 380 295" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M168 295C246.997 295 311 231.2 311 152.5C311 73.8 246.997 10 168 10C89.0028 10 25 73.8 25 152.5C25 231.2 89.0028 295 168 295Z" fill="#E8EAF2"/> <path d="M168 295C246.997 295 311 231.2 311 152.5C311 73.8 246.997 10 168 10C89.0028 10 25 73.8 25 152.5C25 231.2 89.0028 295 168 295Z" fill="#E8EAF2"/>
@ -72,6 +75,10 @@ import { SortDirection } from '@/types/common';
import { ProjectMember, ProjectMemberHeaderState, ProjectMemberOrderBy } from '@/types/projectMembers'; import { ProjectMember, ProjectMemberHeaderState, ProjectMemberOrderBy } from '@/types/projectMembers';
import { NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames'; import { NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
declare interface ResetPagination {
resetPageIndex(): void;
}
@Component({ @Component({
components: { components: {
HeaderArea, HeaderArea,
@ -83,6 +90,10 @@ import { NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames'
export default class ProjectMembersArea extends Vue { export default class ProjectMembersArea extends Vue {
private FIRST_PAGE = 1; private FIRST_PAGE = 1;
public $refs!: {
pagination: HTMLElement & ResetPagination;
};
public async beforeDestroy(): Promise<void> { public async beforeDestroy(): Promise<void> {
await this.$store.dispatch(PM_ACTIONS.CLEAR_SELECTION); await this.$store.dispatch(PM_ACTIONS.CLEAR_SELECTION);
} }
@ -123,6 +134,14 @@ export default class ProjectMembersArea extends Vue {
return ProjectMemberHeaderState.DEFAULT; return ProjectMemberHeaderState.DEFAULT;
} }
public get isTeamAreaShown(): boolean {
return this.projectMembersCount > 0 || this.projectMembersTotalCount > 0;
}
public get isEmptySearchResultShown(): boolean {
return this.projectMembersCount === 0 && this.projectMembersTotalCount === 0;
}
public async onPageClick(index: number): Promise<void> { public async onPageClick(index: number): Promise<void> {
try { try {
await this.$store.dispatch(PM_ACTIONS.FETCH, index); await this.$store.dispatch(PM_ACTIONS.FETCH, index);
@ -140,7 +159,9 @@ export default class ProjectMembersArea extends Vue {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch project members. ${error.message}`); this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch project members. ${error.message}`);
} }
(this.$refs.pagination as VPagination).resetPageIndex(); if (this.totalPageCount > 1) {
this.$refs.pagination.resetPageIndex();
}
} }
} }
</script> </script>

View File

@ -6,20 +6,23 @@
<div class="sort-header-container__name-container" @click="onHeaderItemClick(ProjectMemberOrderBy.NAME)"> <div class="sort-header-container__name-container" @click="onHeaderItemClick(ProjectMemberOrderBy.NAME)">
<p class="sort-header-container__name-container__title">Name</p> <p class="sort-header-container__name-container__title">Name</p>
<VerticalArrows <VerticalArrows
:is-active="getSortBy === ProjectMemberOrderBy.NAME" :is-active="areProjectMembersSortedByName"
:direction="getSortDirection"/> :direction="getSortDirection"
/>
</div> </div>
<div class="sort-header-container__added-container" @click="onHeaderItemClick(ProjectMemberOrderBy.CREATED_AT)"> <div class="sort-header-container__added-container" @click="onHeaderItemClick(ProjectMemberOrderBy.CREATED_AT)">
<p class="sort-header-container__added-container__title">Added</p> <p class="sort-header-container__added-container__title">Added</p>
<VerticalArrows <VerticalArrows
:is-active="getSortBy === ProjectMemberOrderBy.CREATED_AT" :is-active="areProjectMembersSortedByDate"
:direction="getSortDirection"/> :direction="getSortDirection"
/>
</div> </div>
<div class="sort-header-container__email-container" @click="onHeaderItemClick(ProjectMemberOrderBy.EMAIL)"> <div class="sort-header-container__email-container" @click="onHeaderItemClick(ProjectMemberOrderBy.EMAIL)">
<p class="sort-header-container__email-container__title">Email</p> <p class="sort-header-container__email-container__title">Email</p>
<VerticalArrows <VerticalArrows
:is-active="getSortBy === ProjectMemberOrderBy.EMAIL" :is-active="areProjectMembersSortedByEmail"
:direction="getSortDirection"/> :direction="getSortDirection"
/>
</div> </div>
</div> </div>
</template> </template>
@ -54,8 +57,16 @@ export default class SortingListHeader extends Vue {
return SortDirection.DESCENDING; return SortDirection.DESCENDING;
} }
public get getSortBy() { public areProjectMembersSortedByName(): boolean {
return this.sortBy; return this.sortBy === ProjectMemberOrderBy.NAME;
}
public areProjectMembersSortedByDate(): boolean {
return this.sortBy === ProjectMemberOrderBy.CREATED_AT;
}
public areProjectMembersSortedByEmail(): boolean {
return this.sortBy === ProjectMemberOrderBy.EMAIL;
} }
public async onHeaderItemClick(sortBy: ProjectMemberOrderBy): Promise<void> { public async onHeaderItemClick(sortBy: ProjectMemberOrderBy): Promise<void> {

View File

@ -4,7 +4,7 @@
<template> <template>
<div class="dashboard-container"> <div class="dashboard-container">
<div v-if="isLoading" class="loading-overlay active"> <div v-if="isLoading" class="loading-overlay active">
<img class="loading-image" src="../../static/images/register/Loading.gif"> <img class="loading-image" src="@/../static/images/register/Loading.gif">
</div> </div>
<div v-if="!isLoading" class="dashboard-container__wrap"> <div v-if="!isLoading" class="dashboard-container__wrap">
<NavigationArea class="regular-navigation"/> <NavigationArea class="regular-navigation"/>

View File

@ -3,12 +3,12 @@
<div class="forgot-password-container"> <div class="forgot-password-container">
<div :class="loadingClassName"> <div :class="loadingClassName">
<img class="loading-image" src="../../../static/images/register/Loading.gif"> <img class="loading-image" src="@/../static/images/register/Loading.gif">
</div> </div>
<img class="image" src="../../../static/images/AuthImage.svg" alt="" > <img class="image" src="@/../static/images/AuthImage.svg" alt="">
<div class="forgot-password-container__wrapper"> <div class="forgot-password-container__wrapper">
<div class="forgot-password-container__header"> <div class="forgot-password-container__header">
<img @click="onLogoClick" class="forgot-password-container__logo" src="../../../static/images/Logo.svg" alt="logo"> <img @click="onLogoClick" class="forgot-password-container__logo" src="@/../static/images/Logo.svg" alt="logo">
<div class="forgot-password-container__login-button" @click="onBackToLoginClick"> <div class="forgot-password-container__login-button" @click="onBackToLoginClick">
<p class="forgot-password-container__login-button__label">Back to Login</p> <p class="forgot-password-container__login-button__label">Back to Login</p>
</div> </div>
@ -25,7 +25,8 @@
:error="emailError" :error="emailError"
@setData="setEmail" @setData="setEmail"
width="100%" width="100%"
height="46px" /> height="46px"
/>
<div class="forgot-password-area__submit-container" @click.prevent="onSendConfigurations"> <div class="forgot-password-area__submit-container" @click.prevent="onSendConfigurations">
<div class="forgot-password-area__submit-container__send-button"> <div class="forgot-password-area__submit-container__send-button">
<p class="forgot-password-area__submit-container__send-button__label">Reset Password</p> <p class="forgot-password-area__submit-container__send-button__label">Reset Password</p>

View File

@ -3,11 +3,11 @@
<div class="login-container" @keyup.enter="onLogin"> <div class="login-container" @keyup.enter="onLogin">
<div :class="loadingClassName"></div> <div :class="loadingClassName"></div>
<img :class="loadingLogoClassName" src="../../../static/images/LogoWhite.svg" alt="loading-logo"> <img :class="loadingLogoClassName" src="@/../static/images/LogoWhite.svg" alt="loading-logo">
<img class="image" src="../../../static/images/AuthImage.svg" alt="" > <img class="image" src="@/../static/images/AuthImage.svg" alt="" >
<div class="login-container__wrapper"> <div class="login-container__wrapper">
<div class="login-container__header"> <div class="login-container__header">
<img class="login-container__logo" src="../../../static/images/Logo.svg" alt="logo" @click="onLogoClick"> <img class="login-container__logo" src="@/../static/images/Logo.svg" alt="logo" @click="onLogoClick">
<div class="login-container__register-button" @click.prevent="onSignUpClick"> <div class="login-container__register-button" @click.prevent="onSignUpClick">
<p class="login-container__register-button__label">Create Account</p> <p class="login-container__register-button__label">Create Account</p>
</div> </div>
@ -23,7 +23,8 @@
:error="emailError" :error="emailError"
@setData="setEmail" @setData="setEmail"
height="46px" height="46px"
width="100%" /> width="100%"
/>
<HeaderlessInput <HeaderlessInput
class="login-area__password-input" class="login-area__password-input"
placeholder="Password" placeholder="Password"
@ -31,7 +32,8 @@
@setData="setPassword" @setData="setPassword"
width="100%" width="100%"
height="46px" height="46px"
is-password="true" /> is-password="true"
/>
<div class="login-area__submit-area"> <div class="login-area__submit-area">
<router-link :to="forgotPasswordPath" class="login-area__navigation-area__nav-link" exact> <router-link :to="forgotPasswordPath" class="login-area__navigation-area__nav-link" exact>
<h3 class="login-area__navigation-area__nav-link__link"><strong>Forgot password?</strong></h3> <h3 class="login-area__navigation-area__nav-link__link"><strong>Forgot password?</strong></h3>

View File

@ -3,12 +3,12 @@
<div class="register-container" @keyup.enter="onCreateClick"> <div class="register-container" @keyup.enter="onCreateClick">
<div :class="loadingClassName"> <div :class="loadingClassName">
<img class="loading-image" src="../../../static/images/register/Loading.gif"> <img class="loading-image" src="@/../static/images/register/Loading.gif">
</div> </div>
<img class="image" src="../../../static/images/AuthImage.svg" alt="" > <img class="image" src="@/../static/images/AuthImage.svg" alt="" >
<div class="register-container__wrapper"> <div class="register-container__wrapper">
<div class="register-container__header"> <div class="register-container__header">
<img class="register-container__logo" src="../../../static/images/Logo.svg" alt="logo" @click="onLogoClick"> <img class="register-container__logo" src="@/../static/images/Logo.svg" alt="logo" @click="onLogoClick">
<div class="register-container__register-button" @click.prevent="onLoginClick"> <div class="register-container__register-button" @click.prevent="onLoginClick">
<p class="register-container__register-button__label">Login</p> <p class="register-container__register-button__label">Login</p>
</div> </div>
@ -25,14 +25,16 @@
:error="fullNameError" :error="fullNameError"
@setData="setFullName" @setData="setFullName"
width="100%" width="100%"
height="46px" /> height="46px"
/>
<HeaderlessInput <HeaderlessInput
class="full-input" class="full-input"
label="Nickname" label="Nickname"
placeholder="Enter Nickname" placeholder="Enter Nickname"
@setData="setShortName" @setData="setShortName"
width="100%" width="100%"
height="46px" /> height="46px"
/>
<HeaderlessInput <HeaderlessInput
class="full-input" class="full-input"
label="Email" label="Email"
@ -40,7 +42,8 @@
:error="emailError" :error="emailError"
@setData="setEmail" @setData="setEmail"
width="100%" width="100%"
height="46px" /> height="46px"
/>
<div class="register-input"> <div class="register-input">
<HeaderlessInput <HeaderlessInput
class="full-input" class="full-input"
@ -50,7 +53,8 @@
@setData="setPassword" @setData="setPassword"
width="100%" width="100%"
height="46px" height="46px"
is-password="true" /> is-password="true"
/>
<VInfo <VInfo
class="register-input__info-button" class="register-input__info-button"
bold-text="Use 6 or more characters with a mix of letters, numbers & symbols" > bold-text="Use 6 or more characters with a mix of letters, numbers & symbols" >
@ -70,7 +74,8 @@
@setData="setRepeatedPassword" @setData="setRepeatedPassword"
width="100%" width="100%"
height="46px" height="46px"
is-password="true" /> is-password="true"
/>
<VInfo <VInfo
class="register-input__info-button" class="register-input__info-button"
bold-text="Use 6 or more characters with a mix of letters, numbers & symbols"> bold-text="Use 6 or more characters with a mix of letters, numbers & symbols">
@ -85,7 +90,7 @@
<div class="register-area__submit-container__terms-area"> <div class="register-area__submit-container__terms-area">
<label class="container"> <label class="container">
<input type="checkbox" v-model="isTermsAccepted"> <input type="checkbox" v-model="isTermsAccepted">
<span :class="[isTermsAcceptedError ? 'checkmark error': 'checkmark']"></span> <span class="checkmark" :class="{'error': isTermsAcceptedError}"></span>
</label> </label>
<h2 class="register-area__submit-container__terms-area__terms-confirmation">I agree to the <a class="register-area__submit-container__terms-area__link" href="https://tardigrade.io/terms-of-use/" target="_blank">Terms & Conditions</a></h2> <h2 class="register-area__submit-container__terms-area__terms-confirmation">I agree to the <a class="register-area__submit-container__terms-area__link" href="https://tardigrade.io/terms-of-use/" target="_blank">Terms & Conditions</a></h2>
</div> </div>

View File

@ -86,6 +86,7 @@ exports[`NavigationArea snapshot not changed with project 1`] = `
<!----> <!---->
<!----> <!---->
</div> </div>
<div class="navigation-area__account-area">
<router-link-stub to="/account/profile" tag="a" event="click" class="navigation-area__item-container account-item"> <router-link-stub to="/account/profile" tag="a" event="click" class="navigation-area__item-container account-item">
<div class="navigation-area__item-container__link-container"> <div class="navigation-area__item-container__link-container">
<h1 class="navigation-area__item-container__link-container__title account-item">Profile</h1> <h1 class="navigation-area__item-container__link-container__title account-item">Profile</h1>
@ -101,6 +102,7 @@ exports[`NavigationArea snapshot not changed with project 1`] = `
<h1 class="navigation-area__item-container__link-container__title account-item">Payment Methods</h1> <h1 class="navigation-area__item-container__link-container__title account-item">Payment Methods</h1>
</div> </div>
</router-link-stub> </router-link-stub>
</div>
<div class="divider custom-divider"></div> <div class="divider custom-divider"></div>
</div> </div>
</div> </div>
@ -192,6 +194,7 @@ exports[`NavigationArea snapshot not changed without project 1`] = `
<!----> <!---->
<!----> <!---->
</div> </div>
<div class="navigation-area__account-area">
<router-link-stub to="/account/profile" tag="a" event="click" class="navigation-area__item-container account-item"> <router-link-stub to="/account/profile" tag="a" event="click" class="navigation-area__item-container account-item">
<div class="navigation-area__item-container__link-container"> <div class="navigation-area__item-container__link-container">
<h1 class="navigation-area__item-container__link-container__title account-item">Profile</h1> <h1 class="navigation-area__item-container__link-container__title account-item">Profile</h1>
@ -207,6 +210,7 @@ exports[`NavigationArea snapshot not changed without project 1`] = `
<h1 class="navigation-area__item-container__link-container__title account-item">Payment Methods</h1> <h1 class="navigation-area__item-container__link-container__title account-item">Payment Methods</h1>
</div> </div>
</router-link-stub> </router-link-stub>
</div>
<div class="divider custom-divider"></div> <div class="divider custom-divider"></div>
</div> </div>
</div> </div>

View File

@ -14,7 +14,7 @@ exports[`SortingListHeader.vue should render correctly 1`] = `
<p class="sort-header-container__added-container__title">Added</p> <p class="sort-header-container__added-container__title">Added</p>
<div class="container"><svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" class=""> <div class="container"><svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" class="">
<path d="M4.73684 5.70565e-07L9 6L-9.53674e-07 6L4.73684 5.70565e-07Z" fill="#354049" class="arrow-svg-path"></path> <path d="M4.73684 5.70565e-07L9 6L-9.53674e-07 6L4.73684 5.70565e-07Z" fill="#354049" class="arrow-svg-path"></path>
</svg> <svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" class=""> </svg> <svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" class="active">
<path d="M4.26316 6L1.90735e-06 0L9 1.59559e-06L4.26316 6Z" fill="#354049" class="arrow-svg-path"></path> <path d="M4.26316 6L1.90735e-06 0L9 1.59559e-06L4.26316 6Z" fill="#354049" class="arrow-svg-path"></path>
</svg></div> </svg></div>
</div> </div>
@ -22,7 +22,7 @@ exports[`SortingListHeader.vue should render correctly 1`] = `
<p class="sort-header-container__email-container__title">Email</p> <p class="sort-header-container__email-container__title">Email</p>
<div class="container"><svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" class=""> <div class="container"><svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" class="">
<path d="M4.73684 5.70565e-07L9 6L-9.53674e-07 6L4.73684 5.70565e-07Z" fill="#354049" class="arrow-svg-path"></path> <path d="M4.73684 5.70565e-07L9 6L-9.53674e-07 6L4.73684 5.70565e-07Z" fill="#354049" class="arrow-svg-path"></path>
</svg> <svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" class=""> </svg> <svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" class="active">
<path d="M4.26316 6L1.90735e-06 0L9 1.59559e-06L4.26316 6Z" fill="#354049" class="arrow-svg-path"></path> <path d="M4.26316 6L1.90735e-06 0L9 1.59559e-06L4.26316 6Z" fill="#354049" class="arrow-svg-path"></path>
</svg></div> </svg></div>
</div> </div>

View File

@ -17,7 +17,7 @@ exports[`Dashboard renders correctly when data is loaded 1`] = `
exports[`Dashboard renders correctly when data is loading 1`] = ` exports[`Dashboard renders correctly when data is loading 1`] = `
<div class="dashboard-container"> <div class="dashboard-container">
<div class="loading-overlay active"><img src="../../static/images/register/Loading.gif" class="loading-image"></div> <div class="loading-overlay active"><img src="@/../static/images/register/Loading.gif" class="loading-image"></div>
<!----> <!---->
</div> </div>
`; `;