Skip to content

Commit 11676f2

Browse files
feat(condo): DOMA-11185 notifications sound switch (#5906)
* feat(condo): DOMA-11185 added sound switch * chore(condo): DOMA-11185 remove featureflag
1 parent 7fdbb19 commit 11676f2

File tree

15 files changed

+161
-174
lines changed

15 files changed

+161
-174
lines changed

apps/condo/domains/common/components/containers/BaseLayout/Header.tsx

+34-73
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import get from 'lodash/get'
66
import { useRouter } from 'next/router'
77
import React, { useCallback } from 'react'
88

9-
import { useFeatureFlags } from '@open-condo/featureflags/FeatureFlagsContext'
109
import { Menu } from '@open-condo/icons'
1110
import { useMutation } from '@open-condo/next/apollo'
1211
import { useAuth } from '@open-condo/next/auth'
@@ -16,7 +15,6 @@ import { Space } from '@open-condo/ui'
1615
import { useLayoutContext } from '@condo/domains/common/components/LayoutContext'
1716
import { Logo } from '@condo/domains/common/components/Logo'
1817
import { ResidentActions } from '@condo/domains/common/components/ResidentActions/ResidentActions'
19-
import { PLATFORM_NOTIFICATIONS } from '@condo/domains/common/constants/featureflags'
2018
import { UserMessagesList } from '@condo/domains/notification/components/UserMessagesList'
2119
import { UserMessagesListContextProvider } from '@condo/domains/notification/contexts/UserMessagesListContext'
2220
import { InlineOrganizationSelect } from '@condo/domains/organization/components/OrganizationSelect'
@@ -39,7 +37,6 @@ interface IHeaderProps {
3937
export const Header: React.FC<IHeaderProps> = (props) => {
4038
const client = useApolloClient()
4139
const { breakpoints, toggleCollapsed } = useLayoutContext()
42-
const { useFlag } = useFeatureFlags()
4340
const router = useRouter()
4441

4542
const { isAuthenticated } = useAuth()
@@ -73,78 +70,42 @@ export const Header: React.FC<IHeaderProps> = (props) => {
7370
}
7471
}, [isAuthenticated, router])
7572

76-
const isPlatformNotificationsFeatureEnabled = useFlag(PLATFORM_NOTIFICATIONS)
77-
78-
if (isPlatformNotificationsFeatureEnabled) {
79-
return (
80-
<UserMessagesListContextProvider>
81-
{
82-
!breakpoints.TABLET_LARGE
83-
? (
84-
<>
85-
<div id='tasks-container' className='tasks-container' />
86-
<Layout.Header className='header mobile-header'>
87-
<div className='context-bar'>
88-
<UserMessagesList />
89-
<div className='organization-user-block'>
90-
<Space direction='horizontal' size={4}>
91-
<SBBOLIndicator organization={organization} />
92-
<InlineOrganizationSelect/>
93-
</Space>
94-
<UserMenu/>
95-
</div>
73+
return (
74+
<UserMessagesListContextProvider>
75+
{
76+
!breakpoints.TABLET_LARGE
77+
? (
78+
<>
79+
<div id='tasks-container' className='tasks-container' />
80+
<Layout.Header className='header mobile-header'>
81+
<div className='context-bar'>
82+
<UserMessagesList />
83+
<div className='organization-user-block'>
84+
<Space direction='horizontal' size={4}>
85+
<SBBOLIndicator organization={organization} />
86+
<InlineOrganizationSelect/>
87+
</Space>
88+
<UserMenu/>
9689
</div>
97-
<div className='appeals-bar'>
98-
<Menu size='large' onClick={toggleCollapsed}/>
99-
<Logo onClick={handleLogoClick} minified/>
100-
<div>
101-
{hasAccessToAppeals && (
102-
<ResidentActions minified/>
103-
)}
104-
</div>
90+
</div>
91+
<div className='appeals-bar'>
92+
<Menu size='large' onClick={toggleCollapsed}/>
93+
<Logo onClick={handleLogoClick} minified/>
94+
<div>
95+
{hasAccessToAppeals && (
96+
<ResidentActions minified/>
97+
)}
10598
</div>
106-
</Layout.Header>
107-
</>
108-
)
109-
: (
110-
<Layout.Header className='header desktop-header'>
111-
<TopMenuItems headerAction={props.headerAction}/>
99+
</div>
112100
</Layout.Header>
113-
)
114-
}
115-
</UserMessagesListContextProvider>
116-
)
117-
}
118-
119-
return (
120-
!breakpoints.TABLET_LARGE
121-
? (
122-
<>
123-
<div id='tasks-container' className='tasks-container' />
124-
<Layout.Header className='header mobile-header'>
125-
<div className='context-bar'>
126-
<Space direction='horizontal' size={4}>
127-
<SBBOLIndicator organization={organization} />
128-
<InlineOrganizationSelect/>
129-
</Space>
130-
<UserMenu/>
131-
</div>
132-
<div className='appeals-bar'>
133-
<Menu size='large' onClick={toggleCollapsed}/>
134-
<Logo onClick={handleLogoClick} minified/>
135-
<div>
136-
{hasAccessToAppeals && (
137-
<ResidentActions minified/>
138-
)}
139-
</div>
140-
</div>
141-
</Layout.Header>
142-
</>
143-
)
144-
: (
145-
<Layout.Header className='header desktop-header'>
146-
<TopMenuItems headerAction={props.headerAction}/>
147-
</Layout.Header>
148-
)
101+
</>
102+
)
103+
: (
104+
<Layout.Header className='header desktop-header'>
105+
<TopMenuItems headerAction={props.headerAction}/>
106+
</Layout.Header>
107+
)
108+
}
109+
</UserMessagesListContextProvider>
149110
)
150111
}

apps/condo/domains/common/components/containers/BaseLayout/components/TopMenuItems.tsx

+3-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import React from 'react'
22

3-
import { useFeatureFlags } from '@open-condo/featureflags/FeatureFlagsContext'
43
import { useAuth } from '@open-condo/next/auth'
54
import { useOrganization } from '@open-condo/next/organization'
65
import { Space } from '@open-condo/ui'
76

8-
import { PLATFORM_NOTIFICATIONS } from '@condo/domains/common/constants/featureflags'
97
import { UserMessagesList } from '@condo/domains/notification/components/UserMessagesList'
108
import { InlineOrganizationSelect } from '@condo/domains/organization/components/OrganizationSelect'
119
import { SBBOLIndicator } from '@condo/domains/organization/components/SBBOLIndicator'
@@ -21,20 +19,15 @@ export const TopMenuItems: React.FC<ITopMenuItemsProps> = (props) => {
2119
const auth = useAuth()
2220
const { organization } = useOrganization()
2321

24-
const { useFlag } = useFeatureFlags()
25-
const isPlatformNotificationsFeatureEnabled = useFlag(PLATFORM_NOTIFICATIONS)
26-
2722
if (auth.isLoading) return null
2823

2924
return (
3025
<>
3126
{props.headerAction ? props.headerAction : null}
3227
<Space direction='horizontal' size={40} className='top-menu-items'>
33-
{isPlatformNotificationsFeatureEnabled && (
34-
<div style={{ maxHeight: '24px' }}>
35-
<UserMessagesList />
36-
</div>
37-
)}
28+
<div style={{ maxHeight: '24px' }}>
29+
<UserMessagesList />
30+
</div>
3831
<Space size={12}>
3932
<SBBOLIndicator organization={organization} />
4033
<ServiceSubscriptionIndicator />

apps/condo/domains/common/constants/featureflags.js

-4
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ const POLL_TICKET_COMMENTS = 'poll-ticket-comments'
2929
const REASSIGN_EMPLOYEE_TICKETS = 'reassign-employee-tickets'
3030
const SNOWFLAKES_SETTINGS = 'snowflakes-settings'
3131
const USER_WHITE_LIST_FOR_FIND_ORGANIZATIONS_BY_TIN = 'user-white-list-for-find-organizations-by-tin'
32-
const PLATFORM_NOTIFICATIONS = 'platform-notifications'
3332
const METER_REPORTING_PERIOD_STRICT_RULE = 'meter-reporting-period-strict-rule'
34-
const PLATFORM_NOTIFICATIONS_SOUND = 'platform-notifications-sound'
3533

3634
module.exports = {
3735
SMS_AFTER_TICKET_CREATION,
@@ -65,7 +63,5 @@ module.exports = {
6563
REASSIGN_EMPLOYEE_TICKETS,
6664
SNOWFLAKES_SETTINGS,
6765
USER_WHITE_LIST_FOR_FIND_ORGANIZATIONS_BY_TIN,
68-
PLATFORM_NOTIFICATIONS,
6966
METER_REPORTING_PERIOD_STRICT_RULE,
70-
PLATFORM_NOTIFICATIONS_SOUND,
7167
}

apps/condo/domains/notification/components/UserMessagesList/UserMessagesList.css

+4
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@
3939
height: calc(100vh - 40px - 32px);
4040
max-height: unset;
4141
margin: 16px auto auto;
42+
}
43+
44+
.user-messages-settings-sound-tooltip.condo-tooltip {
45+
max-width: unset;
4246
}

apps/condo/domains/notification/components/UserMessagesList/UserMessagesSettingsModal.tsx

+60-22
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import React, { Dispatch, SetStateAction, useCallback } from 'react'
1+
import React, { Dispatch, SetStateAction, useCallback, useMemo } from 'react'
22

3+
import { QuestionCircle } from '@open-condo/icons'
34
import { useIntl } from '@open-condo/next/intl'
4-
import { Button, Switch, Modal, Space, Typography } from '@open-condo/ui'
5+
import { Button, Switch, Modal, Space, Typography, Tooltip } from '@open-condo/ui'
6+
import { colors } from '@open-condo/ui/dist/colors'
57

8+
import { useUserMessagesList } from '@condo/domains/notification/contexts/UserMessagesListContext'
69
import { useAllowedToFilterMessageTypes } from '@condo/domains/notification/hooks/useAllowedToFilterMessageTypes'
710
import {
811
useUserMessagesListSettingsStorage,
@@ -23,9 +26,13 @@ export const UserMessagesSettingsModal: React.FC<UserMessagesSettingsModalProps>
2326
const intl = useIntl()
2427
const ModalTitleMessage = intl.formatMessage({ id: 'notification.UserMessagesSettingModal.title' })
2528
const ApplyChanges = intl.formatMessage({ id: 'ApplyChanges' })
29+
const SoundMessage = intl.formatMessage({ id: 'notification.UserMessagesSettingModal.sound' })
30+
const SoundEnabledTooltip = intl.formatMessage({ id: 'notification.UserMessagesSettingModal.sound.tooltip.enabled' })
31+
const SoundDisabledTooltip = intl.formatMessage({ id: 'notification.UserMessagesSettingModal.sound.tooltip.disabled' })
2632

2733
const { messageTypes } = useAllowedToFilterMessageTypes()
2834
const { userMessagesSettingsStorage } = useUserMessagesListSettingsStorage()
35+
const { isNotificationSoundEnabled, setIsNotificationSoundEnabled } = useUserMessagesList()
2936

3037
const handleSwitchChange = useCallback((checked: boolean, checkedType: MessageTypeAllowedToFilterType) => {
3138
setExcludedMessageTypes((prevExcludedTypes) => {
@@ -42,6 +49,8 @@ export const UserMessagesSettingsModal: React.FC<UserMessagesSettingsModalProps>
4249
setOpen(false)
4350
}, [setOpen])
4451

52+
const isAllMessageTypesDisabled = useMemo(() => messageTypes.every(type => excludedMessageTypes.includes(type)), [excludedMessageTypes, messageTypes])
53+
4554
return (
4655
<Modal
4756
open={open}
@@ -53,26 +62,55 @@ export const UserMessagesSettingsModal: React.FC<UserMessagesSettingsModalProps>
5362
</Button>
5463
)}
5564
>
56-
<Space size={12} direction='vertical'>
57-
{messageTypes.map((type) => (
58-
<label key={type}>
59-
<Space size={8}>
60-
<Switch
61-
id={type}
62-
checked={!excludedMessageTypes.includes(type)}
63-
onChange={(checked) => handleSwitchChange(checked, type)}
64-
size='small'
65-
/>
66-
<Typography.Text>
67-
{
68-
intl.formatMessage(
69-
{ id: `notification.UserMessagesSettingModal.messageType.${type}.label` }
70-
)
71-
}
72-
</Typography.Text>
73-
</Space>
74-
</label>
75-
))}
65+
<Space size={24} direction='vertical'>
66+
<Space size={12} direction='vertical'>
67+
{messageTypes.map((type) => (
68+
<label key={type}>
69+
<Space size={8}>
70+
<Switch
71+
id={type}
72+
checked={!excludedMessageTypes.includes(type)}
73+
onChange={(checked) => handleSwitchChange(checked, type)}
74+
size='small'
75+
/>
76+
<Typography.Text>
77+
{
78+
intl.formatMessage(
79+
{ id: `notification.UserMessagesSettingModal.messageType.${type}.label` }
80+
)
81+
}
82+
</Typography.Text>
83+
</Space>
84+
</label>
85+
))}
86+
</Space>
87+
{
88+
!isAllMessageTypesDisabled && (
89+
<label>
90+
<Space size={4}>
91+
<Space size={8}>
92+
<Switch
93+
checked={isNotificationSoundEnabled}
94+
onChange={setIsNotificationSoundEnabled}
95+
size='small'
96+
/>
97+
<Typography.Text>
98+
{SoundMessage}
99+
</Typography.Text>
100+
</Space>
101+
<Tooltip
102+
overlayClassName='user-messages-settings-sound-tooltip'
103+
title={isNotificationSoundEnabled ? SoundEnabledTooltip : SoundDisabledTooltip}
104+
placement='topLeft'
105+
>
106+
<div style={{ display: 'flex' }}>
107+
<QuestionCircle size='small' color={colors.gray[7]} />
108+
</div>
109+
</Tooltip>
110+
</Space>
111+
</label>
112+
)
113+
}
76114
</Space>
77115
</Modal>
78116
)

apps/condo/domains/notification/contexts/UserMessagesListContext.tsx

+15-22
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ type UserMessagesListContextType = {
3535
isDropdownOpen: boolean
3636
setIsDropdownOpen: Dispatch<SetStateAction<boolean>>
3737

38+
isNotificationSoundEnabled: boolean
39+
setIsNotificationSoundEnabled: Dispatch<SetStateAction<boolean>>
40+
3841
excludedMessageTypes: Array<MessageTypeAllowedToFilterType>
3942
setExcludedMessageTypes: Dispatch<SetStateAction<Array<MessageTypeAllowedToFilterType>>>
4043
}
@@ -48,6 +51,8 @@ const UserMessageListContext = createContext<UserMessagesListContextType>({
4851
moreMessagesLoading: false,
4952
isDropdownOpen: false,
5053
setIsDropdownOpen: null,
54+
isNotificationSoundEnabled: false,
55+
setIsNotificationSoundEnabled: null,
5156
excludedMessageTypes: [],
5257
setExcludedMessageTypes: null,
5358
})
@@ -62,6 +67,7 @@ export const UserMessagesListContextProvider: React.FC<UserMessagesListContextPr
6267
const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false)
6368
const [readUserMessagesAt, setReadUserMessagesAt] = useState<string>()
6469
const [excludedMessageTypes, setExcludedMessageTypes] = useState<Array<MessageTypeAllowedToFilterType>>([])
70+
const [isNotificationSoundEnabled, setIsNotificationSoundEnabled] = useState<boolean>()
6571

6672
const { user } = useAuth()
6773
const { organization } = useOrganization()
@@ -88,28 +94,6 @@ export const UserMessagesListContextProvider: React.FC<UserMessagesListContextPr
8894
!userId || !organizationId || allowedMessageTypesLoading || !readUserMessagesAt || messageTypesToFilter.length === 0,
8995
})
9096

91-
const handleStorageChange = useCallback((event: StorageEvent) => {
92-
if (event.key === userMessagesSettingsStorage.getStorageKey()) {
93-
const lastReadUserMessagesAt = userMessagesSettingsStorage.getReadUserMessagesAt()
94-
if (!isEqual(lastReadUserMessagesAt, readUserMessagesAt)) {
95-
setReadUserMessagesAt(lastReadUserMessagesAt)
96-
}
97-
98-
const excludedMessageTypesToFilter = userMessagesSettingsStorage.getExcludedUserMessagesTypes()
99-
if (!isEqual(excludedMessageTypesToFilter, excludedMessageTypes)) {
100-
setExcludedMessageTypes(excludedMessageTypesToFilter)
101-
}
102-
}
103-
}, [excludedMessageTypes, readUserMessagesAt, userMessagesSettingsStorage])
104-
105-
useEffect(() => {
106-
window.addEventListener('storage', handleStorageChange)
107-
108-
return () => {
109-
window.removeEventListener('storage', handleStorageChange)
110-
}
111-
}, [handleStorageChange])
112-
11397
// Set initial settings to state
11498
useEffect(() => {
11599
let lastReadUserMessagesAt = userMessagesSettingsStorage.getReadUserMessagesAt()
@@ -121,6 +105,9 @@ export const UserMessagesListContextProvider: React.FC<UserMessagesListContextPr
121105

122106
const excludedMessageTypesToFilter = userMessagesSettingsStorage.getExcludedUserMessagesTypes()
123107
setExcludedMessageTypes(excludedMessageTypesToFilter)
108+
109+
const isSoundEnabled = userMessagesSettingsStorage.getIsNotificationSoundEnabled()
110+
setIsNotificationSoundEnabled(isSoundEnabled)
124111
}, [organizationId, userId, userMessagesSettingsStorage])
125112

126113
const updateReadUserMessagesAt = useCallback(() => {
@@ -150,6 +137,10 @@ export const UserMessagesListContextProvider: React.FC<UserMessagesListContextPr
150137
clearLoadedMessages()
151138
}, [clearLoadedMessages, messagesListRef, updateReadUserMessagesAt])
152139

140+
const handleIsNotificationSoundEnabledChange = useCallback((isEnabled: boolean) => {
141+
setIsNotificationSoundEnabled(isEnabled)
142+
userMessagesSettingsStorage.setIsNotificationSoundEnabled(isEnabled)
143+
}, [userMessagesSettingsStorage])
153144

154145
return (
155146
<UserMessageListContext.Provider
@@ -162,6 +153,8 @@ export const UserMessagesListContextProvider: React.FC<UserMessagesListContextPr
162153
moreMessagesLoading,
163154
isDropdownOpen,
164155
setIsDropdownOpen: handleDropdownOpenChange,
156+
isNotificationSoundEnabled,
157+
setIsNotificationSoundEnabled: handleIsNotificationSoundEnabledChange,
165158
excludedMessageTypes,
166159
setExcludedMessageTypes,
167160
}}

0 commit comments

Comments
 (0)