Skip to content

Commit

Permalink
feat(notifications): add clients tab
Browse files Browse the repository at this point in the history
See: BEDS-188
  • Loading branch information
marcel-bitfly committed Oct 2, 2024
1 parent 040f770 commit 5cf390f
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 4 deletions.
129 changes: 129 additions & 0 deletions frontend/components/bc/BcDropdownToggle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<script lang="ts" setup>
const props = defineProps<{
optionIdentifier: string,
optionLabel: string,
options: any[],
optionValue: string,
screenreaderHeading?: string,
screenreaderText: string,
text: string,
}>()
const hasOptions = computed(() => !!props.options.length)
const popover = ref()
const isVisible = ref(false)
const toggle = (event: Event) => {
popover.value?.toggle(event)
isVisible.value = !isVisible.value
}
const idScreenreaderHeading = useId()
const handleFocus = () => {
const screenreaderHeadingElement = document.getElementById(idScreenreaderHeading)
screenreaderHeadingElement?.focus()
}
const emit = defineEmits<{
change: [{
id: number,
value: boolean,
}],
}>()
</script>

<template>
<span>
<button
type="button"
class="bc-dropdown-toggle__button"
:aria-label="screenreaderText"
@click="hasOptions && toggle($event)"
>
<span>{{ text }}</span>
<IconChevron
v-if="hasOptions"
width="0.5rem"
:direction="isVisible ? 'left' : 'bottom'"
/>
</button>

<Popover
ref="popover"
unstyled
@keydown.esc.stop
@show="handleFocus"
@hide="isVisible = false"
>
<ul
class="content"
>
<BcScreenreaderOnly
:id="idScreenreaderHeading"
tabindex="-1"
tag="h2"
>
{{ props.screenreaderHeading }}
</BcScreenreaderOnly>
<li
v-for="option in props.options"
:key="option[props.optionIdentifier]"
class="content-item"
>
<label
class="content-item__label"
:for="`${option[props.optionIdentifier]}`"
>
{{ option[optionLabel] }}
</label>
<BcToggle
v-model="option.is_subscribed"
:input-id="`${option[props.optionIdentifier]}`"
@update:model-value="emit('change', {
id: option[props.optionIdentifier],
value: option[props.optionValue],
})"
/>
</li>
</ul>
</Popover>
</span>
</template>

