mirror of
https://github.com/overleaf/overleaf.git
synced 2025-01-30 15:43:21 +00:00
Merge pull request #13569 from overleaf/jdt-collab-events
feat: adding events when adding and removing collaborators GitOrigin-RevId: 5a78a2fc1fb3937ca2c5e08625c628c993545d97
This commit is contained in:
parent
53c613906f
commit
30d0c268ca
5 changed files with 42 additions and 8 deletions
|
@ -8,6 +8,7 @@ import { resendInvite, sendInvite } from '../utils/api'
|
|||
import { useUserContacts } from '../hooks/use-user-contacts'
|
||||
import useIsMounted from '../../../shared/hooks/use-is-mounted'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
import { sendMB } from '../../../infrastructure/event-tracking'
|
||||
|
||||
export default function AddCollaborators() {
|
||||
const [privileges, setPrivileges] = useState('readAndWrite')
|
||||
|
@ -82,6 +83,15 @@ export default function AddCollaborators() {
|
|||
} else {
|
||||
data = await sendInvite(projectId, email, privileges)
|
||||
}
|
||||
|
||||
sendMB('collaborator-invited', {
|
||||
project_id: projectId,
|
||||
// invitation is only populated on successful invite, meaning that for paywall and other cases this will be null
|
||||
successful_invite: !!data.invite,
|
||||
users_updated: !!(data.users || data.user),
|
||||
current_collaborators_amount: members.length,
|
||||
current_invites_amount: invites.length,
|
||||
})
|
||||
} catch (error) {
|
||||
setInFlight(false)
|
||||
setError(
|
||||
|
|
|
@ -8,6 +8,7 @@ import { Button, Col, Form, FormControl, FormGroup } from 'react-bootstrap'
|
|||
import Tooltip from '../../../shared/components/tooltip'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
import { sendMB } from '../../../infrastructure/event-tracking'
|
||||
|
||||
export default function EditMember({ member }) {
|
||||
const [privileges, setPrivileges] = useState(member.privileges)
|
||||
|
@ -112,15 +113,21 @@ SelectPrivilege.propTypes = {
|
|||
function RemoveMemberAction({ member }) {
|
||||
const { t } = useTranslation()
|
||||
const { updateProject, monitorRequest } = useShareProjectContext()
|
||||
const { _id: projectId, members } = useProjectContext()
|
||||
const { _id: projectId, members, invites } = useProjectContext()
|
||||
|
||||
function handleClick(event) {
|
||||
event.preventDefault()
|
||||
|
||||
monitorRequest(() => removeMemberFromProject(projectId, member)).then(
|
||||
() => {
|
||||
const updatedMembers = members.filter(existing => existing !== member)
|
||||
updateProject({
|
||||
members: members.filter(existing => existing !== member),
|
||||
members: updatedMembers,
|
||||
})
|
||||
sendMB('collaborator-removed', {
|
||||
project_id: projectId,
|
||||
current_collaborators_amount: updatedMembers.length,
|
||||
current_invites_amount: invites.length,
|
||||
})
|
||||
}
|
||||
)
|
||||
|
|
|
@ -8,6 +8,7 @@ import { Trans, useTranslation } from 'react-i18next'
|
|||
import MemberPrivileges from './member-privileges'
|
||||
import { resendInvite, revokeInvite } from '../utils/api'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
import { sendMB } from '../../../infrastructure/event-tracking'
|
||||
|
||||
export default function Invite({ invite, isProjectOwner }) {
|
||||
return (
|
||||
|
@ -77,14 +78,20 @@ ResendInvite.propTypes = {
|
|||
function RevokeInvite({ invite }) {
|
||||
const { t } = useTranslation()
|
||||
const { updateProject, monitorRequest } = useShareProjectContext()
|
||||
const { _id: projectId, invites } = useProjectContext()
|
||||
const { _id: projectId, invites, members } = useProjectContext()
|
||||
|
||||
function handleClick(event) {
|
||||
event.preventDefault()
|
||||
|
||||
monitorRequest(() => revokeInvite(projectId, invite)).then(() => {
|
||||
const updatedInvites = invites.filter(existing => existing !== invite)
|
||||
updateProject({
|
||||
invites: invites.filter(existing => existing !== invite),
|
||||
invites: updatedInvites,
|
||||
})
|
||||
sendMB('collaborator-invite-revoked', {
|
||||
project_id: projectId,
|
||||
current_invites_amount: updatedInvites.length,
|
||||
current_collaborators_amount: members.length,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import CopyLink from '../../../shared/components/copy-link'
|
|||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
import * as eventTracking from '../../../infrastructure/event-tracking'
|
||||
import { useUserContext } from '../../../shared/context/user-context'
|
||||
import { sendMB } from '../../../infrastructure/event-tracking'
|
||||
import { getJSON } from '../../../infrastructure/fetch-json'
|
||||
import useAbortController from '../../../shared/hooks/use-abort-controller'
|
||||
|
||||
|
@ -24,6 +25,9 @@ export default function LinkSharing({ canAddCollaborators }) {
|
|||
const setAccessLevel = useCallback(
|
||||
newPublicAccessLevel => {
|
||||
setInflight(true)
|
||||
sendMB('link-sharing-click-off', {
|
||||
project_id: projectId,
|
||||
})
|
||||
monitorRequest(() =>
|
||||
setProjectAccessLevel(projectId, newPublicAccessLevel)
|
||||
)
|
||||
|
@ -43,7 +47,11 @@ export default function LinkSharing({ canAddCollaborators }) {
|
|||
// Private (with token-access available)
|
||||
case 'private':
|
||||
return (
|
||||
<PrivateSharing setAccessLevel={setAccessLevel} inflight={inflight} />
|
||||
<PrivateSharing
|
||||
setAccessLevel={setAccessLevel}
|
||||
inflight={inflight}
|
||||
projectId={projectId}
|
||||
/>
|
||||
)
|
||||
|
||||
// Token-based access
|
||||
|
@ -76,7 +84,7 @@ LinkSharing.propTypes = {
|
|||
canAddCollaborators: PropTypes.bool,
|
||||
}
|
||||
|
||||
function PrivateSharing({ setAccessLevel, inflight }) {
|
||||
function PrivateSharing({ setAccessLevel, inflight, projectId }) {
|
||||
return (
|
||||
<Row className="public-access-level">
|
||||
<Col xs={12} className="text-center">
|
||||
|
@ -88,7 +96,7 @@ function PrivateSharing({ setAccessLevel, inflight }) {
|
|||
className="btn-inline-link"
|
||||
onClick={() => {
|
||||
setAccessLevel('tokenBased')
|
||||
eventTracking.sendMB('link-sharing-click')
|
||||
eventTracking.sendMB('link-sharing-click', { projectId })
|
||||
}}
|
||||
disabled={inflight}
|
||||
>
|
||||
|
@ -104,6 +112,7 @@ function PrivateSharing({ setAccessLevel, inflight }) {
|
|||
PrivateSharing.propTypes = {
|
||||
setAccessLevel: PropTypes.func.isRequired,
|
||||
inflight: PropTypes.bool,
|
||||
projectId: PropTypes.string,
|
||||
}
|
||||
|
||||
function TokenBasedSharing({ setAccessLevel, inflight, canAddCollaborators }) {
|
||||
|
|
|
@ -58,9 +58,10 @@ const ShareProjectModal = React.memo(function ShareProjectModal({
|
|||
if (show) {
|
||||
sendMB('share-modal-opened', {
|
||||
splitTestVariant: splitTestVariants['null-test-share-modal'],
|
||||
project_id: project._id,
|
||||
})
|
||||
}
|
||||
}, [splitTestVariants, show])
|
||||
}, [splitTestVariants, project._id, show])
|
||||
|
||||
// reset error when the modal is opened
|
||||
useEffect(() => {
|
||||
|
|
Loading…
Reference in a new issue