storj/web/satellite/src/components/team/ProjectMembersArea.vue

228 lines
6.5 KiB
Vue
Raw Normal View History

2019-01-24 20:15:10 +00:00
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="team-area">
<div class="team-area__header">
<HeaderArea
:header-state="headerState"
:selected-project-members-count="selectedProjectMembersLength"
@onSuccessAction="resetPaginator"
/>
</div>
<div class="team-area__container" id="team-container" v-if="isTeamAreaShown">
<SortingListHeader :on-header-click-callback="onHeaderSectionClickCallback"/>
<div class="team-area__container__content">
<VList
:data-set="projectMembers"
:item-component="getItemComponent"
:on-item-click="onMemberClick"
/>
</div>
<VPagination
v-if="totalPageCount > 1"
class="pagination-area"
ref="pagination"
:total-page-count="totalPageCount"
:on-page-click-callback="onPageClick"
/>
</div>
<div class="team-area__empty-search-result-area" v-if="isEmptySearchResultShown">
<h1 class="team-area__empty-search-result-area__title">No results found</h1>
<EmptySearchResultIcon class="team-area__empty-search-result-area__image"/>
</div>
</div>
</template>
<script lang="ts">
2019-09-09 11:33:39 +01:00
import { Component, Vue } from 'vue-property-decorator';
import VList from '@/components/common/VList.vue';
import VPagination from '@/components/common/VPagination.vue';
2019-09-09 11:33:39 +01:00
import HeaderArea from '@/components/team/HeaderArea.vue';
import ProjectMemberListItem from '@/components/team/ProjectMemberListItem.vue';
import SortingListHeader from '@/components/team/SortingListHeader.vue';
import EmptySearchResultIcon from '@/../static/images/common/emptySearchResult.svg';
2019-09-09 11:33:39 +01:00
import { SortDirection } from '@/types/common';
import { ProjectMember, ProjectMemberHeaderState, ProjectMemberOrderBy } from '@/types/projectMembers';
import { NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
const {
FETCH,
DELETE,
TOGGLE_SELECTION,
CLEAR,
CLEAR_SELECTION,
SET_SEARCH_QUERY,
SET_SORT_BY,
SET_SORT_DIRECTION,
} = PM_ACTIONS;
declare interface ResetPagination {
resetPageIndex(): void;
}
2019-09-09 11:33:39 +01:00
@Component({
components: {
HeaderArea,
VList,
VPagination,
2019-09-09 11:33:39 +01:00
SortingListHeader,
EmptySearchResultIcon,
},
2019-09-09 11:33:39 +01:00
})
export default class ProjectMembersArea extends Vue {
private FIRST_PAGE = 1;
public $refs!: {
pagination: HTMLElement & ResetPagination;
};
public async mounted(): Promise<void> {
await this.$store.dispatch(FETCH, 1);
}
2019-09-09 11:33:39 +01:00
public async beforeDestroy(): Promise<void> {
await this.$store.dispatch(CLEAR);
2019-09-09 11:33:39 +01:00
}
2019-09-09 11:33:39 +01:00
public onMemberClick(member: ProjectMember): void {
this.$store.dispatch(TOGGLE_SELECTION, member);
2019-09-09 11:33:39 +01:00
}
2019-09-09 11:33:39 +01:00
public get projectMembers(): ProjectMember[] {
return this.$store.state.projectMembersModule.page.projectMembers;
}
2019-09-09 11:33:39 +01:00
public get getItemComponent() {
return ProjectMemberListItem;
}
2019-09-09 11:33:39 +01:00
public get projectMembersTotalCount(): number {
return this.$store.state.projectMembersModule.page.totalCount;
}
2019-09-09 11:33:39 +01:00
public get projectMembersCount(): number {
return this.$store.state.projectMembersModule.page.projectMembers.length;
}
2019-09-09 11:33:39 +01:00
public get totalPageCount(): number {
return this.$store.state.projectMembersModule.page.pageCount;
}
public get selectedProjectMembersLength(): number {
return this.$store.state.projectMembersModule.selectedProjectMembersEmails.length;
2019-09-09 11:33:39 +01:00
}
public get headerState(): number {
if (this.selectedProjectMembersLength > 0) {
2019-09-09 11:33:39 +01:00
return ProjectMemberHeaderState.ON_SELECT;
}
2019-09-09 11:33:39 +01:00
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> {
2019-09-09 11:33:39 +01:00
try {
await this.$store.dispatch(FETCH, index);
} catch (error) {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch project members. ${error.message}`);
}
2019-09-09 11:33:39 +01:00
}
2019-09-09 11:33:39 +01:00
public async onHeaderSectionClickCallback(sortBy: ProjectMemberOrderBy, sortDirection: SortDirection): Promise<void> {
await this.$store.dispatch(SET_SORT_BY, sortBy);
await this.$store.dispatch(SET_SORT_DIRECTION, sortDirection);
2019-09-09 11:33:39 +01:00
try {
await this.$store.dispatch(FETCH, this.FIRST_PAGE);
2019-09-09 11:33:39 +01:00
} catch (error) {
await this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch project members. ${error.message}`);
}
this.resetPaginator();
}
public resetPaginator(): void {
if (this.totalPageCount > 1) {
this.$refs.pagination.resetPageIndex();
}
}
2019-09-09 11:33:39 +01:00
}
</script>
<style scoped lang="scss">
.team-area {
padding: 40px 65px 55px 64px;
font-family: 'font_regular';
&__header {
width: 100%;
background-color: #F5F6FA;
top: auto;
}
&__container {
max-height: 84vh;
&__content {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
flex-direction: column;
height: 49.4vh;
}
}
&__empty-search-result-area {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
&__title {
font-family: 'font_bold';
font-size: 32px;
line-height: 39px;
margin-top: 100px;
}
&__image {
margin-top: 40px;
}
}
}
.pagination-area {
margin-left: -25px;
}
@media screen and (max-width: 1024px) {
.team-area {
padding: 40px 40px 55px 40px;
}
}
@media screen and (max-height: 800px) {
.team-area {
&__container {
&__content {
height: 41.5vh !important;
}
}
}
2019-07-10 10:55:40 +01:00
}
</style>