From e7460da8b9db8e618cad9311d4d246280f0b409c Mon Sep 17 00:00:00 2001 From: Kiryl Budnik Date: Mon, 11 Sep 2023 09:53:55 +0300 Subject: [PATCH 01/24] add new actions to the feed item action menu --- .../DiscussionFeedCard/DiscussionFeedCard.tsx | 2 + .../DiscussionFeedCard/hooks/useMenuItems.tsx | 41 ++++++++++++++++++- .../utils/getAllowedItems.ts | 13 ++++++ .../common/components/FeedCard/FeedCard.tsx | 3 ++ .../FeedCardTags/FeedCardTags.module.scss | 6 +++ .../components/FeedCardTags/FeedCardTags.tsx | 6 +++ .../FeedItemBaseContent.tsx | 3 +- .../common/components/FeedItem/FeedItem.tsx | 12 +++++- .../ProjectFeedItem/ProjectFeedItem.tsx | 9 ++-- .../FeedItem/constants/feedItemMenuItem.ts | 2 + .../common/components/FeedItem/context.ts | 1 + .../FeedItem/hooks/useFeedItemCounters.ts | 8 ++-- src/pages/common/components/FeedItem/types.ts | 2 + .../ProposalFeedCard/ProposalFeedCard.tsx | 2 + .../FeedItemBaseContent.tsx | 2 + src/services/CommonFeed.ts | 10 +++++ src/shared/constants/endpoint.ts | 1 + src/shared/icons/index.ts | 1 + src/shared/icons/message3.icon.tsx | 37 +++++++++++++++++ .../models/CommonFeedObjectUserUnique.ts | 3 +- 20 files changed, 150 insertions(+), 14 deletions(-) create mode 100644 src/shared/icons/message3.icon.tsx diff --git a/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx b/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx index cc7951603e..3ba0ea685d 100644 --- a/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx +++ b/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx @@ -135,6 +135,7 @@ const DiscussionFeedCard = forwardRef( commonMember, feedItemFollow, getNonAllowedItems, + feedItemUserMetadata, }, { report: onReportModalOpen, @@ -324,6 +325,7 @@ const DiscussionFeedCard = forwardRef( isLoading={isLoading} menuItems={menuItems} seenOnce={feedItemUserMetadata?.seenOnce} + seen={feedItemUserMetadata?.seen} ownerId={item.userId} discussionPredefinedType={discussion?.predefinedType} > diff --git a/src/pages/common/components/DiscussionFeedCard/hooks/useMenuItems.tsx b/src/pages/common/components/DiscussionFeedCard/hooks/useMenuItems.tsx index 8a45faa153..1ce6e71779 100644 --- a/src/pages/common/components/DiscussionFeedCard/hooks/useMenuItems.tsx +++ b/src/pages/common/components/DiscussionFeedCard/hooks/useMenuItems.tsx @@ -12,6 +12,7 @@ import { Trash2Icon, UnfollowIcon, UnpinIcon, + Message3Icon, } from "@/shared/icons"; import { ContextMenuItem as Item, UploadFile } from "@/shared/interfaces"; import { parseStringToTextEditorValue } from "@/shared/ui-kit"; @@ -31,7 +32,13 @@ export const useMenuItems = ( actions: Actions, ): Item[] => { const dispatch = useDispatch(); - const { discussion, commonId, feedItem, feedItemFollow } = options; + const { + discussion, + commonId, + feedItem, + feedItemFollow, + feedItemUserMetadata, + } = options; const { report, share, remove } = actions; const allowedMenuItems = getAllowedItems({ ...options, feedItemFollow }); const items: Item[] = [ @@ -59,6 +66,38 @@ export const useMenuItems = ( onClick: share, icon: , }, + { + id: FeedItemMenuItem.MarkUnread, + text: "Mark as unread", + onClick: async () => { + if (!commonId || !feedItem) { + return; + } + + await CommonFeedService.markCommonFeedItemAsUnseen( + commonId, + feedItem.id, + ); + }, + icon: , + }, + { + id: FeedItemMenuItem.MarkRead, + text: "Mark as read", + onClick: async () => { + if (!commonId || !feedItem) { + return; + } + + await CommonFeedService.markCommonFeedItemAsSeen({ + commonId, + feedObjectId: feedItem.id, + lastSeenId: feedItemUserMetadata?.lastSeen?.id, + type: feedItemUserMetadata?.lastSeen?.type, + }); + }, + icon: , + }, { id: FeedItemMenuItem.Report, text: "Report", diff --git a/src/pages/common/components/DiscussionFeedCard/utils/getAllowedItems.ts b/src/pages/common/components/DiscussionFeedCard/utils/getAllowedItems.ts index c220fb84a3..c253616b6c 100644 --- a/src/pages/common/components/DiscussionFeedCard/utils/getAllowedItems.ts +++ b/src/pages/common/components/DiscussionFeedCard/utils/getAllowedItems.ts @@ -1,4 +1,5 @@ import { CommonFeedType } from "@/shared/models"; +import { notEmpty } from "@/shared/utils/notEmpty"; import { FeedItemMenuItem, FeedItemPinAction } from "../../FeedItem/constants"; import { GetAllowedItemsOptions } from "../../FeedItem/types"; import { checkIsEditItemAllowed } from "./checkIsEditItemAllowed"; @@ -27,6 +28,16 @@ const MENU_ITEM_TO_CHECK_FUNCTION_MAP: Record< !options.feedItemFollow.isDisabled && options.feedItemFollow.isFollowing ); }, + [FeedItemMenuItem.MarkUnread]: ({ feedItemUserMetadata }) => { + const { count, seen } = feedItemUserMetadata || {}; + + return notEmpty(count) && notEmpty(seen) && count === 0 && seen; + }, + [FeedItemMenuItem.MarkRead]: ({ feedItemUserMetadata }) => { + const { count, seen } = feedItemUserMetadata || {}; + + return Boolean(count) || !seen; + }, }; export const getAllowedItems = ( @@ -38,6 +49,8 @@ export const getAllowedItems = ( FeedItemMenuItem.Pin, FeedItemMenuItem.Unpin, FeedItemMenuItem.Share, + FeedItemMenuItem.MarkUnread, + FeedItemMenuItem.MarkRead, FeedItemMenuItem.Report, FeedItemMenuItem.Edit, FeedItemMenuItem.Remove, diff --git a/src/pages/common/components/FeedCard/FeedCard.tsx b/src/pages/common/components/FeedCard/FeedCard.tsx index ea660ca610..d1ea7ab55a 100644 --- a/src/pages/common/components/FeedCard/FeedCard.tsx +++ b/src/pages/common/components/FeedCard/FeedCard.tsx @@ -40,6 +40,7 @@ type FeedCardProps = PropsWithChildren<{ type?: CommonFeedType; menuItems?: ContextMenuItem[]; seenOnce?: boolean; + seen?: boolean; ownerId?: string; discussionPredefinedType?: PredefinedTypes; hasFiles?: boolean; @@ -77,6 +78,7 @@ export const FeedCard = forwardRef((props, ref) => { type, menuItems, seenOnce, + seen, ownerId, discussionPredefinedType, hasImages, @@ -197,6 +199,7 @@ export const FeedCard = forwardRef((props, ref) => { isFollowing, type, seenOnce, + seen, ownerId, discussionPredefinedType, hasFiles, diff --git a/src/pages/common/components/FeedCard/components/FeedCardTags/FeedCardTags.module.scss b/src/pages/common/components/FeedCard/components/FeedCardTags/FeedCardTags.module.scss index 41c3f0fd31..0f0985d0b5 100644 --- a/src/pages/common/components/FeedCard/components/FeedCardTags/FeedCardTags.module.scss +++ b/src/pages/common/components/FeedCard/components/FeedCardTags/FeedCardTags.module.scss @@ -50,3 +50,9 @@ margin-left: 0.75rem; color: $c-gray-800; } + +.unseen { + width: 1.4375rem; + border-radius: 50%; + background-color: $c-pink-primary; +} diff --git a/src/pages/common/components/FeedCard/components/FeedCardTags/FeedCardTags.tsx b/src/pages/common/components/FeedCard/components/FeedCardTags/FeedCardTags.tsx index 03868c5aa5..ca794ad258 100644 --- a/src/pages/common/components/FeedCard/components/FeedCardTags/FeedCardTags.tsx +++ b/src/pages/common/components/FeedCard/components/FeedCardTags/FeedCardTags.tsx @@ -4,12 +4,14 @@ import classNames from "classnames"; import { selectUser } from "@/pages/Auth/store/selectors"; import { PinIcon, StarIcon } from "@/shared/icons"; import { CommonFeedType } from "@/shared/models"; +import { notEmpty } from "@/shared/utils/notEmpty"; import styles from "./FeedCardTags.module.scss"; interface FeedCardTagsProps { unreadMessages?: number; type?: CommonFeedType; seenOnce?: boolean; + seen?: boolean; ownerId?: string; isActive: boolean; isPinned?: boolean; @@ -21,6 +23,7 @@ export const FeedCardTags: FC = (props) => { unreadMessages, type, seenOnce, + seen, ownerId, isActive, isPinned, @@ -69,6 +72,9 @@ export const FeedCardTags: FC = (props) => { {unreadMessages} )} + {!unreadMessages && notEmpty(seen) && !seen && ( +
+ )} ); }; diff --git a/src/pages/common/components/FeedCard/components/FeedItemBaseContent/FeedItemBaseContent.tsx b/src/pages/common/components/FeedCard/components/FeedItemBaseContent/FeedItemBaseContent.tsx index a2e8bd22a3..f51be70090 100644 --- a/src/pages/common/components/FeedCard/components/FeedItemBaseContent/FeedItemBaseContent.tsx +++ b/src/pages/common/components/FeedCard/components/FeedItemBaseContent/FeedItemBaseContent.tsx @@ -1,7 +1,6 @@ import React, { FC, MouseEventHandler, useRef, useState } from "react"; import classNames from "classnames"; import { useLongPress } from "use-long-press"; -import { PredefinedTypes } from "@/shared/models"; import { checkIsTextEditorValueEmpty, ContextMenu, @@ -29,6 +28,7 @@ export const FeedItemBaseContent: FC = (props) => { type, menuItems, seenOnce, + seen, ownerId, renderLeftContent, isPinned, @@ -149,6 +149,7 @@ export const FeedItemBaseContent: FC = (props) => { unreadMessages={unreadMessages} type={type} seenOnce={seenOnce} + seen={seen} ownerId={ownerId} isActive={isActive} isPinned={isPinned} diff --git a/src/pages/common/components/FeedItem/FeedItem.tsx b/src/pages/common/components/FeedItem/FeedItem.tsx index 96b79f19fb..bafa9ab5eb 100644 --- a/src/pages/common/components/FeedItem/FeedItem.tsx +++ b/src/pages/common/components/FeedItem/FeedItem.tsx @@ -15,6 +15,7 @@ import { DiscussionFeedCard } from "../DiscussionFeedCard"; import { ProposalFeedCard } from "../ProposalFeedCard"; import { ProjectFeedItem } from "./components"; import { useFeedItemContext } from "./context"; +import { useFeedItemCounters } from "./hooks"; import { FeedItemRef } from "./types"; interface FeedItemProps { @@ -67,6 +68,8 @@ const FeedItem = forwardRef((props, ref) => { const { onFeedItemUpdate, getLastMessage, getNonAllowedItems, onUserSelect } = useFeedItemContext(); useFeedItemSubscription(item.id, commonId, onFeedItemUpdate); + const { projectUnreadStreamsCount, projectUnreadMessages } = + useFeedItemCounters(item.id, commonId); if ( shouldCheckItemVisibility && @@ -115,7 +118,14 @@ const FeedItem = forwardRef((props, ref) => { } if (item.data.type === CommonFeedType.Project) { - return ; + return ( + + ); } return null; diff --git a/src/pages/common/components/FeedItem/components/ProjectFeedItem/ProjectFeedItem.tsx b/src/pages/common/components/FeedItem/components/ProjectFeedItem/ProjectFeedItem.tsx index 7c948ed356..fdb107b579 100644 --- a/src/pages/common/components/FeedItem/components/ProjectFeedItem/ProjectFeedItem.tsx +++ b/src/pages/common/components/FeedItem/components/ProjectFeedItem/ProjectFeedItem.tsx @@ -8,24 +8,21 @@ import { OpenIcon } from "@/shared/icons"; import { CommonFeed } from "@/shared/models"; import { CommonAvatar, parseStringToTextEditorValue } from "@/shared/ui-kit"; import { checkIsProject } from "@/shared/utils"; -import { useFeedItemCounters } from "../../hooks"; import styles from "./ProjectFeedItem.module.scss"; interface ProjectFeedItemProps { item: CommonFeed; isMobileVersion: boolean; + unreadStreamsCount?: number; + unreadMessages?: number; } export const ProjectFeedItem: FC = (props) => { - const { item, isMobileVersion } = props; + const { item, isMobileVersion, unreadStreamsCount, unreadMessages } = props; const history = useHistory(); const { getCommonPagePath } = useRoutesContext(); const { renderFeedItemBaseContent } = useFeedItemContext(); const { data: common, fetched: isCommonFetched, fetchCommon } = useCommon(); - const { unreadStreamsCount, unreadMessages } = useFeedItemCounters( - item.id, - common?.directParent?.commonId, - ); const commonId = item.data.id; const lastMessage = parseStringToTextEditorValue( Number.isInteger(unreadStreamsCount) diff --git a/src/pages/common/components/FeedItem/constants/feedItemMenuItem.ts b/src/pages/common/components/FeedItem/constants/feedItemMenuItem.ts index fd35388a18..2e6995333b 100644 --- a/src/pages/common/components/FeedItem/constants/feedItemMenuItem.ts +++ b/src/pages/common/components/FeedItem/constants/feedItemMenuItem.ts @@ -7,4 +7,6 @@ export enum FeedItemMenuItem { Remove = "remove", Follow = "follow", Unfollow = "unfollow", + MarkUnread = "markUnread", + MarkRead = "markRead", } diff --git a/src/pages/common/components/FeedItem/context.ts b/src/pages/common/components/FeedItem/context.ts index d4cae0d68d..67cf765193 100644 --- a/src/pages/common/components/FeedItem/context.ts +++ b/src/pages/common/components/FeedItem/context.ts @@ -26,6 +26,7 @@ export interface FeedItemBaseContentProps { menuItems?: ContextMenuItem[]; type?: CommonFeedType; seenOnce?: boolean; + seen?: boolean; ownerId?: string; commonName?: string; renderImage?: (className?: string) => ReactNode; diff --git a/src/pages/common/components/FeedItem/hooks/useFeedItemCounters.ts b/src/pages/common/components/FeedItem/hooks/useFeedItemCounters.ts index 3b362207db..0b1efacea5 100644 --- a/src/pages/common/components/FeedItem/hooks/useFeedItemCounters.ts +++ b/src/pages/common/components/FeedItem/hooks/useFeedItemCounters.ts @@ -3,8 +3,8 @@ import { useCommonMember } from "@/pages/OldCommon/hooks"; import { useGovernanceByCommonId } from "@/shared/hooks/useCases"; interface Return { - unreadStreamsCount?: number; - unreadMessages?: number; + projectUnreadStreamsCount?: number; + projectUnreadMessages?: number; } export const useFeedItemCounters = ( @@ -28,7 +28,7 @@ export const useFeedItemCounters = ( }, [fetchGovernance, commonId]); return { - unreadStreamsCount: streamsUnreadCountByProjectStream?.[feedItemId], - unreadMessages: unreadCountByProjectStream?.[feedItemId], + projectUnreadStreamsCount: streamsUnreadCountByProjectStream?.[feedItemId], + projectUnreadMessages: unreadCountByProjectStream?.[feedItemId], }; }; diff --git a/src/pages/common/components/FeedItem/types.ts b/src/pages/common/components/FeedItem/types.ts index dea8ade8a1..0745776e70 100644 --- a/src/pages/common/components/FeedItem/types.ts +++ b/src/pages/common/components/FeedItem/types.ts @@ -7,6 +7,7 @@ import { Discussion, Proposal, CommonFeedType, + CommonFeedObjectUserUnique, } from "@/shared/models"; import { FeedItemMenuItem } from "./constants"; @@ -25,6 +26,7 @@ export interface GetAllowedItemsOptions { commonMember?: CommonMember | null; feedItemFollow: FeedItemFollowState; getNonAllowedItems?: GetNonAllowedItemsOptions; + feedItemUserMetadata: CommonFeedObjectUserUnique | null; } export type MenuItemOptions = Omit; diff --git a/src/pages/common/components/ProposalFeedCard/ProposalFeedCard.tsx b/src/pages/common/components/ProposalFeedCard/ProposalFeedCard.tsx index 106f2bccc2..4284c62e37 100644 --- a/src/pages/common/components/ProposalFeedCard/ProposalFeedCard.tsx +++ b/src/pages/common/components/ProposalFeedCard/ProposalFeedCard.tsx @@ -176,6 +176,7 @@ const ProposalFeedCard = forwardRef( commonMember, feedItemFollow, getNonAllowedItems, + feedItemUserMetadata, }, { report: () => {}, @@ -426,6 +427,7 @@ const ProposalFeedCard = forwardRef( isLoading={isLoading} type={item.data.type} seenOnce={feedItemUserMetadata?.seenOnce} + seen={feedItemUserMetadata?.seen} menuItems={menuItems} ownerId={item.userId} > diff --git a/src/pages/inbox/components/FeedItemBaseContent/FeedItemBaseContent.tsx b/src/pages/inbox/components/FeedItemBaseContent/FeedItemBaseContent.tsx index 67d2ffff44..04238c3472 100644 --- a/src/pages/inbox/components/FeedItemBaseContent/FeedItemBaseContent.tsx +++ b/src/pages/inbox/components/FeedItemBaseContent/FeedItemBaseContent.tsx @@ -27,6 +27,7 @@ export const FeedItemBaseContent: FC = (props) => { type, menuItems, seenOnce, + seen, ownerId, commonName, renderImage, @@ -155,6 +156,7 @@ export const FeedItemBaseContent: FC = (props) => { unreadMessages={unreadMessages} type={type} seenOnce={seenOnce} + seen={seen} ownerId={ownerId} isActive={isActive} isPinned={false} diff --git a/src/services/CommonFeed.ts b/src/services/CommonFeed.ts index c4269783b0..f9920217aa 100644 --- a/src/services/CommonFeed.ts +++ b/src/services/CommonFeed.ts @@ -220,6 +220,16 @@ class CommonFeedService { return convertObjectDatesToFirestoreTimestamps(data); }; + public markCommonFeedItemAsUnseen = ( + commonId: string, + feedObjectId: string, + ) => { + return Api.post(ApiEndpoint.MarkFeedObjectUnseenForUser, { + commonId, + feedObjectId, + }); + }; + public subscribeToCommonFeedItem = ( commonId: string, feedItemId: string, diff --git a/src/shared/constants/endpoint.ts b/src/shared/constants/endpoint.ts index e149c875b7..88af6d488c 100644 --- a/src/shared/constants/endpoint.ts +++ b/src/shared/constants/endpoint.ts @@ -6,6 +6,7 @@ export const ApiEndpoint = { UpdateCommon: "/commons/update", CreateSubCommon: "/commons/subcommon/create", MarkFeedObjectSeenForUser: "/commons/mark-feed-object-seen-for-user", + MarkFeedObjectUnseenForUser: "/commons/mark-feed-object-unseen-for-user", AcceptRules: "/commons/accept-rules", GetCommonFeedItems: "/commons/:commonId/feed-items", GetCommonPinnedFeedItems: "/commons/:commonId/pinned-feed-items", diff --git a/src/shared/icons/index.ts b/src/shared/icons/index.ts index 02183e0235..0af15350b7 100644 --- a/src/shared/icons/index.ts +++ b/src/shared/icons/index.ts @@ -44,6 +44,7 @@ export { default as UploadIcon } from "./upload.icon"; export { default as WalletIcon } from "./wallet.icon"; export { default as MessageIcon } from "./message.icon"; export { default as Message2Icon } from "./message2.icon"; +export { default as Message3Icon } from "./message3.icon"; export { default as Trash2Icon } from "./trash2.icon"; export { UnfollowIcon } from "./unfollow.icon"; export { UnpinIcon } from "./unpin.icon"; diff --git a/src/shared/icons/message3.icon.tsx b/src/shared/icons/message3.icon.tsx new file mode 100644 index 0000000000..8a48992260 --- /dev/null +++ b/src/shared/icons/message3.icon.tsx @@ -0,0 +1,37 @@ +import React, { FC } from "react"; + +interface Message3IconProps { + className?: string; +} + +const Message3Icon: FC = ({ className }) => { + const color = "currentColor"; + + return ( + + + + + ); +}; + +export default Message3Icon; diff --git a/src/shared/models/CommonFeedObjectUserUnique.ts b/src/shared/models/CommonFeedObjectUserUnique.ts index c37fcd5495..ba4ce206e7 100644 --- a/src/shared/models/CommonFeedObjectUserUnique.ts +++ b/src/shared/models/CommonFeedObjectUserUnique.ts @@ -4,7 +4,7 @@ import { Timestamp } from "./Timestamp"; export interface CommonFeedObjectUserUnique extends BaseEntity { userId: string; - lastSeen: { + lastSeen?: { type: LastSeenEntity; id: string; }; @@ -13,4 +13,5 @@ export interface CommonFeedObjectUserUnique extends BaseEntity { feedObjectId: string; commonId: string; seenOnce?: boolean; + seen?: boolean; } From 051eb8075cec50180d1c154bee8e1d58871257a7 Mon Sep 17 00:00:00 2001 From: Pavel Meyer Date: Mon, 11 Sep 2023 15:19:02 +0300 Subject: [PATCH 02/24] CW-Hotfix-mention Added getUserName util --- src/shared/ui-kit/TextEditor/utils/insertMention.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/ui-kit/TextEditor/utils/insertMention.ts b/src/shared/ui-kit/TextEditor/utils/insertMention.ts index fe19cbfa4b..dd1c52e6cc 100644 --- a/src/shared/ui-kit/TextEditor/utils/insertMention.ts +++ b/src/shared/ui-kit/TextEditor/utils/insertMention.ts @@ -1,12 +1,13 @@ import { Transforms } from "slate"; import { ReactEditor } from "slate-react"; +import { getUserName } from "@/shared/utils"; import { ElementType } from "../constants"; import { MentionElement } from "../types"; export const insertMention = (editor, character) => { const mention: MentionElement = { type: ElementType.Mention, - displayName: `${character?.displayName} `, + displayName: `${getUserName(character)} `, userId: character?.uid, children: [{ text: "" }], }; From c18013e3389386d8ba4f99b11234cfe0bd0256cd Mon Sep 17 00:00:00 2001 From: Daniel Reinoso Date: Tue, 12 Sep 2023 00:23:48 -0300 Subject: [PATCH 03/24] Fix local emulator --- src/shared/utils/firebase.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/shared/utils/firebase.tsx b/src/shared/utils/firebase.tsx index 9c61562f4e..d1643fa017 100644 --- a/src/shared/utils/firebase.tsx +++ b/src/shared/utils/firebase.tsx @@ -11,12 +11,6 @@ interface FirebaseError extends Error { } firebase.initializeApp(config.firebase); -firebase - .firestore() - .enablePersistence() - .catch((error) => { - console.error("Error enabling persistence", error); - }); if (REACT_APP_ENV === Environment.Local) { firebase.auth().useEmulator(local.firebase.authDomain); @@ -26,6 +20,13 @@ if (REACT_APP_ENV === Environment.Local) { "localhost", Number(local.firebase.databaseURL.split(/:/g)[2]), ); +} else { + firebase + .firestore() + .enablePersistence() + .catch((error) => { + console.error("Error enabling persistence", error); + }); } export const isFirebaseError = (error: any): error is FirebaseError => { From 6c64595a42b05650fb17bcb6a50664e99601afe9 Mon Sep 17 00:00:00 2001 From: Daniel Reinoso Date: Tue, 12 Sep 2023 00:57:19 -0300 Subject: [PATCH 04/24] Support circle visibility by common --- package.json | 2 +- .../DiscussionDetailModal.tsx | 6 ++-- .../DiscussionItemComponent.tsx | 6 ++-- .../CommonDetailContainer.tsx | 5 +-- .../interfaces/CreateProposalPayload.ts | 34 ++++++++++++++++--- .../ChatComponent/ChatComponent.tsx | 7 ++-- .../DiscussionFeedCard/DiscussionFeedCard.tsx | 5 ++- src/shared/models/Discussion.tsx | 2 +- .../governance/proposals/BasicArgsProposal.ts | 2 +- 9 files changed, 50 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 26375b9ba8..15a9effe22 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "scripts": { "build": "craco build", "build:storybook": "build-storybook -s public", - "start": "REACT_APP_ENV=dev craco start", + "start": "REACT_APP_ENV=local craco start", "test": "TZ=UTC jest", "test:watch": "yarn test --watch", "test:storybook": "test-storybook", diff --git a/src/pages/OldCommon/components/CommonDetailContainer/DiscussionDetailModal/DiscussionDetailModal.tsx b/src/pages/OldCommon/components/CommonDetailContainer/DiscussionDetailModal/DiscussionDetailModal.tsx index 5df3fbe4c8..e660b548bf 100644 --- a/src/pages/OldCommon/components/CommonDetailContainer/DiscussionDetailModal/DiscussionDetailModal.tsx +++ b/src/pages/OldCommon/components/CommonDetailContainer/DiscussionDetailModal/DiscussionDetailModal.tsx @@ -83,14 +83,14 @@ export default function DiscussionDetailModal({ ); useEffect(() => { - if (discussion?.circleVisibility) { + if (discussion?.circleVisibilityByCommon?.[governance.commonId]) { (async () => { const governanceCircles = await getCommonGovernanceCircles( governance.id, ); const filteredByIdCircles = getFilteredByIdCircles( governanceCircles ? Object.values(governanceCircles) : null, - discussion?.circleVisibility, + discussion?.circleVisibilityByCommon?.[governance.commonId], ); const names = getCirclesWithLowestTier(filteredByIdCircles) .map(({ name }) => name) @@ -102,7 +102,7 @@ export default function DiscussionDetailModal({ return () => { dispatch(chatActions.clearCurrentDiscussionMessageReply()); }; - }, [governance.id, discussion]); + }, [governance.id, governance.commonId, discussion]); const sendMessage = useCallback( (message: string) => { diff --git a/src/pages/OldCommon/components/CommonDetailContainer/DiscussionsComponent/DiscussionItemComponent.tsx b/src/pages/OldCommon/components/CommonDetailContainer/DiscussionsComponent/DiscussionItemComponent.tsx index d6886bc347..ea2ecf08a2 100644 --- a/src/pages/OldCommon/components/CommonDetailContainer/DiscussionsComponent/DiscussionItemComponent.tsx +++ b/src/pages/OldCommon/components/CommonDetailContainer/DiscussionsComponent/DiscussionItemComponent.tsx @@ -52,14 +52,14 @@ export default function DiscussionItemComponent({ const date = new Date(); useEffect(() => { - if (discussion.circleVisibility) { + if (discussion.circleVisibilityByCommon) { (async () => { const governanceCircles = await getCommonGovernanceCircles( governance.id, ); const filteredByIdCircles = getFilteredByIdCircles( governanceCircles ? Object.values(governanceCircles) : null, - discussion.circleVisibility, + discussion.circleVisibilityByCommon?.[governance.commonId], ); const names = getCirclesWithLowestTier(filteredByIdCircles) .map(({ name }) => name) @@ -67,7 +67,7 @@ export default function DiscussionItemComponent({ setCircleNames(names); })(); } - }, [governance.id, discussion.circleVisibility]); + }, [governance.id, governance.commonId, discussion.circleVisibilityByCommon]); return (
diff --git a/src/pages/OldCommon/containers/CommonDetailContainer/CommonDetailContainer.tsx b/src/pages/OldCommon/containers/CommonDetailContainer/CommonDetailContainer.tsx index 23f8adb176..3a2cfd7d07 100644 --- a/src/pages/OldCommon/containers/CommonDetailContainer/CommonDetailContainer.tsx +++ b/src/pages/OldCommon/containers/CommonDetailContainer/CommonDetailContainer.tsx @@ -189,11 +189,12 @@ export default function CommonDetail(props: CommonDetailProps = {}) { const circleIds = new Set( commonMember ? Object.values(commonMember.circles.map) : [], ); - return discussions.filter(({ circleVisibility, moderation }) => { + return discussions.filter(({ circleVisibilityByCommon, moderation }) => { if (moderation?.flag === ModerationFlags.Hidden) { return false; } + const circleVisibility = circleVisibilityByCommon?.[id]; if (!circleVisibility?.length) { return true; } @@ -201,7 +202,7 @@ export default function CommonDetail(props: CommonDetailProps = {}) { circleIds.has(discussionCircleId), ); }); - }, [discussions, commonMember]); + }, [discussions, commonMember, id]); const activeProposals = useMemo( () => proposals.filter((d) => checkIsCountdownState(d)), diff --git a/src/pages/OldCommon/interfaces/CreateProposalPayload.ts b/src/pages/OldCommon/interfaces/CreateProposalPayload.ts index de81666a64..5854cb0820 100644 --- a/src/pages/OldCommon/interfaces/CreateProposalPayload.ts +++ b/src/pages/OldCommon/interfaces/CreateProposalPayload.ts @@ -17,33 +17,57 @@ interface CreateFundsAllocation { interface CreateMemberAdmittance { type: ProposalsTypes.MEMBER_ADMITTANCE; - args: Omit & { + args: Omit< + MemberAdmittance["data"]["args"], + "proposerId" | "circleVisibilityByCommon" + > & { contributionSourceType?: ContributionSourceType; feeMonthly: PaymentAmount | null; feeOneTime: PaymentAmount | null; fromSupportersFlow?: boolean; receiveEmails?: boolean; userWhatsapp?: boolean; + circleVisibility?: string[] | null; }; } interface CreateAssignCircle { type: ProposalsTypes.ASSIGN_CIRCLE; - args: Omit; + args: Omit< + AssignCircle["data"]["args"], + "proposerId" | "circleVisibilityByCommon" + > & { + circleVisibility?: string[] | null; + }; } interface CreateRemoveCircle { type: ProposalsTypes.REMOVE_CIRCLE; - args: Omit; + args: Omit< + RemoveCircle["data"]["args"], + "proposerId" | "circleVisibilityByCommon" + > & { + circleVisibility?: string[] | null; + }; } interface CreateSurvey { type: ProposalsTypes.SURVEY; - args: Omit; + args: Omit< + Survey["data"]["args"], + "proposerId" | "circleVisibilityByCommon" + > & { + circleVisibility?: string[] | null; + }; } interface CreateDeleteCommon { type: ProposalsTypes.DELETE_COMMON; - args: Omit; + args: Omit< + DeleteCommon["data"]["args"], + "proposerId" | "circleVisibilityByCommon" + > & { + circleVisibility?: string[] | null; + }; } interface Request { diff --git a/src/pages/common/components/ChatComponent/ChatComponent.tsx b/src/pages/common/components/ChatComponent/ChatComponent.tsx index a6da5e4335..46f285e799 100644 --- a/src/pages/common/components/ChatComponent/ChatComponent.tsx +++ b/src/pages/common/components/ChatComponent/ChatComponent.tsx @@ -209,9 +209,12 @@ export default function ChatComponent({ useEffect(() => { if (commonId && !isChatChannel) { - fetchDiscussionUsers(commonId, discussion?.circleVisibility); + fetchDiscussionUsers( + commonId, + discussion?.circleVisibilityByCommon?.[commonId], + ); } - }, [commonId, discussion?.circleVisibility]); + }, [commonId, discussion?.circleVisibilityByCommon]); useEffect(() => { if (chatChannel?.id) { diff --git a/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx b/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx index 3ba0ea685d..5d707e7bfd 100644 --- a/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx +++ b/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx @@ -247,7 +247,10 @@ const DiscussionFeedCard = forwardRef( } const circleVisibility = governanceCircles - ? getVisibilityString(governanceCircles, discussion?.circleVisibility) + ? getVisibilityString( + governanceCircles, + discussion?.circleVisibilityByCommon?.[commonId], + ) : undefined; return ( diff --git a/src/shared/models/Discussion.tsx b/src/shared/models/Discussion.tsx index a3a6053dc9..da1bd0c723 100644 --- a/src/shared/models/Discussion.tsx +++ b/src/shared/models/Discussion.tsx @@ -33,7 +33,7 @@ export interface Discussion extends BaseEntity { * If array is empty, everyone in common can view. * If discussion is attached to a proposal, this field will be not exist. */ - circleVisibility?: string[]; + circleVisibilityByCommon?: Record; } export interface DiscussionWithOwnerInfo extends Discussion { diff --git a/src/shared/models/governance/proposals/BasicArgsProposal.ts b/src/shared/models/governance/proposals/BasicArgsProposal.ts index 76f615e772..623e3c3ed6 100644 --- a/src/shared/models/governance/proposals/BasicArgsProposal.ts +++ b/src/shared/models/governance/proposals/BasicArgsProposal.ts @@ -15,7 +15,7 @@ export interface BasicArgsProposal { links: CommonLink[]; - circleVisibility?: string[] | null; + circleVisibilityByCommon?: Record | null; } export interface ProposalImage { From d43345d6fe6efd4ea8fee54c4d03bd536c9cd618 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 09:48:42 +0300 Subject: [PATCH 05/24] fix created item selection --- src/pages/commonFeed/CommonFeed.tsx | 7 +++-- .../components/FeedLayout/FeedLayout.tsx | 28 +------------------ 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index 682b14d731..0b84d4038d 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -253,8 +253,11 @@ const CommonFeedComponent: FC = (props) => { checkIsFeedItemFollowLayoutItem(firstItem) && recentStreamId === firstItem.feedItem.data.id ) { - feedLayoutRef?.setShouldAllowChatAutoOpen(true); - feedLayoutRef?.setExpandedFeedItemId(firstItem.feedItem.id); + feedLayoutRef?.setActiveItem({ + feedItemId: firstItem.feedItem.id, + circleVisibility: [], + }); + dispatch(commonActions.setRecentStreamId("")); } }, [feedLayoutRef, recentStreamId, firstItem]); diff --git a/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx b/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx index dc7cbb6ef0..806d5413ff 100644 --- a/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx +++ b/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx @@ -10,7 +10,7 @@ import React, { useRef, useState, } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useSelector } from "react-redux"; import { useHistory } from "react-router-dom"; import { useWindowSize } from "react-use"; import classNames from "classnames"; @@ -66,7 +66,6 @@ import { getParamsFromOneOfRoutes, getUserName, } from "@/shared/utils"; -import { commonActions, selectRecentStreamId } from "@/store/states"; import { MIN_CHAT_WIDTH } from "../../constants"; import { DesktopChat, @@ -169,7 +168,6 @@ const FeedLayout: ForwardRefRenderFunction = ( outerStyles, settings, } = props; - const dispatch = useDispatch(); const { getCommonPagePath } = useRoutesContext(); const refsByItemId = useRef>({}); const { width: windowWidth } = useWindowSize(); @@ -177,7 +175,6 @@ const FeedLayout: ForwardRefRenderFunction = ( const queryParams = useQueryParams(); const isTabletView = useIsTabletView(); const user = useSelector(selectUser()); - const recentStreamId = useSelector(selectRecentStreamId); const userId = user?.uid; const [chatItem, setChatItem] = useState(); const [isShowFeedItemDetailsModal, setIsShowFeedItemDetailsModal] = @@ -270,19 +267,9 @@ const FeedLayout: ForwardRefRenderFunction = ( ) { return; } - if (recentStreamId) { - const foundItem = allFeedItems.find( - (item) => - checkIsFeedItemFollowLayoutItem(item) && - item.feedItem.data.id === recentStreamId, - ); - return foundItem?.itemId; - } - if (sharedFeedItemId) { return sharedFeedItemId; } - if (chatItem?.feedItemId) { return; } @@ -300,7 +287,6 @@ const FeedLayout: ForwardRefRenderFunction = ( chatChannelItemForProfile?.itemId, allFeedItems, chatItem?.feedItemId, - recentStreamId, sharedFeedItemId, userForProfile.userForProfileData, shouldAllowChatAutoOpen, @@ -633,18 +619,6 @@ const FeedLayout: ForwardRefRenderFunction = ( } }, [isTabletView, shouldAutoExpandItem, activeFeedItemId]); - useEffect(() => { - if (!recentStreamId || !selectedFeedItem) { - return; - } - if ( - !checkIsFeedItemFollowLayoutItem(selectedFeedItem) || - recentStreamId === selectedFeedItem?.feedItem.data.id - ) { - dispatch(commonActions.setRecentStreamId("")); - } - }, [recentStreamId, selectedFeedItem]); - useImperativeHandle( ref, () => ({ From 872ce688837aae8c3ffa2da08706f40de9ab5c71 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 09:50:15 +0300 Subject: [PATCH 06/24] mark circleVisibility as nullable in ChatItem --- src/pages/common/components/ChatComponent/context.ts | 2 +- .../components/FeedTab/utils/checkHasAccessToChat.ts | 8 ++++---- src/pages/commonFeed/CommonFeed.tsx | 1 - src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx | 5 +---- .../components/DesktopProfile/DesktopProfile.tsx | 1 - .../FeedLayout/components/MobileProfile/MobileProfile.tsx | 1 - src/pages/inbox/BaseInbox.tsx | 1 - .../inbox/components/ChatChannelItem/ChatChannelItem.tsx | 1 - 8 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/pages/common/components/ChatComponent/context.ts b/src/pages/common/components/ChatComponent/context.ts index 518c6ba7b4..2db6aeda1d 100644 --- a/src/pages/common/components/ChatComponent/context.ts +++ b/src/pages/common/components/ChatComponent/context.ts @@ -11,7 +11,7 @@ export interface ChatItem { proposal?: Proposal; discussion?: Discussion; chatChannel?: ChatChannel; - circleVisibility: string[]; + circleVisibility?: string[]; lastSeenItem?: CommonFeedObjectUserUnique["lastSeen"]; lastSeenAt?: CommonFeedObjectUserUnique["lastSeenAt"]; seenOnce?: boolean; diff --git a/src/pages/common/components/CommonTabPanels/components/FeedTab/utils/checkHasAccessToChat.ts b/src/pages/common/components/CommonTabPanels/components/FeedTab/utils/checkHasAccessToChat.ts index 8394a90da2..f0fb06e2e1 100644 --- a/src/pages/common/components/CommonTabPanels/components/FeedTab/utils/checkHasAccessToChat.ts +++ b/src/pages/common/components/CommonTabPanels/components/FeedTab/utils/checkHasAccessToChat.ts @@ -8,10 +8,10 @@ export const checkHasAccessToChat = ( return false; } + const { circleVisibility = [] } = chatItem; + return ( - !chatItem.circleVisibility.length || - chatItem.circleVisibility.some((circleId) => - userCircleIds.includes(circleId), - ) + !circleVisibility.length || + circleVisibility.some((circleId) => userCircleIds.includes(circleId)) ); }; diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index 0b84d4038d..d19b4729b7 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -255,7 +255,6 @@ const CommonFeedComponent: FC = (props) => { ) { feedLayoutRef?.setActiveItem({ feedItemId: firstItem.feedItem.id, - circleVisibility: [], }); dispatch(commonActions.setRecentStreamId("")); } diff --git a/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx b/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx index 806d5413ff..c167b02997 100644 --- a/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx +++ b/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx @@ -492,10 +492,7 @@ const FeedLayout: ForwardRefRenderFunction = ( return; } - setActiveChatItem({ - feedItemId, - circleVisibility: [], - }); + setActiveChatItem({ feedItemId }); const itemExists = allFeedItems.some((item) => item.itemId === feedItemId); diff --git a/src/pages/commonFeed/components/FeedLayout/components/DesktopProfile/DesktopProfile.tsx b/src/pages/commonFeed/components/FeedLayout/components/DesktopProfile/DesktopProfile.tsx index e3fa9d7760..664bc238ab 100644 --- a/src/pages/commonFeed/components/FeedLayout/components/DesktopProfile/DesktopProfile.tsx +++ b/src/pages/commonFeed/components/FeedLayout/components/DesktopProfile/DesktopProfile.tsx @@ -46,7 +46,6 @@ const DesktopProfile: FC = (props) => { chatChannel: chatChannel, discussion: ChatChannelToDiscussionConverter.toTargetEntity(chatChannel), - circleVisibility: [], }} governanceCircles={governanceCircles} commonId={""} diff --git a/src/pages/commonFeed/components/FeedLayout/components/MobileProfile/MobileProfile.tsx b/src/pages/commonFeed/components/FeedLayout/components/MobileProfile/MobileProfile.tsx index b90b2cc010..b5f8871ebb 100644 --- a/src/pages/commonFeed/components/FeedLayout/components/MobileProfile/MobileProfile.tsx +++ b/src/pages/commonFeed/components/FeedLayout/components/MobileProfile/MobileProfile.tsx @@ -37,7 +37,6 @@ const MobileProfile: FC = (props) => { chatChannel: chatChannel, discussion: ChatChannelToDiscussionConverter.toTargetEntity(chatChannel), - circleVisibility: [], }} commonId={""} commonName={""} diff --git a/src/pages/inbox/BaseInbox.tsx b/src/pages/inbox/BaseInbox.tsx index 93221eaa16..a0f97b8667 100644 --- a/src/pages/inbox/BaseInbox.tsx +++ b/src/pages/inbox/BaseInbox.tsx @@ -199,7 +199,6 @@ const InboxPage: FC = (props) => { discussion: ChatChannelToDiscussionConverter.toTargetEntity( chatChannelItem.chatChannel, ), - circleVisibility: [], }); }, [nextChatChannelItemId, feedLayoutRef]); diff --git a/src/pages/inbox/components/ChatChannelItem/ChatChannelItem.tsx b/src/pages/inbox/components/ChatChannelItem/ChatChannelItem.tsx index 3ed0393b8f..8df21cc437 100644 --- a/src/pages/inbox/components/ChatChannelItem/ChatChannelItem.tsx +++ b/src/pages/inbox/components/ChatChannelItem/ChatChannelItem.tsx @@ -47,7 +47,6 @@ export const ChatChannelItem: FC = (props) => { feedItemId: chatChannel.id, discussion: ChatChannelToDiscussionConverter.toTargetEntity(chatChannel), chatChannel, - circleVisibility: [], lastSeenItem: chatChannelUserStatus?.lastSeenChatMessageId ? { type: LastSeenEntity.DiscussionMessage, From 4581ed9c1f064f7e175adbb0a7a75fa5a25b88dd Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 11:47:10 +0300 Subject: [PATCH 07/24] refactor addProjectToBreadcrumbs action to allow updating the item --- .../handlers/CommonHandler/CommonHandler.tsx | 4 +- .../states/multipleSpacesLayout/actions.ts | 4 +- .../states/multipleSpacesLayout/constants.ts | 2 +- .../states/multipleSpacesLayout/reducer.ts | 50 +++++++++++++------ 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/pages/App/handlers/CommonHandler/CommonHandler.tsx b/src/pages/App/handlers/CommonHandler/CommonHandler.tsx index 311b42763a..7f352f2259 100644 --- a/src/pages/App/handlers/CommonHandler/CommonHandler.tsx +++ b/src/pages/App/handlers/CommonHandler/CommonHandler.tsx @@ -45,7 +45,9 @@ const CommonHandler: FC = () => { projectsStateItem, ) => { dispatch( - multipleSpacesLayoutActions.addProjectToBreadcrumbs(projectsStateItem), + multipleSpacesLayoutActions.addOrUpdateProjectInBreadcrumbs( + projectsStateItem, + ), ); dispatch(commonLayoutActions.addProject(projectsStateItem)); dispatch(projectsActions.addProject(projectsStateItem)); diff --git a/src/store/states/multipleSpacesLayout/actions.ts b/src/store/states/multipleSpacesLayout/actions.ts index 04b9f3fa97..cb8210e550 100644 --- a/src/store/states/multipleSpacesLayout/actions.ts +++ b/src/store/states/multipleSpacesLayout/actions.ts @@ -40,8 +40,8 @@ export const moveBreadcrumbsToPrevious = createStandardAction( MultipleSpacesLayoutActionType.MOVE_BREADCRUMBS_TO_PREVIOUS, )(); -export const addProjectToBreadcrumbs = createStandardAction( - MultipleSpacesLayoutActionType.ADD_PROJECT_TO_BREADCRUMBS, +export const addOrUpdateProjectInBreadcrumbs = createStandardAction( + MultipleSpacesLayoutActionType.ADD_OR_UPDATE_PROJECT_IN_BREADCRUMBS, )(); export const updateProjectInBreadcrumbs = createStandardAction( diff --git a/src/store/states/multipleSpacesLayout/constants.ts b/src/store/states/multipleSpacesLayout/constants.ts index cf1580c9aa..7c5574dedb 100644 --- a/src/store/states/multipleSpacesLayout/constants.ts +++ b/src/store/states/multipleSpacesLayout/constants.ts @@ -12,7 +12,7 @@ export enum MultipleSpacesLayoutActionType { MOVE_BREADCRUMBS_TO_PREVIOUS = "@MULTIPLE_SPACES_LAYOUT/MOVE_BREADCRUMBS_TO_PREVIOUS", - ADD_PROJECT_TO_BREADCRUMBS = "@MULTIPLE_SPACES_LAYOUT/ADD_PROJECT_TO_BREADCRUMBS", + ADD_OR_UPDATE_PROJECT_IN_BREADCRUMBS = "@MULTIPLE_SPACES_LAYOUT/ADD_OR_UPDATE_PROJECT_IN_BREADCRUMBS", UPDATE_PROJECT_IN_BREADCRUMBS = "@MULTIPLE_SPACES_LAYOUT/UPDATE_PROJECT_IN_BREADCRUMBS", diff --git a/src/store/states/multipleSpacesLayout/reducer.ts b/src/store/states/multipleSpacesLayout/reducer.ts index de00b83de0..347ae0914f 100644 --- a/src/store/states/multipleSpacesLayout/reducer.ts +++ b/src/store/states/multipleSpacesLayout/reducer.ts @@ -1,9 +1,10 @@ import produce from "immer"; +import { WritableDraft } from "immer/dist/types/types-external"; import { cloneDeep } from "lodash"; import { ActionType, createReducer } from "typesafe-actions"; import { InboxItemType } from "@/shared/constants"; import * as actions from "./actions"; -import { MultipleSpacesLayoutState } from "./types"; +import { MultipleSpacesLayoutState, ProjectsStateItem } from "./types"; type Action = ActionType; @@ -14,6 +15,26 @@ const initialState: MultipleSpacesLayoutState = { mainWidth: window.innerWidth, }; +const updateProjectInBreadcrumbs = ( + state: WritableDraft, + payload: { commonId: string } & Partial>, +): void => { + if (state.breadcrumbs?.type !== InboxItemType.FeedItemFollow) { + return; + } + + const itemIndex = state.breadcrumbs.items.findIndex( + (item) => item.commonId === payload.commonId, + ); + + if (itemIndex > -1) { + state.breadcrumbs.items[itemIndex] = { + ...state.breadcrumbs.items[itemIndex], + ...payload, + }; + } +}; + export const reducer = createReducer( initialState, ) @@ -33,32 +54,29 @@ export const reducer = createReducer( nextState.breadcrumbs = null; }), ) - .handleAction(actions.addProjectToBreadcrumbs, (state, { payload }) => - produce(state, (nextState) => { - if (nextState.breadcrumbs?.type === InboxItemType.FeedItemFollow) { - nextState.breadcrumbs.items = - nextState.breadcrumbs.items.concat(payload); - } - }), - ) - .handleAction(actions.updateProjectInBreadcrumbs, (state, { payload }) => + .handleAction(actions.addOrUpdateProjectInBreadcrumbs, (state, { payload }) => produce(state, (nextState) => { if (nextState.breadcrumbs?.type !== InboxItemType.FeedItemFollow) { return; } - const itemIndex = nextState.breadcrumbs.items.findIndex( + const isItemFound = nextState.breadcrumbs.items.some( (item) => item.commonId === payload.commonId, ); - if (itemIndex > -1) { - nextState.breadcrumbs.items[itemIndex] = { - ...nextState.breadcrumbs.items[itemIndex], - ...payload, - }; + if (isItemFound) { + updateProjectInBreadcrumbs(nextState, payload); + } else { + nextState.breadcrumbs.items = + nextState.breadcrumbs.items.concat(payload); } }), ) + .handleAction(actions.updateProjectInBreadcrumbs, (state, { payload }) => + produce(state, (nextState) => { + updateProjectInBreadcrumbs(nextState, payload); + }), + ) .handleAction(actions.setBackUrl, (state, { payload }) => produce(state, (nextState) => { nextState.backUrl = payload; From a16ab744284c802ffcb407fd6384149953166581 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 11:55:45 +0300 Subject: [PATCH 08/24] refactor addProject commonLayoutActions to allow updating the item --- .../handlers/CommonHandler/CommonHandler.tsx | 2 +- src/store/states/commonLayout/actions.ts | 4 +- src/store/states/commonLayout/constants.ts | 2 +- src/store/states/commonLayout/reducer.ts | 64 ++++++++++++------- 4 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/pages/App/handlers/CommonHandler/CommonHandler.tsx b/src/pages/App/handlers/CommonHandler/CommonHandler.tsx index 7f352f2259..6e0bfa87ce 100644 --- a/src/pages/App/handlers/CommonHandler/CommonHandler.tsx +++ b/src/pages/App/handlers/CommonHandler/CommonHandler.tsx @@ -49,7 +49,7 @@ const CommonHandler: FC = () => { projectsStateItem, ), ); - dispatch(commonLayoutActions.addProject(projectsStateItem)); + dispatch(commonLayoutActions.addOrUpdateProject(projectsStateItem)); dispatch(projectsActions.addProject(projectsStateItem)); }; diff --git a/src/store/states/commonLayout/actions.ts b/src/store/states/commonLayout/actions.ts index c42fdf08d7..93078619a1 100644 --- a/src/store/states/commonLayout/actions.ts +++ b/src/store/states/commonLayout/actions.ts @@ -21,8 +21,8 @@ export const getProjects = createAsyncAction( CommonLayoutActionType.GET_PROJECTS_FAILURE, )(); -export const addProject = createStandardAction( - CommonLayoutActionType.ADD_PROJECT, +export const addOrUpdateProject = createStandardAction( + CommonLayoutActionType.ADD_OR_UPDATE_PROJECT, )(); export const updateCommonOrProject = createStandardAction( diff --git a/src/store/states/commonLayout/constants.ts b/src/store/states/commonLayout/constants.ts index 386bb3a441..38f9c2f751 100644 --- a/src/store/states/commonLayout/constants.ts +++ b/src/store/states/commonLayout/constants.ts @@ -7,7 +7,7 @@ export enum CommonLayoutActionType { GET_PROJECTS_SUCCESS = "@COMMON_LAYOUT/GET_PROJECTS_SUCCESS", GET_PROJECTS_FAILURE = "@COMMON_LAYOUT/GET_PROJECTS_FAILURE", - ADD_PROJECT = "@COMMON_LAYOUT/ADD_PROJECT", + ADD_OR_UPDATE_PROJECT = "@COMMON_LAYOUT/ADD_OR_UPDATE_PROJECT", UPDATE_COMMON_OR_PROJECT = "@COMMON_LAYOUT/UPDATE_COMMON_OR_PROJECT", diff --git a/src/store/states/commonLayout/reducer.ts b/src/store/states/commonLayout/reducer.ts index 402c73cd18..6ee068348b 100644 --- a/src/store/states/commonLayout/reducer.ts +++ b/src/store/states/commonLayout/reducer.ts @@ -3,7 +3,7 @@ import { WritableDraft } from "immer/dist/types/types-external"; import { ActionType, createReducer } from "typesafe-actions"; import { getAllNestedItems } from "../projects/utils"; import * as actions from "./actions"; -import { CommonLayoutState } from "./types"; +import { CommonLayoutState, ProjectsStateItem } from "./types"; type Action = ActionType; @@ -26,6 +26,37 @@ const clearData = (state: WritableDraft): void => { state.areProjectsFetched = false; }; +const updateCommonOrProject = ( + state: WritableDraft, + payload: { commonId: string } & Partial>, +): boolean => { + const commonItemIndex = state.commons.findIndex( + (item) => item.commonId === payload.commonId, + ); + + if (commonItemIndex > -1) { + state.commons[commonItemIndex] = { + ...state.commons[commonItemIndex], + ...payload, + }; + return true; + } + + const projectItemIndex = state.projects.findIndex( + (item) => item.commonId === payload.commonId, + ); + + if (projectItemIndex > -1) { + state.projects[projectItemIndex] = { + ...state.projects[projectItemIndex], + ...payload, + }; + return true; + } + + return false; +}; + export const reducer = createReducer(initialState) .handleAction(actions.getCommons.request, (state) => produce(state, (nextState) => { @@ -67,8 +98,14 @@ export const reducer = createReducer(initialState) nextState.areProjectsFetched = true; }), ) - .handleAction(actions.addProject, (state, { payload }) => + .handleAction(actions.addOrUpdateProject, (state, { payload }) => produce(state, (nextState) => { + const isUpdated = updateCommonOrProject(nextState, payload); + + if (isUpdated) { + return; + } + if (!payload.directParent) { nextState.commons.push(payload); } else { @@ -78,28 +115,7 @@ export const reducer = createReducer(initialState) ) .handleAction(actions.updateCommonOrProject, (state, { payload }) => produce(state, (nextState) => { - const commonItemIndex = nextState.commons.findIndex( - (item) => item.commonId === payload.commonId, - ); - - if (commonItemIndex > -1) { - nextState.commons[commonItemIndex] = { - ...nextState.commons[commonItemIndex], - ...payload, - }; - return; - } - - const projectItemIndex = nextState.projects.findIndex( - (item) => item.commonId === payload.commonId, - ); - - if (projectItemIndex > -1) { - nextState.projects[projectItemIndex] = { - ...nextState.projects[projectItemIndex], - ...payload, - }; - } + updateCommonOrProject(nextState, payload); }), ) .handleAction(actions.setCurrentCommonId, (state, { payload }) => From 59e457f29f28da96974ee52f2720681f90cc566c Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 11:58:59 +0300 Subject: [PATCH 09/24] refactor addProject projectsActions to allow updating the item --- .../handlers/CommonHandler/CommonHandler.tsx | 2 +- src/store/states/projects/actions.ts | 4 +- src/store/states/projects/constants.ts | 2 +- src/store/states/projects/reducer.ts | 40 +++++++++++++------ 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/pages/App/handlers/CommonHandler/CommonHandler.tsx b/src/pages/App/handlers/CommonHandler/CommonHandler.tsx index 6e0bfa87ce..c3dc6b6262 100644 --- a/src/pages/App/handlers/CommonHandler/CommonHandler.tsx +++ b/src/pages/App/handlers/CommonHandler/CommonHandler.tsx @@ -50,7 +50,7 @@ const CommonHandler: FC = () => { ), ); dispatch(commonLayoutActions.addOrUpdateProject(projectsStateItem)); - dispatch(projectsActions.addProject(projectsStateItem)); + dispatch(projectsActions.addOrUpdateProject(projectsStateItem)); }; CommonEventEmitter.on(CommonEvent.ProjectCreated, handler); diff --git a/src/store/states/projects/actions.ts b/src/store/states/projects/actions.ts index 989170ad66..0e879efe86 100644 --- a/src/store/states/projects/actions.ts +++ b/src/store/states/projects/actions.ts @@ -8,8 +8,8 @@ export const getProjects = createAsyncAction( ProjectsActionType.GET_PROJECTS_FAILURE, )(); -export const addProject = createStandardAction( - ProjectsActionType.ADD_PROJECT, +export const addOrUpdateProject = createStandardAction( + ProjectsActionType.ADD_OR_UPDATE_PROJECT, )(); export const updateProject = createStandardAction( diff --git a/src/store/states/projects/constants.ts b/src/store/states/projects/constants.ts index e25bfb1d5f..0a8ae4942f 100644 --- a/src/store/states/projects/constants.ts +++ b/src/store/states/projects/constants.ts @@ -3,7 +3,7 @@ export enum ProjectsActionType { GET_PROJECTS_SUCCESS = "@PROJECTS/GET_PROJECTS_SUCCESS", GET_PROJECTS_FAILURE = "@PROJECTS/GET_PROJECTS_FAILURE", - ADD_PROJECT = "@PROJECTS/ADD_PROJECT", + ADD_OR_UPDATE_PROJECT = "@PROJECTS/ADD_OR_UPDATE_PROJECT", UPDATE_PROJECT = "@PROJECTS/UPDATE_PROJECT", diff --git a/src/store/states/projects/reducer.ts b/src/store/states/projects/reducer.ts index ed803c59fa..2a5195e86d 100644 --- a/src/store/states/projects/reducer.ts +++ b/src/store/states/projects/reducer.ts @@ -2,7 +2,7 @@ import produce from "immer"; import { WritableDraft } from "immer/dist/types/types-external"; import { ActionType, createReducer } from "typesafe-actions"; import * as actions from "./actions"; -import { ProjectsState } from "./types"; +import { ProjectsState, ProjectsStateItem } from "./types"; import { getAllNestedItems, getRelatedToIdItems } from "./utils"; type Action = ActionType; @@ -20,6 +20,25 @@ const clearProjects = (state: WritableDraft): void => { state.isDataFetched = false; }; +const updateProject = ( + state: WritableDraft, + payload: { commonId: string } & Partial>, +): boolean => { + const itemIndex = state.data.findIndex( + (item) => item.commonId === payload.commonId, + ); + + if (itemIndex > -1) { + state.data[itemIndex] = { + ...state.data[itemIndex], + ...payload, + }; + return true; + } + + return false; +}; + export const reducer = createReducer(initialState) .handleAction(actions.getProjects.request, (state) => produce(state, (nextState) => { @@ -40,23 +59,18 @@ export const reducer = createReducer(initialState) nextState.isDataFetched = true; }), ) - .handleAction(actions.addProject, (state, { payload }) => + .handleAction(actions.addOrUpdateProject, (state, { payload }) => produce(state, (nextState) => { - nextState.data.push(payload); + const isUpdated = updateProject(nextState, payload); + + if (!isUpdated) { + nextState.data.push(payload); + } }), ) .handleAction(actions.updateProject, (state, { payload }) => produce(state, (nextState) => { - const itemIndex = nextState.data.findIndex( - (item) => item.commonId === payload.commonId, - ); - - if (itemIndex > -1) { - nextState.data[itemIndex] = { - ...nextState.data[itemIndex], - ...payload, - }; - } + updateProject(nextState, payload); }), ) .handleAction(actions.clearProjects, (state) => From ecd51871bd3bd9269859addb57964cfa122257d4 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 13:20:20 +0300 Subject: [PATCH 10/24] subscribe to projects update in the sidenav content --- src/events/CommonEventEmitter.ts | 6 ++-- .../handlers/CommonHandler/CommonHandler.tsx | 25 +++++++-------- .../CreateCommonModal/CreateCommonModal.tsx | 5 ++- .../CommonCreation/CommonCreation.tsx | 2 +- .../ProjectCreation/ProjectCreation.tsx | 5 ++- src/services/Common.ts | 5 +++ .../SidenavContent/hooks/useProjectsData.ts | 32 +++++++++++++++++++ 7 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/events/CommonEventEmitter.ts b/src/events/CommonEventEmitter.ts index f635ac3227..1ec16cc5e3 100644 --- a/src/events/CommonEventEmitter.ts +++ b/src/events/CommonEventEmitter.ts @@ -6,7 +6,7 @@ export enum CommonEvent { CommonCreated = "common-created", CommonUpdated = "common-updated", CommonDeleted = "common-deleted", - ProjectCreated = "project-created", + ProjectCreatedOrUpdated = "project-created-or-updated", ProjectUpdated = "project-updated", } @@ -14,7 +14,9 @@ export interface CommonEventToListener { [CommonEvent.CommonCreated]: (common: Common) => void; [CommonEvent.CommonUpdated]: (common: Common) => void; [CommonEvent.CommonDeleted]: (deletedCommonId: string) => void; - [CommonEvent.ProjectCreated]: (projectsStateItem: ProjectsStateItem) => void; + [CommonEvent.ProjectCreatedOrUpdated]: ( + projectsStateItem: ProjectsStateItem, + ) => void; [CommonEvent.ProjectUpdated]: ( projectsStateItem: { commonId: string } & Partial< Omit diff --git a/src/pages/App/handlers/CommonHandler/CommonHandler.tsx b/src/pages/App/handlers/CommonHandler/CommonHandler.tsx index c3dc6b6262..36f75d4236 100644 --- a/src/pages/App/handlers/CommonHandler/CommonHandler.tsx +++ b/src/pages/App/handlers/CommonHandler/CommonHandler.tsx @@ -41,22 +41,21 @@ const CommonHandler: FC = () => { }, []); useEffect(() => { - const handler: CommonEventToListener[CommonEvent.ProjectCreated] = ( - projectsStateItem, - ) => { - dispatch( - multipleSpacesLayoutActions.addOrUpdateProjectInBreadcrumbs( - projectsStateItem, - ), - ); - dispatch(commonLayoutActions.addOrUpdateProject(projectsStateItem)); - dispatch(projectsActions.addOrUpdateProject(projectsStateItem)); - }; + const handler: CommonEventToListener[CommonEvent.ProjectCreatedOrUpdated] = + (projectsStateItem) => { + dispatch( + multipleSpacesLayoutActions.addOrUpdateProjectInBreadcrumbs( + projectsStateItem, + ), + ); + dispatch(commonLayoutActions.addOrUpdateProject(projectsStateItem)); + dispatch(projectsActions.addOrUpdateProject(projectsStateItem)); + }; - CommonEventEmitter.on(CommonEvent.ProjectCreated, handler); + CommonEventEmitter.on(CommonEvent.ProjectCreatedOrUpdated, handler); return () => { - CommonEventEmitter.off(CommonEvent.ProjectCreated, handler); + CommonEventEmitter.off(CommonEvent.ProjectCreatedOrUpdated, handler); }; }, []); diff --git a/src/pages/OldCommon/components/CommonListContainer/CreateCommonModal/CreateCommonModal.tsx b/src/pages/OldCommon/components/CommonListContainer/CreateCommonModal/CreateCommonModal.tsx index 389107b0c8..7548b94acb 100644 --- a/src/pages/OldCommon/components/CommonListContainer/CreateCommonModal/CreateCommonModal.tsx +++ b/src/pages/OldCommon/components/CommonListContainer/CreateCommonModal/CreateCommonModal.tsx @@ -289,7 +289,10 @@ export default function CreateCommonModal(props: CreateCommonModalProps) { notificationsAmount: 0, }; - CommonEventEmitter.emit(CommonEvent.ProjectCreated, projectsStateItem); + CommonEventEmitter.emit( + CommonEvent.ProjectCreatedOrUpdated, + projectsStateItem, + ); CommonEventEmitter.emit( CommonEvent.CommonCreated, createdCommonData.common, diff --git a/src/pages/commonCreation/components/CommonCreation/CommonCreation.tsx b/src/pages/commonCreation/components/CommonCreation/CommonCreation.tsx index d48ded7561..b5bc88bfe7 100644 --- a/src/pages/commonCreation/components/CommonCreation/CommonCreation.tsx +++ b/src/pages/commonCreation/components/CommonCreation/CommonCreation.tsx @@ -24,7 +24,7 @@ const CommonCreation: FC = () => { (circle) => circle.allowedActions[GovernanceActions.CREATE_PROJECT], ); - CommonEventEmitter.emit(CommonEvent.ProjectCreated, { + CommonEventEmitter.emit(CommonEvent.ProjectCreatedOrUpdated, { commonId: common.id, image: common.image, name: common.name, diff --git a/src/pages/commonCreation/components/ProjectCreation/ProjectCreation.tsx b/src/pages/commonCreation/components/ProjectCreation/ProjectCreation.tsx index 6a71f896da..72c1f6112d 100644 --- a/src/pages/commonCreation/components/ProjectCreation/ProjectCreation.tsx +++ b/src/pages/commonCreation/components/ProjectCreation/ProjectCreation.tsx @@ -69,7 +69,10 @@ const ProjectCreation: FC = (props) => { }; dispatch(commonActions.setIsNewProjectCreated(true)); - CommonEventEmitter.emit(CommonEvent.ProjectCreated, projectsStateItem); + CommonEventEmitter.emit( + CommonEvent.ProjectCreatedOrUpdated, + projectsStateItem, + ); } CommonEventEmitter.emit(CommonEvent.CommonUpdated, createdProject); history.push(getCommonPagePath(createdProject.id)); diff --git a/src/services/Common.ts b/src/services/Common.ts index b9c88e2a57..925591a04b 100644 --- a/src/services/Common.ts +++ b/src/services/Common.ts @@ -17,6 +17,7 @@ import { } from "@/shared/models"; import { convertObjectDatesToFirestoreTimestamps, + emptyFunction, firestoreDataConverter, transformFirebaseDataList, } from "@/shared/utils"; @@ -296,6 +297,10 @@ class CommonService { parentCommonId: string, callback: (data: { common: Common; isRemoved: boolean }[]) => void, ): UnsubscribeFunction => { + if (!parentCommonId) { + return emptyFunction; + } + const query = firebase .firestore() .collection(Collection.Daos) diff --git a/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts b/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts index 5633af13bf..bc40f93909 100644 --- a/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts +++ b/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts @@ -1,7 +1,9 @@ import { useCallback, useEffect, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useHistory } from "react-router"; +import { CommonEvent, CommonEventEmitter } from "@/events"; import { authentificated } from "@/pages/Auth/store/selectors"; +import { CommonService } from "@/services"; import { useRoutesContext } from "@/shared/contexts"; import { commonLayoutActions, @@ -126,6 +128,36 @@ export const useProjectsData = (): Return => { dispatch(commonLayoutActions.clearProjects()); }, [activeItemId]); + useEffect(() => { + if (!areProjectsFetched) { + return; + } + + const unsubscribe = CommonService.subscribeToSubCommons( + activeItemId, + (data) => { + data.forEach(({ common, isRemoved }) => { + if (isRemoved) { + return; + } + + CommonEventEmitter.emit(CommonEvent.CommonUpdated, common); + CommonEventEmitter.emit(CommonEvent.ProjectCreatedOrUpdated, { + commonId: common.id, + image: common.image, + name: common.name, + directParent: common.directParent, + hasMembership: true, + hasPermissionToAddProject: true, + notificationsAmount: 0, + }); + }); + }, + ); + + return unsubscribe; + }, [areProjectsFetched, activeItemId]); + return { currentCommonId, parentItem, From 8fb2ce06db25562e612ab2c5a0440eb796911cdc Mon Sep 17 00:00:00 2001 From: Pavel Meyer Date: Tue, 12 Sep 2023 13:34:53 +0300 Subject: [PATCH 11/24] CW-2059 Fixed plural for circle naming --- .../MembersTab/components/MemberDropdown/AssignCircleModal.tsx | 2 +- .../MembersTab/components/MemberDropdown/MemberDropdown.tsx | 2 +- .../CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/AssignCircleModal.tsx b/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/AssignCircleModal.tsx index b971253472..ee475b998f 100644 --- a/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/AssignCircleModal.tsx +++ b/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/AssignCircleModal.tsx @@ -62,7 +62,7 @@ export default function AssignCircleModal({ onClose={handleClose} hideCloseButton={isAdding} className={styles.modal} - title={`Add ${memberName} to ${selectedCircle?.name}?`} + title={`Add ${memberName} to ${selectedCircle?.name}s?`} >
diff --git a/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/MemberDropdown.tsx b/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/MemberDropdown.tsx index c421734382..ddfcc9c410 100644 --- a/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/MemberDropdown.tsx +++ b/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/MemberDropdown.tsx @@ -31,7 +31,7 @@ const MemberDropdown: FC = (props) => { () => notMemberCircles.map((circle) => ({ id: circle.id, - text: `Add to ${circle.name}`, + text: `Add to ${circle.name}s`, onClick: () => { setSelectedCircle(circle); onOpen(); diff --git a/src/pages/common/providers/CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx b/src/pages/common/providers/CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx index 6854ed284f..6e241da6b7 100644 --- a/src/pages/common/providers/CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx +++ b/src/pages/common/providers/CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx @@ -61,7 +61,7 @@ const LeaveCircleModal: FC = (props) => { aria-hidden />

- Are you sure you want to leave {circle.name}? + Are you sure you want to leave {circle.name}s?

If you leave this circle, you might lose permissions associated with From 0ce524897ae27886769099b3749eba041ada8227 Mon Sep 17 00:00:00 2001 From: Pavel Meyer Date: Tue, 12 Sep 2023 13:39:24 +0300 Subject: [PATCH 12/24] CW-2054 Fixed infinity loading for guest user --- src/services/CommonFeedObjectUserUnique.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/services/CommonFeedObjectUserUnique.ts b/src/services/CommonFeedObjectUserUnique.ts index b391bb358d..b2f7109902 100644 --- a/src/services/CommonFeedObjectUserUnique.ts +++ b/src/services/CommonFeedObjectUserUnique.ts @@ -40,9 +40,15 @@ class CommonFeedObjectUserUniqueService { feedObjectId: string, callback: (data: CommonFeedObjectUserUnique) => void, ): UnsubscribeFunction => { - const query = this.getCommonFeedObjectUserUniqueSubCollection(commonId) - .where("feedObjectId", "==", feedObjectId) - .where("userId", "==", userId); + let query = this.getCommonFeedObjectUserUniqueSubCollection(commonId).where( + "feedObjectId", + "==", + feedObjectId, + ); + + if (userId) { + query = query.where("userId", "==", userId); + } return query.onSnapshot((snapshot) => { const data = snapshot.docChanges()[0]?.doc.data(); From 0db892227bea3e104d253e31abc629f38d038de6 Mon Sep 17 00:00:00 2001 From: Daniel Reinoso Date: Tue, 12 Sep 2023 08:36:55 -0300 Subject: [PATCH 13/24] Revert change to package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15a9effe22..26375b9ba8 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "scripts": { "build": "craco build", "build:storybook": "build-storybook -s public", - "start": "REACT_APP_ENV=local craco start", + "start": "REACT_APP_ENV=dev craco start", "test": "TZ=UTC jest", "test:watch": "yarn test --watch", "test:storybook": "test-storybook", From 8bad502469e2616ff63bccdca29a42dfc1f654ab Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 14:32:00 +0300 Subject: [PATCH 14/24] add membership and permissions check for new spaces --- .../SidenavContent/hooks/useProjectsData.ts | 124 +++++++++++++++--- 1 file changed, 107 insertions(+), 17 deletions(-) diff --git a/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts b/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts index bc40f93909..7fd1269cbc 100644 --- a/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts +++ b/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts @@ -1,10 +1,13 @@ -import { useCallback, useEffect, useMemo } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useHistory } from "react-router"; import { CommonEvent, CommonEventEmitter } from "@/events"; -import { authentificated } from "@/pages/Auth/store/selectors"; -import { CommonService } from "@/services"; +import { authentificated, selectUser } from "@/pages/Auth/store/selectors"; +import { CommonService, GovernanceService, Logger } from "@/services"; +import { GovernanceActions } from "@/shared/constants"; import { useRoutesContext } from "@/shared/contexts"; +import { Common } from "@/shared/models"; +import { generateCirclesDataForCommonMember } from "@/shared/utils"; import { commonLayoutActions, ProjectsStateItem, @@ -34,6 +37,55 @@ interface Return { parentItemIds: string[]; } +const getProjectItemFromCommon = async ( + common: Common, + userId?: string, + initialItem?: ProjectsStateItem, +): Promise => { + const baseItem: Omit< + ProjectsStateItem, + "hasMembership" | "hasPermissionToAddProject" + > = { + commonId: common.id, + image: common.image, + name: common.name, + directParent: common.directParent, + }; + + if (initialItem) { + return { + ...baseItem, + hasMembership: initialItem.hasMembership, + hasPermissionToAddProject: initialItem.hasPermissionToAddProject, + }; + } + if (!userId) { + return { + ...baseItem, + hasMembership: false, + hasPermissionToAddProject: false, + }; + } + + const [governance, commonMember] = await Promise.all([ + GovernanceService.getGovernanceByCommonId(common.id), + CommonService.getCommonMemberByUserId(common.id, userId), + ]); + + return { + ...baseItem, + hasMembership: Boolean(commonMember), + hasPermissionToAddProject: Boolean( + governance && + commonMember && + generateCirclesDataForCommonMember( + governance.circles, + commonMember.circleIds, + ).allowedActions[GovernanceActions.CREATE_PROJECT], + ), + }; +}; + export const useProjectsData = (): Return => { const dispatch = useDispatch(); const history = useHistory(); @@ -47,6 +99,10 @@ export const useProjectsData = (): Return => { const { projects, areProjectsLoading, areProjectsFetched } = useSelector( selectCommonLayoutProjectsState, ); + const user = useSelector(selectUser()); + const userId = user?.uid; + const [updatedItemsQueue, setUpdatedItemsQueue] = useState([]); + const nextUpdatedItems = updatedItemsQueue[0]; const currentCommon = commons.find( ({ commonId }) => commonId === currentCommonId, ); @@ -136,28 +192,62 @@ export const useProjectsData = (): Return => { const unsubscribe = CommonService.subscribeToSubCommons( activeItemId, (data) => { - data.forEach(({ common, isRemoved }) => { - if (isRemoved) { - return; + const commons = data.reduce((acc, { common, isRemoved }) => { + if (!isRemoved) { + CommonEventEmitter.emit(CommonEvent.CommonUpdated, common); + return acc.concat(common); } - CommonEventEmitter.emit(CommonEvent.CommonUpdated, common); - CommonEventEmitter.emit(CommonEvent.ProjectCreatedOrUpdated, { - commonId: common.id, - image: common.image, - name: common.name, - directParent: common.directParent, - hasMembership: true, - hasPermissionToAddProject: true, - notificationsAmount: 0, - }); - }); + return acc; + }, []); + + if (commons.length !== 0) { + setUpdatedItemsQueue((currentItems) => + currentItems.concat([commons]), + ); + } }, ); return unsubscribe; }, [areProjectsFetched, activeItemId]); + useEffect(() => { + if (!nextUpdatedItems) { + return; + } + if (nextUpdatedItems.length === 0) { + setUpdatedItemsQueue((currentItems) => currentItems.slice(1)); + return; + } + + (async () => { + try { + const items = await Promise.all( + nextUpdatedItems.map(async (nextUpdatedItem) => { + const existingItem = + commons.find((item) => item.commonId === nextUpdatedItem.id) || + projects.find((item) => item.commonId === nextUpdatedItem.id); + + return await getProjectItemFromCommon( + nextUpdatedItem, + userId, + existingItem, + ); + }), + ); + + items.forEach((item) => { + CommonEventEmitter.emit(CommonEvent.ProjectCreatedOrUpdated, item); + }); + } catch (error) { + Logger.error(error); + } finally { + setUpdatedItemsQueue((currentItems) => currentItems.slice(1)); + } + })(); + }, [nextUpdatedItems]); + return { currentCommonId, parentItem, From 0a8bb237abbc7f98e3a6771cd4bc6f6359a891b8 Mon Sep 17 00:00:00 2001 From: Kiryl Budnik Date: Tue, 12 Sep 2023 15:46:17 +0300 Subject: [PATCH 15/24] update join button text --- .../CommonDetailContainer/EmptyTabContent/EmptyTabComponent.tsx | 2 +- src/pages/common/components/ChatComponent/ChatComponent.tsx | 2 +- src/pages/common/components/CommonHeader/CommonHeader.tsx | 2 +- .../components/CommonEntranceJoin/CommonEntranceJoin.tsx | 2 +- .../components/JoinProjectForm/JoinProjectForm.tsx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/OldCommon/components/CommonDetailContainer/EmptyTabContent/EmptyTabComponent.tsx b/src/pages/OldCommon/components/CommonDetailContainer/EmptyTabContent/EmptyTabComponent.tsx index e856f50093..dafc3000eb 100644 --- a/src/pages/OldCommon/components/CommonDetailContainer/EmptyTabContent/EmptyTabComponent.tsx +++ b/src/pages/OldCommon/components/CommonDetailContainer/EmptyTabContent/EmptyTabComponent.tsx @@ -93,7 +93,7 @@ export default function EmptyTabComponent({ className="button-blue empty-tab-content-wrapper__button" onClick={handleModalOpen} > - Join the effort + Join )}

diff --git a/src/pages/common/components/ChatComponent/ChatComponent.tsx b/src/pages/common/components/ChatComponent/ChatComponent.tsx index a6da5e4335..13abe69dab 100644 --- a/src/pages/common/components/ChatComponent/ChatComponent.tsx +++ b/src/pages/common/components/ChatComponent/ChatComponent.tsx @@ -577,7 +577,7 @@ export default function ChatComponent({ return ( - {directParent ? "Join the space" : "Join the effort"} + Join ); }; diff --git a/src/pages/common/components/CommonHeader/CommonHeader.tsx b/src/pages/common/components/CommonHeader/CommonHeader.tsx index 30f40d757d..171e5597c0 100644 --- a/src/pages/common/components/CommonHeader/CommonHeader.tsx +++ b/src/pages/common/components/CommonHeader/CommonHeader.tsx @@ -25,7 +25,7 @@ const CommonHeader: FC = (props) => { details = [], isProject = false, withJoin = true, - joinButtonText = isProject ? "Join the space" : "Join the effort", + joinButtonText = "Join", } = props; const { isJoinAllowed, onJoinCommon } = useCommonDataContext(); const isTabletView = useIsTabletView(); diff --git a/src/pages/common/components/CommonTabPanels/components/AboutTab/components/CommonEntranceInfo/components/CommonEntranceJoin/CommonEntranceJoin.tsx b/src/pages/common/components/CommonTabPanels/components/AboutTab/components/CommonEntranceInfo/components/CommonEntranceJoin/CommonEntranceJoin.tsx index 8d07136727..7bf4b3d441 100644 --- a/src/pages/common/components/CommonTabPanels/components/AboutTab/components/CommonEntranceInfo/components/CommonEntranceJoin/CommonEntranceJoin.tsx +++ b/src/pages/common/components/CommonTabPanels/components/AboutTab/components/CommonEntranceInfo/components/CommonEntranceJoin/CommonEntranceJoin.tsx @@ -44,7 +44,7 @@ const CommonEntranceJoin: FC = (props) => { : onJoinCommon } > - Join the {isProject ? "space" : "effort"} + Join )} diff --git a/src/pages/common/components/JoinProjectModal/components/JoinProjectForm/JoinProjectForm.tsx b/src/pages/common/components/JoinProjectModal/components/JoinProjectForm/JoinProjectForm.tsx index eea13a366a..f84b3a57bb 100644 --- a/src/pages/common/components/JoinProjectModal/components/JoinProjectForm/JoinProjectForm.tsx +++ b/src/pages/common/components/JoinProjectModal/components/JoinProjectForm/JoinProjectForm.tsx @@ -42,7 +42,7 @@ const JoinProjectForm: FC> = ( disabled={!message} onClick={handleRequestToJoin} > - {isJoinMemberAdmittanceRequest ? "Request to join" : "Join space"} + {isJoinMemberAdmittanceRequest ? "Request to join" : "Join"}
From c5c93697a6f7b95503091f6d4fd240e622b22e21 Mon Sep 17 00:00:00 2001 From: Kiryl Budnik Date: Tue, 12 Sep 2023 15:47:38 +0300 Subject: [PATCH 16/24] redirect to the common about page if user is not a member of the parent common --- src/pages/commonFeed/CommonFeed.tsx | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index d19b4729b7..54943aa6f0 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -38,6 +38,7 @@ import { selectRecentStreamId, selectSharedFeedItem, } from "@/store/states"; +import { useCommonMember } from "../OldCommon/hooks"; import { NewDiscussionCreation, NewProposalCreation, @@ -120,6 +121,11 @@ const CommonFeedComponent: FC = (props) => { loading: areCommonPinnedFeedItemsLoading, fetch: fetchCommonPinnedFeedItems, } = useCommonPinnedFeedItems(commonId, pinnedItemIds); + const { + data: parentCommonMember, + fetched: isParentCommonMemberFetched, + fetchCommonMember: fetchParentCommonMember, + } = useCommonMember(); const commonFeedItemIdsForNotListening = useMemo(() => { const items: string[] = []; @@ -159,7 +165,9 @@ const CommonFeedComponent: FC = (props) => { return items; }, [sharedFeedItem, sharedFeedItemId, commonPinnedFeedItems]); const firstItem = commonFeedItems?.[0]; - const isDataFetched = isCommonDataFetched; + const isDataFetched = + isCommonDataFetched && + (parentCommonId ? isParentCommonMemberFetched : true); const hasPublicItem = true; const fetchData = () => { @@ -193,6 +201,18 @@ const CommonFeedComponent: FC = (props) => { [dispatch], ); + useEffect(() => { + if (parentCommonId) { + fetchParentCommonMember(parentCommonId, {}, true); + } + }, [parentCommonId]); + + useEffect(() => { + if (isParentCommonMemberFetched && !parentCommonMember) { + history.replace(getCommonPageAboutTabPath(commonId)); + } + }, [parentCommonMember?.id, isParentCommonMemberFetched, commonId]); + useEffect(() => { if (!isCommonDataFetched || !isGlobalDataFetched || commonMember) { return; From d21da196557e6174d41753e914844b3369725328 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 15:47:49 +0300 Subject: [PATCH 17/24] move projects subscription logic to a separate hook --- .../SidenavContent/hooks/useProjectsData.ts | 133 ++--------------- .../hooks/useProjectsSubscription.ts | 137 ++++++++++++++++++ 2 files changed, 146 insertions(+), 124 deletions(-) create mode 100644 src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsSubscription.ts diff --git a/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts b/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts index 7fd1269cbc..3e7b0fb903 100644 --- a/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts +++ b/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsData.ts @@ -1,13 +1,8 @@ -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useHistory } from "react-router"; -import { CommonEvent, CommonEventEmitter } from "@/events"; -import { authentificated, selectUser } from "@/pages/Auth/store/selectors"; -import { CommonService, GovernanceService, Logger } from "@/services"; -import { GovernanceActions } from "@/shared/constants"; +import { authentificated } from "@/pages/Auth/store/selectors"; import { useRoutesContext } from "@/shared/contexts"; -import { Common } from "@/shared/models"; -import { generateCirclesDataForCommonMember } from "@/shared/utils"; import { commonLayoutActions, ProjectsStateItem, @@ -24,6 +19,7 @@ import { getParentItemIds, Item, } from "../../../../SidenavLayout/components/SidenavContent/components"; +import { useProjectsSubscription } from "./useProjectsSubscription"; interface Return { currentCommonId: string | null; @@ -37,55 +33,6 @@ interface Return { parentItemIds: string[]; } -const getProjectItemFromCommon = async ( - common: Common, - userId?: string, - initialItem?: ProjectsStateItem, -): Promise => { - const baseItem: Omit< - ProjectsStateItem, - "hasMembership" | "hasPermissionToAddProject" - > = { - commonId: common.id, - image: common.image, - name: common.name, - directParent: common.directParent, - }; - - if (initialItem) { - return { - ...baseItem, - hasMembership: initialItem.hasMembership, - hasPermissionToAddProject: initialItem.hasPermissionToAddProject, - }; - } - if (!userId) { - return { - ...baseItem, - hasMembership: false, - hasPermissionToAddProject: false, - }; - } - - const [governance, commonMember] = await Promise.all([ - GovernanceService.getGovernanceByCommonId(common.id), - CommonService.getCommonMemberByUserId(common.id, userId), - ]); - - return { - ...baseItem, - hasMembership: Boolean(commonMember), - hasPermissionToAddProject: Boolean( - governance && - commonMember && - generateCirclesDataForCommonMember( - governance.circles, - commonMember.circleIds, - ).allowedActions[GovernanceActions.CREATE_PROJECT], - ), - }; -}; - export const useProjectsData = (): Return => { const dispatch = useDispatch(); const history = useHistory(); @@ -99,10 +46,6 @@ export const useProjectsData = (): Return => { const { projects, areProjectsLoading, areProjectsFetched } = useSelector( selectCommonLayoutProjectsState, ); - const user = useSelector(selectUser()); - const userId = user?.uid; - const [updatedItemsQueue, setUpdatedItemsQueue] = useState([]); - const nextUpdatedItems = updatedItemsQueue[0]; const currentCommon = commons.find( ({ commonId }) => commonId === currentCommonId, ); @@ -141,6 +84,12 @@ export const useProjectsData = (): Return => { const itemIdWithNewProjectCreation = getItemIdWithNewProjectCreationByPath( location.pathname, ); + useProjectsSubscription({ + activeItemId, + areProjectsFetched, + commons, + projects, + }); useEffect(() => { if (isAuthenticated) { @@ -184,70 +133,6 @@ export const useProjectsData = (): Return => { dispatch(commonLayoutActions.clearProjects()); }, [activeItemId]); - useEffect(() => { - if (!areProjectsFetched) { - return; - } - - const unsubscribe = CommonService.subscribeToSubCommons( - activeItemId, - (data) => { - const commons = data.reduce((acc, { common, isRemoved }) => { - if (!isRemoved) { - CommonEventEmitter.emit(CommonEvent.CommonUpdated, common); - return acc.concat(common); - } - - return acc; - }, []); - - if (commons.length !== 0) { - setUpdatedItemsQueue((currentItems) => - currentItems.concat([commons]), - ); - } - }, - ); - - return unsubscribe; - }, [areProjectsFetched, activeItemId]); - - useEffect(() => { - if (!nextUpdatedItems) { - return; - } - if (nextUpdatedItems.length === 0) { - setUpdatedItemsQueue((currentItems) => currentItems.slice(1)); - return; - } - - (async () => { - try { - const items = await Promise.all( - nextUpdatedItems.map(async (nextUpdatedItem) => { - const existingItem = - commons.find((item) => item.commonId === nextUpdatedItem.id) || - projects.find((item) => item.commonId === nextUpdatedItem.id); - - return await getProjectItemFromCommon( - nextUpdatedItem, - userId, - existingItem, - ); - }), - ); - - items.forEach((item) => { - CommonEventEmitter.emit(CommonEvent.ProjectCreatedOrUpdated, item); - }); - } catch (error) { - Logger.error(error); - } finally { - setUpdatedItemsQueue((currentItems) => currentItems.slice(1)); - } - })(); - }, [nextUpdatedItems]); - return { currentCommonId, parentItem, diff --git a/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsSubscription.ts b/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsSubscription.ts new file mode 100644 index 0000000000..54797df4b4 --- /dev/null +++ b/src/shared/layouts/CommonSidenavLayout/components/SidenavContent/hooks/useProjectsSubscription.ts @@ -0,0 +1,137 @@ +import { useEffect, useState } from "react"; +import { useSelector } from "react-redux"; +import { CommonEvent, CommonEventEmitter } from "@/events"; +import { selectUser } from "@/pages/Auth/store/selectors"; +import { CommonService, GovernanceService, Logger } from "@/services"; +import { GovernanceActions } from "@/shared/constants"; +import { Common } from "@/shared/models"; +import { generateCirclesDataForCommonMember } from "@/shared/utils"; +import { ProjectsStateItem } from "@/store/states"; + +interface Data { + activeItemId: string; + areProjectsFetched: boolean; + commons: ProjectsStateItem[]; + projects: ProjectsStateItem[]; +} + +const getProjectItemFromCommon = async ( + common: Common, + userId?: string, + initialItem?: ProjectsStateItem, +): Promise => { + const baseItem: Omit< + ProjectsStateItem, + "hasMembership" | "hasPermissionToAddProject" + > = { + commonId: common.id, + image: common.image, + name: common.name, + directParent: common.directParent, + }; + + if (initialItem) { + return { + ...baseItem, + hasMembership: initialItem.hasMembership, + hasPermissionToAddProject: initialItem.hasPermissionToAddProject, + }; + } + if (!userId) { + return { + ...baseItem, + hasMembership: false, + hasPermissionToAddProject: false, + }; + } + + const [governance, commonMember] = await Promise.all([ + GovernanceService.getGovernanceByCommonId(common.id), + CommonService.getCommonMemberByUserId(common.id, userId), + ]); + + return { + ...baseItem, + hasMembership: Boolean(commonMember), + hasPermissionToAddProject: Boolean( + governance && + commonMember && + generateCirclesDataForCommonMember( + governance.circles, + commonMember.circleIds, + ).allowedActions[GovernanceActions.CREATE_PROJECT], + ), + }; +}; + +export const useProjectsSubscription = (data: Data) => { + const { activeItemId, areProjectsFetched, commons, projects } = data; + const [updatedItemsQueue, setUpdatedItemsQueue] = useState([]); + const user = useSelector(selectUser()); + const userId = user?.uid; + const nextUpdatedItems = updatedItemsQueue[0]; + + useEffect(() => { + if (!areProjectsFetched) { + return; + } + + const unsubscribe = CommonService.subscribeToSubCommons( + activeItemId, + (data) => { + const commons = data.reduce((acc, { common, isRemoved }) => { + if (!isRemoved) { + CommonEventEmitter.emit(CommonEvent.CommonUpdated, common); + return acc.concat(common); + } + + return acc; + }, []); + + if (commons.length !== 0) { + setUpdatedItemsQueue((currentItems) => + currentItems.concat([commons]), + ); + } + }, + ); + + return unsubscribe; + }, [areProjectsFetched, activeItemId]); + + useEffect(() => { + if (!nextUpdatedItems) { + return; + } + if (nextUpdatedItems.length === 0) { + setUpdatedItemsQueue((currentItems) => currentItems.slice(1)); + return; + } + + (async () => { + try { + const items = await Promise.all( + nextUpdatedItems.map(async (nextUpdatedItem) => { + const existingItem = + commons.find((item) => item.commonId === nextUpdatedItem.id) || + projects.find((item) => item.commonId === nextUpdatedItem.id); + + return await getProjectItemFromCommon( + nextUpdatedItem, + userId, + existingItem, + ); + }), + ); + + items.forEach((item) => { + CommonEventEmitter.emit(CommonEvent.ProjectCreatedOrUpdated, item); + }); + } catch (error) { + Logger.error(error); + } finally { + setUpdatedItemsQueue((currentItems) => currentItems.slice(1)); + } + })(); + }, [nextUpdatedItems]); +}; From d4f84c01c81f4d215aa5f54de3768b2c966107af Mon Sep 17 00:00:00 2001 From: Pavel Meyer Date: Tue, 12 Sep 2023 16:51:14 +0300 Subject: [PATCH 18/24] CW-2059 Added pluralize library --- package.json | 1 + .../components/MemberDropdown/AssignCircleModal.tsx | 3 ++- .../components/MemberDropdown/MemberDropdown.tsx | 3 ++- .../components/LeaveCircleModal/LeaveCircleModal.tsx | 3 ++- src/shared/utils/index.tsx | 1 + src/shared/utils/pluralizeWord.ts | 9 +++++++++ yarn.lock | 5 +++++ 7 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 src/shared/utils/pluralizeWord.ts diff --git a/package.json b/package.json index 26375b9ba8..c9f9c2bf94 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "moment": "^2.29.1", "node-sass": "^4.14.1", "openpgp": "4.10.4", + "pluralize": "^8.0.0", "query-string": "^7.1.0", "react": "^17.0.1", "react-aria-menubutton": "^7.0.3", diff --git a/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/AssignCircleModal.tsx b/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/AssignCircleModal.tsx index ee475b998f..6717fb1d73 100644 --- a/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/AssignCircleModal.tsx +++ b/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/AssignCircleModal.tsx @@ -5,6 +5,7 @@ import { Modal } from "@/shared/components"; import { ErrorText } from "@/shared/components/Form"; import { Circle } from "@/shared/models"; import { Button, ButtonVariant } from "@/shared/ui-kit"; +import { pluralizeWord } from "@/shared/utils"; import { commonActions } from "@/store/states"; import styles from "./AssignCircleModal.module.scss"; @@ -62,7 +63,7 @@ export default function AssignCircleModal({ onClose={handleClose} hideCloseButton={isAdding} className={styles.modal} - title={`Add ${memberName} to ${selectedCircle?.name}s?`} + title={`Add ${memberName} to ${pluralizeWord(selectedCircle?.name)}?`} >
diff --git a/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/MemberDropdown.tsx b/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/MemberDropdown.tsx index ddfcc9c410..0aae207690 100644 --- a/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/MemberDropdown.tsx +++ b/src/pages/common/components/CommonTabPanels/components/MembersTab/components/MemberDropdown/MemberDropdown.tsx @@ -3,6 +3,7 @@ import { useModal } from "@/shared/hooks"; import { ContextMenuItem as Item } from "@/shared/interfaces"; import { Circle } from "@/shared/models"; import { ContextMenu, ContextMenuRef } from "@/shared/ui-kit"; +import { pluralizeWord } from "@/shared/utils"; import AssignCircleModal from "./AssignCircleModal"; import elementDropdownStyles from "./MemberDropdown.module.scss"; @@ -31,7 +32,7 @@ const MemberDropdown: FC = (props) => { () => notMemberCircles.map((circle) => ({ id: circle.id, - text: `Add to ${circle.name}s`, + text: `Add to ${pluralizeWord(circle.name)}`, onClick: () => { setSelectedCircle(circle); onOpen(); diff --git a/src/pages/common/providers/CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx b/src/pages/common/providers/CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx index 6e241da6b7..8a28e06ded 100644 --- a/src/pages/common/providers/CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx +++ b/src/pages/common/providers/CommonData/components/LeaveCircleModal/LeaveCircleModal.tsx @@ -6,6 +6,7 @@ import { Image, Modal } from "@/shared/components"; import { ErrorText } from "@/shared/components/Form"; import { Circle } from "@/shared/models"; import { Button, ButtonSize, ButtonVariant } from "@/shared/ui-kit"; +import { pluralizeWord } from "@/shared/utils"; import { emptyFunction } from "@/shared/utils"; import styles from "./LeaveCircleModal.module.scss"; @@ -61,7 +62,7 @@ const LeaveCircleModal: FC = (props) => { aria-hidden />

- Are you sure you want to leave {circle.name}s? + Are you sure you want to leave {pluralizeWord(circle.name)}?

If you leave this circle, you might lose permissions associated with diff --git a/src/shared/utils/index.tsx b/src/shared/utils/index.tsx index fd2386e8a3..dbf698daac 100755 --- a/src/shared/utils/index.tsx +++ b/src/shared/utils/index.tsx @@ -34,3 +34,4 @@ export * from "./hasPermission"; export * from "./getProjectCircleDefinition"; export * from "./generateStaticShareLink"; export * from "./getTheme"; +export * from "./pluralizeWord"; diff --git a/src/shared/utils/pluralizeWord.ts b/src/shared/utils/pluralizeWord.ts new file mode 100644 index 0000000000..f382b38cb4 --- /dev/null +++ b/src/shared/utils/pluralizeWord.ts @@ -0,0 +1,9 @@ +import pluralize from "pluralize"; + +export const pluralizeWord = (word?: string) => { + if (!word) { + return ""; + } + + return pluralize.plural(word); +}; diff --git a/yarn.lock b/yarn.lock index 7f63942f64..11e925ebf6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15493,6 +15493,11 @@ playwright@^1.14.0: dependencies: playwright-core "1.27.1" +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + pnp-webpack-plugin@1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" From d267791863ee4b4812b70b0f6c4627b408a98b4e Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 16:58:10 +0300 Subject: [PATCH 19/24] use rootCommonId in root common member fetch --- src/pages/commonFeed/hooks/useCommonData/index.ts | 8 +++++--- src/shared/models/Common.tsx | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/pages/commonFeed/hooks/useCommonData/index.ts b/src/pages/commonFeed/hooks/useCommonData/index.ts index 4f13b5e7c1..61270ca2d5 100644 --- a/src/pages/commonFeed/hooks/useCommonData/index.ts +++ b/src/pages/commonFeed/hooks/useCommonData/index.ts @@ -64,13 +64,15 @@ export const useCommonData = (userId?: string): Return => { ); } - const rootCommonId = common.directParent?.commonId; const [parentCommons, subCommons, rootCommonMember] = await Promise.all([ CommonService.getAllParentCommonsForCommon(common), CommonService.getCommonsByDirectParentIds([common.id]), - rootCommonId && userId - ? CommonService.getCommonMemberByUserId(rootCommonId, userId) + common.rootCommonId && userId + ? CommonService.getCommonMemberByUserId( + common.rootCommonId, + userId, + ) : null, ]); diff --git a/src/shared/models/Common.tsx b/src/shared/models/Common.tsx index 14a04fea5a..00c0423b5d 100644 --- a/src/shared/models/Common.tsx +++ b/src/shared/models/Common.tsx @@ -115,6 +115,8 @@ export interface Common extends BaseEntity { messages?: DiscussionMessage[]; pinnedFeedItems: FeedItem[]; + + rootCommonId?: string; } export interface Project extends Common { From 01663e1287374fae3997489f2230feae1e00b817 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 12 Sep 2023 17:10:08 +0300 Subject: [PATCH 20/24] cover deleted feed item in system messages --- .../utils/getFeedItemDisplayingData.ts | 32 +++++++++++++++++++ .../utils/getFeedItemTitleByDataIdAndType.ts | 20 ------------ .../utils/getTextFromSystemMessage.tsx | 19 +++++++---- .../Chat/ChatMessage/utils/index.ts | 2 +- .../ChatChannelToDiscussionConverter.ts | 1 + src/shared/models/Discussion.tsx | 3 +- 6 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 src/shared/components/Chat/ChatMessage/utils/getFeedItemDisplayingData.ts delete mode 100644 src/shared/components/Chat/ChatMessage/utils/getFeedItemTitleByDataIdAndType.ts diff --git a/src/shared/components/Chat/ChatMessage/utils/getFeedItemDisplayingData.ts b/src/shared/components/Chat/ChatMessage/utils/getFeedItemDisplayingData.ts new file mode 100644 index 0000000000..3c2d64fa43 --- /dev/null +++ b/src/shared/components/Chat/ChatMessage/utils/getFeedItemDisplayingData.ts @@ -0,0 +1,32 @@ +import { DiscussionService, ProposalService } from "@/services"; +import { CommonFeedType } from "@/shared/models"; + +export const getFeedItemDisplayingData = async ( + feedItemDataId: string, + feedItemType: CommonFeedType, +): Promise<{ + title: string; + isDeleted: boolean; +}> => { + if (feedItemType === CommonFeedType.Discussion) { + const discussion = await DiscussionService.getDiscussionById( + feedItemDataId, + ); + return { + title: discussion?.title || "", + isDeleted: discussion?.isDeleted ?? true, + }; + } + if (feedItemType === CommonFeedType.Proposal) { + const proposal = await ProposalService.getProposalById(feedItemDataId); + return { + title: proposal?.data.args.title || "", + isDeleted: false, + }; + } + + return { + title: "", + isDeleted: false, + }; +}; diff --git a/src/shared/components/Chat/ChatMessage/utils/getFeedItemTitleByDataIdAndType.ts b/src/shared/components/Chat/ChatMessage/utils/getFeedItemTitleByDataIdAndType.ts deleted file mode 100644 index 52d12827cc..0000000000 --- a/src/shared/components/Chat/ChatMessage/utils/getFeedItemTitleByDataIdAndType.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { DiscussionService, ProposalService } from "@/services"; -import { CommonFeedType } from "@/shared/models"; - -export const getFeedItemTitleByDataIdAndType = async ( - feedItemDataId: string, - feedItemType: CommonFeedType, -): Promise => { - if (feedItemType === CommonFeedType.Discussion) { - const discussion = await DiscussionService.getDiscussionById( - feedItemDataId, - ); - return discussion?.title || ""; - } - if (feedItemType === CommonFeedType.Proposal) { - const discussion = await ProposalService.getProposalById(feedItemDataId); - return discussion?.data.args.title || ""; - } - - return ""; -}; diff --git a/src/shared/components/Chat/ChatMessage/utils/getTextFromSystemMessage.tsx b/src/shared/components/Chat/ChatMessage/utils/getTextFromSystemMessage.tsx index b49443cebb..6ff55d6e16 100644 --- a/src/shared/components/Chat/ChatMessage/utils/getTextFromSystemMessage.tsx +++ b/src/shared/components/Chat/ChatMessage/utils/getTextFromSystemMessage.tsx @@ -19,7 +19,7 @@ import { } from "@/shared/utils"; import { UserMention } from "../components"; import { Text, TextData } from "../types"; -import { getFeedItemTitleByDataIdAndType } from "./getFeedItemTitleByDataIdAndType"; +import { getFeedItemDisplayingData } from "./getFeedItemDisplayingData"; import styles from "../ChatMessage.module.scss"; const getUser = async (userId: string, users: User[]): Promise => @@ -130,20 +130,27 @@ const getFeedItemCreatedSystemMessageText = async ( systemMessageData: CommonFeedItemCreatedSystemMessage["systemMessageData"], data: TextData, ): Promise => { - const [user, title] = await Promise.all([ + const [user, feedItemDisplayingData] = await Promise.all([ getUser(systemMessageData.userId, data.users), - getFeedItemTitleByDataIdAndType( + getFeedItemDisplayingData( systemMessageData.feedItemDataId, systemMessageData.feedItemType, ), ]); const userEl = renderUserMention(user, data); + const title = + feedItemDisplayingData.title && + `${feedItemDisplayingData.title}${ + feedItemDisplayingData.isDeleted ? " (deleted)" : "" + }`; const titleEl = title ? ( <> {" "} - {renderClickableText(title, () => - data.onFeedItemClick?.(systemMessageData.feedItemId), - )} + {feedItemDisplayingData.isDeleted + ? title + : renderClickableText(title, () => + data.onFeedItemClick?.(systemMessageData.feedItemId), + )} ) : ( "" diff --git a/src/shared/components/Chat/ChatMessage/utils/index.ts b/src/shared/components/Chat/ChatMessage/utils/index.ts index 09a42a51db..eed09b6154 100644 --- a/src/shared/components/Chat/ChatMessage/utils/index.ts +++ b/src/shared/components/Chat/ChatMessage/utils/index.ts @@ -1,2 +1,2 @@ -export * from "./getFeedItemTitleByDataIdAndType"; +export * from "./getFeedItemDisplayingData"; export * from "./getTextFromTextEditorString"; diff --git a/src/shared/converters/ChatChannelToDiscussionConverter.ts b/src/shared/converters/ChatChannelToDiscussionConverter.ts index e83a4aa993..31e0b7fbc9 100644 --- a/src/shared/converters/ChatChannelToDiscussionConverter.ts +++ b/src/shared/converters/ChatChannelToDiscussionConverter.ts @@ -17,6 +17,7 @@ class ChatChannelToDiscussionConverter extends Converter< followers: [], messageCount: chatChannel.messageCount, discussionMessages: [], + isDeleted: false, createdAt: chatChannel.createdAt, updatedAt: chatChannel.updatedAt, }); diff --git a/src/shared/models/Discussion.tsx b/src/shared/models/Discussion.tsx index a3a6053dc9..e9605fed56 100644 --- a/src/shared/models/Discussion.tsx +++ b/src/shared/models/Discussion.tsx @@ -2,6 +2,7 @@ import firebase from "@/shared/utils/firebase"; import { BaseEntity } from "./BaseEntity"; import { DiscussionMessage } from "./DiscussionMessage"; import { Link } from "./Link"; +import { SoftDeleteEntity } from "./SoftDeleteEntity"; import { User } from "./User"; import { Moderation } from "./shared"; @@ -9,7 +10,7 @@ export enum PredefinedTypes { General = "general", } -export interface Discussion extends BaseEntity { +export interface Discussion extends BaseEntity, SoftDeleteEntity { title: string; message: string; ownerId: string; From 03278bfd0ffc671e18a8857cac580810eb770e04 Mon Sep 17 00:00:00 2001 From: Kiryl Budnik Date: Wed, 13 Sep 2023 10:41:58 +0300 Subject: [PATCH 21/24] Revert "use rootCommonId in root common member fetch" This reverts commit d267791863ee4b4812b70b0f6c4627b408a98b4e. --- src/pages/commonFeed/hooks/useCommonData/index.ts | 8 +++----- src/shared/models/Common.tsx | 2 -- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/pages/commonFeed/hooks/useCommonData/index.ts b/src/pages/commonFeed/hooks/useCommonData/index.ts index 61270ca2d5..4f13b5e7c1 100644 --- a/src/pages/commonFeed/hooks/useCommonData/index.ts +++ b/src/pages/commonFeed/hooks/useCommonData/index.ts @@ -64,15 +64,13 @@ export const useCommonData = (userId?: string): Return => { ); } + const rootCommonId = common.directParent?.commonId; const [parentCommons, subCommons, rootCommonMember] = await Promise.all([ CommonService.getAllParentCommonsForCommon(common), CommonService.getCommonsByDirectParentIds([common.id]), - common.rootCommonId && userId - ? CommonService.getCommonMemberByUserId( - common.rootCommonId, - userId, - ) + rootCommonId && userId + ? CommonService.getCommonMemberByUserId(rootCommonId, userId) : null, ]); diff --git a/src/shared/models/Common.tsx b/src/shared/models/Common.tsx index 00c0423b5d..14a04fea5a 100644 --- a/src/shared/models/Common.tsx +++ b/src/shared/models/Common.tsx @@ -115,8 +115,6 @@ export interface Common extends BaseEntity { messages?: DiscussionMessage[]; pinnedFeedItems: FeedItem[]; - - rootCommonId?: string; } export interface Project extends Common { From 6f949b0f64124c02de9a4d52f0c3c22cb73b124c Mon Sep 17 00:00:00 2001 From: Kiryl Budnik Date: Wed, 13 Sep 2023 10:51:22 +0300 Subject: [PATCH 22/24] move fetching parent common member logic to the useCommonData hook --- src/pages/commonFeed/CommonFeed.tsx | 21 +++------------ .../commonFeed/hooks/useCommonData/index.ts | 27 +++++++++++++------ .../commonFeed/hooks/useCommonData/types.ts | 1 + 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index 54943aa6f0..53b484b50c 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -38,7 +38,6 @@ import { selectRecentStreamId, selectSharedFeedItem, } from "@/store/states"; -import { useCommonMember } from "../OldCommon/hooks"; import { NewDiscussionCreation, NewProposalCreation, @@ -99,6 +98,7 @@ const CommonFeedComponent: FC = (props) => { fetchCommonData, } = useCommonData(userId); const parentCommonId = commonData?.common.directParent?.commonId; + const parentCommonMember = commonData?.parentCommonMember; const isRootCommon = !parentCommonId; const isRootCommonMember = Boolean(commonData?.rootCommonMember); const anotherCommonId = @@ -121,11 +121,6 @@ const CommonFeedComponent: FC = (props) => { loading: areCommonPinnedFeedItemsLoading, fetch: fetchCommonPinnedFeedItems, } = useCommonPinnedFeedItems(commonId, pinnedItemIds); - const { - data: parentCommonMember, - fetched: isParentCommonMemberFetched, - fetchCommonMember: fetchParentCommonMember, - } = useCommonMember(); const commonFeedItemIdsForNotListening = useMemo(() => { const items: string[] = []; @@ -165,9 +160,7 @@ const CommonFeedComponent: FC = (props) => { return items; }, [sharedFeedItem, sharedFeedItemId, commonPinnedFeedItems]); const firstItem = commonFeedItems?.[0]; - const isDataFetched = - isCommonDataFetched && - (parentCommonId ? isParentCommonMemberFetched : true); + const isDataFetched = isCommonDataFetched; const hasPublicItem = true; const fetchData = () => { @@ -202,16 +195,10 @@ const CommonFeedComponent: FC = (props) => { ); useEffect(() => { - if (parentCommonId) { - fetchParentCommonMember(parentCommonId, {}, true); - } - }, [parentCommonId]); - - useEffect(() => { - if (isParentCommonMemberFetched && !parentCommonMember) { + if (isCommonDataFetched && parentCommonId && !parentCommonMember) { history.replace(getCommonPageAboutTabPath(commonId)); } - }, [parentCommonMember?.id, isParentCommonMemberFetched, commonId]); + }, [isCommonDataFetched, parentCommonMember?.id, commonId]); useEffect(() => { if (!isCommonDataFetched || !isGlobalDataFetched || commonMember) { diff --git a/src/pages/commonFeed/hooks/useCommonData/index.ts b/src/pages/commonFeed/hooks/useCommonData/index.ts index 4f13b5e7c1..1fe7a183c7 100644 --- a/src/pages/commonFeed/hooks/useCommonData/index.ts +++ b/src/pages/commonFeed/hooks/useCommonData/index.ts @@ -65,14 +65,24 @@ export const useCommonData = (userId?: string): Return => { } const rootCommonId = common.directParent?.commonId; - const [parentCommons, subCommons, rootCommonMember] = - await Promise.all([ - CommonService.getAllParentCommonsForCommon(common), - CommonService.getCommonsByDirectParentIds([common.id]), - rootCommonId && userId - ? CommonService.getCommonMemberByUserId(rootCommonId, userId) - : null, - ]); + const [ + parentCommons, + subCommons, + rootCommonMember, + parentCommonMember, + ] = await Promise.all([ + CommonService.getAllParentCommonsForCommon(common), + CommonService.getCommonsByDirectParentIds([common.id]), + rootCommonId && userId + ? CommonService.getCommonMemberByUserId(rootCommonId, userId) + : null, + common.directParent?.commonId && userId + ? CommonService.getCommonMemberByUserId( + common.directParent.commonId, + userId, + ) + : null, + ]); setState({ loading: false, @@ -85,6 +95,7 @@ export const useCommonData = (userId?: string): Return => { commonMembersAmount, sharedFeedItem, rootCommonMember, + parentCommonMember, parentCommon: last(parentCommons), }, }); diff --git a/src/pages/commonFeed/hooks/useCommonData/types.ts b/src/pages/commonFeed/hooks/useCommonData/types.ts index 5b68f37c7d..599181ec31 100644 --- a/src/pages/commonFeed/hooks/useCommonData/types.ts +++ b/src/pages/commonFeed/hooks/useCommonData/types.ts @@ -9,6 +9,7 @@ export interface Data { commonMembersAmount: number; sharedFeedItem: CommonFeed | null; rootCommonMember: CommonMember | null; + parentCommonMember: CommonMember | null; parentCommon?: Common; } From 9df14a107b89487b239e9ccd4bd9add171bab4c5 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 13 Sep 2023 10:52:29 +0300 Subject: [PATCH 23/24] check permissions to add project after space creation --- .../ProjectCreation/ProjectCreation.tsx | 12 +++++++-- .../ProjectCreationForm.tsx | 27 ++++++++++++++----- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/pages/commonCreation/components/ProjectCreation/ProjectCreation.tsx b/src/pages/commonCreation/components/ProjectCreation/ProjectCreation.tsx index 72c1f6112d..5dd74b89c6 100644 --- a/src/pages/commonCreation/components/ProjectCreation/ProjectCreation.tsx +++ b/src/pages/commonCreation/components/ProjectCreation/ProjectCreation.tsx @@ -8,7 +8,7 @@ import { GovernanceActions } from "@/shared/constants"; import { useRoutesContext } from "@/shared/contexts"; import { useCommon, useGovernance } from "@/shared/hooks/useCases"; import { LongLeftArrowIcon } from "@/shared/icons"; -import { Common, Project } from "@/shared/models"; +import { Common, Governance, Project } from "@/shared/models"; import { Container, Loader } from "@/shared/ui-kit"; import { commonActions, ProjectsStateItem } from "@/store/states"; import { CenterWrapper } from "../CenterWrapper"; @@ -51,7 +51,12 @@ const ProjectCreation: FC = (props) => { ); - const handleCreatedProject = (createdProject: Common) => { + const handleCreatedProject = (data: { + project: Common; + governance: Governance; + }) => { + const { project: createdProject, governance } = data; + if (isEditing) { CommonEventEmitter.emit(CommonEvent.ProjectUpdated, { commonId: createdProject.id, @@ -65,6 +70,9 @@ const ProjectCreation: FC = (props) => { name: createdProject.name, directParent: createdProject.directParent, hasMembership: true, + hasPermissionToAddProject: Object.values(governance.circles).some( + (circle) => circle.allowedActions[GovernanceActions.CREATE_PROJECT], + ), notificationsAmount: 0, }; diff --git a/src/pages/commonCreation/components/ProjectCreation/components/ProjectCreationForm/ProjectCreationForm.tsx b/src/pages/commonCreation/components/ProjectCreation/components/ProjectCreationForm/ProjectCreationForm.tsx index 683c2fc63b..dfe07cfd45 100644 --- a/src/pages/commonCreation/components/ProjectCreation/components/ProjectCreationForm/ProjectCreationForm.tsx +++ b/src/pages/commonCreation/components/ProjectCreation/components/ProjectCreationForm/ProjectCreationForm.tsx @@ -2,8 +2,11 @@ import React, { FC, useCallback, useEffect, useMemo, useRef } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useCommonUpdate } from "@/pages/OldCommon/components/CommonListContainer/EditCommonModal/useCases"; import { usePreventReload } from "@/shared/hooks"; -import { useProjectCreation } from "@/shared/hooks/useCases"; -import { Circles, Common, Project } from "@/shared/models"; +import { + useGovernanceByCommonId, + useProjectCreation, +} from "@/shared/hooks/useCases"; +import { Circles, Common, Governance, Project } from "@/shared/models"; import { Loader, LoaderVariant, @@ -27,7 +30,7 @@ interface ProjectCreationFormProps { governanceCircles: Circles; initialCommon?: Project; isEditing: boolean; - onFinish: (createdProject: Common) => void; + onFinish: (data: { project: Common; governance: Governance }) => void; onCancel: () => void; } @@ -75,8 +78,8 @@ const ProjectCreationForm: FC = (props) => { } = props; const dispatch = useDispatch(); const projects = useSelector(selectCommonLayoutProjects); - const formRef = useRef(null); + const { data: governance, fetchGovernance } = useGovernanceByCommonId(); const { isProjectCreationLoading, project, @@ -95,6 +98,7 @@ const ProjectCreationForm: FC = (props) => { () => getInitialValues(governanceCircles, initialCommon), [governanceCircles], ); + const projectId = initialCommon?.id || project?.id; const existingProjectsNames = projects .map((project) => project?.name) @@ -134,13 +138,22 @@ const ProjectCreationForm: FC = (props) => { }; }, []); + useEffect(() => { + if (projectId) { + fetchGovernance(projectId); + } + }, [projectId]); + useEffect(() => { const finalProject = project || updatedProject; - if (finalProject) { - onFinish(finalProject); + if (finalProject && governance) { + onFinish({ + project: finalProject, + governance, + }); } - }, [project, updatedProject]); + }, [project, updatedProject, governance]); return ( <> From 86ec43516c9da712e2aa3fbd4d056debac2740a5 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 13 Sep 2023 12:15:53 +0300 Subject: [PATCH 24/24] create local CircleVisibility type --- .../OldCommon/interfaces/CreateProposalPayload.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/pages/OldCommon/interfaces/CreateProposalPayload.ts b/src/pages/OldCommon/interfaces/CreateProposalPayload.ts index 5854cb0820..9955d3a66f 100644 --- a/src/pages/OldCommon/interfaces/CreateProposalPayload.ts +++ b/src/pages/OldCommon/interfaces/CreateProposalPayload.ts @@ -10,6 +10,8 @@ import { Survey, } from "@/shared/models/governance/proposals"; +type CircleVisibility = string[] | null; + interface CreateFundsAllocation { type: ProposalsTypes.FUNDS_ALLOCATION; args: Omit; @@ -27,7 +29,7 @@ interface CreateMemberAdmittance { fromSupportersFlow?: boolean; receiveEmails?: boolean; userWhatsapp?: boolean; - circleVisibility?: string[] | null; + circleVisibility?: CircleVisibility; }; } @@ -37,7 +39,7 @@ interface CreateAssignCircle { AssignCircle["data"]["args"], "proposerId" | "circleVisibilityByCommon" > & { - circleVisibility?: string[] | null; + circleVisibility?: CircleVisibility; }; } interface CreateRemoveCircle { @@ -46,7 +48,7 @@ interface CreateRemoveCircle { RemoveCircle["data"]["args"], "proposerId" | "circleVisibilityByCommon" > & { - circleVisibility?: string[] | null; + circleVisibility?: CircleVisibility; }; } @@ -56,7 +58,7 @@ interface CreateSurvey { Survey["data"]["args"], "proposerId" | "circleVisibilityByCommon" > & { - circleVisibility?: string[] | null; + circleVisibility?: CircleVisibility; }; } @@ -66,7 +68,7 @@ interface CreateDeleteCommon { DeleteCommon["data"]["args"], "proposerId" | "circleVisibilityByCommon" > & { - circleVisibility?: string[] | null; + circleVisibility?: CircleVisibility; }; }