import { useCallback, useState, useEffect } from 'react' import PropTypes from 'prop-types' import { useTranslation } from 'react-i18next' import Icon from '@/shared/components/icon' import { useShareProjectContext } from './share-project-modal' import { setProjectAccessLevel } from '../../utils/api' import { CopyToClipboard } from '@/shared/components/copy-to-clipboard' 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' import { debugConsole } from '@/utils/debugging' import getMeta from '@/utils/meta' import OLRow from '@/features/ui/components/ol/ol-row' import OLCol from '@/features/ui/components/ol/ol-col' import OLButton from '@/features/ui/components/ol/ol-button' import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import MaterialIcon from '@/shared/components/material-icon' export default function LinkSharing() { const [inflight, setInflight] = useState(false) const [showLinks, setShowLinks] = useState(true) const { monitorRequest } = useShareProjectContext() const { _id: projectId, publicAccessLevel } = useProjectContext() // set the access level of a project const setAccessLevel = useCallback( newPublicAccessLevel => { setInflight(true) sendMB('link-sharing-click-off', { project_id: projectId, }) monitorRequest(() => setProjectAccessLevel(projectId, newPublicAccessLevel) ) .then(() => { // NOTE: not calling `updateProject` here as it receives data via // project:publicAccessLevel:changed over the websocket connection // TODO: eventTracking.sendMB('project-make-token-based') when newPublicAccessLevel is 'tokenBased' }) .finally(() => { setInflight(false) }) }, [monitorRequest, projectId] ) switch (publicAccessLevel) { // Private (with token-access available) case 'private': return ( ) // Token-based access case 'tokenBased': return ( ) // Legacy public-access case 'readAndWrite': case 'readOnly': return ( ) default: return null } } function PrivateSharing({ setAccessLevel, inflight, projectId, setShowLinks }) { const { t } = useTranslation() return ( {t('link_sharing_is_off_short')}    { setAccessLevel('tokenBased') eventTracking.sendMB('link-sharing-click', { projectId }) setShowLinks(true) }} disabled={inflight} > {t('turn_on_link_sharing')}    ) } PrivateSharing.propTypes = { setAccessLevel: PropTypes.func.isRequired, inflight: PropTypes.bool, projectId: PropTypes.string, setShowLinks: PropTypes.func.isRequired, } function TokenBasedSharing({ setAccessLevel, inflight, setShowLinks, showLinks, }) { const { t } = useTranslation() const { _id: projectId } = useProjectContext() const [tokens, setTokens] = useState(null) const { signal } = useAbortController() useEffect(() => { getJSON(`/project/${projectId}/tokens`, { signal }) .then(data => setTokens(data)) .catch(debugConsole.error) }, [projectId, signal]) return ( {t('link_sharing_is_on')}    setAccessLevel('private')} disabled={inflight} > {t('turn_off_link_sharing')}    setShowLinks(!showLinks)} > } bs5={ } /> {showLinks && (
{t('anyone_with_link_can_edit')}
{t('anyone_with_link_can_view')}
)}
) } TokenBasedSharing.propTypes = { setAccessLevel: PropTypes.func.isRequired, inflight: PropTypes.bool, setShowLinks: PropTypes.func.isRequired, showLinks: PropTypes.bool, } function LegacySharing({ accessLevel, setAccessLevel, inflight }) { const { t } = useTranslation() return ( {accessLevel === 'readAndWrite' && t('this_project_is_public')} {accessLevel === 'readOnly' && t('this_project_is_public_read_only')}    setAccessLevel('private')} disabled={inflight} > {t('make_private')}    ) } LegacySharing.propTypes = { accessLevel: PropTypes.string.isRequired, setAccessLevel: PropTypes.func.isRequired, inflight: PropTypes.bool, } export function ReadOnlyTokenLink() { const { t } = useTranslation() const { _id: projectId } = useProjectContext() const [tokens, setTokens] = useState(null) const { signal } = useAbortController() useEffect(() => { getJSON(`/project/${projectId}/tokens`, { signal }) .then(data => setTokens(data)) .catch(debugConsole.error) }, [projectId, signal]) return (
{t('anyone_with_link_can_view')}
) } function AccessToken({ token, tokenHashPrefix, path, tooltipId }) { const { t } = useTranslation() const { isAdmin } = useUserContext() if (!token) { return (
        {t('loading')}…
      
) } let origin = window.location.origin if (isAdmin) { origin = getMeta('ol-ExposedSettings').siteUrl } const link = `${origin}${path}${token}${ tokenHashPrefix ? `#${tokenHashPrefix}` : '' }` return (
{link}
) } AccessToken.propTypes = { token: PropTypes.string, tokenHashPrefix: PropTypes.string, tooltipId: PropTypes.string.isRequired, path: PropTypes.string.isRequired, } function LinkSharingInfo() { const { t } = useTranslation() return ( } bs5={} /> ) }