Просмотр исходного кода

Merge pull request #33163 from overleaf/ii-share-modal-give-feedback

[web] Share modal give feedback link

GitOrigin-RevId: 5e83dec6c6b97c172b7600d8ded285db49178a64
ilkin-overleaf 3 месяцев назад
Родитель
Сommit
faec27d7b0

+ 4 - 0
services/web/app/src/Features/Project/ProjectController.mjs

@@ -17,6 +17,7 @@ import { User } from '../../models/User.mjs'
 import SubscriptionLocator from '../Subscription/SubscriptionLocator.mjs'
 import SubscriptionHelper from '../Subscription/SubscriptionHelper.mjs'
 import LimitationsManager from '../Subscription/LimitationsManager.mjs'
+import { isProfessionalGroupPlan } from '../Subscription/PlansHelper.mjs'
 import Settings from '@overleaf/settings'
 import AuthorizationManager from '../Authorization/AuthorizationManager.mjs'
 import InactiveProjectManager from '../InactiveData/InactiveProjectManager.mjs'
@@ -932,6 +933,9 @@ const _ProjectController = {
           planCode,
           planName: planDetails?.name,
           isAnnualPlan: planCode && planDetails?.annual,
+          isProfessionalGroupPlan: Boolean(
+            subscription && isProfessionalGroupPlan(subscription)
+          ),
           isMemberOfGroupSubscription: userIsMemberOfGroupSubscription,
           hasInstitutionLicence: userHasInstitutionLicence,
         },

+ 25 - 0
services/web/frontend/js/features/share-project-modal/components/give-feedback-link.tsx

@@ -0,0 +1,25 @@
+import { useTranslation } from 'react-i18next'
+import OLButton from '@/shared/components/ol/ol-button'
+import getMeta from '@/utils/meta'
+
+export default function GiveFeedbackLink() {
+  const { t } = useTranslation()
+  const isProfessionalGroupPlan = getMeta('ol-user')?.isProfessionalGroupPlan
+
+  const link = isProfessionalGroupPlan
+    ? 'https://forms.gle/rz1JDMuNajWG4ZY49'
+    : 'https://forms.gle/WLEjzG4Ayp8zFscM9'
+
+  return (
+    <OLButton
+      variant="link"
+      size="sm"
+      href={link}
+      target="_blank"
+      rel="noopener noreferrer"
+      className="fw-bold"
+    >
+      {t('give_feedback')}
+    </OLButton>
+  )
+}

+ 3 - 2
services/web/frontend/js/features/share-project-modal/components/share-project-modal-content.tsx

@@ -15,6 +15,7 @@ import OLButton from '@/shared/components/ol/ol-button'
 import OLSpinner from '@/shared/components/ol/ol-spinner'
 import MaterialIcon from '@/shared/components/material-icon'
 import ErrorMessage from '@/features/share-project-modal/components/error-message'
+import GiveFeedbackLink from '@/features/share-project-modal/components/give-feedback-link'
 import classNames from 'classnames'
 import { useFeatureFlag } from '@/shared/context/split-test-context'
 import { useShareProjectContext } from '@/features/share-project-modal/components/share-project-modal'
@@ -49,8 +50,7 @@ export default function ShareProjectModalContent({
   const isSharingUpdatesEnabled = useFeatureFlag('sharing-updates')
   const [isInvitedPeopleScreen, setIsInvitedPeopleScreen] = useState(false)
   const { successActionMessage } = useShareProjectContext()
-
-  const { isRestrictedTokenMember } = useEditorContext()
+  const { isRestrictedTokenMember, isProjectOwner } = useEditorContext()
 
   return (
     <OLModal show={show} onHide={cancel} animation={animation}>
@@ -71,6 +71,7 @@ export default function ShareProjectModalContent({
                 : t('share_project')}
             </OLModalTitle>
           )}
+          {isSharingUpdatesEnabled && isProjectOwner && <GiveFeedbackLink />}
         </div>
       </OLModalHeader>
 

+ 68 - 0
services/web/test/frontend/features/share-project-modal/components/share-project-modal.test.tsx

@@ -1053,6 +1053,15 @@ describe('<ShareProjectModal/>', function () {
     })
   })
 
+  it('does not show the "Give feedback" link when the "sharing-updates" feature flag is disabled', async function () {
+    renderWithEditorContext(
+      <ShareProjectModal {...modalProps} />,
+      createContextProps()
+    )
+
+    expect(screen.queryByRole('link', { name: 'Give feedback' })).to.be.null
+  })
+
   describe('with "sharing-updates" feature flag', function () {
     beforeEach(function () {
       window.metaAttributesCache.set('ol-splitTestVariants', {
@@ -1174,5 +1183,64 @@ describe('<ShareProjectModal/>', function () {
 
       await screen.findByText('Invitation(s) sent.')
     })
+
+    it('shows the "Give feedback" link for the project owner', async function () {
+      renderWithEditorContext(
+        <ShareProjectModal {...modalProps} />,
+        createContextProps()
+      )
+
+      await screen.findByRole('link', { name: 'Give feedback' })
+    })
+
+    it('does not show the "Give feedback" link for non-owners', async function () {
+      renderWithEditorContext(<ShareProjectModal {...modalProps} />, {
+        ...createContextProps(),
+        user: {
+          id: 'non-project-owner',
+          email: 'non-project-owner@example.com',
+        },
+      })
+
+      expect(screen.queryByRole('link', { name: 'Give feedback' })).to.be.null
+    })
+
+    describe('"Give feedback" link URL based on subscription plan', function () {
+      it('links to the professional feedback URL when the user has a professional group plan', async function () {
+        renderWithEditorContext(<ShareProjectModal {...modalProps} />, {
+          ...createContextProps(),
+          user: {
+            id: USER_ID,
+            email: USER_EMAIL,
+            isProfessionalGroupPlan: true,
+          },
+        })
+
+        const feedbackLink = await screen.findByRole('link', {
+          name: 'Give feedback',
+        })
+        expect(feedbackLink.getAttribute('href')).to.equal(
+          'https://forms.gle/rz1JDMuNajWG4ZY49'
+        )
+      })
+
+      it('links to the standard feedback URL when the user does not have a professional group plan', async function () {
+        renderWithEditorContext(<ShareProjectModal {...modalProps} />, {
+          ...createContextProps(),
+          user: {
+            id: USER_ID,
+            email: USER_EMAIL,
+            isProfessionalGroupPlan: false,
+          },
+        })
+
+        const feedbackLink = await screen.findByRole('link', {
+          name: 'Give feedback',
+        })
+        expect(feedbackLink.getAttribute('href')).to.equal(
+          'https://forms.gle/WLEjzG4Ayp8zFscM9'
+        )
+      })
+    })
   })
 })

+ 6 - 1
services/web/test/frontend/helpers/editor-providers.tsx

@@ -70,7 +70,12 @@ const defaultUserSettings = {
 } satisfies UserSettings
 
 export type EditorProvidersProps = {
-  user?: { id: string; email: string; signUpDate?: string }
+  user?: {
+    id: string
+    email: string
+    signUpDate?: string
+    isProfessionalGroupPlan?: boolean
+  }
   projectId?: string
   projectName?: string
   projectOwner?: ProjectMetadata['owner']

+ 1 - 0
services/web/types/user.ts

@@ -62,6 +62,7 @@ export type User = {
   planName?: string
   isAnnualPlan?: boolean
   isMemberOfGroupSubscription?: boolean
+  isProfessionalGroupPlan?: boolean
   hasInstitutionLicence?: boolean
 }