Skip to content

Commit

Permalink
feat: add NotificationsClientTable component with store and API integ…
Browse files Browse the repository at this point in the history
…ration

- Created a new NotificationsClientsTable.vue component to display `notifications client` data.
 - Implemented a new useNotificationsClientsStore for handling the API calls related to `notifications client` data.
 - Updated `customFetch.ts` to include the new API endpoints and methods for fetching `notifications client` data.
 - Added translations for the `NotificationsClientsTable.vue` component in the en.json file.
 - Applied code styling updates in `notifications.vue` and added the ClientsTab to display the `NotificationsClientsTable.vue` component.

See: BEDS-324
  • Loading branch information
benji-bitfly committed Sep 10, 2024
1 parent 4d5ed1e commit 488fc7c
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 1 deletion.
160 changes: 160 additions & 0 deletions frontend/components/notifications/NotificationsClientsTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<script setup lang="ts">
import { useNotificationsClientsStore } from '~/stores/notifications/useNotificationsClientsStore';

Check failure on line 2 in frontend/components/notifications/NotificationsClientsTable.vue

View workflow job for this annotation

GitHub Actions / lint and typecheck

Extra semicolon
import type { Cursor } from '~/types/datatable'
defineEmits<{ (e: 'openDialog'): void }>()
const { width } = useWindowSize()
const cursor = ref<Cursor>()
const pageSize = ref<number>(10)
const { t: $t } = useTranslation()
const {
clientsNotifications,
isLoading,
onSort,
query,
setCursor,
setPageSize,
setSearch,
} = useNotificationsClientsStore()
const colsVisible = computed(() => {
return {
footer: 1024,
threshold: width.value > 830,
}
})
const clientLink = computed(() => {
// TODO: implement client link when it's available from the API
// TODO: Test the endpoints
// return `/client/${data.clientId}`
return '/notifications'
})
</script>

<template>
<div>
<BcTableControl
:title="$t('notifications.clients.title')"
:search-placeholder="$t('notifications.dashboards.search_placeholder')"
@set-search="setSearch"
>
<template #table>
<ClientOnly fallback-tag="span">
<BcTable
:data="clientsNotifications"
data-key="notification_id"
:cursor
:page-size
:selected-sort="query?.sort"
:loading="isLoading"
:add-spacer="true"
@set-cursor="setCursor"
@sort="onSort"
@set-page-size="setPageSize"
>
<Column
field="machine_name"
sortable
header-class="col-client-name"
body-class="col-client-name"
:header="$t('notifications.clients.col.client_name')"
>
<template #body="slotProps">
<pre>
{{ slotProps.data.client_name }}
</pre>
</template>
</Column>
<Column
field="machine_name"
header-class="col-client-name"
body-class="col-client-name"
:header="$t('notifications.clients.col.version')"
>
<template #body="slotProps">
<BcLink
:to="clientLink"
class="link link-dashboard"
target="_blank"
>
{{ slotProps.data.version }}
</BcLink>
</template>
</Column>
<Column
field="timestamp"
sortable
header-class="col-age"
body-class="col-age"
>
<template #header>
<BcTableAgeHeader />
</template>
<template #body="slotProps">
<BcFormatTimePassed
:value="slotProps.data.timestamp"
type="go-timestamp"
/>
</template>
</Column>
<template #empty>
<NotificationsDashboardsTableEmpty
v-if="!clientsNotifications?.data.length"
@open-dialog="$emit('openDialog')"
/>
</template>
<!-- TODO: implement number of clients subscriptions -->
<template #bc-table-footer-right>
<template v-if="colsVisible">
{{ $t('notifications.clients.footer.subscriptions', { count: 3 }) }}
</template>
</template>
</BcTable>
</ClientOnly>
</template>
</BcTableControl>
</div>
</template>