<style lang="scss" scoped>
.content {
margin-block: 0.25rem;
max-width: 25rem;
min-width: 15rem;
padding: var(--padding);
border-radius: var(--border-radius);
border: 1px solid var(--input-border-color);
background-color: var(--input-background);
list-style: none;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.content-item {
display: flex;
justify-content: space-between;
align-items: center;
gap: 0.625rem;
&__label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.bc-dropdown-toggle__button {
padding-inline: 0.5rem;
padding-block: 0.25rem;
width: 9rem;
background-color: var(--input-background);
border-radius: var(--border-radius);
border: 1px solid var(--input-border-color);
color: var(--input-active-text-color);
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<script lang="ts" setup>
const { t: $t } = useTranslation()
const notificationsManagementStore = useNotificationsManagementStore()
await notificationsManagementStore.getSettings()
const executionClients = computed(
() => notificationsManagementStore.settings.clients.filter(client => client.category === 'execution_layer'),
)
const consensusClients = computed(
() => notificationsManagementStore.settings.clients.filter(client => client.category === 'consensus_layer'),
)
const otherClients = computed(
() => notificationsManagementStore.settings.clients.filter(client => client.category === 'other'),
)
const screenreaderTextExcutionClients = computed(
() => executionClients.value.length
? $t('notifications.clients.settings.screenreader.edit_notifications', [
executionClients.value.length,
$t('notifications.clients.settings.execution_clients'),
])
: $t('notifications.clients.settings.screenreader.empty_clients'),
)
const screenreaderTextConsensusClients = computed(
() => consensusClients.value.length
? $t('notifications.clients.settings.screenreader.edit_notifications', [
consensusClients.value.length,
$t('notifications.clients.settings.execution_clients'),
])
: $t('notifications.clients.settings.screenreader.empty_clients'),
)
const screenreaderTextOtherClients = computed(
() => executionClients.value.length
? $t('notifications.clients.settings.screenreader.edit_notifications', [
executionClients.value.length,
$t('notifications.clients.settings.execution_clients'),
])
: $t('notifications.clients.settings.screenreader.empty_clients'),
)
const setNotificationForClient = ({
id,
value,
}: {
id: number,
value: boolean,
},
) => {
notificationsManagementStore.setNotificationForClient({
client_id: id,
is_subscribed: value,
})
}
</script>

<template>
<BcTabPanel>
<BcListSection>
<span class="grid-span-2">
{{ $t('notifications.clients.settings.execution_clients') }}
</span>
<BcDropdownToggle
:options="executionClients"
option-label="name"
option-value="is_subscribed"
option-identifier="id"
:screenreader-text="screenreaderTextExcutionClients"
:screenreader-heading="$t('notifications.clients.settings.execution_clients')"
:text="$t('notifications.clients.settings.clients', [executionClients.length])"
@change="setNotificationForClient"
/>
<span class="grid-span-2">
{{ $t('notifications.clients.settings.consensus_clients') }}
</span>
<BcDropdownToggle
:options="consensusClients"
option-label="name"
option-value="is_subscribed"
option-identifier="id"
:screenreader-text="screenreaderTextConsensusClients"
:screenreader-heading="$t('notifications.clients.settings.consensus_clients')"
:text="$t('notifications.clients.settings.clients', [consensusClients.length])"
@change="setNotificationForClient"
/>
<span class="grid-span-2">
{{ $t('notifications.clients.settings.other_clients') }}
</span>
<BcDropdownToggle
:options="otherClients"
option-label="name"
option-value="is_subscribed"
option-identifier="id"
:screenreader-text="screenreaderTextOtherClients"
:screenreader-heading="$t('notifications.clients.settings.other_clients')"
:text="$t('notifications.clients.settings.clients', [otherClients.length])"
@change="setNotificationForClient"
/>
</BcListSection>
</BcTabPanel>
</template>

<style lang="scss" scoped>
.toggle {
justify-content: end;
margin: 0;
}
.grid-span-2{
grid-column: span 2;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ const tabs: HashTabs = [
{
icon: faBolt,
key: 'clients',
placeholder: 'Clients coming soon!',
title: $t('notifications.tabs.clients'),
},
{
Expand Down Expand Up @@ -64,12 +63,12 @@ const tabs: HashTabs = [
<template #tab-panel-machines>
<NotificationsManagementMachines />
</template>
<template #tab-panel-clients>
<NotificationsManagementClients />
</template>
<template #tab-panel-network>
<NotificationsManagementNetwork />
</template>
<template #tab-header-icon-rocketpool>
<IconRocketPool />
</template>
</BcTabList>
<Button
class="done-button"
Expand Down
10 changes: 10 additions & 0 deletions frontend/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,16 @@
"subscriptions": "Clients ({count} Subscriptions)"
},
"search_placeholder":"Client",
"settings": {
"clients": "Clients ({0})",
"consensus_clients": "Consensus Clients",
"execution_clients": "Execution Clients",
"other_clients": "Others Clients",
"screenreader": {
"edit_notifications": "Edit Notifications for {0} {1}",
"empty_clients": "0 clients to edit."
}
},
"title": "Clients"
},
"col": {
Expand Down
20 changes: 20 additions & 0 deletions frontend/stores/notifications/useNotificationsManagementStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,31 @@ export const useNotificationsManagementStore = defineStore('notifications-manage
},
)
}
const setNotificationForClient = async ({
client_id,
is_subscribed,
}: {
client_id: number,
is_subscribed: boolean,
}) => {
await fetch<InternalPutUserNotificationSettingsNetworksResponse>(
API_PATH.NOTIFICATIONS_MANAGEMENT_CLIENTS_SET_NOTIFICATION,
{
body: {
is_subscribed,
},
},
{
client_id,
},
)
}

return {
getSettings,
removeDevice,
saveSettings,
setNotificationForClient,
setNotificationForNetwork,
setNotificationForPairedDevice,
settings,
Expand Down
7 changes: 7 additions & 0 deletions frontend/types/customFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export enum API_PATH {
NOTIFICATIONS_CLIENTS = '/notifications/clients',
NOTIFICATIONS_DASHBOARDS = '/notifications/dashboards',
NOTIFICATIONS_MACHINE = '/notifications/machines',
NOTIFICATIONS_MANAGEMENT_CLIENTS_SET_NOTIFICATION = '/notifications/management/clients/set_notifications',
NOTIFICATIONS_MANAGEMENT_GENERAL = '/notifications/management/general',
NOTIFICATIONS_MANAGEMENT_NETWORK_SET_NOTIFICATION = '/notifications/management/network/set_notification',
NOTIFICATIONS_MANAGEMENT_PAIRED_DEVICES_DELETE = '/notifications/management/paired_devices/delete',
Expand Down Expand Up @@ -295,6 +296,12 @@ export const mapping: Record<string, MappingData> = {
[API_PATH.NOTIFICATIONS_MACHINE]: {
path: '/users/me/notifications/machines',
},
[API_PATH.NOTIFICATIONS_MANAGEMENT_CLIENTS_SET_NOTIFICATION]: {
getPath: pathValues =>
`/users/me/notifications/settings/clients/${pathValues?.client_id}`,
method: 'PUT',
path: '/users/me/notifications/settings/clients/{client_id}',
},
[API_PATH.NOTIFICATIONS_MANAGEMENT_GENERAL]: {
path: '/users/me/notifications/settings',
},
Expand Down

0 comments on commit 5cf390f

Please sign in to comment.