import { useCallback, useState, useEffect } from 'react' import { useTranslation } from 'react-i18next' import { useShareProjectContext } from './share-project-modal' import { setPublicAccessLevel } 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 MaterialIcon from '@/shared/components/material-icon' type Tokens = { readAndWrite: string readAndWriteHashPrefix: string readAndWritePrefix: string readOnly: string readOnlyHashPrefix: string } type AccessLevel = 'private' | 'tokenBased' | 'readAndWrite' | 'readOnly' export default function LinkSharing() { const [inflight, setInflight] = useState(false) const [showLinks, setShowLinks] = useState(true) const { monitorRequest } = useShareProjectContext() const { projectId, project } = useProjectContext() const { publicAccessLevel } = project || {} // set the access level of a project const setAccessLevel = useCallback( (newPublicAccessLevel: string) => { setInflight(true) sendMB('link-sharing-click-off', { project_id: projectId, }) monitorRequest(() => setPublicAccessLevel(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 ( // TODO: do we even need this anymore? ) default: return null } } function PrivateSharing({ setAccessLevel, inflight, projectId, setShowLinks, }: { setAccessLevel: (level: AccessLevel) => void inflight: boolean projectId: string setShowLinks: (show: boolean) => void }) { 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')}    ) } function TokenBasedSharing({ setAccessLevel, inflight, setShowLinks, showLinks, }: { setAccessLevel: (level: AccessLevel) => void inflight: boolean setShowLinks: (show: boolean) => void showLinks: boolean }) { const { t } = useTranslation() const { 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)} > {showLinks && (
{t('anyone_with_link_can_edit')}
{t('anyone_with_link_can_view')}
)}
) } function LegacySharing({ accessLevel, setAccessLevel, inflight, }: { accessLevel: AccessLevel setAccessLevel: (level: AccessLevel) => void inflight: boolean }) { 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')}    ) } export function ReadOnlyTokenLink() { const { t } = useTranslation() const { 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, }: { token?: string tokenHashPrefix?: string path: string tooltipId: string }) { 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}
) } function LinkSharingInfo() { const { t } = useTranslation() return ( ) }