From 4a028c6ca4a8e1c46ba7570835819ffb704597ee Mon Sep 17 00:00:00 2001 From: bobbykolev <bobbykolev@abv.bg> Date: Mon, 28 Oct 2024 19:06:10 +0200 Subject: [PATCH 1/8] Dashboard Menu, UI, main logic, configuration and functionality* --- src/core/apollo/generated/apollo-hooks.ts | 4 + src/core/apollo/generated/graphql-schema.ts | 14 ++- src/core/i18n/en/translation.en.json | 9 ++ .../UserProvider/UserProvider.graphql | 4 + .../providers/UserProvider/UserProvider.tsx | 3 + src/main/routing/urlBuilders.ts | 4 + .../myDashboard/DashboardContext.tsx | 8 +- .../DashboardDialogs/DashboardDialogs.tsx | 18 ++++ .../DashboardDialogs/DashboardDialogsProps.ts | 5 + .../DashboardMenu/DashboardMenu.tsx | 102 ++++++++++++++---- .../DashboardMenu/dashboardMenuTypes.ts | 15 +++ .../DashboardMenu/useHomeMenuItems.ts | 89 +++++++++++++++ .../MyDashboardWithMemberships.tsx | 2 + .../MyDashboardWithoutMemberships.tsx | 2 + .../myMemberships/MyMembershipsDialog.tsx | 2 +- 15 files changed, 257 insertions(+), 24 deletions(-) create mode 100644 src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx create mode 100644 src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogsProps.ts create mode 100644 src/main/topLevelPages/myDashboard/DashboardMenu/useHomeMenuItems.ts diff --git a/src/core/apollo/generated/apollo-hooks.ts b/src/core/apollo/generated/apollo-hooks.ts index 40ddec8437..4fe349254e 100644 --- a/src/core/apollo/generated/apollo-hooks.ts +++ b/src/core/apollo/generated/apollo-hooks.ts @@ -13533,6 +13533,10 @@ export const UserProviderDocument = gql` ...UserDetails account { id + authorization { + id + myPrivileges + } } } } diff --git a/src/core/apollo/generated/graphql-schema.ts b/src/core/apollo/generated/graphql-schema.ts index cd3a921b71..cf80bfaccb 100644 --- a/src/core/apollo/generated/graphql-schema.ts +++ b/src/core/apollo/generated/graphql-schema.ts @@ -18062,7 +18062,19 @@ export type UserProviderQuery = { lastName: string; email: string; phone?: string | undefined; - account?: { __typename?: 'Account'; id: string } | undefined; + account?: + | { + __typename?: 'Account'; + id: string; + authorization?: + | { + __typename?: 'Authorization'; + id: string; + myPrivileges?: Array<AuthorizationPrivilege> | undefined; + } + | undefined; + } + | undefined; profile: { __typename?: 'Profile'; id: string; diff --git a/src/core/i18n/en/translation.en.json b/src/core/i18n/en/translation.en.json index 79415ce00b..2b5bbd22ca 100644 --- a/src/core/i18n/en/translation.en.json +++ b/src/core/i18n/en/translation.en.json @@ -2162,6 +2162,15 @@ "home": { "title": "My Dashboard", "subtitle": "Ready to make some impact?", + "mainNavigation": { + "invitations": "Invitations", + "myLatestActivity": "My Latest Activity", + "myLatestSpacesActivity": "Latest Activity In My Spaces", + "tipsAndTricks": "Tips & Tricks", + "myAccount": "My Account", + "createSpace": "Create my own Space", + "activityView": "Activity View" + }, "sections": { "latestContributions": { "title": "Latest Contributions in my Spaces", diff --git a/src/domain/community/user/providers/UserProvider/UserProvider.graphql b/src/domain/community/user/providers/UserProvider/UserProvider.graphql index c612cc77c6..0955603dbf 100644 --- a/src/domain/community/user/providers/UserProvider/UserProvider.graphql +++ b/src/domain/community/user/providers/UserProvider/UserProvider.graphql @@ -4,6 +4,10 @@ query UserProvider { ...UserDetails account { id + authorization { + id + myPrivileges + } } } } diff --git a/src/domain/community/user/providers/UserProvider/UserProvider.tsx b/src/domain/community/user/providers/UserProvider/UserProvider.tsx index f9c6e53421..715d075d3a 100644 --- a/src/domain/community/user/providers/UserProvider/UserProvider.tsx +++ b/src/domain/community/user/providers/UserProvider/UserProvider.tsx @@ -17,6 +17,7 @@ export interface UserContextValue { loadingMe: boolean; // Loading Authentication and Profile data. Once it's false that's enough for showing the page header and avatar. verified: boolean; isAuthenticated: boolean; + accountPrivileges: string[]; } const UserContext = React.createContext<UserContextValue>({ @@ -26,6 +27,7 @@ const UserContext = React.createContext<UserContextValue>({ loadingMe: true, verified: false, isAuthenticated: false, + accountPrivileges: [], }); const UserProvider: FC<{}> = ({ children }) => { @@ -73,6 +75,7 @@ const UserProvider: FC<{}> = ({ children }) => { loadingMe: loadingMeAndParentQueries, verified, isAuthenticated, + accountPrivileges: meData?.me.user?.account?.authorization?.myPrivileges ?? [], }), [userMetadata, loading, loadingMeAndParentQueries, verified, isAuthenticated] ); diff --git a/src/main/routing/urlBuilders.ts b/src/main/routing/urlBuilders.ts index dcc9c6f7d3..2640dc7795 100644 --- a/src/main/routing/urlBuilders.ts +++ b/src/main/routing/urlBuilders.ts @@ -71,3 +71,7 @@ export const buildInnovationHubUrl = (subdomain: string): string => { } } }; + +export const getAccountLink = (profileUrl?: string) => { + return profileUrl ? `${profileUrl}/settings/account` : ''; +}; diff --git a/src/main/topLevelPages/myDashboard/DashboardContext.tsx b/src/main/topLevelPages/myDashboard/DashboardContext.tsx index 93d01973ef..4138604fb3 100644 --- a/src/main/topLevelPages/myDashboard/DashboardContext.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardContext.tsx @@ -1,5 +1,6 @@ import React, { createContext, useState, useContext, ReactNode } from 'react'; import { getCachedView, setViewToCache } from './dashboardUtil'; +import { DashboardDialog } from './DashboardDialogs/DashboardDialogsProps'; const enum DashboardViews { ACTIVITY = 'ACTIVITY', @@ -9,6 +10,8 @@ const enum DashboardViews { interface DashboardContextProps { activityEnabled: boolean; setActivityEnabled: (item: boolean) => void; + openedDialog: DashboardDialog | undefined; + setOpenedDialog: (item: DashboardDialog | undefined) => void; } const DashboardContext = createContext<DashboardContextProps | undefined>(undefined); @@ -17,6 +20,7 @@ export const DashboardProvider = ({ children }: { children: ReactNode }) => { const cachedView = getCachedView(); const isActivityEnabled = cachedView === DashboardViews.ACTIVITY; const [activityEnabled, setEnabled] = useState<boolean>(isActivityEnabled); + const [openedDialog, setOpenedDialog] = useState<DashboardDialog | undefined>(undefined); const setActivityEnabled = (val: boolean) => { setViewToCache(val ? DashboardViews.ACTIVITY : DashboardViews.SPACES); @@ -24,7 +28,9 @@ export const DashboardProvider = ({ children }: { children: ReactNode }) => { }; return ( - <DashboardContext.Provider value={{ activityEnabled, setActivityEnabled }}>{children}</DashboardContext.Provider> + <DashboardContext.Provider value={{ activityEnabled, setActivityEnabled, openedDialog, setOpenedDialog }}> + {children} + </DashboardContext.Provider> ); }; diff --git a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx new file mode 100644 index 0000000000..41d864cb2b --- /dev/null +++ b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx @@ -0,0 +1,18 @@ +import { DialogContent } from '@mui/material'; +import DialogHeader from '../../../../core/ui/dialog/DialogHeader'; +import DialogWithGrid from '../../../../core/ui/dialog/DialogWithGrid'; +import { useDashboardContext } from '../DashboardContext'; +import { DashboardDialog } from './DashboardDialogsProps'; + +export const DashboardDialogs = () => { + const { openedDialog, setOpenedDialog } = useDashboardContext(); + + return ( + <> + <DialogWithGrid open={openedDialog === DashboardDialog.TipsAndTricks}> + <DialogHeader onClose={() => setOpenedDialog(undefined)}>Tips and Tricks</DialogHeader> + <DialogContent>Dialog content</DialogContent> + </DialogWithGrid> + </> + ); +}; diff --git a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogsProps.ts b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogsProps.ts new file mode 100644 index 0000000000..e1523666f4 --- /dev/null +++ b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogsProps.ts @@ -0,0 +1,5 @@ +export const enum DashboardDialog { + TipsAndTricks = 'tips-and-tricks', + MyActivity = 'my-activity', + MySpaceActivity = 'my-space-activity', +} diff --git a/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx b/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx index 33b5d72267..f76998b94e 100644 --- a/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx @@ -1,33 +1,93 @@ -import { FormControlLabel, Switch } from '@mui/material'; +import React from 'react'; +import { Divider, FormControlLabel, List, ListItem, ListItemButton, Switch } from '@mui/material'; import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; -import { DashboardMenuProps } from './dashboardMenuTypes'; +import { DashboardMenuProps, MenuOptionProps } from './dashboardMenuTypes'; import { useDashboardContext } from '../DashboardContext'; - -/* TODO: extrat in dialogs */ -/* - <TipsAndTricks /> - <InnovationLibraryBlock /> - <NewMembershipsBlock hiddenIfEmpty /> - <MyLatestContributions /> - <RecentForumMessages /> -*/ +import { Caption } from '../../../../core/ui/typography'; +import { gutters } from '../../../../core/ui/grid/utils'; +import { useTranslation } from 'react-i18next'; +import TranslationKey from '../../../../core/i18n/utils/TranslationKey'; +import RouterLink from '../../../../core/ui/link/RouterLink'; +import { useHomeMenuItems } from './useHomeMenuItems'; +import { DashboardDialog } from '../DashboardDialogs/DashboardDialogsProps'; +import { + PendingMembershipsDialogType, + usePendingMembershipsDialog, +} from '../../../../domain/community/pendingMembership/PendingMembershipsDialogContext'; export const DashboardMenu = ({ compact = false }: DashboardMenuProps) => { - const context = useDashboardContext(); + const { t } = useTranslation(); + const { activityEnabled, setActivityEnabled, setOpenedDialog } = useDashboardContext(); + const { items, loading: itemsConfigLoading } = useHomeMenuItems(); + const { setOpenDialog } = usePendingMembershipsDialog(); const changeView = (event: React.ChangeEvent<HTMLInputElement>) => { - context.setActivityEnabled(event.target.checked); + setActivityEnabled(event.target.checked); + }; + + const getTranslationByKey = (key: string) => t(`${key}` as TranslationKey, { defaultValue: key }); + + const openDialog = (dialog: DashboardDialog | undefined) => () => setOpenedDialog(dialog); + + const getItemContent = (item: MenuOptionProps) => ( + <> + {item.icon && <item.icon fontSize="small" sx={{ color: 'neutral.light' }} />} + <Caption paddingLeft={gutters()}>{getTranslationByKey(item.label)}</Caption> + </> + ); + + const renderMenuItem = (item: MenuOptionProps, index: number) => { + switch (item.type) { + case 'invites': + return ( + <ListItemButton + key={index} + sx={{ paddingY: gutters(0.75) }} + onClick={() => setOpenDialog({ type: PendingMembershipsDialogType.PendingMembershipsList })} + > + {getItemContent(item)} + </ListItemButton> + ); + case 'link': + return ( + <ListItemButton key={index} component={RouterLink} to={item.to ?? ''} sx={{ paddingY: gutters(0.75) }}> + {getItemContent(item)} + </ListItemButton> + ); + case 'dialog': + return ( + <ListItemButton key={index} sx={{ paddingY: gutters(0.75) }} onClick={openDialog(item.dialog)}> + {getItemContent(item)} + </ListItemButton> + ); + case 'switch': + return ( + <ListItem key={index} sx={{ paddingY: gutters(0.75) }}> + <FormControlLabel + key={index} + label={<Caption paddingLeft={gutters(0.5)}>{getTranslationByKey(item.label)}</Caption>} + control={<Switch size="small" name="view" checked={activityEnabled} onChange={changeView} />} + /> + </ListItem> + ); + case 'divider': + return <Divider key={index} />; + default: + return null; + } }; + if (itemsConfigLoading) { + return null; + } + return ( - <PageContentBlock> - Menu - {!compact && ( - <FormControlLabel - label="Activity View" - control={<Switch name={'view'} checked={context.activityEnabled} onChange={changeView} />} - /> - )} + <PageContentBlock disablePadding> + <List disablePadding> + {items + .filter(item => item.isVisible(activityEnabled, compact)) + .map((item, index) => renderMenuItem(item, index))} + </List> </PageContentBlock> ); }; diff --git a/src/main/topLevelPages/myDashboard/DashboardMenu/dashboardMenuTypes.ts b/src/main/topLevelPages/myDashboard/DashboardMenu/dashboardMenuTypes.ts index 7d053744ee..83795270a5 100644 --- a/src/main/topLevelPages/myDashboard/DashboardMenu/dashboardMenuTypes.ts +++ b/src/main/topLevelPages/myDashboard/DashboardMenu/dashboardMenuTypes.ts @@ -1,3 +1,18 @@ +import { ComponentType } from 'react'; +import { SvgIconProps } from '@mui/material'; +import { DashboardDialog } from '../DashboardDialogs/DashboardDialogsProps'; + export type DashboardMenuProps = { compact?: boolean; }; + +type MenuOptionType = 'invites' | 'link' | 'dialog' | 'switch' | 'divider'; + +export interface MenuOptionProps { + label: string; + type: MenuOptionType; + icon?: ComponentType<SvgIconProps>; + to?: string; + isVisible: (viewEnabled: boolean, compactMode: boolean) => boolean; + dialog?: DashboardDialog; +} diff --git a/src/main/topLevelPages/myDashboard/DashboardMenu/useHomeMenuItems.ts b/src/main/topLevelPages/myDashboard/DashboardMenu/useHomeMenuItems.ts new file mode 100644 index 0000000000..ad5746453d --- /dev/null +++ b/src/main/topLevelPages/myDashboard/DashboardMenu/useHomeMenuItems.ts @@ -0,0 +1,89 @@ +import MailOutlineOutlinedIcon from '@mui/icons-material/MailOutlineOutlined'; +import EmojiObjectsOutlinedIcon from '@mui/icons-material/EmojiObjectsOutlined'; +import LocalOfferOutlinedIcon from '@mui/icons-material/LocalOfferOutlined'; +import RocketLaunchOutlinedIcon from '@mui/icons-material/RocketLaunchOutlined'; +import DrawOutlinedIcon from '@mui/icons-material/DrawOutlined'; +import HistoryOutlinedIcon from '@mui/icons-material/HistoryOutlined'; +import { useUserContext } from '../../../../domain/community/user'; +import { getAccountLink } from '../../../routing/urlBuilders'; +import { AuthorizationPrivilege } from '../../../../core/apollo/generated/graphql-schema'; +import { TopLevelRoutePath } from '../../../routing/TopLevelRoutePath'; +import { useTranslation } from 'react-i18next'; +import { MenuOptionProps } from './dashboardMenuTypes'; +import { DashboardDialog } from '../DashboardDialogs/DashboardDialogsProps'; +import { useMemo } from 'react'; + +export const useHomeMenuItems = () => { + const { t } = useTranslation(); + const { user, accountPrivileges, loading } = useUserContext(); + + let createLink = t('pages.home.sections.startingSpace.url'); + + if (accountPrivileges.includes(AuthorizationPrivilege.CreateSpace)) { + createLink = `/${TopLevelRoutePath.CreateSpace}`; + } + + const dashboardMenuItems: MenuOptionProps[] = useMemo( + () => [ + { + label: 'pages.home.mainNavigation.invitations', + type: 'invites', + icon: MailOutlineOutlinedIcon, + isVisible: (_, __) => true, + }, + { + label: 'pages.home.mainNavigation.myLatestActivity', + type: 'dialog', + icon: DrawOutlinedIcon, + isVisible: (viewEnabled, compactMode) => !compactMode && !viewEnabled, + dialog: DashboardDialog.MyActivity, + }, + { + label: 'pages.home.mainNavigation.myLatestSpacesActivity', + type: 'dialog', + icon: HistoryOutlinedIcon, + isVisible: (viewEnabled, compactMode) => !compactMode && !viewEnabled, + dialog: DashboardDialog.MySpaceActivity, + }, + { + label: '', + type: 'divider', + isVisible: (_, __) => true, + }, + { + label: 'pages.home.mainNavigation.tipsAndTricks', + type: 'dialog', + icon: EmojiObjectsOutlinedIcon, + isVisible: (_, __) => true, + dialog: DashboardDialog.TipsAndTricks, + }, + { + label: 'pages.home.mainNavigation.myAccount', + type: 'link', + to: getAccountLink(user?.user.profile?.url), + icon: LocalOfferOutlinedIcon, + isVisible: (_, __) => true, + }, + { + label: 'pages.home.mainNavigation.createSpace', + type: 'link', + to: createLink, + icon: RocketLaunchOutlinedIcon, + isVisible: (_, __) => true, + }, + { + label: '', + type: 'divider', + isVisible: (_, compactMode) => !compactMode, + }, + { + label: 'pages.home.mainNavigation.activityView', + type: 'switch', + isVisible: (_, compactMode) => !compactMode, + }, + ], + [user, createLink] + ); + + return { items: dashboardMenuItems, loading }; +}; diff --git a/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx b/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx index 4e6ae9b65f..86cd7f8417 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx @@ -9,6 +9,7 @@ import ContentColumn from '../../../core/ui/content/ContentColumn'; import DashboardActivity from './DashboardWithMemberships/DashboardActivity'; import DashboardSpaces from './DashboardWithMemberships/DashboardSpaces'; import { useDashboardContext } from './DashboardContext'; +import { DashboardDialogs } from './DashboardDialogs/DashboardDialogs'; const MyDashboardWithMemberships = () => { const { activityEnabled } = useDashboardContext(); @@ -26,6 +27,7 @@ const MyDashboardWithMemberships = () => { <CampaignBlock /> {activityEnabled ? <DashboardActivity /> : <DashboardSpaces />} </ContentColumn> + <DashboardDialogs /> </PageContentColumn> ); }; diff --git a/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx b/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx index 07d4a35079..976f447dc8 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx @@ -9,6 +9,7 @@ import { DashboardMenu } from './DashboardMenu/DashboardMenu'; import ExploreSpaces from './ExploreSpaces/ExploreSpaces'; import PageContentBlock from '../../../core/ui/content/PageContentBlock'; import { InvitationsBlock } from './InvitationsBlock/InvitationsBlock'; +import { DashboardDialogs } from './DashboardDialogs/DashboardDialogs'; const MyDashboardWithoutMemberships = () => { const { data } = useLatestReleaseDiscussionQuery({ @@ -29,6 +30,7 @@ const MyDashboardWithoutMemberships = () => { </PageContentBlock> {/* TODO: implement create space btn component */} </ContentColumn> + <DashboardDialogs /> </PageContentColumn> ); }; diff --git a/src/main/topLevelPages/myDashboard/myMemberships/MyMembershipsDialog.tsx b/src/main/topLevelPages/myDashboard/myMemberships/MyMembershipsDialog.tsx index 0df74039b5..dea71d0c9b 100644 --- a/src/main/topLevelPages/myDashboard/myMemberships/MyMembershipsDialog.tsx +++ b/src/main/topLevelPages/myDashboard/myMemberships/MyMembershipsDialog.tsx @@ -60,7 +60,7 @@ const MyMembershipsDialog = ({ open, onClose }: MyJourneysDialogProps) => { {loading && <Loading />} <Gutters disablePadding disableGap> {data?.me.spaceMembershipsHierarchical?.map(spaceMembership => ( - <ExpandableSpaceTree membership={spaceMembership} /> + <ExpandableSpaceTree key={spaceMembership.id} membership={spaceMembership} /> ))} <Caption alignSelf="center" paddingTop={gutters(0.5)}> <Trans From 21b650bdb97b65f4d732ff0b0906c00d363788d0 Mon Sep 17 00:00:00 2001 From: bobbykolev <bobbykolev@abv.bg> Date: Tue, 29 Oct 2024 11:25:27 +0200 Subject: [PATCH 2/8] TipsAndTricks dialog --- .../DashboardDialogs/DashboardDialogs.tsx | 11 +++++++++-- .../myDashboard/tipsAndTricks/TipsAndTricks.tsx | 17 ++++------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx index 41d864cb2b..37931d4ec8 100644 --- a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx @@ -3,15 +3,22 @@ import DialogHeader from '../../../../core/ui/dialog/DialogHeader'; import DialogWithGrid from '../../../../core/ui/dialog/DialogWithGrid'; import { useDashboardContext } from '../DashboardContext'; import { DashboardDialog } from './DashboardDialogsProps'; +import { TipsAndTricks } from '../tipsAndTricks/TipsAndTricks'; +import { useTranslation } from 'react-i18next'; export const DashboardDialogs = () => { + const { t } = useTranslation(); const { openedDialog, setOpenedDialog } = useDashboardContext(); return ( <> <DialogWithGrid open={openedDialog === DashboardDialog.TipsAndTricks}> - <DialogHeader onClose={() => setOpenedDialog(undefined)}>Tips and Tricks</DialogHeader> - <DialogContent>Dialog content</DialogContent> + <DialogHeader onClose={() => setOpenedDialog(undefined)}> + {t('pages.home.sections.tipsAndTricks.title')} + </DialogHeader> + <DialogContent> + <TipsAndTricks /> + </DialogContent> </DialogWithGrid> </> ); diff --git a/src/main/topLevelPages/myDashboard/tipsAndTricks/TipsAndTricks.tsx b/src/main/topLevelPages/myDashboard/tipsAndTricks/TipsAndTricks.tsx index 7a86336085..88fe04b832 100644 --- a/src/main/topLevelPages/myDashboard/tipsAndTricks/TipsAndTricks.tsx +++ b/src/main/topLevelPages/myDashboard/tipsAndTricks/TipsAndTricks.tsx @@ -1,25 +1,18 @@ -import { FC } from 'react'; -import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; import { useTranslation } from 'react-i18next'; -import PageContentBlockHeader from '../../../../core/ui/content/PageContentBlockHeader'; import SeeMore from '../../../../core/ui/content/SeeMore'; import BadgeCardView from '../../../../core/ui/list/BadgeCardView'; import Avatar from '../../../../core/ui/avatar/Avatar'; import RouterLink from '../../../../core/ui/link/RouterLink'; import { Caption } from '../../../../core/ui/typography'; +import Gutters from '../../../../core/ui/grid/Gutters'; -interface TipsAndTricksProps { - halfWidth?: boolean; -} - -const TipsAndTricks: FC<TipsAndTricksProps> = ({ halfWidth }) => { +export const TipsAndTricks = () => { const { t } = useTranslation(); const items = t('pages.home.sections.tipsAndTricks.items', { returnObjects: true }); return ( - <PageContentBlock halfWidth={halfWidth} sx={{ justifyContent: 'space-around' }}> - <PageContentBlockHeader title={t('pages.home.sections.tipsAndTricks.title')} /> + <Gutters disablePadding> {items.map((item, index) => ( <BadgeCardView key={index} @@ -36,8 +29,6 @@ const TipsAndTricks: FC<TipsAndTricksProps> = ({ halfWidth }) => { </BadgeCardView> ))} <SeeMore label="pages.home.sections.tipsAndTricks.findMore" to="/forum" /> - </PageContentBlock> + </Gutters> ); }; - -export default TipsAndTricks; From 90373e2fef4def2c226f968fd1e780eda6007502 Mon Sep 17 00:00:00 2001 From: bobbykolev <bobbykolev@abv.bg> Date: Tue, 29 Oct 2024 14:20:36 +0200 Subject: [PATCH 3/8] Activity dialogs + space filter on My Activity + dashboard activity blocks --- src/core/i18n/en/translation.en.json | 4 +- .../DashboardDialogs/DashboardDialogs.tsx | 22 ++++++++ .../DashboardActivity.tsx | 14 ++++- .../LatestContributions.tsx | 23 ++------ .../LatestContributionsProps.ts | 14 +++++ .../MyLatestContributions.tsx | 54 +++++++++++++++---- 6 files changed, 98 insertions(+), 33 deletions(-) create mode 100644 src/main/topLevelPages/myDashboard/latestContributions/LatestContributionsProps.ts diff --git a/src/core/i18n/en/translation.en.json b/src/core/i18n/en/translation.en.json index 2b5bbd22ca..38cc41fcfa 100644 --- a/src/core/i18n/en/translation.en.json +++ b/src/core/i18n/en/translation.en.json @@ -2173,7 +2173,7 @@ }, "sections": { "latestContributions": { - "title": "Latest Contributions in my Spaces", + "title": "Latest Activity in my Spaces", "filter": { "space": { "label": "Space:", @@ -2186,7 +2186,7 @@ } }, "myLatestContributions": { - "title": "My Latest Contributions", + "title": "My Latest Activity", "card": { "journey": "in: <journeyicon /> {{journey}}" }, diff --git a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx index 37931d4ec8..6ad4f216e9 100644 --- a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx @@ -5,11 +5,17 @@ import { useDashboardContext } from '../DashboardContext'; import { DashboardDialog } from './DashboardDialogsProps'; import { TipsAndTricks } from '../tipsAndTricks/TipsAndTricks'; import { useTranslation } from 'react-i18next'; +import MyLatestContributions from '../latestContributions/myLatestContributions/MyLatestContributions'; +import LatestContributions from '../latestContributions/LatestContributions'; +import { useLatestContributionsSpacesFlatQuery } from '../../../../core/apollo/generated/apollo-hooks'; export const DashboardDialogs = () => { const { t } = useTranslation(); const { openedDialog, setOpenedDialog } = useDashboardContext(); + const { data: spacesData } = useLatestContributionsSpacesFlatQuery(); + const flatSpacesWithMemberships = spacesData?.me.spaceMembershipsFlat.map(membership => membership.space); + return ( <> <DialogWithGrid open={openedDialog === DashboardDialog.TipsAndTricks}> @@ -20,6 +26,22 @@ export const DashboardDialogs = () => { <TipsAndTricks /> </DialogContent> </DialogWithGrid> + <DialogWithGrid open={openedDialog === DashboardDialog.MyActivity}> + <DialogHeader onClose={() => setOpenedDialog(undefined)}> + {t('pages.home.sections.myLatestContributions.title')} + </DialogHeader> + <DialogContent> + <MyLatestContributions spaceMemberships={flatSpacesWithMemberships} /> + </DialogContent> + </DialogWithGrid> + <DialogWithGrid open={openedDialog === DashboardDialog.MySpaceActivity}> + <DialogHeader onClose={() => setOpenedDialog(undefined)}> + {t('pages.home.sections.latestContributions.title')} + </DialogHeader> + <DialogContent> + <LatestContributions spaceMemberships={flatSpacesWithMemberships} /> + </DialogContent> + </DialogWithGrid> </> ); }; diff --git a/src/main/topLevelPages/myDashboard/DashboardWithMemberships/DashboardActivity.tsx b/src/main/topLevelPages/myDashboard/DashboardWithMemberships/DashboardActivity.tsx index 7cf5e06d3a..b7b8ecd45d 100644 --- a/src/main/topLevelPages/myDashboard/DashboardWithMemberships/DashboardActivity.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardWithMemberships/DashboardActivity.tsx @@ -6,8 +6,12 @@ import MyMembershipsDialog from '../myMemberships/MyMembershipsDialog'; import { useLatestContributionsSpacesFlatQuery } from '../../../../core/apollo/generated/apollo-hooks'; import { useColumns } from '../../../../core/ui/grid/GridContext'; import PageContentColumn from '../../../../core/ui/content/PageContentColumn'; +import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; +import PageContentBlockHeader from '../../../../core/ui/content/PageContentBlockHeader'; +import { useTranslation } from 'react-i18next'; const DashboardActivity = () => { + const { t } = useTranslation(); const [isMyMembershipsDialogOpen, setIsMyMembershipsDialogOpen] = useState(false); const { data: spacesData } = useLatestContributionsSpacesFlatQuery(); const flatSpacesWithMemberships = spacesData?.me.spaceMembershipsFlat.map(membership => membership.space); @@ -18,10 +22,16 @@ const DashboardActivity = () => { <> <RecentSpacesList onSeeMore={() => setIsMyMembershipsDialogOpen(true)} /> <PageContentColumn columns={columns / 2}> - <LatestContributions spaceMemberships={flatSpacesWithMemberships} /> + <PageContentBlock> + <PageContentBlockHeader title={t('pages.home.sections.latestContributions.title')} /> + <LatestContributions spaceMemberships={flatSpacesWithMemberships} /> + </PageContentBlock> </PageContentColumn> <PageContentColumn columns={columns / 2}> - <MyLatestContributions /> + <PageContentBlock> + <PageContentBlockHeader title={t('pages.home.sections.myLatestContributions.title')} /> + <MyLatestContributions spaceMemberships={flatSpacesWithMemberships} /> + </PageContentBlock> </PageContentColumn> <MyMembershipsDialog open={isMyMembershipsDialogOpen} onClose={() => setIsMyMembershipsDialogOpen(false)} /> </> diff --git a/src/main/topLevelPages/myDashboard/latestContributions/LatestContributions.tsx b/src/main/topLevelPages/myDashboard/latestContributions/LatestContributions.tsx index fc8d604475..2fa7b95afc 100644 --- a/src/main/topLevelPages/myDashboard/latestContributions/LatestContributions.tsx +++ b/src/main/topLevelPages/myDashboard/latestContributions/LatestContributions.tsx @@ -1,6 +1,4 @@ -import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; import { useTranslation } from 'react-i18next'; -import PageContentBlockHeader from '../../../../core/ui/content/PageContentBlockHeader'; import ScrollerWithGradient from '../../../../core/ui/overflow/ScrollerWithGradient'; import { useLatestContributionsQuery } from '../../../../core/apollo/generated/apollo-hooks'; import usePaginatedQuery from '../../../../domain/shared/pagination/usePaginatedQuery'; @@ -21,10 +19,8 @@ import { SelectOption } from '@mui/base'; import useLazyLoading from '../../../../domain/shared/pagination/useLazyLoading'; import BadgeCardView from '../../../../core/ui/list/BadgeCardView'; import { gutters } from '../../../../core/ui/grid/utils'; -import { Identifiable } from '../../../../core/utils/Identifiable'; - -const ROLE_OPTION_ALL = 'ROLE_OPTION_ALL'; -const SPACE_OPTION_ALL = 'SPACE_OPTION_ALL'; +import Gutters from '../../../../core/ui/grid/Gutters'; +import { LatestContributionsProps, ROLE_OPTION_ALL, SPACE_OPTION_ALL } from './LatestContributionsProps'; const SELECTABLE_ROLES = [ActivityFeedRoles.Member, ActivityFeedRoles.Admin, ActivityFeedRoles.Lead] as const; @@ -45,16 +41,6 @@ const Loader = forwardRef((props, ref) => { ); }); -interface LatestContributionsProps { - spaceMemberships: - | (Identifiable & { - profile: { - displayName: string; - }; - })[] - | undefined; -} - const LatestContributions = ({ spaceMemberships }: LatestContributionsProps) => { const { t } = useTranslation(); const isMobile = useMediaQuery((theme: Theme) => theme.breakpoints.down('lg')); @@ -127,8 +113,7 @@ const LatestContributions = ({ spaceMemberships }: LatestContributionsProps) => }, [t]); return ( - <PageContentBlock sx={{ flexGrow: 1, flexShrink: 1, flexBasis: isMobile ? gutters(30) : 0 }}> - <PageContentBlockHeader title={t('pages.home.sections.latestContributions.title')} /> + <Gutters disablePadding disableGap sx={{ flexGrow: 1, flexShrink: 1, flexBasis: isMobile ? gutters(30) : 0 }}> <Box display="flex" justifyContent="end" alignItems="center"> <SeamlessSelect value={filter.space} @@ -157,7 +142,7 @@ const LatestContributions = ({ spaceMemberships }: LatestContributionsProps) => {loader} </Box> </ScrollerWithGradient> - </PageContentBlock> + </Gutters> ); }; diff --git a/src/main/topLevelPages/myDashboard/latestContributions/LatestContributionsProps.ts b/src/main/topLevelPages/myDashboard/latestContributions/LatestContributionsProps.ts new file mode 100644 index 0000000000..50f6314a04 --- /dev/null +++ b/src/main/topLevelPages/myDashboard/latestContributions/LatestContributionsProps.ts @@ -0,0 +1,14 @@ +import { Identifiable } from '../../../../core/utils/Identifiable'; + +export const ROLE_OPTION_ALL = 'ROLE_OPTION_ALL'; +export const SPACE_OPTION_ALL = 'SPACE_OPTION_ALL'; + +export interface LatestContributionsProps { + spaceMemberships: + | (Identifiable & { + profile: { + displayName: string; + }; + })[] + | undefined; +} diff --git a/src/main/topLevelPages/myDashboard/latestContributions/myLatestContributions/MyLatestContributions.tsx b/src/main/topLevelPages/myDashboard/latestContributions/myLatestContributions/MyLatestContributions.tsx index c21e2658eb..e7b0d98742 100644 --- a/src/main/topLevelPages/myDashboard/latestContributions/myLatestContributions/MyLatestContributions.tsx +++ b/src/main/topLevelPages/myDashboard/latestContributions/myLatestContributions/MyLatestContributions.tsx @@ -1,7 +1,5 @@ -import { useMemo } from 'react'; -import PageContentBlock from '../../../../../core/ui/content/PageContentBlock'; +import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import PageContentBlockHeader from '../../../../../core/ui/content/PageContentBlockHeader'; import ScrollerWithGradient from '../../../../../core/ui/overflow/ScrollerWithGradient'; import { useLatestContributionsGroupedQuery } from '../../../../../core/apollo/generated/apollo-hooks'; import { @@ -9,15 +7,18 @@ import { ActivityLogCalloutWhiteboardContentModifiedFragment, ActivityLogCalloutWhiteboardCreatedFragment, } from '../../../../../core/apollo/generated/graphql-schema'; -import { Box } from '@mui/material'; +import { Box, SelectChangeEvent } from '@mui/material'; import { ActivityLogResultType, ActivityViewChooser, } from '../../../../../domain/collaboration/activity/ActivityLog/ActivityComponent'; import { CaptionSmall } from '../../../../../core/ui/typography/components'; import defaultJourneyAvatar from '../../../../../domain/journey/defaultVisuals/Avatar.jpg'; +import { LatestContributionsProps, SPACE_OPTION_ALL } from '../LatestContributionsProps'; +import { SelectOption } from '@mui/base'; +import SeamlessSelect from '../../../../../core/ui/forms/select/SeamlessSelect'; -const MY_LATEST_CONTRIBUTIONS_COUNT = 4; +const MY_LATEST_CONTRIBUTIONS_COUNT = 20; const ACTIVITY_TYPES = [ // Callout-related activities only @@ -30,15 +31,26 @@ const ACTIVITY_TYPES = [ ActivityEventType.DiscussionComment, ]; -const MyLatestContributions = () => { +const MyLatestContributions = ({ spaceMemberships }: LatestContributionsProps) => { const { t } = useTranslation(); + const [filter, setFilter] = useState<{ + space: string; + }>({ + space: SPACE_OPTION_ALL, + }); + + const handleSpaceSelect = (event: SelectChangeEvent<unknown>) => + setFilter({ + space: event.target.value as string | typeof SPACE_OPTION_ALL, + }); const { data } = useLatestContributionsGroupedQuery({ variables: { filter: { myActivity: true, types: ACTIVITY_TYPES, - limit: MY_LATEST_CONTRIBUTIONS_COUNT + 3, // Fetch 3 extra in case that last 8 events are whiteboard creation and modification + limit: MY_LATEST_CONTRIBUTIONS_COUNT, + spaceIds: filter.space === SPACE_OPTION_ALL ? undefined : [filter.space], }, }, }); @@ -59,9 +71,31 @@ const MyLatestContributions = () => { return filteredActivities?.slice(0, MY_LATEST_CONTRIBUTIONS_COUNT); }, [data?.activityFeedGrouped]); + const spaceOptions = useMemo(() => { + const spaces: Partial<SelectOption<string | typeof SPACE_OPTION_ALL>>[] = + spaceMemberships?.map(space => ({ + value: space.id, + label: space.profile.displayName, + })) ?? []; + + spaces?.unshift({ + value: SPACE_OPTION_ALL, + label: t('pages.home.sections.latestContributions.filter.space.all'), + }); + + return spaces; + }, [spaceMemberships, t]); + return ( - <PageContentBlock columns={4}> - <PageContentBlockHeader title={t('pages.home.sections.myLatestContributions.title')} /> + <> + <Box display="flex" justifyContent="end" alignItems="center"> + <SeamlessSelect + value={filter.space} + options={spaceOptions} + label={t('pages.home.sections.latestContributions.filter.space.label')} + onChange={handleSpaceSelect} + /> + </Box> <ScrollerWithGradient> <Box padding={1}> {activities && activities.length > 0 ? ( @@ -79,7 +113,7 @@ const MyLatestContributions = () => { )} </Box> </ScrollerWithGradient> - </PageContentBlock> + </> ); }; From 66cc4dd0833c33338a384008e42cf49cdd335152 Mon Sep 17 00:00:00 2001 From: bobbykolev <bobbykolev@abv.bg> Date: Tue, 29 Oct 2024 14:55:18 +0200 Subject: [PATCH 4/8] Pending Invitations BadgeCounter --- src/core/apollo/generated/apollo-hooks.ts | 61 +++++++++++++++++++ src/core/apollo/generated/graphql-schema.ts | 11 ++++ .../DashboardMenu/DashboardMenu.tsx | 24 +++++++- .../PendingInvitationsCount.graphql | 7 +++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/main/topLevelPages/myDashboard/DashboardMenu/PendingInvitationsCount.graphql diff --git a/src/core/apollo/generated/apollo-hooks.ts b/src/core/apollo/generated/apollo-hooks.ts index 4fe349254e..bb498978cf 100644 --- a/src/core/apollo/generated/apollo-hooks.ts +++ b/src/core/apollo/generated/apollo-hooks.ts @@ -21773,6 +21773,67 @@ export function refetchInnovationLibraryQuery(variables?: SchemaTypes.Innovation return { query: InnovationLibraryDocument, variables: variables }; } +export const PendingInvitationsCountDocument = gql` + query PendingInvitationsCount { + me { + communityInvitations(states: ["invited"]) { + id + } + } + } +`; + +/** + * __usePendingInvitationsCountQuery__ + * + * To run a query within a React component, call `usePendingInvitationsCountQuery` and pass it any options that fit your needs. + * When your component renders, `usePendingInvitationsCountQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = usePendingInvitationsCountQuery({ + * variables: { + * }, + * }); + */ +export function usePendingInvitationsCountQuery( + baseOptions?: Apollo.QueryHookOptions< + SchemaTypes.PendingInvitationsCountQuery, + SchemaTypes.PendingInvitationsCountQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useQuery<SchemaTypes.PendingInvitationsCountQuery, SchemaTypes.PendingInvitationsCountQueryVariables>( + PendingInvitationsCountDocument, + options + ); +} + +export function usePendingInvitationsCountLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + SchemaTypes.PendingInvitationsCountQuery, + SchemaTypes.PendingInvitationsCountQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useLazyQuery< + SchemaTypes.PendingInvitationsCountQuery, + SchemaTypes.PendingInvitationsCountQueryVariables + >(PendingInvitationsCountDocument, options); +} + +export type PendingInvitationsCountQueryHookResult = ReturnType<typeof usePendingInvitationsCountQuery>; +export type PendingInvitationsCountLazyQueryHookResult = ReturnType<typeof usePendingInvitationsCountLazyQuery>; +export type PendingInvitationsCountQueryResult = Apollo.QueryResult< + SchemaTypes.PendingInvitationsCountQuery, + SchemaTypes.PendingInvitationsCountQueryVariables +>; +export function refetchPendingInvitationsCountQuery(variables?: SchemaTypes.PendingInvitationsCountQueryVariables) { + return { query: PendingInvitationsCountDocument, variables: variables }; +} + export const ExploreSpacesSearchDocument = gql` query ExploreSpacesSearch($searchData: SearchInput!) { search(searchData: $searchData) { diff --git a/src/core/apollo/generated/graphql-schema.ts b/src/core/apollo/generated/graphql-schema.ts index cf80bfaccb..fb098c0161 100644 --- a/src/core/apollo/generated/graphql-schema.ts +++ b/src/core/apollo/generated/graphql-schema.ts @@ -5344,6 +5344,7 @@ export enum SearchResultType { Organization = 'ORGANIZATION', Post = 'POST', Space = 'SPACE', + Subspace = 'SUBSPACE', User = 'USER', Usergroup = 'USERGROUP', Whiteboard = 'WHITEBOARD', @@ -28185,6 +28186,16 @@ export type LibraryTemplatesFragment = { }>; }; +export type PendingInvitationsCountQueryVariables = Exact<{ [key: string]: never }>; + +export type PendingInvitationsCountQuery = { + __typename?: 'Query'; + me: { + __typename?: 'MeQueryResults'; + communityInvitations: Array<{ __typename?: 'CommunityInvitationResult'; id: string }>; + }; +}; + export type ExploreSpacesSearchQueryVariables = Exact<{ searchData: SearchInput; }>; diff --git a/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx b/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx index f76998b94e..ccff547ea3 100644 --- a/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Divider, FormControlLabel, List, ListItem, ListItemButton, Switch } from '@mui/material'; +import { Box, Divider, FormControlLabel, List, ListItem, ListItemButton, Switch } from '@mui/material'; import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; import { DashboardMenuProps, MenuOptionProps } from './dashboardMenuTypes'; import { useDashboardContext } from '../DashboardContext'; @@ -14,13 +14,29 @@ import { PendingMembershipsDialogType, usePendingMembershipsDialog, } from '../../../../domain/community/pendingMembership/PendingMembershipsDialogContext'; +import { usePendingInvitationsCountQuery } from '../../../../core/apollo/generated/apollo-hooks'; +import BadgeCounter from '../../../../core/ui/icon/BadgeCounter'; +/** + * DashboardMenu Component + * + * This component renders the home menu with various menu items by type. + * It uses the `useHomeMenuItems` hook to fetch and prepare the menu items, + * A special case is the 'invites' type, requiring a query for the count. + * + * @component + */ export const DashboardMenu = ({ compact = false }: DashboardMenuProps) => { const { t } = useTranslation(); const { activityEnabled, setActivityEnabled, setOpenedDialog } = useDashboardContext(); const { items, loading: itemsConfigLoading } = useHomeMenuItems(); const { setOpenDialog } = usePendingMembershipsDialog(); + const { data: invitesData } = usePendingInvitationsCountQuery({ + fetchPolicy: 'network-only', + }); + const pendingInvitationsCount = invitesData?.me?.communityInvitations?.length ?? 0; + const changeView = (event: React.ChangeEvent<HTMLInputElement>) => { setActivityEnabled(event.target.checked); }; @@ -46,6 +62,12 @@ export const DashboardMenu = ({ compact = false }: DashboardMenuProps) => { onClick={() => setOpenDialog({ type: PendingMembershipsDialogType.PendingMembershipsList })} > {getItemContent(item)} + {pendingInvitationsCount > 0 && ( + <> + <Box sx={{ flexGrow: 1 }} /> + <BadgeCounter count={pendingInvitationsCount} size="small" /> + </> + )} </ListItemButton> ); case 'link': diff --git a/src/main/topLevelPages/myDashboard/DashboardMenu/PendingInvitationsCount.graphql b/src/main/topLevelPages/myDashboard/DashboardMenu/PendingInvitationsCount.graphql new file mode 100644 index 0000000000..b4044bfd71 --- /dev/null +++ b/src/main/topLevelPages/myDashboard/DashboardMenu/PendingInvitationsCount.graphql @@ -0,0 +1,7 @@ +query PendingInvitationsCount { + me { + communityInvitations(states: ["invited"]) { + id + } + } +} \ No newline at end of file From d6fa458beef630adc86a1e28f604c35a0f468309 Mon Sep 17 00:00:00 2001 From: bobbykolev <bobbykolev@abv.bg> Date: Tue, 29 Oct 2024 15:32:30 +0200 Subject: [PATCH 5/8] Loading and alignment of Activity components --- .../LatestContributions.tsx | 65 +++++++++++-------- .../MyLatestContributions.tsx | 52 +++++++++------ 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/src/main/topLevelPages/myDashboard/latestContributions/LatestContributions.tsx b/src/main/topLevelPages/myDashboard/latestContributions/LatestContributions.tsx index 2fa7b95afc..ba8296be6c 100644 --- a/src/main/topLevelPages/myDashboard/latestContributions/LatestContributions.tsx +++ b/src/main/topLevelPages/myDashboard/latestContributions/LatestContributions.tsx @@ -21,6 +21,7 @@ import BadgeCardView from '../../../../core/ui/list/BadgeCardView'; import { gutters } from '../../../../core/ui/grid/utils'; import Gutters from '../../../../core/ui/grid/Gutters'; import { LatestContributionsProps, ROLE_OPTION_ALL, SPACE_OPTION_ALL } from './LatestContributionsProps'; +import Loading from '../../../../core/ui/loading/Loading'; const SELECTABLE_ROLES = [ActivityFeedRoles.Member, ActivityFeedRoles.Admin, ActivityFeedRoles.Lead] as const; @@ -112,36 +113,44 @@ const LatestContributions = ({ spaceMemberships }: LatestContributionsProps) => return options; }, [t]); + const renderFilters = () => ( + <Box display="flex" justifyContent="end" alignItems="center"> + <SeamlessSelect + value={filter.space} + options={spaceOptions} + label={t('pages.home.sections.latestContributions.filter.space.label')} + onChange={handleSpaceSelect} + /> + <SeamlessSelect + value={filter.role} + options={roleOptions} + label={t('pages.home.sections.latestContributions.filter.role.label')} + onChange={handleRoleSelect} + /> + </Box> + ); + return ( <Gutters disablePadding disableGap sx={{ flexGrow: 1, flexShrink: 1, flexBasis: isMobile ? gutters(30) : 0 }}> - <Box display="flex" justifyContent="end" alignItems="center"> - <SeamlessSelect - value={filter.space} - options={spaceOptions} - label={t('pages.home.sections.latestContributions.filter.space.label')} - onChange={handleSpaceSelect} - /> - <SeamlessSelect - value={filter.role} - options={roleOptions} - label={t('pages.home.sections.latestContributions.filter.role.label')} - onChange={handleRoleSelect} - /> - </Box> - <ScrollerWithGradient> - <Box padding={1}> - {data?.activityFeed.activityFeed.map(activity => { - return ( - <ActivityViewChooser - key={activity.id} - activity={activity as ActivityLogResultType} - avatarUrl={activity.triggeredBy.profile.avatar?.uri} - /> - ); - })} - {loader} - </Box> - </ScrollerWithGradient> + {renderFilters()} + {!data && loading ? ( + <Loading /> + ) : ( + <ScrollerWithGradient> + <Box padding={gutters(0.5)}> + {data?.activityFeed.activityFeed.map(activity => { + return ( + <ActivityViewChooser + key={activity.id} + activity={activity as ActivityLogResultType} + avatarUrl={activity.triggeredBy.profile.avatar?.uri} + /> + ); + })} + {loader} + </Box> + </ScrollerWithGradient> + )} </Gutters> ); }; diff --git a/src/main/topLevelPages/myDashboard/latestContributions/myLatestContributions/MyLatestContributions.tsx b/src/main/topLevelPages/myDashboard/latestContributions/myLatestContributions/MyLatestContributions.tsx index e7b0d98742..4d5d79b887 100644 --- a/src/main/topLevelPages/myDashboard/latestContributions/myLatestContributions/MyLatestContributions.tsx +++ b/src/main/topLevelPages/myDashboard/latestContributions/myLatestContributions/MyLatestContributions.tsx @@ -17,6 +17,9 @@ import defaultJourneyAvatar from '../../../../../domain/journey/defaultVisuals/A import { LatestContributionsProps, SPACE_OPTION_ALL } from '../LatestContributionsProps'; import { SelectOption } from '@mui/base'; import SeamlessSelect from '../../../../../core/ui/forms/select/SeamlessSelect'; +import Loading from '../../../../../core/ui/loading/Loading'; +import Gutters from '../../../../../core/ui/grid/Gutters'; +import { gutters } from '../../../../../core/ui/grid/utils'; const MY_LATEST_CONTRIBUTIONS_COUNT = 20; @@ -44,7 +47,7 @@ const MyLatestContributions = ({ spaceMemberships }: LatestContributionsProps) = space: event.target.value as string | typeof SPACE_OPTION_ALL, }); - const { data } = useLatestContributionsGroupedQuery({ + const { data, loading } = useLatestContributionsGroupedQuery({ variables: { filter: { myActivity: true, @@ -86,8 +89,11 @@ const MyLatestContributions = ({ spaceMemberships }: LatestContributionsProps) = return spaces; }, [spaceMemberships, t]); + const hasActivity = activities && activities.length > 0; + const isAllSpcesSelected = filter.space === SPACE_OPTION_ALL; + return ( - <> + <Gutters disableGap disablePadding> <Box display="flex" justifyContent="end" alignItems="center"> <SeamlessSelect value={filter.space} @@ -96,24 +102,30 @@ const MyLatestContributions = ({ spaceMemberships }: LatestContributionsProps) = onChange={handleSpaceSelect} /> </Box> - <ScrollerWithGradient> - <Box padding={1}> - {activities && activities.length > 0 ? ( - activities.map(activity => { - return ( - <ActivityViewChooser - key={activity.id} - activity={activity as ActivityLogResultType} - avatarUrl={activity.space?.profile.avatar?.uri || defaultJourneyAvatar} - /> - ); - }) - ) : ( - <CaptionSmall padding={1}>{t('pages.home.sections.myLatestContributions.noContributions')}</CaptionSmall> - )} - </Box> - </ScrollerWithGradient> - </> + {loading ? ( + <Loading /> + ) : ( + <ScrollerWithGradient> + <Box padding={gutters(0.5)}> + {hasActivity && + activities.map(activity => { + return ( + <ActivityViewChooser + key={activity.id} + activity={activity as ActivityLogResultType} + avatarUrl={activity.space?.profile.avatar?.uri || defaultJourneyAvatar} + /> + ); + })} + {!hasActivity && isAllSpcesSelected && ( + <CaptionSmall padding={gutters()}> + {t('pages.home.sections.myLatestContributions.noContributions')} + </CaptionSmall> + )} + </Box> + </ScrollerWithGradient> + )} + </Gutters> ); }; From 3f968c77b1191b8b32302ab65ccc601c2079cf8a Mon Sep 17 00:00:00 2001 From: bobbykolev <bobbykolev@abv.bg> Date: Tue, 29 Oct 2024 16:30:07 +0200 Subject: [PATCH 6/8] Lazy load dashboard components --- src/main/topLevelPages/Home/HomePage.tsx | 16 ++++-- .../DashboardDialogs/DashboardDialogs.tsx | 4 +- .../topLevelPages/myDashboard/MyDashboard.tsx | 49 ++++++++++--------- .../MyDashboardUnauthenticated.tsx | 1 + .../MyDashboardWithMemberships.tsx | 13 +++-- .../MyDashboardWithoutMemberships.tsx | 9 ++-- 6 files changed, 56 insertions(+), 36 deletions(-) diff --git a/src/main/topLevelPages/Home/HomePage.tsx b/src/main/topLevelPages/Home/HomePage.tsx index 8c37931d06..163156a2be 100644 --- a/src/main/topLevelPages/Home/HomePage.tsx +++ b/src/main/topLevelPages/Home/HomePage.tsx @@ -1,9 +1,11 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import HomePageLayout from './HomePageLayout'; import InnovationHubHomePage from '../../../domain/innovationHub/InnovationHubHomePage/InnovationHubHomePage'; import Loading from '../../../core/ui/loading/Loading'; import useInnovationHub from '../../../domain/innovationHub/useInnovationHub/useInnovationHub'; -import MyDashboard from '../myDashboard/MyDashboard'; +import PageContent from '../../../core/ui/content/PageContent'; + +const MyDashboard = React.lazy(() => import('../myDashboard/MyDashboard')); const HomePage = () => { const { innovationHub, innovationHubLoading } = useInnovationHub(); @@ -20,7 +22,15 @@ const HomePage = () => { return <InnovationHubHomePage innovationHub={innovationHub} />; } - return <MyDashboard />; + return ( + <HomePageLayout> + <PageContent> + <Suspense fallback={<Loading />}> + <MyDashboard /> + </Suspense> + </PageContent> + </HomePageLayout> + ); }; export default HomePage; diff --git a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx index 6ad4f216e9..7d24a5cbbb 100644 --- a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx @@ -9,7 +9,7 @@ import MyLatestContributions from '../latestContributions/myLatestContributions/ import LatestContributions from '../latestContributions/LatestContributions'; import { useLatestContributionsSpacesFlatQuery } from '../../../../core/apollo/generated/apollo-hooks'; -export const DashboardDialogs = () => { +const DashboardDialogs = () => { const { t } = useTranslation(); const { openedDialog, setOpenedDialog } = useDashboardContext(); @@ -45,3 +45,5 @@ export const DashboardDialogs = () => { </> ); }; + +export default DashboardDialogs; diff --git a/src/main/topLevelPages/myDashboard/MyDashboard.tsx b/src/main/topLevelPages/myDashboard/MyDashboard.tsx index 7455750f4f..8994605b7b 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboard.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboard.tsx @@ -1,14 +1,13 @@ -import React from 'react'; -import HomePageLayout from '../Home/HomePageLayout'; -import PageContent from '../../../core/ui/content/PageContent'; +import React, { Suspense } from 'react'; import { useLatestContributionsSpacesFlatQuery } from '../../../core/apollo/generated/apollo-hooks'; import Loading from '../../../core/ui/loading/Loading'; -import MyDashboardWithMemberships from './MyDashboardWithMemberships'; -import MyDashboardWithoutMemberships from './MyDashboardWithoutMemberships'; import { useAuthenticationContext } from '../../../core/auth/authentication/hooks/useAuthenticationContext'; -import MyDashboardUnauthenticated from './MyDashboardUnauthenticated'; import { DashboardProvider } from './DashboardContext'; +const MyDashboardUnauthenticated = React.lazy(() => import('./MyDashboardUnauthenticated')); +const MyDashboardWithMemberships = React.lazy(() => import('./MyDashboardWithMemberships')); +const MyDashboardWithoutMemberships = React.lazy(() => import('./MyDashboardWithoutMemberships')); + export const MyDashboard = () => { const { isAuthenticated, loading: isLoadingAuthentication } = useAuthenticationContext(); @@ -16,31 +15,33 @@ export const MyDashboard = () => { const hasSpaceMemberships = !!spacesData?.me.spaceMembershipsFlat.length; if (areSpacesLoading) { + return <Loading />; + } + + if (!isAuthenticated && !isLoadingAuthentication) { + return ( + <Suspense fallback={<Loading />}> + <MyDashboardUnauthenticated /> + </Suspense> + ); + } + + if (hasSpaceMemberships) { return ( - <HomePageLayout> - <Loading /> - </HomePageLayout> + <Suspense fallback={<Loading />}> + <DashboardProvider> + <MyDashboardWithMemberships /> + </DashboardProvider> + </Suspense> ); } return ( - <HomePageLayout> + <Suspense fallback={<Loading />}> <DashboardProvider> - {!isAuthenticated && !isLoadingAuthentication ? ( - <PageContent> - <MyDashboardUnauthenticated /> - </PageContent> - ) : hasSpaceMemberships ? ( - <PageContent> - <MyDashboardWithMemberships /> - </PageContent> - ) : ( - <PageContent> - <MyDashboardWithoutMemberships /> - </PageContent> - )} + <MyDashboardWithoutMemberships /> </DashboardProvider> - </HomePageLayout> + </Suspense> ); }; diff --git a/src/main/topLevelPages/myDashboard/MyDashboardUnauthenticated.tsx b/src/main/topLevelPages/myDashboard/MyDashboardUnauthenticated.tsx index 81ccec9845..e1ec58f605 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardUnauthenticated.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardUnauthenticated.tsx @@ -12,6 +12,7 @@ interface MyDashboardUnauthenticatedProps {} const MyDashboardUnauthenticated: FC<MyDashboardUnauthenticatedProps> = () => { const { t } = useTranslation(); + return ( <PageContentBlock columns={12}> <ExploreSpaces /> diff --git a/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx b/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx index 86cd7f8417..0e238db26b 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import PageContentColumn from '../../../core/ui/content/PageContentColumn'; import ReleaseNotesBanner from './releaseNotesBanner/ReleaseNotesBanner'; import { useLatestReleaseDiscussionQuery } from '../../../core/apollo/generated/apollo-hooks'; @@ -6,10 +6,11 @@ import CampaignBlock from './campaignBlock/CampaignBlock'; import InfoColumn from '../../../core/ui/content/InfoColumn'; import { DashboardMenu } from './DashboardMenu/DashboardMenu'; import ContentColumn from '../../../core/ui/content/ContentColumn'; -import DashboardActivity from './DashboardWithMemberships/DashboardActivity'; -import DashboardSpaces from './DashboardWithMemberships/DashboardSpaces'; import { useDashboardContext } from './DashboardContext'; -import { DashboardDialogs } from './DashboardDialogs/DashboardDialogs'; + +const DashboardDialogs = React.lazy(() => import('./DashboardDialogs/DashboardDialogs')); +const DashboardActivity = React.lazy(() => import('./DashboardWithMemberships/DashboardActivity')); +const DashboardSpaces = React.lazy(() => import('./DashboardWithMemberships/DashboardSpaces')); const MyDashboardWithMemberships = () => { const { activityEnabled } = useDashboardContext(); @@ -27,7 +28,9 @@ const MyDashboardWithMemberships = () => { <CampaignBlock /> {activityEnabled ? <DashboardActivity /> : <DashboardSpaces />} </ContentColumn> - <DashboardDialogs /> + <Suspense fallback={null}> + <DashboardDialogs /> + </Suspense> </PageContentColumn> ); }; diff --git a/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx b/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx index 976f447dc8..c039f94f5a 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import PageContentColumn from '../../../core/ui/content/PageContentColumn'; import CampaignBlock from './campaignBlock/CampaignBlock'; import InfoColumn from '../../../core/ui/content/InfoColumn'; @@ -9,7 +9,8 @@ import { DashboardMenu } from './DashboardMenu/DashboardMenu'; import ExploreSpaces from './ExploreSpaces/ExploreSpaces'; import PageContentBlock from '../../../core/ui/content/PageContentBlock'; import { InvitationsBlock } from './InvitationsBlock/InvitationsBlock'; -import { DashboardDialogs } from './DashboardDialogs/DashboardDialogs'; + +const DashboardDialogs = React.lazy(() => import('./DashboardDialogs/DashboardDialogs')); const MyDashboardWithoutMemberships = () => { const { data } = useLatestReleaseDiscussionQuery({ @@ -30,7 +31,9 @@ const MyDashboardWithoutMemberships = () => { </PageContentBlock> {/* TODO: implement create space btn component */} </ContentColumn> - <DashboardDialogs /> + <Suspense fallback={null}> + <DashboardDialogs /> + </Suspense> </PageContentColumn> ); }; From 6bc57dc0771a54f68e4020b61b9f4536defa3361 Mon Sep 17 00:00:00 2001 From: bobbykolev <bobbykolev@abv.bg> Date: Wed, 30 Oct 2024 12:42:00 +0200 Subject: [PATCH 7/8] Unused files cleanup, pr fixes --- src/core/apollo/generated/apollo-hooks.ts | 750 +++++------------- src/core/apollo/generated/graphql-schema.ts | 686 +++++----------- .../admin/AdminInnovationPacks.graphql | 26 + .../PendingMembershipsUserMenuItem.tsx | 6 - .../DashboardSpaces.graphql | 5 + .../space/FilterByTag/FilterButtons.tsx | 139 ---- .../journey/space/FilterByTag/FilterByTag.tsx | 77 -- .../myDashboard/DashboardContext.tsx | 8 +- .../DashboardDialogs/DashboardDialogs.tsx | 16 +- .../DashboardMenu/DashboardMenu.tsx | 4 +- .../DashboardActivity.tsx | 4 +- .../MyDashboardWithMemberships.tsx | 2 +- .../MyDashboardWithoutMemberships.tsx | 2 +- .../DashboardSpaces.graphql | 16 - .../ExploreOtherChallenges.tsx | 108 --- .../InnovationLibraryBlock.graphql | 36 - .../InnovationLibraryBlock.tsx | 45 -- .../MembershipSuggestions.graphql | 22 - .../MembershipSuggestions.tsx | 90 --- .../newMemberships/NewMembershipCard.tsx | 52 -- .../newMemberships/NewMemberships.graphql | 48 -- .../newMemberships/NewMembershipsBlock.md | 25 - .../newMemberships/NewMembershipsBlock.tsx | 309 -------- .../RecentForumMessages.graphql | 30 - .../RecentForumMessages.tsx | 43 - 25 files changed, 440 insertions(+), 2109 deletions(-) create mode 100644 src/domain/innovationHub/InnovationHubHomePage/DashboardSpaces.graphql delete mode 100644 src/domain/journey/space/FilterByTag/FilterButtons.tsx delete mode 100644 src/domain/journey/space/FilterByTag/FilterByTag.tsx delete mode 100644 src/main/topLevelPages/myDashboard/exploreOtherChallenges/DashboardSpaces.graphql delete mode 100644 src/main/topLevelPages/myDashboard/exploreOtherChallenges/ExploreOtherChallenges.tsx delete mode 100644 src/main/topLevelPages/myDashboard/innovationLibraryBlock/InnovationLibraryBlock.graphql delete mode 100644 src/main/topLevelPages/myDashboard/innovationLibraryBlock/InnovationLibraryBlock.tsx delete mode 100644 src/main/topLevelPages/myDashboard/membershipSuggestions/MembershipSuggestions.graphql delete mode 100644 src/main/topLevelPages/myDashboard/membershipSuggestions/MembershipSuggestions.tsx delete mode 100644 src/main/topLevelPages/myDashboard/newMemberships/NewMembershipCard.tsx delete mode 100644 src/main/topLevelPages/myDashboard/newMemberships/NewMemberships.graphql delete mode 100644 src/main/topLevelPages/myDashboard/newMemberships/NewMembershipsBlock.md delete mode 100644 src/main/topLevelPages/myDashboard/newMemberships/NewMembershipsBlock.tsx delete mode 100644 src/main/topLevelPages/myDashboard/recentForumMessages/RecentForumMessages.graphql delete mode 100644 src/main/topLevelPages/myDashboard/recentForumMessages/RecentForumMessages.tsx diff --git a/src/core/apollo/generated/apollo-hooks.ts b/src/core/apollo/generated/apollo-hooks.ts index bb498978cf..b5bcbe88fb 100644 --- a/src/core/apollo/generated/apollo-hooks.ts +++ b/src/core/apollo/generated/apollo-hooks.ts @@ -36,6 +36,56 @@ export const InnovationPackProfileFragmentDoc = gql` } ${TagsetDetailsFragmentDoc} `; +export const VisualUriFragmentDoc = gql` + fragment VisualUri on Visual { + id + uri + name + } +`; +export const InnovationPackProviderProfileWithAvatarFragmentDoc = gql` + fragment InnovationPackProviderProfileWithAvatar on Contributor { + id + nameID + profile { + id + displayName + avatar: visual(type: AVATAR) { + ...VisualUri + } + url + } + } + ${VisualUriFragmentDoc} +`; +export const InnovationPackCardFragmentDoc = gql` + fragment InnovationPackCard on InnovationPack { + id + nameID + profile { + id + displayName + description + tagset { + ...TagsetDetails + } + url + } + templatesSet { + id + postTemplatesCount + whiteboardTemplatesCount + innovationFlowTemplatesCount + calloutTemplatesCount + communityGuidelinesTemplatesCount + } + provider { + ...InnovationPackProviderProfileWithAvatar + } + } + ${TagsetDetailsFragmentDoc} + ${InnovationPackProviderProfileWithAvatarFragmentDoc} +`; export const AvailableUserFragmentDoc = gql` fragment AvailableUser on User { id @@ -83,13 +133,6 @@ export const RoleSetAvailableMemberUsersFragmentDoc = gql` ${AvailableUserFragmentDoc} ${PageInfoFragmentDoc} `; -export const VisualUriFragmentDoc = gql` - fragment VisualUri on Visual { - id - uri - name - } -`; export const AdminCommunityCandidateMemberFragmentDoc = gql` fragment AdminCommunityCandidateMember on Contributor { id @@ -3392,49 +3435,6 @@ export const NewMembershipsBasicSpaceFragmentDoc = gql` } } `; -export const InnovationPackProviderProfileWithAvatarFragmentDoc = gql` - fragment InnovationPackProviderProfileWithAvatar on Contributor { - id - nameID - profile { - id - displayName - avatar: visual(type: AVATAR) { - ...VisualUri - } - url - } - } - ${VisualUriFragmentDoc} -`; -export const InnovationPackCardFragmentDoc = gql` - fragment InnovationPackCard on InnovationPack { - id - nameID - profile { - id - displayName - description - tagset { - ...TagsetDetails - } - url - } - templatesSet { - id - postTemplatesCount - whiteboardTemplatesCount - innovationFlowTemplatesCount - calloutTemplatesCount - communityGuidelinesTemplatesCount - } - provider { - ...InnovationPackProviderProfileWithAvatar - } - } - ${TagsetDetailsFragmentDoc} - ${InnovationPackProviderProfileWithAvatarFragmentDoc} -`; export const RecentContributionsJourneyProfileFragmentDoc = gql` fragment RecentContributionsJourneyProfile on Profile { id @@ -14455,6 +14455,61 @@ export type VirtualContributorUpdatesSubscriptionHookResult = ReturnType< >; export type VirtualContributorUpdatesSubscriptionResult = Apollo.SubscriptionResult<SchemaTypes.VirtualContributorUpdatesSubscription>; +export const DashboardSpacesDocument = gql` + query DashboardSpaces($visibilities: [SpaceVisibility!] = [ACTIVE]) { + spaces(filter: { visibilities: $visibilities }) { + ...SpaceCard + } + } + ${SpaceCardFragmentDoc} +`; + +/** + * __useDashboardSpacesQuery__ + * + * To run a query within a React component, call `useDashboardSpacesQuery` and pass it any options that fit your needs. + * When your component renders, `useDashboardSpacesQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useDashboardSpacesQuery({ + * variables: { + * visibilities: // value for 'visibilities' + * }, + * }); + */ +export function useDashboardSpacesQuery( + baseOptions?: Apollo.QueryHookOptions<SchemaTypes.DashboardSpacesQuery, SchemaTypes.DashboardSpacesQueryVariables> +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useQuery<SchemaTypes.DashboardSpacesQuery, SchemaTypes.DashboardSpacesQueryVariables>( + DashboardSpacesDocument, + options + ); +} + +export function useDashboardSpacesLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions<SchemaTypes.DashboardSpacesQuery, SchemaTypes.DashboardSpacesQueryVariables> +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useLazyQuery<SchemaTypes.DashboardSpacesQuery, SchemaTypes.DashboardSpacesQueryVariables>( + DashboardSpacesDocument, + options + ); +} + +export type DashboardSpacesQueryHookResult = ReturnType<typeof useDashboardSpacesQuery>; +export type DashboardSpacesLazyQueryHookResult = ReturnType<typeof useDashboardSpacesLazyQuery>; +export type DashboardSpacesQueryResult = Apollo.QueryResult< + SchemaTypes.DashboardSpacesQuery, + SchemaTypes.DashboardSpacesQueryVariables +>; +export function refetchDashboardSpacesQuery(variables?: SchemaTypes.DashboardSpacesQueryVariables) { + return { query: DashboardSpacesDocument, variables: variables }; +} + export const AccountsListDocument = gql` query AccountsList { accounts { @@ -21773,6 +21828,74 @@ export function refetchInnovationLibraryQuery(variables?: SchemaTypes.Innovation return { query: InnovationLibraryDocument, variables: variables }; } +export const CampaignBlockCredentialsDocument = gql` + query CampaignBlockCredentials { + me { + user { + id + agent { + id + credentials { + resourceID + type + } + } + } + } + } +`; + +/** + * __useCampaignBlockCredentialsQuery__ + * + * To run a query within a React component, call `useCampaignBlockCredentialsQuery` and pass it any options that fit your needs. + * When your component renders, `useCampaignBlockCredentialsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useCampaignBlockCredentialsQuery({ + * variables: { + * }, + * }); + */ +export function useCampaignBlockCredentialsQuery( + baseOptions?: Apollo.QueryHookOptions< + SchemaTypes.CampaignBlockCredentialsQuery, + SchemaTypes.CampaignBlockCredentialsQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useQuery<SchemaTypes.CampaignBlockCredentialsQuery, SchemaTypes.CampaignBlockCredentialsQueryVariables>( + CampaignBlockCredentialsDocument, + options + ); +} + +export function useCampaignBlockCredentialsLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + SchemaTypes.CampaignBlockCredentialsQuery, + SchemaTypes.CampaignBlockCredentialsQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useLazyQuery< + SchemaTypes.CampaignBlockCredentialsQuery, + SchemaTypes.CampaignBlockCredentialsQueryVariables + >(CampaignBlockCredentialsDocument, options); +} + +export type CampaignBlockCredentialsQueryHookResult = ReturnType<typeof useCampaignBlockCredentialsQuery>; +export type CampaignBlockCredentialsLazyQueryHookResult = ReturnType<typeof useCampaignBlockCredentialsLazyQuery>; +export type CampaignBlockCredentialsQueryResult = Apollo.QueryResult< + SchemaTypes.CampaignBlockCredentialsQuery, + SchemaTypes.CampaignBlockCredentialsQueryVariables +>; +export function refetchCampaignBlockCredentialsQuery(variables?: SchemaTypes.CampaignBlockCredentialsQueryVariables) { + return { query: CampaignBlockCredentialsDocument, variables: variables }; +} + export const PendingInvitationsCountDocument = gql` query PendingInvitationsCount { me { @@ -22091,282 +22214,24 @@ export function refetchPendingInvitationsQuery(variables?: SchemaTypes.PendingIn return { query: PendingInvitationsDocument, variables: variables }; } -export const CampaignBlockCredentialsDocument = gql` - query CampaignBlockCredentials { - me { - user { +export const LatestContributionsDocument = gql` + query LatestContributions($first: Int!, $after: UUID, $filter: ActivityFeedQueryArgs) { + activityFeed(after: $after, first: $first, args: $filter) { + activityFeed { id - agent { + collaborationID + createdDate + description + type + child + parentNameID + journeyDisplayName: parentDisplayName + space { id - credentials { - resourceID - type - } - } - } - } - } -`; - -/** - * __useCampaignBlockCredentialsQuery__ - * - * To run a query within a React component, call `useCampaignBlockCredentialsQuery` and pass it any options that fit your needs. - * When your component renders, `useCampaignBlockCredentialsQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useCampaignBlockCredentialsQuery({ - * variables: { - * }, - * }); - */ -export function useCampaignBlockCredentialsQuery( - baseOptions?: Apollo.QueryHookOptions< - SchemaTypes.CampaignBlockCredentialsQuery, - SchemaTypes.CampaignBlockCredentialsQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery<SchemaTypes.CampaignBlockCredentialsQuery, SchemaTypes.CampaignBlockCredentialsQueryVariables>( - CampaignBlockCredentialsDocument, - options - ); -} - -export function useCampaignBlockCredentialsLazyQuery( - baseOptions?: Apollo.LazyQueryHookOptions< - SchemaTypes.CampaignBlockCredentialsQuery, - SchemaTypes.CampaignBlockCredentialsQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useLazyQuery< - SchemaTypes.CampaignBlockCredentialsQuery, - SchemaTypes.CampaignBlockCredentialsQueryVariables - >(CampaignBlockCredentialsDocument, options); -} - -export type CampaignBlockCredentialsQueryHookResult = ReturnType<typeof useCampaignBlockCredentialsQuery>; -export type CampaignBlockCredentialsLazyQueryHookResult = ReturnType<typeof useCampaignBlockCredentialsLazyQuery>; -export type CampaignBlockCredentialsQueryResult = Apollo.QueryResult< - SchemaTypes.CampaignBlockCredentialsQuery, - SchemaTypes.CampaignBlockCredentialsQueryVariables ->; -export function refetchCampaignBlockCredentialsQuery(variables?: SchemaTypes.CampaignBlockCredentialsQueryVariables) { - return { query: CampaignBlockCredentialsDocument, variables: variables }; -} - -export const DashboardSpacesDocument = gql` - query DashboardSpaces($visibilities: [SpaceVisibility!] = [ACTIVE]) { - spaces(filter: { visibilities: $visibilities }) { - ...SpaceCard - } - } - ${SpaceCardFragmentDoc} -`; - -/** - * __useDashboardSpacesQuery__ - * - * To run a query within a React component, call `useDashboardSpacesQuery` and pass it any options that fit your needs. - * When your component renders, `useDashboardSpacesQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useDashboardSpacesQuery({ - * variables: { - * visibilities: // value for 'visibilities' - * }, - * }); - */ -export function useDashboardSpacesQuery( - baseOptions?: Apollo.QueryHookOptions<SchemaTypes.DashboardSpacesQuery, SchemaTypes.DashboardSpacesQueryVariables> -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery<SchemaTypes.DashboardSpacesQuery, SchemaTypes.DashboardSpacesQueryVariables>( - DashboardSpacesDocument, - options - ); -} - -export function useDashboardSpacesLazyQuery( - baseOptions?: Apollo.LazyQueryHookOptions<SchemaTypes.DashboardSpacesQuery, SchemaTypes.DashboardSpacesQueryVariables> -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useLazyQuery<SchemaTypes.DashboardSpacesQuery, SchemaTypes.DashboardSpacesQueryVariables>( - DashboardSpacesDocument, - options - ); -} - -export type DashboardSpacesQueryHookResult = ReturnType<typeof useDashboardSpacesQuery>; -export type DashboardSpacesLazyQueryHookResult = ReturnType<typeof useDashboardSpacesLazyQuery>; -export type DashboardSpacesQueryResult = Apollo.QueryResult< - SchemaTypes.DashboardSpacesQuery, - SchemaTypes.DashboardSpacesQueryVariables ->; -export function refetchDashboardSpacesQuery(variables?: SchemaTypes.DashboardSpacesQueryVariables) { - return { query: DashboardSpacesDocument, variables: variables }; -} - -export const DashboardSpacesPaginatedDocument = gql` - query DashboardSpacesPaginated($first: Int!, $after: UUID, $visibilities: [SpaceVisibility!] = [ACTIVE]) { - spacesPaginated(first: $first, after: $after, filter: { visibilities: $visibilities }) { - spaces { - ...SpaceCard - } - pageInfo { - ...PageInfo - } - } - } - ${SpaceCardFragmentDoc} - ${PageInfoFragmentDoc} -`; - -/** - * __useDashboardSpacesPaginatedQuery__ - * - * To run a query within a React component, call `useDashboardSpacesPaginatedQuery` and pass it any options that fit your needs. - * When your component renders, `useDashboardSpacesPaginatedQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useDashboardSpacesPaginatedQuery({ - * variables: { - * first: // value for 'first' - * after: // value for 'after' - * visibilities: // value for 'visibilities' - * }, - * }); - */ -export function useDashboardSpacesPaginatedQuery( - baseOptions: Apollo.QueryHookOptions< - SchemaTypes.DashboardSpacesPaginatedQuery, - SchemaTypes.DashboardSpacesPaginatedQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery<SchemaTypes.DashboardSpacesPaginatedQuery, SchemaTypes.DashboardSpacesPaginatedQueryVariables>( - DashboardSpacesPaginatedDocument, - options - ); -} - -export function useDashboardSpacesPaginatedLazyQuery( - baseOptions?: Apollo.LazyQueryHookOptions< - SchemaTypes.DashboardSpacesPaginatedQuery, - SchemaTypes.DashboardSpacesPaginatedQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useLazyQuery< - SchemaTypes.DashboardSpacesPaginatedQuery, - SchemaTypes.DashboardSpacesPaginatedQueryVariables - >(DashboardSpacesPaginatedDocument, options); -} - -export type DashboardSpacesPaginatedQueryHookResult = ReturnType<typeof useDashboardSpacesPaginatedQuery>; -export type DashboardSpacesPaginatedLazyQueryHookResult = ReturnType<typeof useDashboardSpacesPaginatedLazyQuery>; -export type DashboardSpacesPaginatedQueryResult = Apollo.QueryResult< - SchemaTypes.DashboardSpacesPaginatedQuery, - SchemaTypes.DashboardSpacesPaginatedQueryVariables ->; -export function refetchDashboardSpacesPaginatedQuery(variables: SchemaTypes.DashboardSpacesPaginatedQueryVariables) { - return { query: DashboardSpacesPaginatedDocument, variables: variables }; -} - -export const InnovationLibraryBlockDocument = gql` - query InnovationLibraryBlock { - platform { - id - library { - id - innovationPacks(queryData: { limit: 1, orderBy: RANDOM }) { - ...InnovationPackCard - } - } - } - } - ${InnovationPackCardFragmentDoc} -`; - -/** - * __useInnovationLibraryBlockQuery__ - * - * To run a query within a React component, call `useInnovationLibraryBlockQuery` and pass it any options that fit your needs. - * When your component renders, `useInnovationLibraryBlockQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useInnovationLibraryBlockQuery({ - * variables: { - * }, - * }); - */ -export function useInnovationLibraryBlockQuery( - baseOptions?: Apollo.QueryHookOptions< - SchemaTypes.InnovationLibraryBlockQuery, - SchemaTypes.InnovationLibraryBlockQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery<SchemaTypes.InnovationLibraryBlockQuery, SchemaTypes.InnovationLibraryBlockQueryVariables>( - InnovationLibraryBlockDocument, - options - ); -} - -export function useInnovationLibraryBlockLazyQuery( - baseOptions?: Apollo.LazyQueryHookOptions< - SchemaTypes.InnovationLibraryBlockQuery, - SchemaTypes.InnovationLibraryBlockQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useLazyQuery<SchemaTypes.InnovationLibraryBlockQuery, SchemaTypes.InnovationLibraryBlockQueryVariables>( - InnovationLibraryBlockDocument, - options - ); -} - -export type InnovationLibraryBlockQueryHookResult = ReturnType<typeof useInnovationLibraryBlockQuery>; -export type InnovationLibraryBlockLazyQueryHookResult = ReturnType<typeof useInnovationLibraryBlockLazyQuery>; -export type InnovationLibraryBlockQueryResult = Apollo.QueryResult< - SchemaTypes.InnovationLibraryBlockQuery, - SchemaTypes.InnovationLibraryBlockQueryVariables ->; -export function refetchInnovationLibraryBlockQuery(variables?: SchemaTypes.InnovationLibraryBlockQueryVariables) { - return { query: InnovationLibraryBlockDocument, variables: variables }; -} - -export const LatestContributionsDocument = gql` - query LatestContributions($first: Int!, $after: UUID, $filter: ActivityFeedQueryArgs) { - activityFeed(after: $after, first: $first, args: $filter) { - activityFeed { - id - collaborationID - createdDate - description - type - child - parentNameID - journeyDisplayName: parentDisplayName - space { - id - ... on Space { - profile { - ...RecentContributionsSpaceProfile - } + ... on Space { + profile { + ...RecentContributionsSpaceProfile + } } } triggeredBy { @@ -22690,84 +22555,6 @@ export function refetchLatestContributionsSpacesFlatQuery( return { query: LatestContributionsSpacesFlatDocument, variables: variables }; } -export const MembershipSuggestionSpaceDocument = gql` - query MembershipSuggestionSpace($spaceNameId: UUID_NAMEID!) { - space(ID: $spaceNameId) { - id - nameID - profile { - id - displayName - tagline - url - avatar: visual(type: CARD) { - ...VisualUri - } - } - community { - id - roleSet { - id - myRoles - } - } - } - } - ${VisualUriFragmentDoc} -`; - -/** - * __useMembershipSuggestionSpaceQuery__ - * - * To run a query within a React component, call `useMembershipSuggestionSpaceQuery` and pass it any options that fit your needs. - * When your component renders, `useMembershipSuggestionSpaceQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useMembershipSuggestionSpaceQuery({ - * variables: { - * spaceNameId: // value for 'spaceNameId' - * }, - * }); - */ -export function useMembershipSuggestionSpaceQuery( - baseOptions: Apollo.QueryHookOptions< - SchemaTypes.MembershipSuggestionSpaceQuery, - SchemaTypes.MembershipSuggestionSpaceQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery< - SchemaTypes.MembershipSuggestionSpaceQuery, - SchemaTypes.MembershipSuggestionSpaceQueryVariables - >(MembershipSuggestionSpaceDocument, options); -} - -export function useMembershipSuggestionSpaceLazyQuery( - baseOptions?: Apollo.LazyQueryHookOptions< - SchemaTypes.MembershipSuggestionSpaceQuery, - SchemaTypes.MembershipSuggestionSpaceQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useLazyQuery< - SchemaTypes.MembershipSuggestionSpaceQuery, - SchemaTypes.MembershipSuggestionSpaceQueryVariables - >(MembershipSuggestionSpaceDocument, options); -} - -export type MembershipSuggestionSpaceQueryHookResult = ReturnType<typeof useMembershipSuggestionSpaceQuery>; -export type MembershipSuggestionSpaceLazyQueryHookResult = ReturnType<typeof useMembershipSuggestionSpaceLazyQuery>; -export type MembershipSuggestionSpaceQueryResult = Apollo.QueryResult< - SchemaTypes.MembershipSuggestionSpaceQuery, - SchemaTypes.MembershipSuggestionSpaceQueryVariables ->; -export function refetchMembershipSuggestionSpaceQuery(variables: SchemaTypes.MembershipSuggestionSpaceQueryVariables) { - return { query: MembershipSuggestionSpaceDocument, variables: variables }; -} - export const MyMembershipsDocument = gql` query MyMemberships { me { @@ -22839,92 +22626,6 @@ export function refetchMyMembershipsQuery(variables?: SchemaTypes.MyMembershipsQ return { query: MyMembershipsDocument, variables: variables }; } -export const NewMembershipsDocument = gql` - query NewMemberships { - me { - communityApplications(states: ["new", "approved"]) { - id - spacePendingMembershipInfo { - ...NewMembershipsBasicSpace - } - application { - id - lifecycle { - id - state - } - createdDate - } - } - communityInvitations(states: ["invited", "accepted"]) { - id - spacePendingMembershipInfo { - ...NewMembershipsBasicSpace - } - invitation { - id - welcomeMessage - contributorType - createdBy { - id - } - lifecycle { - id - state - } - createdDate - } - } - } - } - ${NewMembershipsBasicSpaceFragmentDoc} -`; - -/** - * __useNewMembershipsQuery__ - * - * To run a query within a React component, call `useNewMembershipsQuery` and pass it any options that fit your needs. - * When your component renders, `useNewMembershipsQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useNewMembershipsQuery({ - * variables: { - * }, - * }); - */ -export function useNewMembershipsQuery( - baseOptions?: Apollo.QueryHookOptions<SchemaTypes.NewMembershipsQuery, SchemaTypes.NewMembershipsQueryVariables> -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery<SchemaTypes.NewMembershipsQuery, SchemaTypes.NewMembershipsQueryVariables>( - NewMembershipsDocument, - options - ); -} - -export function useNewMembershipsLazyQuery( - baseOptions?: Apollo.LazyQueryHookOptions<SchemaTypes.NewMembershipsQuery, SchemaTypes.NewMembershipsQueryVariables> -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useLazyQuery<SchemaTypes.NewMembershipsQuery, SchemaTypes.NewMembershipsQueryVariables>( - NewMembershipsDocument, - options - ); -} - -export type NewMembershipsQueryHookResult = ReturnType<typeof useNewMembershipsQuery>; -export type NewMembershipsLazyQueryHookResult = ReturnType<typeof useNewMembershipsLazyQuery>; -export type NewMembershipsQueryResult = Apollo.QueryResult< - SchemaTypes.NewMembershipsQuery, - SchemaTypes.NewMembershipsQueryVariables ->; -export function refetchNewMembershipsQuery(variables?: SchemaTypes.NewMembershipsQueryVariables) { - return { query: NewMembershipsDocument, variables: variables }; -} - export const NewVirtualContributorMySpacesDocument = gql` query NewVirtualContributorMySpaces { me { @@ -23034,79 +22735,6 @@ export function refetchNewVirtualContributorMySpacesQuery( return { query: NewVirtualContributorMySpacesDocument, variables: variables }; } -export const RecentForumMessagesDocument = gql` - query recentForumMessages($limit: Float = 5) { - platform { - id - forum { - id - discussionCategories - authorization { - id - myPrivileges - anonymousReadAccess - } - discussions(queryData: { orderBy: DISCUSSIONS_CREATEDATE_DESC, limit: $limit }) { - ...DiscussionCard - } - } - } - } - ${DiscussionCardFragmentDoc} -`; - -/** - * __useRecentForumMessagesQuery__ - * - * To run a query within a React component, call `useRecentForumMessagesQuery` and pass it any options that fit your needs. - * When your component renders, `useRecentForumMessagesQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useRecentForumMessagesQuery({ - * variables: { - * limit: // value for 'limit' - * }, - * }); - */ -export function useRecentForumMessagesQuery( - baseOptions?: Apollo.QueryHookOptions< - SchemaTypes.RecentForumMessagesQuery, - SchemaTypes.RecentForumMessagesQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery<SchemaTypes.RecentForumMessagesQuery, SchemaTypes.RecentForumMessagesQueryVariables>( - RecentForumMessagesDocument, - options - ); -} - -export function useRecentForumMessagesLazyQuery( - baseOptions?: Apollo.LazyQueryHookOptions< - SchemaTypes.RecentForumMessagesQuery, - SchemaTypes.RecentForumMessagesQueryVariables - > -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useLazyQuery<SchemaTypes.RecentForumMessagesQuery, SchemaTypes.RecentForumMessagesQueryVariables>( - RecentForumMessagesDocument, - options - ); -} - -export type RecentForumMessagesQueryHookResult = ReturnType<typeof useRecentForumMessagesQuery>; -export type RecentForumMessagesLazyQueryHookResult = ReturnType<typeof useRecentForumMessagesLazyQuery>; -export type RecentForumMessagesQueryResult = Apollo.QueryResult< - SchemaTypes.RecentForumMessagesQuery, - SchemaTypes.RecentForumMessagesQueryVariables ->; -export function refetchRecentForumMessagesQuery(variables?: SchemaTypes.RecentForumMessagesQueryVariables) { - return { query: RecentForumMessagesDocument, variables: variables }; -} - export const RecentJourneyDocument = gql` query RecentJourney($spaceId: UUID!) { lookup { diff --git a/src/core/apollo/generated/graphql-schema.ts b/src/core/apollo/generated/graphql-schema.ts index fb098c0161..a70e5a0338 100644 --- a/src/core/apollo/generated/graphql-schema.ts +++ b/src/core/apollo/generated/graphql-schema.ts @@ -7122,6 +7122,77 @@ export type InnovationPackProviderProfileWithAvatarFragment = | InnovationPackProviderProfileWithAvatar_User_Fragment | InnovationPackProviderProfileWithAvatar_VirtualContributor_Fragment; +export type InnovationPackCardFragment = { + __typename?: 'InnovationPack'; + id: string; + nameID: string; + profile: { + __typename?: 'Profile'; + id: string; + displayName: string; + description?: string | undefined; + url: string; + tagset?: + | { + __typename?: 'Tagset'; + id: string; + name: string; + tags: Array<string>; + allowedValues: Array<string>; + type: TagsetType; + } + | undefined; + }; + templatesSet?: + | { + __typename?: 'TemplatesSet'; + id: string; + postTemplatesCount: number; + whiteboardTemplatesCount: number; + innovationFlowTemplatesCount: number; + calloutTemplatesCount: number; + communityGuidelinesTemplatesCount: number; + } + | undefined; + provider: + | { + __typename?: 'Organization'; + id: string; + nameID: string; + profile: { + __typename?: 'Profile'; + id: string; + displayName: string; + url: string; + avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; + }; + } + | { + __typename?: 'User'; + id: string; + nameID: string; + profile: { + __typename?: 'Profile'; + id: string; + displayName: string; + url: string; + avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; + }; + } + | { + __typename?: 'VirtualContributor'; + id: string; + nameID: string; + profile: { + __typename?: 'Profile'; + id: string; + displayName: string; + url: string; + avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; + }; + }; +}; + export type RoleDefinitionPolicyFragment = { __typename?: 'Role'; id: string; @@ -18707,6 +18778,48 @@ export type FullLocationFragment = { postalCode?: string | undefined; }; +export type DashboardSpacesQueryVariables = Exact<{ + visibilities?: InputMaybe<Array<SpaceVisibility> | SpaceVisibility>; +}>; + +export type DashboardSpacesQuery = { + __typename?: 'Query'; + spaces: Array<{ + __typename?: 'Space'; + id: string; + visibility: SpaceVisibility; + profile: { + __typename?: 'Profile'; + id: string; + url: string; + displayName: string; + tagline?: string | undefined; + tagset?: + | { + __typename?: 'Tagset'; + id: string; + name: string; + tags: Array<string>; + allowedValues: Array<string>; + type: TagsetType; + } + | undefined; + cardBanner?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; + }; + metrics?: Array<{ __typename?: 'NVP'; name: string; value: string }> | undefined; + community: { + __typename?: 'Community'; + id: string; + roleSet: { __typename?: 'RoleSet'; id: string; myMembershipStatus?: CommunityMembershipStatus | undefined }; + }; + context: { __typename?: 'Context'; id: string; vision?: string | undefined }; + settings: { + __typename?: 'SpaceSettings'; + privacy: { __typename?: 'SpaceSettingsPrivacy'; mode: SpacePrivacyMode }; + }; + }>; +}; + export type AccountsListQueryVariables = Exact<{ [key: string]: never }>; export type AccountsListQuery = { @@ -28186,6 +28299,26 @@ export type LibraryTemplatesFragment = { }>; }; +export type CampaignBlockCredentialsQueryVariables = Exact<{ [key: string]: never }>; + +export type CampaignBlockCredentialsQuery = { + __typename?: 'Query'; + me: { + __typename?: 'MeQueryResults'; + user?: + | { + __typename?: 'User'; + id: string; + agent: { + __typename?: 'Agent'; + id: string; + credentials?: Array<{ __typename?: 'Credential'; resourceID: string; type: CredentialType }> | undefined; + }; + } + | undefined; + }; +}; + export type PendingInvitationsCountQueryVariables = Exact<{ [key: string]: never }>; export type PendingInvitationsCountQuery = { @@ -28333,353 +28466,83 @@ export type NewMembershipsBasicSpaceFragment = { profile: { __typename?: 'Profile'; id: string; displayName: string; tagline?: string | undefined; url: string }; }; -export type CampaignBlockCredentialsQueryVariables = Exact<{ [key: string]: never }>; +export type LatestContributionsQueryVariables = Exact<{ + first: Scalars['Int']; + after?: InputMaybe<Scalars['UUID']>; + filter?: InputMaybe<ActivityFeedQueryArgs>; +}>; -export type CampaignBlockCredentialsQuery = { +export type LatestContributionsQuery = { __typename?: 'Query'; - me: { - __typename?: 'MeQueryResults'; - user?: + activityFeed: { + __typename?: 'ActivityFeed'; + activityFeed: Array< | { - __typename?: 'User'; + __typename?: 'ActivityLogEntryCalendarEventCreated'; id: string; - agent: { - __typename?: 'Agent'; + collaborationID: string; + createdDate: Date; + description: string; + type: ActivityEventType; + child: boolean; + parentNameID: string; + journeyDisplayName: string; + space?: + | { + __typename?: 'Space'; + id: string; + profile: { + __typename?: 'Profile'; + id: string; + url: string; + displayName: string; + type?: ProfileType | undefined; + avatar?: { __typename?: 'Visual'; id: string; uri: string } | undefined; + }; + } + | undefined; + triggeredBy: { + __typename?: 'User'; id: string; - credentials?: Array<{ __typename?: 'Credential'; resourceID: string; type: CredentialType }> | undefined; + profile: { + __typename?: 'Profile'; + id: string; + displayName: string; + avatar?: { __typename?: 'Visual'; id: string; uri: string } | undefined; + }; + }; + calendarEvent: { + __typename?: 'CalendarEvent'; + id: string; + profile: { __typename?: 'Profile'; id: string; displayName: string; url: string }; }; } - | undefined; - }; -}; - -export type DashboardSpacesQueryVariables = Exact<{ - visibilities?: InputMaybe<Array<SpaceVisibility> | SpaceVisibility>; -}>; - -export type DashboardSpacesQuery = { - __typename?: 'Query'; - spaces: Array<{ - __typename?: 'Space'; - id: string; - visibility: SpaceVisibility; - profile: { - __typename?: 'Profile'; - id: string; - url: string; - displayName: string; - tagline?: string | undefined; - tagset?: - | { - __typename?: 'Tagset'; - id: string; - name: string; - tags: Array<string>; - allowedValues: Array<string>; - type: TagsetType; - } - | undefined; - cardBanner?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - metrics?: Array<{ __typename?: 'NVP'; name: string; value: string }> | undefined; - community: { - __typename?: 'Community'; - id: string; - roleSet: { __typename?: 'RoleSet'; id: string; myMembershipStatus?: CommunityMembershipStatus | undefined }; - }; - context: { __typename?: 'Context'; id: string; vision?: string | undefined }; - settings: { - __typename?: 'SpaceSettings'; - privacy: { __typename?: 'SpaceSettingsPrivacy'; mode: SpacePrivacyMode }; - }; - }>; -}; - -export type DashboardSpacesPaginatedQueryVariables = Exact<{ - first: Scalars['Int']; - after?: InputMaybe<Scalars['UUID']>; - visibilities?: InputMaybe<Array<SpaceVisibility> | SpaceVisibility>; -}>; - -export type DashboardSpacesPaginatedQuery = { - __typename?: 'Query'; - spacesPaginated: { - __typename?: 'PaginatedSpaces'; - spaces: Array<{ - __typename?: 'Space'; - id: string; - visibility: SpaceVisibility; - profile: { - __typename?: 'Profile'; - id: string; - url: string; - displayName: string; - tagline?: string | undefined; - tagset?: - | { - __typename?: 'Tagset'; - id: string; - name: string; - tags: Array<string>; - allowedValues: Array<string>; - type: TagsetType; - } - | undefined; - cardBanner?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - metrics?: Array<{ __typename?: 'NVP'; name: string; value: string }> | undefined; - community: { - __typename?: 'Community'; - id: string; - roleSet: { __typename?: 'RoleSet'; id: string; myMembershipStatus?: CommunityMembershipStatus | undefined }; - }; - context: { __typename?: 'Context'; id: string; vision?: string | undefined }; - settings: { - __typename?: 'SpaceSettings'; - privacy: { __typename?: 'SpaceSettingsPrivacy'; mode: SpacePrivacyMode }; - }; - }>; - pageInfo: { - __typename?: 'PageInfo'; - startCursor?: string | undefined; - endCursor?: string | undefined; - hasNextPage: boolean; - }; - }; -}; - -export type InnovationLibraryBlockQueryVariables = Exact<{ [key: string]: never }>; - -export type InnovationLibraryBlockQuery = { - __typename?: 'Query'; - platform: { - __typename?: 'Platform'; - id: string; - library: { - __typename?: 'Library'; - id: string; - innovationPacks: Array<{ - __typename?: 'InnovationPack'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - description?: string | undefined; - url: string; - tagset?: - | { - __typename?: 'Tagset'; - id: string; - name: string; - tags: Array<string>; - allowedValues: Array<string>; - type: TagsetType; - } - | undefined; - }; - templatesSet?: - | { - __typename?: 'TemplatesSet'; - id: string; - postTemplatesCount: number; - whiteboardTemplatesCount: number; - innovationFlowTemplatesCount: number; - calloutTemplatesCount: number; - communityGuidelinesTemplatesCount: number; - } - | undefined; - provider: - | { - __typename?: 'Organization'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - url: string; - avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - } - | { - __typename?: 'User'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - url: string; - avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - } - | { - __typename?: 'VirtualContributor'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - url: string; - avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - }; - }>; - }; - }; -}; - -export type InnovationPackCardFragment = { - __typename?: 'InnovationPack'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - description?: string | undefined; - url: string; - tagset?: - | { - __typename?: 'Tagset'; - id: string; - name: string; - tags: Array<string>; - allowedValues: Array<string>; - type: TagsetType; - } - | undefined; - }; - templatesSet?: - | { - __typename?: 'TemplatesSet'; - id: string; - postTemplatesCount: number; - whiteboardTemplatesCount: number; - innovationFlowTemplatesCount: number; - calloutTemplatesCount: number; - communityGuidelinesTemplatesCount: number; - } - | undefined; - provider: - | { - __typename?: 'Organization'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - url: string; - avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - } - | { - __typename?: 'User'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - url: string; - avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - } - | { - __typename?: 'VirtualContributor'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - url: string; - avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - }; -}; - -export type LatestContributionsQueryVariables = Exact<{ - first: Scalars['Int']; - after?: InputMaybe<Scalars['UUID']>; - filter?: InputMaybe<ActivityFeedQueryArgs>; -}>; - -export type LatestContributionsQuery = { - __typename?: 'Query'; - activityFeed: { - __typename?: 'ActivityFeed'; - activityFeed: Array< - | { - __typename?: 'ActivityLogEntryCalendarEventCreated'; - id: string; - collaborationID: string; - createdDate: Date; - description: string; - type: ActivityEventType; - child: boolean; - parentNameID: string; - journeyDisplayName: string; - space?: - | { - __typename?: 'Space'; - id: string; - profile: { - __typename?: 'Profile'; - id: string; - url: string; - displayName: string; - type?: ProfileType | undefined; - avatar?: { __typename?: 'Visual'; id: string; uri: string } | undefined; - }; - } - | undefined; - triggeredBy: { - __typename?: 'User'; - id: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - avatar?: { __typename?: 'Visual'; id: string; uri: string } | undefined; - }; - }; - calendarEvent: { - __typename?: 'CalendarEvent'; - id: string; - profile: { __typename?: 'Profile'; id: string; displayName: string; url: string }; - }; - } - | { - __typename?: 'ActivityLogEntryCalloutDiscussionComment'; - id: string; - collaborationID: string; - createdDate: Date; - description: string; - type: ActivityEventType; - child: boolean; - parentNameID: string; - journeyDisplayName: string; - space?: - | { - __typename?: 'Space'; - id: string; - profile: { - __typename?: 'Profile'; - id: string; - url: string; - displayName: string; - type?: ProfileType | undefined; - avatar?: { __typename?: 'Visual'; id: string; uri: string } | undefined; - }; - } - | undefined; - triggeredBy: { - __typename?: 'User'; + | { + __typename?: 'ActivityLogEntryCalloutDiscussionComment'; + id: string; + collaborationID: string; + createdDate: Date; + description: string; + type: ActivityEventType; + child: boolean; + parentNameID: string; + journeyDisplayName: string; + space?: + | { + __typename?: 'Space'; + id: string; + profile: { + __typename?: 'Profile'; + id: string; + url: string; + displayName: string; + type?: ProfileType | undefined; + avatar?: { __typename?: 'Visual'; id: string; uri: string } | undefined; + }; + } + | undefined; + triggeredBy: { + __typename?: 'User'; id: string; profile: { __typename?: 'Profile'; @@ -29651,32 +29514,6 @@ export type LatestContributionsSpacesFlatQuery = { }; }; -export type MembershipSuggestionSpaceQueryVariables = Exact<{ - spaceNameId: Scalars['UUID_NAMEID']; -}>; - -export type MembershipSuggestionSpaceQuery = { - __typename?: 'Query'; - space: { - __typename?: 'Space'; - id: string; - nameID: string; - profile: { - __typename?: 'Profile'; - id: string; - displayName: string; - tagline?: string | undefined; - url: string; - avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; - }; - community: { - __typename?: 'Community'; - id: string; - roleSet: { __typename?: 'RoleSet'; id: string; myRoles: Array<CommunityRoleType> }; - }; - }; -}; - export type MyMembershipsQueryVariables = Exact<{ [key: string]: never }>; export type MyMembershipsQuery = { @@ -29808,50 +29645,6 @@ export type MyMembershipsChildJourneyProfileFragment = { avatar?: { __typename?: 'Visual'; id: string; uri: string; name: string } | undefined; }; -export type NewMembershipsQueryVariables = Exact<{ [key: string]: never }>; - -export type NewMembershipsQuery = { - __typename?: 'Query'; - me: { - __typename?: 'MeQueryResults'; - communityApplications: Array<{ - __typename?: 'CommunityApplicationResult'; - id: string; - spacePendingMembershipInfo: { - __typename?: 'SpacePendingMembershipInfo'; - id: string; - level: SpaceLevel; - profile: { __typename?: 'Profile'; id: string; displayName: string; tagline?: string | undefined; url: string }; - }; - application: { - __typename?: 'Application'; - id: string; - createdDate: Date; - lifecycle: { __typename?: 'Lifecycle'; id: string; state?: string | undefined }; - }; - }>; - communityInvitations: Array<{ - __typename?: 'CommunityInvitationResult'; - id: string; - spacePendingMembershipInfo: { - __typename?: 'SpacePendingMembershipInfo'; - id: string; - level: SpaceLevel; - profile: { __typename?: 'Profile'; id: string; displayName: string; tagline?: string | undefined; url: string }; - }; - invitation: { - __typename?: 'Invitation'; - id: string; - welcomeMessage?: string | undefined; - contributorType: CommunityContributorType; - createdDate: Date; - createdBy: { __typename?: 'User'; id: string }; - lifecycle: { __typename?: 'Lifecycle'; id: string; state?: string | undefined }; - }; - }>; - }; -}; - export type NewVirtualContributorMySpacesQueryVariables = Exact<{ [key: string]: never }>; export type NewVirtualContributorMySpacesQuery = { @@ -29917,79 +29710,6 @@ export type NewVirtualContributorMySpacesQuery = { }; }; -export type RecentForumMessagesQueryVariables = Exact<{ - limit?: InputMaybe<Scalars['Float']>; -}>; - -export type RecentForumMessagesQuery = { - __typename?: 'Query'; - platform: { - __typename?: 'Platform'; - id: string; - forum: { - __typename?: 'Forum'; - id: string; - discussionCategories: Array<ForumDiscussionCategory>; - authorization?: - | { - __typename?: 'Authorization'; - id: string; - myPrivileges?: Array<AuthorizationPrivilege> | undefined; - anonymousReadAccess: boolean; - } - | undefined; - discussions?: - | Array<{ - __typename?: 'Discussion'; - id: string; - category: ForumDiscussionCategory; - timestamp?: number | undefined; - createdBy?: string | undefined; - profile: { - __typename?: 'Profile'; - id: string; - url: string; - displayName: string; - description?: string | undefined; - tagline?: string | undefined; - visual?: - | { - __typename?: 'Visual'; - id: string; - uri: string; - name: string; - allowedTypes: Array<string>; - aspectRatio: number; - maxHeight: number; - maxWidth: number; - minHeight: number; - minWidth: number; - alternativeText?: string | undefined; - } - | undefined; - }; - comments: { - __typename?: 'Room'; - id: string; - messagesCount: number; - authorization?: - | { __typename?: 'Authorization'; myPrivileges?: Array<AuthorizationPrivilege> | undefined } - | undefined; - }; - authorization?: - | { - __typename?: 'Authorization'; - id: string; - myPrivileges?: Array<AuthorizationPrivilege> | undefined; - anonymousReadAccess: boolean; - } - | undefined; - }> - | undefined; - }; - }; -}; - export type RecentJourneyQueryVariables = Exact<{ spaceId: Scalars['UUID']; }>; diff --git a/src/domain/InnovationPack/admin/AdminInnovationPacks.graphql b/src/domain/InnovationPack/admin/AdminInnovationPacks.graphql index b8df963b2c..2388560b99 100644 --- a/src/domain/InnovationPack/admin/AdminInnovationPacks.graphql +++ b/src/domain/InnovationPack/admin/AdminInnovationPacks.graphql @@ -93,3 +93,29 @@ fragment InnovationPackProviderProfileWithAvatar on Contributor { url } } + +fragment InnovationPackCard on InnovationPack { + id + nameID + profile { + id + displayName + description + tagset { + ...TagsetDetails + } + url + } + templatesSet { + id + postTemplatesCount + whiteboardTemplatesCount + innovationFlowTemplatesCount + calloutTemplatesCount + communityGuidelinesTemplatesCount + } + provider { + ...InnovationPackProviderProfileWithAvatar + } +} + diff --git a/src/domain/community/pendingMembership/PendingMembershipsUserMenuItem.tsx b/src/domain/community/pendingMembership/PendingMembershipsUserMenuItem.tsx index 566f9eea96..8db652e4c2 100644 --- a/src/domain/community/pendingMembership/PendingMembershipsUserMenuItem.tsx +++ b/src/domain/community/pendingMembership/PendingMembershipsUserMenuItem.tsx @@ -21,7 +21,6 @@ import InvitationActionsContainer from '../invitations/InvitationActionsContaine import { CommunityContributorType, VisualType } from '../../../core/apollo/generated/graphql-schema'; import BackButton from '../../../core/ui/actions/BackButton'; import useNavigate from '../../../core/routing/useNavigate'; -import { useNewMembershipsQuery } from '../../../core/apollo/generated/apollo-hooks'; import { PendingMembershipsDialogType, usePendingMembershipsDialog } from './PendingMembershipsDialogContext'; import { defer } from 'lodash'; import { getChildJourneyTypeName } from '../../shared/utils/spaceLevel'; @@ -40,8 +39,6 @@ const PendingMembershipsUserMenuItem = ({ children }: PendingMembershipsUserMenu const navigate = useNavigate(); - const { refetch: refetchNewMembershipsQuery } = useNewMembershipsQuery(); - const { openDialog, setOpenDialog } = usePendingMembershipsDialog(); const closeDialog = () => setOpenDialog(undefined); @@ -72,8 +69,6 @@ const PendingMembershipsUserMenuItem = ({ children }: PendingMembershipsUserMenu const pendingMembershipsCount = invitations && applications ? invitations.length + applications.length : undefined; const onInvitationAccept = () => { - refetchNewMembershipsQuery(); - if (openDialog?.journeyUri) { navigate(openDialog?.journeyUri); defer(closeDialog); // Deferring for appearance purpose only @@ -83,7 +78,6 @@ const PendingMembershipsUserMenuItem = ({ children }: PendingMembershipsUserMenu }; const onInvitationReject = () => { - refetchNewMembershipsQuery(); setOpenDialog({ type: PendingMembershipsDialogType.PendingMembershipsList }); }; diff --git a/src/domain/innovationHub/InnovationHubHomePage/DashboardSpaces.graphql b/src/domain/innovationHub/InnovationHubHomePage/DashboardSpaces.graphql new file mode 100644 index 0000000000..982bbeccff --- /dev/null +++ b/src/domain/innovationHub/InnovationHubHomePage/DashboardSpaces.graphql @@ -0,0 +1,5 @@ +query DashboardSpaces($visibilities: [SpaceVisibility!] = [ACTIVE]) { + spaces(filter: { visibilities: $visibilities }) { + ...SpaceCard + } +} diff --git a/src/domain/journey/space/FilterByTag/FilterButtons.tsx b/src/domain/journey/space/FilterByTag/FilterButtons.tsx deleted file mode 100644 index 36b1d23cd4..0000000000 --- a/src/domain/journey/space/FilterByTag/FilterButtons.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import React, { PropsWithChildren, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; -import { Box, Button, ButtonProps, styled } from '@mui/material'; -import { differenceBy, keyBy, uniq, without } from 'lodash'; -import { Caption } from '../../../../core/ui/typography'; -import CloseIcon from '@mui/icons-material/Close'; -import { gutters } from '../../../../core/ui/grid/utils'; - -const showAllKey = 'show-all'; -const otherKey = 'other'; - -const StyledFilterList = styled(Box)(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - flexWrap: 'wrap', - gap: gutters(0.5)(theme), -})); - -interface FilterChipProps { - selected?: boolean; - canRemove?: boolean; - onClick?: ButtonProps['onClick']; -} - -const FilterChip = ({ children, selected = false, canRemove = false, onClick }: PropsWithChildren<FilterChipProps>) => { - return ( - <Button - sx={{ - height: gutters(1.5), - textTransform: 'none', - whiteSpace: 'nowrap', - }} - variant={selected ? 'contained' : 'outlined'} - endIcon={canRemove ? <CloseIcon /> : undefined} - onClick={onClick} - > - {children} - </Button> - ); -}; - -interface Category<Key extends string> { - name: string; - key: Key; - tags: string[]; -} - -interface FilterByTagButtonsProps<Option extends string> { - value: string[]; - config: Category<Option>[]; - onChange: (tags: string[]) => void; -} - -const optionallyAddOther = (tags: string[], showOther: boolean) => (showOther ? [...tags, otherKey] : tags); - -const removeMatchingTags = (source: readonly string[], tags: readonly string[]) => - differenceBy(source, tags, tag => tag.toLowerCase()); - -const FilterByTagButtons = <Option extends string>({ value, config, onChange }: FilterByTagButtonsProps<Option>) => { - const { t } = useTranslation(); - - const showAll = value.length === 0; - const tags = without(value, otherKey); - const showOther = value.includes(otherKey); - - const options = config.map(category => category.key); - const categoriesByKey = useMemo(() => keyBy(config, 'key'), [config]); - - const selectedCategories = options.filter(option => { - const categoryTags = categoriesByKey[option].tags; - return removeMatchingTags(categoryTags, tags).length === 0; - }); - - const unmatchedTags = tags.filter(tag => { - return !selectedCategories.some(option => { - const categoryTags = categoriesByKey[option].tags; - return categoryTags.includes(tag); - }); - }); - - const handleShowAll = () => onChange([]); - - const handleShowOther = () => { - onChange(optionallyAddOther(tags, true)); - }; - - const handleRemoveOther = () => { - onChange(optionallyAddOther(tags, false)); - }; - - const handleAddFilter = (option: Option) => { - const categoryTags = categoriesByKey[option].tags; - onChange(uniq(optionallyAddOther([...tags, ...categoryTags], showOther))); - }; - - const handleRemoveCategory = (option: Option) => { - const categoryTags = categoriesByKey[option].tags; - onChange(removeMatchingTags(value, categoryTags)); - }; - - const handleRemoveTag = (tag: string) => { - onChange(removeMatchingTags(value, [tag])); - }; - - return ( - <> - <StyledFilterList> - <Caption>{t('spaces-filter.current-filter')}</Caption> - {showAll && <FilterChip selected>{t(`spaces-filter.${showAllKey}` as const)}</FilterChip>} - {showOther && ( - <FilterChip selected canRemove onClick={handleRemoveOther}> - {t(`spaces-filter.${otherKey}` as const)} - </FilterChip> - )} - {selectedCategories.map(key => ( - <FilterChip key={key} selected canRemove onClick={() => handleRemoveCategory(key)}> - {categoriesByKey[key].name} - </FilterChip> - ))} - {unmatchedTags.map(tag => ( - <FilterChip key={tag} selected canRemove onClick={() => handleRemoveTag(tag)}> - {tag} - </FilterChip> - ))} - </StyledFilterList> - <StyledFilterList> - {without(options, ...selectedCategories).map(key => ( - <FilterChip key={key} onClick={() => handleAddFilter(key)}> - {categoriesByKey[key].name} - </FilterChip> - ))} - {!showOther && <FilterChip onClick={handleShowOther}>{t(`spaces-filter.${otherKey}` as const)}</FilterChip>} - {!showAll && <FilterChip onClick={handleShowAll}>{t(`spaces-filter.${showAllKey}` as const)}</FilterChip>} - </StyledFilterList> - </> - ); -}; - -export default FilterByTagButtons; diff --git a/src/domain/journey/space/FilterByTag/FilterByTag.tsx b/src/domain/journey/space/FilterByTag/FilterByTag.tsx deleted file mode 100644 index 3650df3330..0000000000 --- a/src/domain/journey/space/FilterByTag/FilterByTag.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React, { ReactNode, useMemo } from 'react'; -import useNavigate from '../../../../core/routing/useNavigate'; -import { Identifiable } from '../../../../core/utils/Identifiable'; -import filterFn, { ValueType } from '../../../../core/utils/filtering/filterFn'; -import { FILTER_PARAM_NAME } from '../../../../main/search/constants'; -import { useQueryParams } from '../../../../core/routing/useQueryParams'; -import { without } from 'lodash'; -import { useTranslation } from 'react-i18next'; - -const otherKey = 'other'; - -interface ChildProps<Item extends Identifiable> { - items: Item[]; - value: string[]; - handleChange: (value: string[]) => void; -} - -interface FilterByTagProps<Item extends Identifiable> { - items: Item[]; - valueGetter: (data: Item) => ValueType; - children: ({ items, value, handleChange }: ChildProps<Item>) => ReactNode; -} - -const FilterByTag = <Item extends Identifiable>({ items, valueGetter, children }: FilterByTagProps<Item>) => { - const navigate = useNavigate(); - const queryParams = useQueryParams(); - const { t } = useTranslation(); - - const termsFromUrl = useMemo(() => queryParams.getAll(FILTER_PARAM_NAME), [queryParams]); - - const tags = without(termsFromUrl, otherKey); - const showOther = termsFromUrl.includes(otherKey); - - const filterValues = t('spaces-filter.config', { returnObjects: true }) - .flatMap(category => category.tags) - .map(x => x.toLocaleLowerCase()); - - const updateQueryString = (nextTags: string[]) => { - const params = new URLSearchParams(window.location.search); - params.delete(FILTER_PARAM_NAME); - for (const tag of nextTags) { - params.append(FILTER_PARAM_NAME, tag); - } - navigate(`./?${params}`, { replace: true }); - }; - - // Items included in the results when the Other filter is selected - // Spaces that don't have any of the selectable filters - const itemsOther = useMemo( - () => - items - .filter(space => !valueGetter(space).values.some(tag => filterValues.includes(tag.toLowerCase()))) - .map(x => ({ ...x, matchedTerms: [] })), - [filterValues, items, valueGetter] - ); - - const filteredItems = useMemo(() => { - if (tags.length === 0) { - if (showOther) { - return itemsOther; // Show only others: - } else { - return items; // Show all - } - } else { - const filtered = filterFn(items, tags, valueGetter); // filter the items - if (showOther) { - return [...filtered, ...itemsOther]; - } else { - return filtered; - } - } - }, [items, tags, valueGetter, showOther, itemsOther]); - - return <>{children({ items: filteredItems, value: termsFromUrl, handleChange: updateQueryString })}</>; -}; - -export default FilterByTag; diff --git a/src/main/topLevelPages/myDashboard/DashboardContext.tsx b/src/main/topLevelPages/myDashboard/DashboardContext.tsx index 4138604fb3..5d9e826fc2 100644 --- a/src/main/topLevelPages/myDashboard/DashboardContext.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardContext.tsx @@ -10,8 +10,8 @@ const enum DashboardViews { interface DashboardContextProps { activityEnabled: boolean; setActivityEnabled: (item: boolean) => void; - openedDialog: DashboardDialog | undefined; - setOpenedDialog: (item: DashboardDialog | undefined) => void; + isOpen: DashboardDialog | undefined; + setIsOpen: (item: DashboardDialog | undefined) => void; } const DashboardContext = createContext<DashboardContextProps | undefined>(undefined); @@ -20,7 +20,7 @@ export const DashboardProvider = ({ children }: { children: ReactNode }) => { const cachedView = getCachedView(); const isActivityEnabled = cachedView === DashboardViews.ACTIVITY; const [activityEnabled, setEnabled] = useState<boolean>(isActivityEnabled); - const [openedDialog, setOpenedDialog] = useState<DashboardDialog | undefined>(undefined); + const [isOpen, setIsOpen] = useState<DashboardDialog>(); const setActivityEnabled = (val: boolean) => { setViewToCache(val ? DashboardViews.ACTIVITY : DashboardViews.SPACES); @@ -28,7 +28,7 @@ export const DashboardProvider = ({ children }: { children: ReactNode }) => { }; return ( - <DashboardContext.Provider value={{ activityEnabled, setActivityEnabled, openedDialog, setOpenedDialog }}> + <DashboardContext.Provider value={{ activityEnabled, setActivityEnabled, isOpen, setIsOpen }}> {children} </DashboardContext.Provider> ); diff --git a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx index 7d24a5cbbb..38ba268a95 100644 --- a/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardDialogs/DashboardDialogs.tsx @@ -11,31 +11,29 @@ import { useLatestContributionsSpacesFlatQuery } from '../../../../core/apollo/g const DashboardDialogs = () => { const { t } = useTranslation(); - const { openedDialog, setOpenedDialog } = useDashboardContext(); + const { isOpen, setIsOpen } = useDashboardContext(); const { data: spacesData } = useLatestContributionsSpacesFlatQuery(); const flatSpacesWithMemberships = spacesData?.me.spaceMembershipsFlat.map(membership => membership.space); return ( <> - <DialogWithGrid open={openedDialog === DashboardDialog.TipsAndTricks}> - <DialogHeader onClose={() => setOpenedDialog(undefined)}> - {t('pages.home.sections.tipsAndTricks.title')} - </DialogHeader> + <DialogWithGrid open={isOpen === DashboardDialog.TipsAndTricks}> + <DialogHeader onClose={() => setIsOpen(undefined)}>{t('pages.home.sections.tipsAndTricks.title')}</DialogHeader> <DialogContent> <TipsAndTricks /> </DialogContent> </DialogWithGrid> - <DialogWithGrid open={openedDialog === DashboardDialog.MyActivity}> - <DialogHeader onClose={() => setOpenedDialog(undefined)}> + <DialogWithGrid open={isOpen === DashboardDialog.MyActivity}> + <DialogHeader onClose={() => setIsOpen(undefined)}> {t('pages.home.sections.myLatestContributions.title')} </DialogHeader> <DialogContent> <MyLatestContributions spaceMemberships={flatSpacesWithMemberships} /> </DialogContent> </DialogWithGrid> - <DialogWithGrid open={openedDialog === DashboardDialog.MySpaceActivity}> - <DialogHeader onClose={() => setOpenedDialog(undefined)}> + <DialogWithGrid open={isOpen === DashboardDialog.MySpaceActivity}> + <DialogHeader onClose={() => setIsOpen(undefined)}> {t('pages.home.sections.latestContributions.title')} </DialogHeader> <DialogContent> diff --git a/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx b/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx index ccff547ea3..09849bdf43 100644 --- a/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardMenu/DashboardMenu.tsx @@ -28,7 +28,7 @@ import BadgeCounter from '../../../../core/ui/icon/BadgeCounter'; */ export const DashboardMenu = ({ compact = false }: DashboardMenuProps) => { const { t } = useTranslation(); - const { activityEnabled, setActivityEnabled, setOpenedDialog } = useDashboardContext(); + const { activityEnabled, setActivityEnabled, setIsOpen } = useDashboardContext(); const { items, loading: itemsConfigLoading } = useHomeMenuItems(); const { setOpenDialog } = usePendingMembershipsDialog(); @@ -43,7 +43,7 @@ export const DashboardMenu = ({ compact = false }: DashboardMenuProps) => { const getTranslationByKey = (key: string) => t(`${key}` as TranslationKey, { defaultValue: key }); - const openDialog = (dialog: DashboardDialog | undefined) => () => setOpenedDialog(dialog); + const openDialog = (dialog: DashboardDialog | undefined) => () => setIsOpen(dialog); const getItemContent = (item: MenuOptionProps) => ( <> diff --git a/src/main/topLevelPages/myDashboard/DashboardWithMemberships/DashboardActivity.tsx b/src/main/topLevelPages/myDashboard/DashboardWithMemberships/DashboardActivity.tsx index b7b8ecd45d..0ce8605f1c 100644 --- a/src/main/topLevelPages/myDashboard/DashboardWithMemberships/DashboardActivity.tsx +++ b/src/main/topLevelPages/myDashboard/DashboardWithMemberships/DashboardActivity.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import RecentSpacesList from '../recentSpaces/RecentJourneysList'; +import RecentJourneysList from '../recentSpaces/RecentJourneysList'; import LatestContributions from '../latestContributions/LatestContributions'; import MyLatestContributions from '../latestContributions/myLatestContributions/MyLatestContributions'; import MyMembershipsDialog from '../myMemberships/MyMembershipsDialog'; @@ -20,7 +20,7 @@ const DashboardActivity = () => { return ( <> - <RecentSpacesList onSeeMore={() => setIsMyMembershipsDialogOpen(true)} /> + <RecentJourneysList onSeeMore={() => setIsMyMembershipsDialogOpen(true)} /> <PageContentColumn columns={columns / 2}> <PageContentBlock> <PageContentBlockHeader title={t('pages.home.sections.latestContributions.title')} /> diff --git a/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx b/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx index 0e238db26b..6462e12d91 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx @@ -2,7 +2,7 @@ import React, { Suspense } from 'react'; import PageContentColumn from '../../../core/ui/content/PageContentColumn'; import ReleaseNotesBanner from './releaseNotesBanner/ReleaseNotesBanner'; import { useLatestReleaseDiscussionQuery } from '../../../core/apollo/generated/apollo-hooks'; -import CampaignBlock from './campaignBlock/CampaignBlock'; +import CampaignBlock from './CampaignBlock/CampaignBlock'; import InfoColumn from '../../../core/ui/content/InfoColumn'; import { DashboardMenu } from './DashboardMenu/DashboardMenu'; import ContentColumn from '../../../core/ui/content/ContentColumn'; diff --git a/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx b/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx index c039f94f5a..80712470c8 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx @@ -1,6 +1,6 @@ import React, { Suspense } from 'react'; import PageContentColumn from '../../../core/ui/content/PageContentColumn'; -import CampaignBlock from './campaignBlock/CampaignBlock'; +import CampaignBlock from './CampaignBlock/CampaignBlock'; import InfoColumn from '../../../core/ui/content/InfoColumn'; import ContentColumn from '../../../core/ui/content/ContentColumn'; import { useLatestReleaseDiscussionQuery } from '../../../core/apollo/generated/apollo-hooks'; diff --git a/src/main/topLevelPages/myDashboard/exploreOtherChallenges/DashboardSpaces.graphql b/src/main/topLevelPages/myDashboard/exploreOtherChallenges/DashboardSpaces.graphql deleted file mode 100644 index b53a58dca1..0000000000 --- a/src/main/topLevelPages/myDashboard/exploreOtherChallenges/DashboardSpaces.graphql +++ /dev/null @@ -1,16 +0,0 @@ -query DashboardSpaces($visibilities: [SpaceVisibility!] = [ACTIVE]) { - spaces(filter: { visibilities: $visibilities }) { - ...SpaceCard - } -} - -query DashboardSpacesPaginated($first: Int!, $after: UUID, $visibilities: [SpaceVisibility!] = [ACTIVE]) { - spacesPaginated(first: $first, after: $after, filter: { visibilities: $visibilities }) { - spaces { - ...SpaceCard - } - pageInfo { - ...PageInfo - } - } -} diff --git a/src/main/topLevelPages/myDashboard/exploreOtherChallenges/ExploreOtherChallenges.tsx b/src/main/topLevelPages/myDashboard/exploreOtherChallenges/ExploreOtherChallenges.tsx deleted file mode 100644 index 34b3771a15..0000000000 --- a/src/main/topLevelPages/myDashboard/exploreOtherChallenges/ExploreOtherChallenges.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React, { useMemo } from 'react'; -import { Box } from '@mui/material'; -import DashboardSpacesSection, { - DashboardSpaceSectionProps, -} from '../../../../domain/shared/components/DashboardSections/DashboardSpacesSection'; -import { useDashboardSpacesPaginatedQuery } from '../../../../core/apollo/generated/apollo-hooks'; -import Loading from '../../../../core/ui/loading/Loading'; -import useTranslationWithLineBreaks from '../../../../core/ui/typography/useTranslationWithLineBreaks'; -import { - CommunityMembershipStatus, - DashboardSpacesPaginatedQuery, - DashboardSpacesPaginatedQueryVariables, - SpacePrivacyMode, - SpaceVisibility, -} from '../../../../core/apollo/generated/graphql-schema'; -import FilterByTag from '../../../../domain/journey/space/FilterByTag/FilterByTag'; -import FilterButtons from '../../../../domain/journey/space/FilterByTag/FilterButtons'; -import { useTranslation } from 'react-i18next'; -import useLazyLoading from '../../../../domain/shared/pagination/useLazyLoading'; -import usePaginatedQuery from '../../../../domain/shared/pagination/usePaginatedQuery'; - -const SPACES_PAGE_SIZE = 10; - -const ExploreOtherChallenges = () => { - const { t: tLineBreaks } = useTranslationWithLineBreaks(); - const { t: tRaw } = useTranslation(); - - const spacesQueryResult = usePaginatedQuery<DashboardSpacesPaginatedQuery, DashboardSpacesPaginatedQueryVariables>({ - useQuery: useDashboardSpacesPaginatedQuery, - options: { - fetchPolicy: 'cache-first', - nextFetchPolicy: 'cache-first', - }, - variables: { - visibilities: [SpaceVisibility.Active], - }, - pageSize: SPACES_PAGE_SIZE, - getPageInfo: result => result.spacesPaginated.pageInfo, - }); - - const spaces = { - items: spacesQueryResult.data?.spacesPaginated.spaces, - loading: spacesQueryResult.loading, - hasMore: spacesQueryResult.hasMore, - pageSize: spacesQueryResult.pageSize, - firstPageSize: spacesQueryResult.firstPageSize, - error: spacesQueryResult.error, - fetchMore: spacesQueryResult.fetchMore, - }; - - const spacesLoader = useLazyLoading(Box, { - hasMore: spaces.hasMore || false, - loading: spaces.loading || false, - fetchMore: () => spaces.fetchMore(), - }); - - const getSpaceCardProps: DashboardSpaceSectionProps<{ - settings?: { - privacy?: { - mode: SpacePrivacyMode; - }; - }; - community?: { - roleSet?: { - myMembershipStatus?: CommunityMembershipStatus; - }; - }; - }>['getSpaceCardProps'] = space => { - return { - locked: space.settings?.privacy?.mode === SpacePrivacyMode.Private, - member: space.community?.roleSet?.myMembershipStatus === CommunityMembershipStatus.Member, - }; - }; - - const spaceItems = useMemo( - () => - (spaces.items ?? []).filter( - space => space.community?.roleSet?.myMembershipStatus !== CommunityMembershipStatus.Member - ) ?? [], - [spaces.items?.length] - ); - - return ( - <FilterByTag - items={spaceItems} - valueGetter={space => ({ id: space.id, values: space?.profile.tagset?.tags ?? [] })} - > - {({ items: filteredSpaces, value, handleChange }) => ( - <DashboardSpacesSection - headerText={tLineBreaks('pages.home.sections.exploreOtherSubspaces.header')} - spaces={filteredSpaces} - getSpaceCardProps={getSpaceCardProps} - loader={spacesLoader} - scrollable - > - <FilterButtons - value={value} - config={tRaw('spaces-filter.config', { returnObjects: true })} - onChange={handleChange} - /> - {spaces.loading && <Loading />} - </DashboardSpacesSection> - )} - </FilterByTag> - ); -}; - -export default ExploreOtherChallenges; diff --git a/src/main/topLevelPages/myDashboard/innovationLibraryBlock/InnovationLibraryBlock.graphql b/src/main/topLevelPages/myDashboard/innovationLibraryBlock/InnovationLibraryBlock.graphql deleted file mode 100644 index be6c4ec8f2..0000000000 --- a/src/main/topLevelPages/myDashboard/innovationLibraryBlock/InnovationLibraryBlock.graphql +++ /dev/null @@ -1,36 +0,0 @@ -query InnovationLibraryBlock { - platform { - id - library { - id - innovationPacks(queryData: { limit: 1, orderBy: RANDOM }) { - ...InnovationPackCard - } - } - } -} - -fragment InnovationPackCard on InnovationPack { - id - nameID - profile { - id - displayName - description - tagset { - ...TagsetDetails - } - url - } - templatesSet { - id - postTemplatesCount - whiteboardTemplatesCount - innovationFlowTemplatesCount - calloutTemplatesCount - communityGuidelinesTemplatesCount - } - provider { - ...InnovationPackProviderProfileWithAvatar - } -} diff --git a/src/main/topLevelPages/myDashboard/innovationLibraryBlock/InnovationLibraryBlock.tsx b/src/main/topLevelPages/myDashboard/innovationLibraryBlock/InnovationLibraryBlock.tsx deleted file mode 100644 index 12de3edb14..0000000000 --- a/src/main/topLevelPages/myDashboard/innovationLibraryBlock/InnovationLibraryBlock.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { FC } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useInnovationLibraryBlockQuery } from '../../../../core/apollo/generated/apollo-hooks'; -import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; -import PageContentBlockHeader from '../../../../core/ui/content/PageContentBlockHeader'; -import SeeMore from '../../../../core/ui/content/SeeMore'; -import { Box } from '@mui/material'; -import InnovationPackCard from '../../../../domain/InnovationPack/InnovationPackCard/InnovationPackCard'; -import useInnovationPackCardProps from '../../../../domain/InnovationPack/DashboardInnovationPacks/useInnovationPackCardProps'; -import { gutters } from '../../../../core/ui/grid/utils'; -import ContributeCardSkeleton from '../../../../core/ui/card/ContributeCardSkeleton'; -import GridProvider from '../../../../core/ui/grid/GridProvider'; -import { CONTRIBUTE_CARD_COLUMNS } from '../../../../core/ui/card/ContributeCard'; -import { useColumns } from '../../../../core/ui/grid/GridContext'; - -interface InnovationLibraryBlockProps { - halfWidth?: boolean; -} - -const InnovationLibraryBlock: FC<InnovationLibraryBlockProps> = ({ halfWidth }) => { - const { t } = useTranslation(); - const { data, loading } = useInnovationLibraryBlockQuery(); - const innovationPacks = useInnovationPackCardProps(data?.platform.library.innovationPacks); - const innovationPack = innovationPacks && innovationPacks.length > 0 ? innovationPacks[0] : undefined; - const isMobile = useColumns() <= 4; - - if (!loading && !innovationPack) { - return null; - } - - return ( - <PageContentBlock halfWidth={halfWidth}> - <PageContentBlockHeader title={t('pages.home.sections.innovationLibraryBlock.title')} /> - <Box display="flex" gap={gutters()} flexWrap={isMobile ? 'wrap' : 'nowrap'} justifyContent="center"> - <GridProvider columns={CONTRIBUTE_CARD_COLUMNS} force> - {loading && <ContributeCardSkeleton />} - {!loading && innovationPack && <InnovationPackCard columns={2} {...innovationPack} />} - </GridProvider> - </Box> - <SeeMore label="pages.home.sections.innovationLibraryBlock.seeMore" to="/innovation-library" /> - </PageContentBlock> - ); -}; - -export default InnovationLibraryBlock; diff --git a/src/main/topLevelPages/myDashboard/membershipSuggestions/MembershipSuggestions.graphql b/src/main/topLevelPages/myDashboard/membershipSuggestions/MembershipSuggestions.graphql deleted file mode 100644 index 527662fcd5..0000000000 --- a/src/main/topLevelPages/myDashboard/membershipSuggestions/MembershipSuggestions.graphql +++ /dev/null @@ -1,22 +0,0 @@ -query MembershipSuggestionSpace($spaceNameId: UUID_NAMEID!) { - space(ID: $spaceNameId) { - id - nameID - profile { - id - displayName - tagline - url - avatar: visual(type: CARD) { - ...VisualUri - } - } - community { - id - roleSet { - id - myRoles - } - } - } -} diff --git a/src/main/topLevelPages/myDashboard/membershipSuggestions/MembershipSuggestions.tsx b/src/main/topLevelPages/myDashboard/membershipSuggestions/MembershipSuggestions.tsx deleted file mode 100644 index e9bbf47188..0000000000 --- a/src/main/topLevelPages/myDashboard/membershipSuggestions/MembershipSuggestions.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { FC, useState } from 'react'; -import useNavigate from '../../../../core/routing/useNavigate'; -import { useLocation } from 'react-router-dom'; -import PageContentBlockGrid from '../../../../core/ui/content/PageContentBlockGrid'; -import PageContentBlockHeader from '../../../../core/ui/content/PageContentBlockHeader'; -import { useTranslation } from 'react-i18next'; -import RocketLaunchOutlinedIcon from '@mui/icons-material/RocketLaunchOutlined'; -import { BlockSectionTitle } from '../../../../core/ui/typography'; -import JourneyCardHorizontal, { - JourneyCardHorizontalSkeleton, -} from '../../../../domain/journey/common/JourneyCardHorizontal/JourneyCardHorizontal'; -import { useMembershipSuggestionSpaceQuery } from '../../../../core/apollo/generated/apollo-hooks'; -import MultipleSelect from '../../../../core/ui/search/MultipleSelect'; -import SearchSuggestions from '../../../../core/ui/search/SearchSuggestions'; -import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; -import GridItem from '../../../../core/ui/grid/GridItem'; -import { SEARCH_TERMS_URL_PARAM } from '../../../search/constants'; -import Gutters from '../../../../core/ui/grid/Gutters'; - -const MembershipSuggestions: FC = () => { - const { t } = useTranslation(); - const navigate = useNavigate(); - const { pathname } = useLocation(); - const [filter, setFilter] = useState<string[]>([]); - - const { data, loading } = useMembershipSuggestionSpaceQuery({ - variables: { - // Id of the space suggested is coming from the translation: - spaceNameId: t('pages.home.sections.membershipSuggestions.suggestedSpace.nameId'), - }, - errorPolicy: 'ignore', - }); - - const handleNavigateToSearchPage = (terms: string[]) => { - if (!terms.length) { - return; - } - const params = new URLSearchParams(); - terms.forEach(term => params.append(SEARCH_TERMS_URL_PARAM, term)); - navigate(`${pathname}?${params}`); - }; - - return ( - <PageContentBlock disableGap disablePadding columns={8}> - <PageContentBlockGrid> - <PageContentBlockHeader - icon={<RocketLaunchOutlinedIcon />} - title={t('pages.home.sections.membershipSuggestions.title')} - fullWidth - /> - <GridItem columns={4}> - <Gutters disablePadding> - <BlockSectionTitle>{t('pages.home.sections.membershipSuggestions.suggestedSpace.join')}</BlockSectionTitle> - {loading && <JourneyCardHorizontalSkeleton />} - {!loading && data?.space && ( - <JourneyCardHorizontal - journeyTypeName="space" - journey={data.space} - deepness={0} - sx={{ display: 'inline-block', maxWidth: '100%' }} - /> - )} - </Gutters> - </GridItem> - <GridItem columns={4}> - <Gutters disablePadding> - <BlockSectionTitle> - {t('pages.home.sections.membershipSuggestions.searchCommunity.title')} - </BlockSectionTitle> - <MultipleSelect - onChange={setFilter} - onSearchClick={handleNavigateToSearchPage} - value={filter} - minLength={2} - size="small" - /> - <SearchSuggestions - title={t('pages.home.sections.membershipSuggestions.searchCommunity.searchSuggestions')} - options={t('pages.home.sections.membershipSuggestions.suggestionsArray', { returnObjects: true })} - onSelect={term => setFilter([...filter, term].slice(0, 5))} - value={filter} - /> - </Gutters> - </GridItem> - </PageContentBlockGrid> - </PageContentBlock> - ); -}; - -export default MembershipSuggestions; diff --git a/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipCard.tsx b/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipCard.tsx deleted file mode 100644 index 4f42baf184..0000000000 --- a/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipCard.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import BadgeCardView from '../../../../core/ui/list/BadgeCardView'; -import { SpaceDetails } from '../../../../domain/community/pendingMembership/PendingMemberships'; -import { Avatar, ButtonBase, ListItemButton, ListItemButtonProps, ListItemButtonTypeMap } from '@mui/material'; -import { Caption } from '../../../../core/ui/typography'; -import { Trans, useTranslation } from 'react-i18next'; -import { gutters } from '../../../../core/ui/grid/utils'; -import defaultJourneyAvatar from '../../../../domain/journey/defaultVisuals/Avatar.jpg'; - -interface NewMembershipCardProps { - space: SpaceDetails | undefined; - to?: string; - onClick?: () => void; - membershipType: 'application' | 'invitation' | 'membership'; -} - -const Wrapper = <D extends React.ElementType = ListItemButtonTypeMap['defaultComponent'], P = {}>({ - ...props -}: ListItemButtonProps<D, P>) => <ListItemButton component={ButtonBase} {...props} />; - -const NewMembershipCard = ({ space, to, onClick, membershipType }: NewMembershipCardProps) => { - const { t } = useTranslation(); - - return ( - <BadgeCardView - component={Wrapper} - visual={<Avatar src={space?.profile.visual?.uri || defaultJourneyAvatar} />} - to={to} - onClick={onClick} - sx={{ textAlign: 'left', paddingLeft: gutters(0.5), width: '100%' }} - > - <Caption whiteSpace="nowrap" overflow="hidden" textOverflow="ellipsis"> - <Trans - t={t} - i18nKey={`pages.home.sections.newMemberships.${membershipType}.message` as const} - components={{ - b: <strong />, - }} - values={{ - journey: space?.profile.displayName, - }} - /> - </Caption> - <Caption color={theme => theme.palette.neutral.light}> - {t(`pages.home.sections.newMemberships.${membershipType}.caption` as const, { - tagline: space?.profile.tagline, - })} - </Caption> - </BadgeCardView> - ); -}; - -export default NewMembershipCard; diff --git a/src/main/topLevelPages/myDashboard/newMemberships/NewMemberships.graphql b/src/main/topLevelPages/myDashboard/newMemberships/NewMemberships.graphql deleted file mode 100644 index d1f71be758..0000000000 --- a/src/main/topLevelPages/myDashboard/newMemberships/NewMemberships.graphql +++ /dev/null @@ -1,48 +0,0 @@ -query NewMemberships { - me { - communityApplications(states: ["new", "approved"]) { - id - spacePendingMembershipInfo { - ...NewMembershipsBasicSpace - } - application { - id - lifecycle { - id - state - } - createdDate - } - } - communityInvitations(states: ["invited", "accepted"]) { - id - spacePendingMembershipInfo { - ...NewMembershipsBasicSpace - } - invitation { - id - welcomeMessage - contributorType - createdBy { - id - } - lifecycle { - id - state - } - createdDate - } - } - } -} - -fragment NewMembershipsBasicSpace on SpacePendingMembershipInfo { - id - level - profile { - id - displayName - tagline - url - } -} \ No newline at end of file diff --git a/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipsBlock.md b/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipsBlock.md deleted file mode 100644 index 875e6e23d3..0000000000 --- a/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipsBlock.md +++ /dev/null @@ -1,25 +0,0 @@ -# NewMembershipsBlock Documentation - -## Overview - -A widget on My Dashboard - -## Function - -It shows the Pending Invites and Applications. User can Accept / Reject an invite through it. - -### Details - -The logic of the block is as follows: - -1. Show up to 4 (PENDING_MEMBERSHIPS_MAX_ITEMS) **Invitations**; -2. Then show up to 4 (minus the length of the invitations) **Applications**; -3. If there are more than PENDING_MEMBERSHIPS_MAX_ITEMS items, show a 'seeMore' button. - -'seeMore' opens all Pending Invitations Dialog. - -The user can accept/reject the individual invitations. - -#### History - -The block used to list recentMemberships & MySpaces. diff --git a/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipsBlock.tsx b/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipsBlock.tsx deleted file mode 100644 index fa752d290d..0000000000 --- a/src/main/topLevelPages/myDashboard/newMemberships/NewMembershipsBlock.tsx +++ /dev/null @@ -1,309 +0,0 @@ -import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; -import PageContentBlockHeader from '../../../../core/ui/content/PageContentBlockHeader'; -import { useTranslation } from 'react-i18next'; -import { BlockSectionTitle, CaptionSmall } from '../../../../core/ui/typography'; -import { gutters } from '../../../../core/ui/grid/utils'; -import { - ApplicationHydrator, - InvitationHydrator, - InvitationWithMeta, -} from '../../../../domain/community/pendingMembership/PendingMemberships'; -import InvitationCardHorizontal from '../../../../domain/community/invitations/InvitationCardHorizontal/InvitationCardHorizontal'; -import React, { useMemo, useState } from 'react'; -import { useNewMembershipsQuery } from '../../../../core/apollo/generated/apollo-hooks'; -import { sortBy } from 'lodash'; -import DialogWithGrid from '../../../../core/ui/dialog/DialogWithGrid'; -import DialogHeader from '../../../../core/ui/dialog/DialogHeader'; -import Gutters from '../../../../core/ui/grid/Gutters'; -import { HdrStrongOutlined } from '@mui/icons-material'; -import ScrollableCardsLayoutContainer from '../../../../core/ui/card/cardsLayout/ScrollableCardsLayoutContainer'; -import JourneyCard from '../../../../domain/journey/common/JourneyCard/JourneyCard'; -import spaceIcon from '../../../../domain/shared/components/JourneyIcon/JourneyIcon'; -import JourneyCardTagline from '../../../../domain/journey/common/JourneyCard/JourneyCardTagline'; -import InvitationActionsContainer from '../../../../domain/community/invitations/InvitationActionsContainer'; -import InvitationDialog from '../../../../domain/community/invitations/InvitationDialog'; -import NewMembershipCard from './NewMembershipCard'; -import SeeMore from '../../../../core/ui/content/SeeMore'; -import { CommunityContributorType, VisualType } from '../../../../core/apollo/generated/graphql-schema'; -import BadgeCounter from '../../../../core/ui/icon/BadgeCounter'; -import HorizontalCardsGroup from '../../../../core/ui/content/HorizontalCardsGroup'; -import useNavigate from '../../../../core/routing/useNavigate'; -import { PendingApplication } from '../../../../domain/community/user'; -import { InvitationItem } from '../../../../domain/community/user/providers/UserProvider/InvitationItem'; -import { getChildJourneyTypeName } from '../../../../domain/shared/utils/spaceLevel'; - -enum PendingMembershipItemType { - Invitation, - Application, -} - -enum DialogType { - PendingMembershipsList, - InvitationView, -} - -interface DialogDetails { - type: DialogType; -} - -interface PendingMembershipsListDialogDetails extends DialogDetails { - type: DialogType.PendingMembershipsList; - journeyUri?: string; -} - -interface InvitationViewDialogDetails extends DialogDetails { - type: DialogType.InvitationView; - invitationId: string; - from: 'dialog' | 'card'; - journeyUri?: string; -} - -const PENDING_MEMBERSHIPS_MAX_ITEMS = 4; - -const RECENT_MEMBERSHIP_STATES = ['approved', 'accepted']; - -interface NewMembershipsBlockProps { - hiddenIfEmpty?: boolean; -} - -const NewMembershipsBlock = ({ hiddenIfEmpty = false }: NewMembershipsBlockProps) => { - const { t } = useTranslation(); - - const navigate = useNavigate(); - - const { data, refetch: refetchNewMembershipsQuery } = useNewMembershipsQuery(); - - const communityInvitations = useMemo( - () => - data?.me.communityInvitations.map( - invitation => - ({ - type: PendingMembershipItemType.Invitation, - ...(invitation as InvitationItem), - } as const) - ) ?? [], - [data?.me.communityInvitations] - ); - - const pendingCommunityInvitations = useMemo( - () => - sortBy( - communityInvitations.filter( - ({ invitation }) => !RECENT_MEMBERSHIP_STATES.includes(invitation.lifecycle.state ?? '') - ), - ({ invitation }) => invitation.createdDate - ).reverse(), - [communityInvitations] - ); - - const communityApplications = useMemo( - () => - data?.me.communityApplications.map( - application => - ({ - type: PendingMembershipItemType.Application, - ...(application as PendingApplication), - } as const) - ) ?? [], - [data?.me.communityApplications] - ); - - const pendingCommunityApplications = communityApplications.filter( - ({ application }) => !RECENT_MEMBERSHIP_STATES.includes(application.lifecycle.state ?? '') - ); - - const newestPendingApplications = useMemo( - () => - sortBy(pendingCommunityApplications, ({ application }) => application.createdDate) - .reverse() - .slice(0, Math.max(0, PENDING_MEMBERSHIPS_MAX_ITEMS - pendingCommunityInvitations.length)), - [communityApplications] - ); - - const pendingMembershipsCount = pendingCommunityInvitations.length + pendingCommunityApplications.length; - - const [openDialog, setOpenDialog] = useState<PendingMembershipsListDialogDetails | InvitationViewDialogDetails>(); - - const closeDialog = () => setOpenDialog(undefined); - - const handleInvitationCardClick = ( - { id, space, invitation }: InvitationWithMeta, - from: InvitationViewDialogDetails['from'] - ) => { - setOpenDialog({ - type: DialogType.InvitationView, - invitationId: id, - from, - journeyUri: invitation.contributorType === CommunityContributorType.Virtual ? undefined : space.profile.url, - }); - }; - - const currentInvitation = - openDialog?.type === DialogType.InvitationView - ? communityInvitations?.find(invitation => invitation.id === openDialog.invitationId) - : undefined; - - const handleInvitationDialogClose = () => { - setOpenDialog(openDialog => { - return openDialog && 'from' in openDialog && openDialog.from === 'card' - ? undefined - : { type: DialogType.PendingMembershipsList }; - }); - }; - - const onInvitationAccept = () => { - refetchNewMembershipsQuery(); - - if (openDialog?.journeyUri) { - navigate(openDialog?.journeyUri); - } else { - setOpenDialog({ type: DialogType.PendingMembershipsList }); - } - }; - - const onInvitationReject = () => { - refetchNewMembershipsQuery(); - setOpenDialog({ type: DialogType.PendingMembershipsList }); - }; - - if (pendingMembershipsCount === 0 && hiddenIfEmpty) { - return null; - } - - return ( - <> - <PageContentBlock columns={4} disableGap flex> - <PageContentBlockHeader title={t('pages.home.sections.newMemberships.title')} /> - - {pendingCommunityInvitations.length === 0 && newestPendingApplications.length === 0 && ( - <CaptionSmall color={theme => theme.palette.neutral.light} marginBottom={gutters(0.5)}> - {t('pages.home.sections.newMemberships.noOpenInvitations')} - </CaptionSmall> - )} - - <HorizontalCardsGroup - title={ - <> - {t('pages.home.sections.newMemberships.openInvitations')} - <BadgeCounter count={pendingCommunityInvitations.length} size="small" /> - </> - } - > - {pendingCommunityInvitations.slice(0, PENDING_MEMBERSHIPS_MAX_ITEMS).map(pendingInvitation => ( - <InvitationHydrator - key={pendingInvitation.id} - invitation={pendingInvitation} - withJourneyDetails - visualType={VisualType.Avatar} - > - {({ invitation }) => ( - <NewMembershipCard - space={invitation?.space} - onClick={() => invitation && handleInvitationCardClick(invitation, 'card')} - membershipType="invitation" - /> - )} - </InvitationHydrator> - ))} - </HorizontalCardsGroup> - - <HorizontalCardsGroup title={t('pages.home.sections.newMemberships.openApplications')}> - {newestPendingApplications.map(pendingApplication => ( - <ApplicationHydrator - key={pendingApplication.id} - application={pendingApplication as PendingApplication} - visualType={VisualType.Avatar} - > - {({ application: hydratedApplication }) => ( - <NewMembershipCard - space={hydratedApplication?.space} - to={hydratedApplication?.space.profile.url} - membershipType="application" - /> - )} - </ApplicationHydrator> - ))} - </HorizontalCardsGroup> - - {pendingMembershipsCount > PENDING_MEMBERSHIPS_MAX_ITEMS && ( - <SeeMore - sx={{ marginTop: gutters() }} - label="pages.home.sections.newMemberships.seeMore" - onClick={() => setOpenDialog({ type: DialogType.PendingMembershipsList })} - /> - )} - </PageContentBlock> - <DialogWithGrid columns={12} open={openDialog?.type === DialogType.PendingMembershipsList} onClose={closeDialog}> - <DialogHeader - title={ - <Gutters row disablePadding> - <HdrStrongOutlined fontSize="small" /> - {t('community.pendingMembership.pendingMemberships')} - </Gutters> - } - onClose={closeDialog} - /> - <Gutters paddingTop={0}> - {pendingCommunityInvitations && pendingCommunityInvitations.length > 0 && ( - <> - <BlockSectionTitle> - {t('community.pendingMembership.invitationsSectionTitle')} - <BadgeCounter count={pendingCommunityInvitations.length} size="small" /> - </BlockSectionTitle> - {pendingCommunityInvitations?.map(invitation => ( - <InvitationHydrator key={invitation.id} invitation={invitation}> - {({ invitation }) => ( - <InvitationCardHorizontal - invitation={invitation} - onClick={() => invitation && handleInvitationCardClick(invitation, 'dialog')} - /> - )} - </InvitationHydrator> - ))} - </> - )} - {pendingCommunityApplications && pendingCommunityApplications.length > 0 && ( - <> - <BlockSectionTitle>{t('community.pendingMembership.applicationsSectionTitle')}</BlockSectionTitle> - <ScrollableCardsLayoutContainer> - {pendingCommunityApplications?.map(applicationItem => ( - <ApplicationHydrator - key={applicationItem.id} - application={applicationItem} - visualType={VisualType.Card} - > - {({ application: hydratedApplication }) => - hydratedApplication && ( - <JourneyCard - iconComponent={spaceIcon[getChildJourneyTypeName(hydratedApplication.space)]} - header={hydratedApplication.space.profile.displayName} - tags={hydratedApplication.space.profile.tagset?.tags ?? []} - banner={hydratedApplication.space.profile.visual} - journeyUri={hydratedApplication.space.profile.url} - > - <JourneyCardTagline>{hydratedApplication.space.profile.tagline ?? ''}</JourneyCardTagline> - </JourneyCard> - ) - } - </ApplicationHydrator> - ))} - </ScrollableCardsLayoutContainer> - </> - )} - </Gutters> - </DialogWithGrid> - <InvitationActionsContainer onAccept={onInvitationAccept} onReject={onInvitationReject}> - {props => ( - <InvitationDialog - open={openDialog?.type === DialogType.InvitationView} - onClose={handleInvitationDialogClose} - invitation={currentInvitation} - {...props} - /> - )} - </InvitationActionsContainer> - </> - ); -}; - -export default NewMembershipsBlock; diff --git a/src/main/topLevelPages/myDashboard/recentForumMessages/RecentForumMessages.graphql b/src/main/topLevelPages/myDashboard/recentForumMessages/RecentForumMessages.graphql deleted file mode 100644 index 6b770df247..0000000000 --- a/src/main/topLevelPages/myDashboard/recentForumMessages/RecentForumMessages.graphql +++ /dev/null @@ -1,30 +0,0 @@ -query recentForumMessages($limit: Float = 5) { - platform { - id - forum { - id - discussionCategories - authorization { - id - myPrivileges - anonymousReadAccess - } - discussions(queryData: { orderBy: DISCUSSIONS_CREATEDATE_DESC, limit: $limit }) { - ...DiscussionCard - } - } - } -} - -fragment VisualFull on Visual { - id - uri - name - allowedTypes - aspectRatio - maxHeight - maxWidth - minHeight - minWidth - alternativeText -} diff --git a/src/main/topLevelPages/myDashboard/recentForumMessages/RecentForumMessages.tsx b/src/main/topLevelPages/myDashboard/recentForumMessages/RecentForumMessages.tsx deleted file mode 100644 index 68ccbe962d..0000000000 --- a/src/main/topLevelPages/myDashboard/recentForumMessages/RecentForumMessages.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { FC } from 'react'; -import PageContentBlock from '../../../../core/ui/content/PageContentBlock'; -import { useRecentForumMessagesQuery } from '../../../../core/apollo/generated/apollo-hooks'; -import { useTranslation } from 'react-i18next'; -import PageContentBlockHeader from '../../../../core/ui/content/PageContentBlockHeader'; -import SeeMore from '../../../../core/ui/content/SeeMore'; -import { DiscussionListView } from '../../../../domain/communication/discussion/views/DiscussionsListView'; -import { useDiscussionMapper } from '../../../../domain/communication/discussion/models/Discussion'; -import { compact } from 'lodash'; -import useNavigate from '../../../../core/routing/useNavigate'; - -interface RecentForumMessagesProps {} - -const RecentForumMessages: FC<RecentForumMessagesProps> = () => { - const { t } = useTranslation(); - const navigate = useNavigate(); - const { data, loading: loadingDiscussions } = useRecentForumMessagesQuery(); - - const { discussionMapper } = useDiscussionMapper(compact(data?.platform.forum.discussions?.map(d => d.createdBy))); - - const handleClickDiscussion = (discussionUrl: string) => { - navigate(discussionUrl); - }; - - return ( - <PageContentBlock> - <PageContentBlockHeader title={t('pages.home.sections.forumMessages.title')} /> - <DiscussionListView - entities={{ - discussions: data?.platform.forum.discussions?.map(discussionMapper) ?? [], - }} - state={{ loading: loadingDiscussions }} - actions={{ - onClickDiscussion: discussion => handleClickDiscussion(discussion.url), - }} - options={{ filterEnabled: false }} - /> - <SeeMore label="pages.home.sections.forumMessages.seeMore" to="/forum" /> - </PageContentBlock> - ); -}; - -export default RecentForumMessages; From 4b307ea4f5fd9aacf1d43ff040f00b9ab1dbdad2 Mon Sep 17 00:00:00 2001 From: bobbykolev <bobbykolev@abv.bg> Date: Wed, 30 Oct 2024 14:50:04 +0200 Subject: [PATCH 8/8] fix git capitalization issue --- .../{campaignBlock => Campaigns}/CampaignBlock.graphql | 0 .../myDashboard/{campaignBlock => Campaigns}/CampaignBlock.tsx | 0 .../{campaignBlock => Campaigns}/CampaignBlockCreateVC.tsx | 0 .../topLevelPages/myDashboard/MyDashboardWithMemberships.tsx | 2 +- .../topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx | 2 +- 5 files changed, 2 insertions(+), 2 deletions(-) rename src/main/topLevelPages/myDashboard/{campaignBlock => Campaigns}/CampaignBlock.graphql (100%) rename src/main/topLevelPages/myDashboard/{campaignBlock => Campaigns}/CampaignBlock.tsx (100%) rename src/main/topLevelPages/myDashboard/{campaignBlock => Campaigns}/CampaignBlockCreateVC.tsx (100%) diff --git a/src/main/topLevelPages/myDashboard/campaignBlock/CampaignBlock.graphql b/src/main/topLevelPages/myDashboard/Campaigns/CampaignBlock.graphql similarity index 100% rename from src/main/topLevelPages/myDashboard/campaignBlock/CampaignBlock.graphql rename to src/main/topLevelPages/myDashboard/Campaigns/CampaignBlock.graphql diff --git a/src/main/topLevelPages/myDashboard/campaignBlock/CampaignBlock.tsx b/src/main/topLevelPages/myDashboard/Campaigns/CampaignBlock.tsx similarity index 100% rename from src/main/topLevelPages/myDashboard/campaignBlock/CampaignBlock.tsx rename to src/main/topLevelPages/myDashboard/Campaigns/CampaignBlock.tsx diff --git a/src/main/topLevelPages/myDashboard/campaignBlock/CampaignBlockCreateVC.tsx b/src/main/topLevelPages/myDashboard/Campaigns/CampaignBlockCreateVC.tsx similarity index 100% rename from src/main/topLevelPages/myDashboard/campaignBlock/CampaignBlockCreateVC.tsx rename to src/main/topLevelPages/myDashboard/Campaigns/CampaignBlockCreateVC.tsx diff --git a/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx b/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx index 6462e12d91..52661fd8bb 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardWithMemberships.tsx @@ -2,7 +2,7 @@ import React, { Suspense } from 'react'; import PageContentColumn from '../../../core/ui/content/PageContentColumn'; import ReleaseNotesBanner from './releaseNotesBanner/ReleaseNotesBanner'; import { useLatestReleaseDiscussionQuery } from '../../../core/apollo/generated/apollo-hooks'; -import CampaignBlock from './CampaignBlock/CampaignBlock'; +import CampaignBlock from './Campaigns/CampaignBlock'; import InfoColumn from '../../../core/ui/content/InfoColumn'; import { DashboardMenu } from './DashboardMenu/DashboardMenu'; import ContentColumn from '../../../core/ui/content/ContentColumn'; diff --git a/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx b/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx index 80712470c8..3570208923 100644 --- a/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx +++ b/src/main/topLevelPages/myDashboard/MyDashboardWithoutMemberships.tsx @@ -1,6 +1,6 @@ import React, { Suspense } from 'react'; import PageContentColumn from '../../../core/ui/content/PageContentColumn'; -import CampaignBlock from './CampaignBlock/CampaignBlock'; +import CampaignBlock from './Campaigns/CampaignBlock'; import InfoColumn from '../../../core/ui/content/InfoColumn'; import ContentColumn from '../../../core/ui/content/ContentColumn'; import { useLatestReleaseDiscussionQuery } from '../../../core/apollo/generated/apollo-hooks';