Skip to content

Commit 5529252

Browse files
feat(condo): DOMA-9723 new organization creation (#5952)
* feat(condo): DOMA-9723 initial invite state * feat(condo): DOMA-9723 check employee existence * feat(condo): DOMA-9723 added cancel button * feat(condo): DOMA-9723 base organization creation screens * feat(condo): DOMA-9723 update invite notification banner * feat(condo): DOMA-9723 temp banner alert ui * feat(condo): DOMA-9723 create organization modal * feat(condo): DOMA-9723 temp added fields in OrganizationEmployeeRequest * feat(condo): DOMA-9723 added organization request banner * feat(ui): DOMA-9723 added action to alert * chore(condo): DOMA-9723 fixes after rebase * fix(condo): DOMA-9723 fix requset notification remove * fix(condo): DOMA-9723 fix organization modal blink after organization creation * fix(ui): DOMA-9723 fix alert content flex * fix(condo): DOMA-9723 added translations * fix(condo): DOMA-9723 added useGetOrganizationEmployeeExistenceQuery query * fix(condo): DOMA-9723 fixes after review * refactor(condo): DOMA-9723 remove unnecessary query * refactor(condo): DOMA-9723 move logic to separate page * feat(condo): DOMA-9723 pass nextUrl in redirects * refactor(condo): DOMA-9723 remove css files * feat(condo): DOMA-9723 added translations to errors * refactor(condo): DOMA-9723 update schema * fix(condo): DOMA-9723 filter requests by user organizations * refactor(condo): DOMA-9723 some fixes after review * refactor(condo): DOMA-9723 update migration * refactor(condo): DOMA-9723 refactor after review * fix(condo): DOMA-11318 clear notifications if user does not exist * refactor(condo): DOMA-9723 remove skipUserPrefetch check in prefetchOrganizationEmployee logic * fix(condo): DOMA-9723 fix bug with refetch employee * fix(condo): DOMA-9723 fix cases when user not redirected to platform * fix(condo): DOMA-9723 fix organization form witdh and added messageForUser for invalid organization name error * feat(condo): DOMA-9723 rebase, recreate migration * fix(condo): DOMA-9723 added permission in role table and added log for duplicate organization in syncOrganization * fix(condo): DOMA-9723 recreate migration
1 parent 4bdabd3 commit 5529252

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3129
-943
lines changed

apps/condo/domains/common/components/LayoutContext.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface ILayoutContext {
1111
isCollapsed?: boolean
1212
toggleCollapsed?: () => void
1313
addNotification?: (notification: ITopNotification) => void
14+
removeNotification?: (notificationId: string) => void
1415
}
1516

1617
const isMobileUserAgent = (): boolean => {
@@ -36,6 +37,7 @@ export const LayoutContextProvider: React.FC<LayoutContextProviderProps> = (prop
3637
const {
3738
TopNotificationComponent,
3839
addNotification,
40+
removeNotification,
3941
} = useTopNotificationsHook(props.serviceProblemsAlert)
4042

4143
const toggleCollapsed = () => {
@@ -59,6 +61,7 @@ export const LayoutContextProvider: React.FC<LayoutContextProviderProps> = (prop
5961
isCollapsed,
6062
toggleCollapsed,
6163
addNotification,
64+
removeNotification,
6265
}}>
6366
<TopNotificationComponent/>
6467
{props.children}
Lines changed: 49 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,85 @@
1-
/** @jsx jsx */
2-
import { InfoCircleFilled } from '@ant-design/icons'
3-
import { css, jsx } from '@emotion/react'
4-
import { Affix, Alert, AlertProps, Space } from 'antd'
5-
import React, { useState } from 'react'
1+
import { Affix, Space } from 'antd'
2+
import React, { useCallback, useState } from 'react'
63

7-
import { Button } from '@condo/domains/common/components/Button'
8-
import { colors } from '@condo/domains/common/constants/style'
4+
import { useAuth } from '@open-condo/next/auth'
5+
import { Alert, Button, AlertProps } from '@open-condo/ui'
96

10-
import { useLayoutContext } from './LayoutContext'
11-
12-
13-
const notificationAlert = ({ isSmall }) => css`
14-
border-bottom: 1px solid ${colors.white};
15-
height: ${isSmall ? 'auto' : '78px'};
16-
& .anticon {
17-
color: ${colors.green[7]};
18-
}
19-
& .ant-alert-message {
20-
font-size: 20px;
21-
line-height: 28px;
22-
color: ${colors.green[7]};
23-
}
24-
${isSmall && `
25-
flex-wrap: wrap;
26-
& .ant-alert-action {
27-
width: 100%;
28-
margin: 0;
29-
display: flex;
30-
flex-direction: column;
31-
align-items: center;
32-
}
33-
`}
34-
`
357

368
export interface ITopNotificationAction {
379
action: () => Promise<void>
3810
title: string
11+
keepNotificationOnClick?: boolean
3912
secondary?: boolean
4013
}
4114

4215
export interface ITopNotification {
4316
id: string
4417
actions: ITopNotificationAction[]
4518
message: string | JSX.Element
19+
description?: string
4620
type: AlertProps['type']
4721
}
4822

4923
interface ITopNotificationHookResult {
5024
TopNotificationComponent: React.FC
5125
addNotification: (notification: ITopNotification) => void
26+
removeNotification: (notificationId: string) => void
5227
}
5328

5429
export const useTopNotificationsHook = (serviceProblemsAlert?: React.ReactNode): ITopNotificationHookResult => {
30+
const { user } = useAuth()
5531
const [topNotifications, setTopNotifications] = useState<ITopNotification[]>([])
56-
const addNotification = (notification: ITopNotification) => {
57-
if (!topNotifications.find(existedNotification => existedNotification.id === notification.id)) {
58-
setTopNotifications([...topNotifications, notification])
59-
}
60-
}
61-
const removeNotification = (notificationId) => {
62-
setTopNotifications([...topNotifications.filter(notification => notification.id !== notificationId)])
63-
}
32+
const addNotification = useCallback((notification: ITopNotification) => {
33+
setTopNotifications(topNotifications => {
34+
if (!topNotifications.find(existedNotification => existedNotification.id === notification.id)) {
35+
return [...topNotifications, notification]
36+
}
37+
return topNotifications
38+
})
39+
}, [])
40+
const removeNotification = useCallback((notificationId) => {
41+
setTopNotifications(topNotifications => topNotifications.filter(notification => notification.id !== notificationId))
42+
}, [])
6443

6544
const TopNotificationComponent: React.FC = () => {
66-
const { breakpoints } = useLayoutContext()
67-
6845
if (topNotifications.length === 0 && !serviceProblemsAlert) return null
6946

7047
return (
7148
<>
7249
<Affix>
7350
{serviceProblemsAlert}
7451
{
75-
topNotifications.map(notification => {
76-
return (
77-
<Alert
78-
banner
79-
showIcon
80-
icon={(<InfoCircleFilled />)}
81-
message={notification.message}
82-
type={notification.type}
83-
key={notification.id}
84-
css={notificationAlert({ isSmall: !breakpoints.TABLET_LARGE })}
85-
action={<Space size={20}>
52+
!!user && topNotifications.map(notification => (
53+
<Alert
54+
banner
55+
showIcon
56+
message={notification.message}
57+
description={notification.description}
58+
type={notification.type}
59+
key={notification.id}
60+
action={
61+
<Space size={16}>
8662
{
87-
notification.actions.map((action, idx) => {
88-
return (
89-
<Button
90-
onClick={async () => {
91-
await action.action()
63+
notification.actions.map((action, idx) => (
64+
<Button
65+
onClick={async () => {
66+
await action.action()
67+
68+
if (!action.keepNotificationOnClick) {
9269
removeNotification(notification.id)
93-
}}
94-
size={!breakpoints.TABLET_LARGE ? 'middle' : 'large'}
95-
type='sberPrimary'
96-
secondary={action.secondary}
97-
key={idx}
98-
>
99-
{action.title}
100-
</Button>
101-
)
102-
})}
103-
</Space>}
104-
/>
105-
)
106-
})
70+
}
71+
}}
72+
type={action.secondary ? 'secondary' : 'primary'}
73+
key={idx}
74+
>
75+
{action.title}
76+
</Button>
77+
))
78+
}
79+
</Space>
80+
}
81+
/>
82+
))
10783
}
10884
</Affix>
10985
</>
@@ -112,6 +88,7 @@ export const useTopNotificationsHook = (serviceProblemsAlert?: React.ReactNode):
11288

11389
return {
11490
addNotification,
91+
removeNotification,
11592
TopNotificationComponent,
11693
}
11794
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { InlineOrganizationSelect } from '@condo/domains/organization/components
2121
import { SBBOLIndicator } from '@condo/domains/organization/components/SBBOLIndicator'
2222
import { MANAGING_COMPANY_TYPE, SERVICE_PROVIDER_TYPE } from '@condo/domains/organization/constants/common'
2323
import { ACCEPT_OR_REJECT_ORGANIZATION_INVITE_BY_ID_MUTATION } from '@condo/domains/organization/gql'
24+
import { useOrganizationEmployeeRequests } from '@condo/domains/organization/hooks/useOrganizationEmployeeRequests'
2425
import { useOrganizationInvites } from '@condo/domains/organization/hooks/useOrganizationInvites'
2526
import { UserMenu } from '@condo/domains/user/components/UserMenu'
2627

@@ -61,6 +62,7 @@ export const Header: React.FC<IHeaderProps> = (props) => {
6162
})
6263

6364
useOrganizationInvites(ORGANIZATION_TYPES, acceptOrReject)
65+
const { ChooseEmployeeRoleModal } = useOrganizationEmployeeRequests()
6466

6567
const handleLogoClick = useCallback(() => {
6668
if (isAuthenticated) {
@@ -72,6 +74,7 @@ export const Header: React.FC<IHeaderProps> = (props) => {
7274

7375
return (
7476
<UserMessagesListContextProvider>
77+
{ChooseEmployeeRoleModal}
7578
{
7679
!breakpoints.TABLET_LARGE
7780
? (

apps/condo/domains/common/utils/next/apollo.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ const cacheConfig: InitCacheConfig = (cacheOptions) => {
121121
read: listHelper.getReadFunction('paginate'),
122122
merge: listHelper.mergeLists,
123123
},
124+
allOrganizationEmployeeRequests: {
125+
keyArgs: ['where'],
126+
read: listHelper.getReadFunction('paginate'),
127+
merge: listHelper.mergeLists,
128+
},
124129
allPaymentsFiles: {
125130
keyArgs: ['where', 'skip'],
126131
read: listHelper.getReadFunction('paginate'),
@@ -200,6 +205,9 @@ const cacheConfig: InitCacheConfig = (cacheOptions) => {
200205
IncidentClassifierIncident: {
201206
timeToLive: 60 * 1000, // 1 minute in milliseconds
202207
},
208+
OrganizationEmployeeRequest: {
209+
timeToLive: 5 * 60 * 1000,
210+
},
203211
},
204212
},
205213
}

apps/condo/domains/onboarding/contexts/TourContext.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { TourStepStatusType, TourStepTypeType } from '@app/condo/schema'
33
import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
44

55
import { MUTATION_RESULT_EVENT, MutationEmitter } from '@open-condo/next/_useEmitterMutation'
6+
import { useAuth } from '@open-condo/next/auth'
67
import { useOrganization } from '@open-condo/next/organization'
78

89
import { IMPORT_EVENT, ImportEmitter } from '@condo/domains/common/components/Import/Index'
@@ -41,7 +42,8 @@ const getActiveTourStepFromStorage = (): ActiveTourStepType => {
4142
}
4243

4344
export const TourProvider: React.FC = ({ children }) => {
44-
const { organization } = useOrganization()
45+
const { user, isLoading: userIsLoading } = useAuth()
46+
const { organization, isLoading: organizationIsLoading } = useOrganization()
4547
const organizationId = organization?.id || null
4648
const organizationType = organization?.type || null
4749

@@ -77,10 +79,10 @@ export const TourProvider: React.FC = ({ children }) => {
7779
})
7880

7981
useEffect(() => {
80-
if (!organizationId) return
82+
if (!organizationId || !user || userIsLoading || organizationIsLoading) return
8183

8284
syncTourStepMutation()
83-
}, [organizationId])
85+
}, [organizationId, organizationIsLoading, syncTourStepMutation, user, userIsLoading])
8486

8587
const [activeStep, setActiveStep] = useState<ActiveTourStepType>(getActiveTourStepFromStorage())
8688

0 commit comments

Comments
 (0)