mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-14 20:40:17 -05:00
247 lines
6.4 KiB
JavaScript
247 lines
6.4 KiB
JavaScript
|
import React, { useCallback, useState } from 'react'
|
||
|
import PropTypes from 'prop-types'
|
||
|
import { Button, Col, OverlayTrigger, Row, Tooltip } from 'react-bootstrap'
|
||
|
import { Trans } from 'react-i18next'
|
||
|
import Icon from '../../../shared/components/icon'
|
||
|
import {
|
||
|
useProjectContext,
|
||
|
useShareProjectContext
|
||
|
} from './share-project-modal'
|
||
|
import { setProjectAccessLevel } from '../utils/api'
|
||
|
import CopyLink from '../../../shared/components/copy-link'
|
||
|
|
||
|
export default function LinkSharing() {
|
||
|
const [inflight, setInflight] = useState(false)
|
||
|
|
||
|
const { monitorRequest, updateProject } = useShareProjectContext()
|
||
|
|
||
|
const project = useProjectContext()
|
||
|
|
||
|
// set the access level of a project
|
||
|
const setAccessLevel = useCallback(
|
||
|
publicAccesLevel => {
|
||
|
setInflight(true)
|
||
|
monitorRequest(() => setProjectAccessLevel(project, publicAccesLevel))
|
||
|
.then(() => {
|
||
|
// TODO: ideally this would use the response from the server
|
||
|
updateProject({ publicAccesLevel })
|
||
|
// TODO: eventTracking.sendMB('project-make-token-based') when publicAccesLevel is 'tokenBased'
|
||
|
})
|
||
|
.finally(() => {
|
||
|
setInflight(false)
|
||
|
})
|
||
|
},
|
||
|
[monitorRequest, project, updateProject]
|
||
|
)
|
||
|
|
||
|
switch (project.publicAccesLevel) {
|
||
|
// Private (with token-access available)
|
||
|
case 'private':
|
||
|
return (
|
||
|
<PrivateSharing setAccessLevel={setAccessLevel} inflight={inflight} />
|
||
|
)
|
||
|
|
||
|
// Token-based access
|
||
|
case 'tokenBased':
|
||
|
return (
|
||
|
<TokenBasedSharing
|
||
|
setAccessLevel={setAccessLevel}
|
||
|
inflight={inflight}
|
||
|
/>
|
||
|
)
|
||
|
|
||
|
// Legacy public-access
|
||
|
case 'readAndWrite':
|
||
|
case 'readOnly':
|
||
|
return (
|
||
|
<LegacySharing
|
||
|
setAccessLevel={setAccessLevel}
|
||
|
accessLevel={project.publicAccesLevel}
|
||
|
inflight={inflight}
|
||
|
/>
|
||
|
)
|
||
|
|
||
|
default:
|
||
|
return null
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function PrivateSharing({ setAccessLevel, inflight }) {
|
||
|
return (
|
||
|
<Row className="public-access-level">
|
||
|
<Col xs={12} className="text-center">
|
||
|
<Trans i18nKey="link_sharing_is_off" />
|
||
|
<span> </span>
|
||
|
<Button
|
||
|
type="button"
|
||
|
bsStyle="link"
|
||
|
className="btn-inline-link"
|
||
|
onClick={() => setAccessLevel('tokenBased')}
|
||
|
disabled={inflight}
|
||
|
>
|
||
|
<Trans i18nKey="turn_on_link_sharing" />
|
||
|
</Button>
|
||
|
<span> </span>
|
||
|
<LinkSharingInfo />
|
||
|
</Col>
|
||
|
</Row>
|
||
|
)
|
||
|
}
|
||
|
PrivateSharing.propTypes = {
|
||
|
setAccessLevel: PropTypes.func.isRequired,
|
||
|
inflight: PropTypes.bool
|
||
|
}
|
||
|
|
||
|
function TokenBasedSharing({ setAccessLevel, inflight }) {
|
||
|
const project = useProjectContext()
|
||
|
|
||
|
return (
|
||
|
<Row className="public-access-level">
|
||
|
<Col xs={12} className="text-center">
|
||
|
<strong>
|
||
|
<Trans i18nKey="link_sharing_is_on" />
|
||
|
</strong>
|
||
|
<span> </span>
|
||
|
<Button
|
||
|
bsStyle="link"
|
||
|
className="btn-inline-link"
|
||
|
onClick={() => setAccessLevel('private')}
|
||
|
disabled={inflight}
|
||
|
>
|
||
|
<Trans i18nKey="turn_off_link_sharing" />
|
||
|
</Button>
|
||
|
<span> </span>
|
||
|
<LinkSharingInfo />
|
||
|
</Col>
|
||
|
<Col xs={12} className="access-token-display-area">
|
||
|
<div className="access-token-wrapper">
|
||
|
<strong>
|
||
|
<Trans i18nKey="anyone_with_link_can_edit" />
|
||
|
</strong>
|
||
|
<AccessToken
|
||
|
token={project?.tokens?.readAndWrite}
|
||
|
path="/"
|
||
|
tooltipId="tooltip-copy-link-rw"
|
||
|
/>
|
||
|
</div>
|
||
|
<div className="access-token-wrapper">
|
||
|
<strong>
|
||
|
<Trans i18nKey="anyone_with_link_can_view" />
|
||
|
</strong>
|
||
|
<AccessToken
|
||
|
token={project?.tokens?.readOnly}
|
||
|
path="/read/"
|
||
|
tooltipId="tooltip-copy-link-ro"
|
||
|
/>
|
||
|
</div>
|
||
|
</Col>
|
||
|
</Row>
|
||
|
)
|
||
|
}
|
||
|
TokenBasedSharing.propTypes = {
|
||
|
setAccessLevel: PropTypes.func.isRequired,
|
||
|
inflight: PropTypes.bool
|
||
|
}
|
||
|
|
||
|
function LegacySharing({ accessLevel, setAccessLevel, inflight }) {
|
||
|
return (
|
||
|
<Row className="public-access-level">
|
||
|
<Col xs={12} className="text-center">
|
||
|
<strong>
|
||
|
{accessLevel === 'readAndWrite' && (
|
||
|
<Trans i18nKey="this_project_is_public" />
|
||
|
)}
|
||
|
{accessLevel === 'readOnly' && (
|
||
|
<Trans i18nKey="this_project_is_public_read_only" />
|
||
|
)}
|
||
|
</strong>
|
||
|
<span> </span>
|
||
|
<Button
|
||
|
type="button"
|
||
|
bsStyle="link"
|
||
|
className="btn-inline-link"
|
||
|
onClick={() => setAccessLevel('private')}
|
||
|
disabled={inflight}
|
||
|
>
|
||
|
<Trans i18nKey="make_private" />
|
||
|
</Button>
|
||
|
<span> </span>
|
||
|
<LinkSharingInfo />
|
||
|
</Col>
|
||
|
</Row>
|
||
|
)
|
||
|
}
|
||
|
LegacySharing.propTypes = {
|
||
|
accessLevel: PropTypes.string.isRequired,
|
||
|
setAccessLevel: PropTypes.func.isRequired,
|
||
|
inflight: PropTypes.bool
|
||
|
}
|
||
|
|
||
|
export function ReadOnlyTokenLink() {
|
||
|
const project = useProjectContext()
|
||
|
|
||
|
return (
|
||
|
<Row className="public-access-level">
|
||
|
<Col xs={12} className="access-token-display-area">
|
||
|
<div className="access-token-wrapper">
|
||
|
<strong>
|
||
|
<Trans i18nKey="anyone_with_link_can_view" />
|
||
|
</strong>
|
||
|
<AccessToken
|
||
|
token={project?.tokens?.readOnly}
|
||
|
path="/read/"
|
||
|
tooltipId="tooltip-copy-link-ro"
|
||
|
/>
|
||
|
</div>
|
||
|
</Col>
|
||
|
</Row>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
function AccessToken({ token, path, tooltipId }) {
|
||
|
if (!token) {
|
||
|
return (
|
||
|
<pre className="access-token">
|
||
|
<span>
|
||
|
<Trans i18nKey="loading" />…
|
||
|
</span>
|
||
|
</pre>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
const link = `${window.location.origin}${path}${token}`
|
||
|
|
||
|
return (
|
||
|
<pre className="access-token">
|
||
|
<span>{link}</span>
|
||
|
<CopyLink link={link} tooltipId={tooltipId} />
|
||
|
</pre>
|
||
|
)
|
||
|
}
|
||
|
AccessToken.propTypes = {
|
||
|
token: PropTypes.string,
|
||
|
tooltipId: PropTypes.string.isRequired,
|
||
|
path: PropTypes.string.isRequired
|
||
|
}
|
||
|
|
||
|
function LinkSharingInfo() {
|
||
|
return (
|
||
|
<OverlayTrigger
|
||
|
placement="top"
|
||
|
overlay={
|
||
|
<Tooltip id="tooltip-link-sharing-info">
|
||
|
<Trans i18nKey="learn_more_about_link_sharing" />
|
||
|
</Tooltip>
|
||
|
}
|
||
|
>
|
||
|
<a
|
||
|
href="/learn/how-to/What_is_Link_Sharing%3F"
|
||
|
target="_blank"
|
||
|
rel="noopener"
|
||
|
>
|
||
|
<Icon type="question-circle" />
|
||
|
</a>
|
||
|
</OverlayTrigger>
|
||
|
)
|
||
|
}
|