feat: notification center (#1612)

Co-authored-by: Pranav <pranav@chatwoot.com>
This commit is contained in:
Muhsin Keloth
2021-01-24 11:29:44 -08:00
committed by GitHub
parent e75916d562
commit c087e75808
23 changed files with 811 additions and 12 deletions

View File

@@ -73,6 +73,13 @@
{{ $t(`AGENT_MGMT.AGENT_TYPES.${currentRole.toUpperCase()}`) }}
</h5>
</div>
<span
class="notifications icon ion-ios-bell"
@click.stop="showNotification"
>
<span v-if="unreadCount" class="unread-badge">{{ unreadCount }}</span>
</span>
<span class="current-user--options icon ion-android-more-vertical" />
</div>
</div>
@@ -134,7 +141,7 @@
/>
</label>
</div>
<div class="modal-footer medium-12 columns">
<div class="modal-footer medium-12 columns">
<div class="medium-12 columns">
<woot-submit-button
:disabled="
@@ -206,6 +213,7 @@ export default {
currentRole: 'getCurrentRole',
uiFlags: 'agents/getUIFlags',
accountLabels: 'labels/getLabelsOnSidebar',
notificationMetadata: 'notifications/getMeta',
}),
currentUserAvailableName() {
return this.currentUser.name;
@@ -284,10 +292,20 @@ export default {
dashboardPath() {
return frontendURL(`accounts/${this.accountId}/dashboard`);
},
unreadCount() {
if (!this.notificationMetadata.unreadCount) {
return 0;
}
return this.notificationMetadata.unreadCount < 100
? this.notificationMetadata.unreadCount
: '99+';
},
},
mounted() {
this.$store.dispatch('labels/get');
this.$store.dispatch('inboxes/get');
this.$store.dispatch('notifications/unReadCount');
},
methods: {
filterMenuItemsByRole(menuItems) {
@@ -307,6 +325,9 @@ export default {
showOptions() {
this.showOptionsMenu = !this.showOptionsMenu;
},
showNotification() {
this.$router.push(`/app/accounts/${this.accountId}/notifications`);
},
changeAccount() {
this.showAccountModal = true;
},

View File

@@ -0,0 +1,211 @@
<template>
<footer v-if="isFooterVisible" class="footer">
<div class="left-aligned-wrap">
<div class="page-meta">
<strong>{{ firstIndex }}</strong>
- <strong>{{ lastIndex }}</strong> of
<strong>{{ totalCount }}</strong> items
</div>
</div>
<div class="right-aligned-wrap">
<div
v-if="totalCount"
class="primary button-group pagination-button-group"
>
<button
class="button small goto-first"
:class="firstPageButtonClass"
@click="onFirstPage"
>
<i class="ion-chevron-left" />
<i class="ion-chevron-left" />
</button>
<button
class="button small"
:class="prevPageButtonClass"
@click="onPrevPage"
>
<i class="ion-chevron-left" />
</button>
<button class="button" @click.prevent>
{{ currentPage }}
</button>
<button
class="button small"
:class="nextPageButtonClass"
@click="onNextPage"
>
<i class="ion-chevron-right" />
</button>
<button
class="button small goto-last"
:class="lastPageButtonClass"
@click="onLastPage"
>
<i class="ion-chevron-right" />
<i class="ion-chevron-right" />
</button>
</div>
</div>
</footer>
</template>
<script>
export default {
components: {},
props: {
currentPage: {
type: Number,
default: 1,
},
pageSize: {
type: Number,
default: 15,
},
totalCount: {
type: Number,
default: 0,
},
onPageChange: {
type: Function,
default: () => {},
},
},
computed: {
isFooterVisible() {
return this.totalCount && !(this.firstIndex > this.totalCount);
},
firstIndex() {
const firstIndex = this.pageSize * (this.currentPage - 1) + 1;
return firstIndex;
},
lastIndex() {
const index = Math.min(this.totalCount, this.pageSize * this.currentPage);
return index;
},
searchButtonClass() {
return this.searchQuery !== '' ? 'show' : '';
},
hasLastPage() {
const isDisabled =
this.currentPage === Math.ceil(this.totalCount / this.pageSize);
return isDisabled;
},
lastPageButtonClass() {
const className = this.hasLastPage ? 'disabled' : '';
return className;
},
hasFirstPage() {
const isDisabled = this.currentPage === 1;
return isDisabled;
},
firstPageButtonClass() {
const className = this.hasFirstPage ? 'disabled' : '';
return className;
},
hasNextPage() {
const isDisabled =
this.currentPage === Math.ceil(this.totalCount / this.pageSize);
return isDisabled;
},
nextPageButtonClass() {
const className = this.hasNextPage ? 'disabled' : '';
return className;
},
hasPrevPage() {
const isDisabled = this.currentPage === 1;
return isDisabled;
},
prevPageButtonClass() {
const className = this.hasPrevPage ? 'disabled' : '';
return className;
},
},
methods: {
onNextPage() {
if (this.hasNextPage) return;
const newPage = this.currentPage + 1;
this.onPageChange(newPage);
},
onPrevPage() {
if (this.hasPrevPage) return;
const newPage = this.currentPage - 1;
this.onPageChange(newPage);
},
onFirstPage() {
if (this.hasFirstPage) return;
const newPage = 1;
this.onPageChange(newPage);
},
onLastPage() {
if (this.hasLastPage) return;
const newPage = Math.ceil(this.totalCount / this.pageSize);
this.onPageChange(newPage);
},
},
};
</script>
<style lang="scss" scoped>
.footer {
height: 60px;
border-top: 1px solid var(--color-border);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--space-normal);
}
.page-meta {
font-size: var(--font-size-mini);
}
.pagination-button-group {
margin: 0;
.button {
background: transparent;
border-color: var(--color-border);
color: var(--color-body);
margin-bottom: 0;
margin-left: -2px;
font-size: var(--font-size-small);
padding: var(--space-small) var(--space-normal);
&:hover,
&:focus,
&:active {
background: var(--s-200);
color: white;
}
&:first-child {
border-top-left-radius: var(--space-smaller);
border-bottom-left-radius: var(--space-smaller);
}
&:last-child {
border-top-right-radius: var(--space-smaller);
border-bottom-right-radius: var(--space-smaller);
}
&.small {
font-size: var(--font-size-micro);
}
&.disabled {
background: var(--s-200);
border-color: var(--s-200);
color: var(--b-900);
}
&.goto-first,
&.goto-last {
i:last-child {
margin-left: var(--space-minus-smaller);
}
}
}
}
</style>