From 853c1153e110c6426de9e1ca00716ede59c9ac48 Mon Sep 17 00:00:00 2001 From: roo hutton Date: Fri, 28 Jun 2024 07:18:21 +0100 Subject: [PATCH] Merge pull request #18891 from overleaf/rh-share-modal-when-over-limit [web]: Show share modal when over collaborator limit GitOrigin-RevId: 6f5594310f21e481d5837ff8d7f098668ecd2957 --- .../components/editor-navigation-toolbar.tsx | 5 ++- .../share-project-modal.tsx | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/services/web/frontend/js/features/ide-react/components/editor-navigation-toolbar.tsx b/services/web/frontend/js/features/ide-react/components/editor-navigation-toolbar.tsx index cabdf5ae3a..b24511caf8 100644 --- a/services/web/frontend/js/features/ide-react/components/editor-navigation-toolbar.tsx +++ b/services/web/frontend/js/features/ide-react/components/editor-navigation-toolbar.tsx @@ -14,10 +14,10 @@ function EditorNavigationToolbar() { const { onlineUsersArray } = useOnlineUsersContext() const { openDoc } = useEditorManagerContext() - const handleOpenShareModal = () => { + const handleOpenShareModal = useCallback(() => { eventTracking.sendMBOnce('ide-open-share-modal-once') setShowShareModal(true) - } + }, []) const handleHideShareModal = useCallback(() => { setShowShareModal(false) @@ -37,6 +37,7 @@ function EditorNavigationToolbar() { diff --git a/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/share-project-modal.tsx b/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/share-project-modal.tsx index d0d79d4164..7216069f1a 100644 --- a/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/share-project-modal.tsx +++ b/services/web/frontend/js/features/share-project-modal/components/restricted-link-sharing/share-project-modal.tsx @@ -10,6 +10,8 @@ import { useProjectContext } from '@/shared/context/project-context' import { useSplitTestContext } from '@/shared/context/split-test-context' import { sendMB } from '@/infrastructure/event-tracking' import { ProjectContextUpdateValue } from '@/shared/context/types/project-context' +import { useEditorContext } from '@/shared/context/editor-context' +import customLocalStorage from '@/infrastructure/local-storage' type ShareProjectContextValue = { updateProject: (project: ProjectContextUpdateValue) => void @@ -24,6 +26,8 @@ type ShareProjectContextValue = { > } +const SHOW_MODAL_COOLDOWN_PERIOD = 24 * 60 * 60 * 1000 // 24 hours + const ShareProjectContext = createContext( undefined ) @@ -43,12 +47,14 @@ export function useShareProjectContext() { type ShareProjectModalProps = { handleHide: () => void show: boolean + handleOpen: () => void animation?: boolean } const ShareProjectModal = React.memo(function ShareProjectModal({ handleHide, show, + handleOpen, animation = true, }: ShareProjectModalProps) { const [inFlight, setInFlight] = @@ -56,9 +62,42 @@ const ShareProjectModal = React.memo(function ShareProjectModal({ const [error, setError] = useState() const project = useProjectContext() + const { isProjectOwner } = useEditorContext() const { splitTestVariants } = useSplitTestContext() + // split test: link-sharing-warning + // show the new share modal if project owner + // is over collaborator limit (once every 24 hours) + useEffect(() => { + const hasExceededCollaboratorLimit = () => { + if (!isProjectOwner || !project.features) { + return false + } + + if (project.features.collaborators === -1) { + return false + } + return ( + project.members.filter(member => member.privileges === 'readAndWrite') + .length > (project.features.collaborators ?? 1) + ) + } + + if (hasExceededCollaboratorLimit()) { + const localStorageKey = `last-shown-share-modal.${project._id}` + const lastShownShareModalTime = + customLocalStorage.getItem(localStorageKey) + if ( + !lastShownShareModalTime || + lastShownShareModalTime + SHOW_MODAL_COOLDOWN_PERIOD < Date.now() + ) { + handleOpen() + customLocalStorage.setItem(localStorageKey, Date.now()) + } + } + }, [project, isProjectOwner, handleOpen]) + // send tracking event when the modal is opened useEffect(() => { if (show) {