Files
nocodb/packages/nc-gui/components/notification/Card.vue
Anbarasu 55425f57de feat: Notifications (#8622)
* feat: notifications wip

* feat: wip

* feat: longpoll and notifications.controller.ts

* feat: longpoll and notifications.controller.ts

* feat: enable email notifications

* fix: notification styles and list

* fix: update swagger feat: connect poller to frontend

* fix: minor ui corrections

* feat: move notifications to ee feat: scroll to commentId fix: polling fail on network error fix: unreadcount not updating fix: add workspace to comment mention event

* fix: pubsub for notifications

* fix: warning maxListeners

* fix: update ui

* fix: minor fixes

* chore: move pub-sub to redis folder

* fix: update ui and schema feat: optimistic comment update and create

* fix: row empty during inital load causing row not loading

* fix: build

* fix: some updated

* fix: minor ui corrections

* fix: manage local state manually for interactivity

* fix: remove prev notifcation data

* fix: review comments

* fix: code rabbit comments

* fix: code rabbit comments

* feat: delete notifications

* fix: code rabbit comments

* fix: row RowMeta manipulation fix: overflow notifications

* fix: invalid offset

* fix: updated widths

* fix: tests

* fix: playwright

* feat: resolved by comments

* feat: update layout

* fix: wait 5 seconds before polling start, after polling starts, reload the notifications

* fix: bug fixes

* fix: disable long polling for playwright

* fix: update migration

* fix: lint

* fix: code rabbit comments

* fix: resolve tooltip

* feat: resolve ee

* fix: build failing

* fix: review comments

* fix: dependency synx

* fix: update notification style
2024-06-07 11:40:54 +05:30

137 lines
4.3 KiB
Vue

<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import InfiniteLoading from 'v3-infinite-loading'
const notificationStore = useNotification()
const { isMobileMode } = useGlobal()
const container = ref()
const { height } = useElementSize(container)
const { loadUnReadNotifications, loadReadNotifications, markAllAsRead } = notificationStore
const { unreadNotifications, readNotifications, readPageInfo, unreadPageInfo, notificationTab } = storeToRefs(notificationStore)
</script>
<template>
<div
ref="container"
style="box-shadow: 0px -12px 16px -4px rgba(0, 0, 0, 0.1), 0px -4px 6px -2px rgba(0, 0, 0, 0.06)"
:style="!isMobileMode ? 'width: min(80svw, 520px);' : ''"
:class="{
'max-h-[70vh] h-[620px]': !isMobileMode,
'h-[100svh] w-[100svw]': isMobileMode,
}"
class="!rounded-lg pt-4"
>
<div class="space-y-3">
<div class="flex px-6 justify-between items-center">
<span class="text-md font-bold text-gray-800" @click.stop> {{ $t('general.notification') }}s </span>
<NcButton v-if="isMobileMode" size="small" type="secondary">
<GeneralIcon icon="close" class="text-gray-700" />
</NcButton>
</div>
<div
v-if="notificationTab !== 'read'"
:class="{
'text-gray-400': !unreadNotifications?.length,
}"
class="cursor-pointer right-5 pointer-events-auto top-12.5 z-2 absolute text-[13px] text-gray-600 font-weight-semibold"
@click.stop="markAllAsRead"
>
{{ $t('activity.markAllAsRead') }}
</div>
<NcTabs v-model:activeKey="notificationTab">
<a-tab-pane key="unread">
<template #tab>
<span
:class="{
'font-semibold': notificationTab === 'unread',
}"
class="text-xs"
>
Unread
</span>
</template>
<div
class="overflow-y-auto"
:style="`height: ${height - 72}px`"
:class="{
'flex flex-col items-center min-h-[48svh] justify-center': !unreadNotifications?.length,
}"
>
<template v-if="!unreadNotifications?.length">
<div class="text-sm !text-gray-500">{{ $t('msg.noNewNotifications') }}</div>
<GeneralIcon icon="inbox" class="!text-40px !text-gray-500" />
</template>
<template v-else>
<NotificationItem v-for="item in unreadNotifications" :key="item.id" :item="item" />
<InfiniteLoading
v-if="unreadNotifications && unreadPageInfo && unreadPageInfo.totalRows > unreadNotifications.length"
@infinite="loadUnReadNotifications(true)"
>
</InfiniteLoading>
</template>
</div>
</a-tab-pane>
<a-tab-pane key="read">
<template #tab>
<span
:class="{
'font-semibold': notificationTab === 'read',
}"
class="text-xs"
>
Read
</span>
</template>
<div
class="overflow-y-auto"
:style="!isMobileMode ? `height: ${height - 72}px` : ''"
:class="{
'flex flex-col items-center min-h-[48svh] justify-center': !readNotifications?.length,
}"
>
<template v-if="!readNotifications?.length">
<div class="text-sm text-gray-500">{{ $t('msg.noNewNotifications') }}</div>
<GeneralIcon icon="inbox" class="!text-40px text-gray-500" />
</template>
<template v-else>
<NotificationItem v-for="item in readNotifications" :key="item.id" :item="item" />
<InfiniteLoading
v-if="readNotifications && readPageInfo && readPageInfo.totalRows > readNotifications.length"
@infinite="loadReadNotifications(true)"
>
</InfiniteLoading>
</template>
</div>
</a-tab-pane>
</NcTabs>
</div>
</div>
</template>
<style scoped>
:deep(.ant-tabs-nav-wrap) {
@apply px-3;
}
:deep(.ant-tabs-tab) {
@apply pb-1.5 pt-1;
}
:deep(.ant-tabs-nav) {
@apply !mb-0;
}
:deep(.ant-tabs-tab-btn) {
@apply !mb-1;
}
</style>