<style lang="scss" scoped>
@use "~/assets/css/utils.scss";
$breakpoint-sm: 630px;
$breakpoint-md: 780px;
$breakpoint-lg: 1024px;
:deep(.col-client-name) {
*:not([data-pc-section="sort"]) {
@include utils.truncate-text;
}
@media (max-width: $breakpoint-lg) {
@include utils.set-all-width(240px);
}
@media (max-width: $breakpoint-md) {
@include utils.set-all-width(200px);
}
@media (max-width: $breakpoint-sm) {
@include utils.set-all-width(106px);
}
}
:deep(.col-age) {
@media (max-width: $breakpoint-lg) {
@include utils.set-all-width(140px);
}
@media (max-width: $breakpoint-sm) {
@include utils.set-all-width(78px);
}
*:not([data-pc-section="sort"]) {
@include utils.truncate-text;
}
}
</style>
10 changes: 10 additions & 0 deletions frontend/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,16 @@
"yes": "Yes"
},
"notifications": {
"clients": {
"col": {
"client_name": "Client ",
"version": "Version"
},
"footer":{
"subscriptions": "Clients ({count} Subscriptions)"
},
"title": "Clients"
},
"col": {
"dashboard": "Dashboard",
"group": "Group",
Expand Down
8 changes: 7 additions & 1 deletion frontend/pages/notifications.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ const openManageNotifications = () => {
/>
</div>
<BcTabList
:tabs default-tab="dashboards"
:tabs
default-tab="dashboards"
:use-route-hash="true"
class="notifications-tab-view"
panels-class="notifications-tab-panels"
Expand All @@ -110,6 +111,11 @@ const openManageNotifications = () => {
@open-dialog="openManageNotifications"
/>
</template>
<template #tab-panel-clients>
<NotificationsClientsTable
@open-dialog="openManageNotifications"
/>
</template>
</BcTabList>
</BcPageWrapper>
</div>
Expand Down
71 changes: 71 additions & 0 deletions frontend/stores/notifications/useNotificationsClientsStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { defineStore } from 'pinia'
import type {
InternalGetUserNotificationClientsResponse, NotificationClientsTableRow

Check failure on line 3 in frontend/stores/notifications/useNotificationsClientsStore.ts

View workflow job for this annotation

GitHub Actions / lint and typecheck

'NotificationClientsTableRow' is defined but never used. Allowed unused vars must match /^_/u

Check failure on line 3 in frontend/stores/notifications/useNotificationsClientsStore.ts

View workflow job for this annotation

GitHub Actions / lint and typecheck

Missing trailing comma
} from '~/types/api/notifications'
import { API_PATH } from '~/types/customFetch'
import type { TableQueryParams } from '~/types/datatable'

const notificationsClientsStore = defineStore('notifications-clients-store', () => {
const data = ref<InternalGetUserNotificationClientsResponse | undefined>()
return { data }
})

export function useNotificationsClientsStore() {
const { isLoggedIn } = useUserStore()

const { fetch } = useCustomFetch()
const { data } = storeToRefs(notificationsClientsStore())
const {
cursor, isStoredQuery, onSort, pageSize, pendingQuery, query, setCursor, setPageSize, setSearch, setStoredQuery,
} = useTableQuery({
limit: 10, sort: 'timestamp:desc',
}, 10)
const isLoading = ref(false)

async function loadClientsNotifications(q: TableQueryParams) {
isLoading.value = true
setStoredQuery(q)
try {
const result = await fetch<InternalGetUserNotificationClientsResponse>(
API_PATH.NOTIFICATIONS_CLIENTS,
undefined,
undefined,
q,
)

isLoading.value = false
if (!isStoredQuery(q)) {
return // in case some query params change while loading
}

data.value = result
}
catch (e) {
data.value = undefined
isLoading.value = false
}
return data.value
}

const clientsNotifications = computed(() => {
return data.value
})

watch(query, (q) => {
if (q) {
isLoggedIn.value && loadClientsNotifications(q)
}
}, { immediate: true })

return {
clientsNotifications,
cursor,
isLoading,
onSort,
pageSize,
query: pendingQuery,
setCursor,
setPageSize,
setSearch,
}
}
5 changes: 5 additions & 0 deletions frontend/types/customFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export enum API_PATH {
LATEST_STATE = '/latestState',
LOGIN = '/login',
LOGOUT = '/logout',
NOTIFICATIONS_CLIENTS = '/notifications/clients',
NOTIFICATIONS_DASHBOARDS = '/notifications/dashboards',
NOTIFICATIONS_MACHINE = '/notifications/machines',
NOTIFICATIONS_MANAGEMENT_GENERAL = '/notifications/managementGeneral',
Expand Down Expand Up @@ -279,6 +280,10 @@ export const mapping: Record<string, MappingData> = {
mock: false,
path: '/logout',
},
[API_PATH.NOTIFICATIONS_CLIENTS]: {
method: 'GET',
path: '/users/me/notifications/clients',
},
[API_PATH.NOTIFICATIONS_DASHBOARDS]: {
path: '/users/me/notifications/dashboards',
},
Expand Down

0 comments on commit 488fc7c

Please sign in to comment.