mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
Admin tools: minor improvements
- enable Projects button in navbar for admin projects page - enable copy of user ID in user info modal - add null check in UserListController (thanks @moschlar)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
.project-ds-nav-page {
|
||||||
|
.manage-projects-page {
|
||||||
|
.nav-item-projects {
|
||||||
|
display: initial !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,3 +11,4 @@
|
|||||||
@import 'labs';
|
@import 'labs';
|
||||||
@import 'admin-tools/user-list';
|
@import 'admin-tools/user-list';
|
||||||
@import 'admin-tools/user-list-ds-nav';
|
@import 'admin-tools/user-list-ds-nav';
|
||||||
|
@import 'admin-tools/manage-projects-page';
|
||||||
|
|||||||
@@ -290,8 +290,8 @@ function _sortAndPaginate(users, sort, page) {
|
|||||||
function _formatUserInfo(user, maxDate) {
|
function _formatUserInfo(user, maxDate) {
|
||||||
let authMethods = []
|
let authMethods = []
|
||||||
if (availableAuthMethods.includes('local') && user.hashedPassword) authMethods.push('local')
|
if (availableAuthMethods.includes('local') && user.hashedPassword) authMethods.push('local')
|
||||||
if (availableAuthMethods.includes('saml') && user.samlIdentifiers.length > 0) authMethods.push('saml')
|
if (availableAuthMethods.includes('saml') && user.samlIdentifiers?.length) authMethods.push('saml')
|
||||||
if (availableAuthMethods.includes('oidc') && user.thirdPartyIdentifiers.length > 0) authMethods.push('oidc')
|
if (availableAuthMethods.includes('oidc') && user.thirdPartyIdentifiers?.length) authMethods.push('oidc')
|
||||||
// If none of the above, mark as LDAP
|
// If none of the above, mark as LDAP
|
||||||
if (availableAuthMethods.includes('ldap') && authMethods.length === 0 && user.loginCount !== 0) authMethods.push('ldap')
|
if (availableAuthMethods.includes('ldap') && authMethods.length === 0 && user.loginCount !== 0) authMethods.push('ldap')
|
||||||
|
|
||||||
|
|||||||
@@ -56,11 +56,13 @@ export function ProjectListDsNav() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="project-ds-nav-page website-redesign">
|
<div className="project-ds-nav-page website-redesign">
|
||||||
<DefaultNavbar
|
<div className="manage-projects-page">
|
||||||
{...navbarProps}
|
<DefaultNavbar
|
||||||
overleafLogo={overleafLogo}
|
{...navbarProps}
|
||||||
showCloseIcon
|
overleafLogo={overleafLogo}
|
||||||
/>
|
showCloseIcon
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="project-list-wrapper">
|
<div className="project-list-wrapper">
|
||||||
<SidebarDsNav />
|
<SidebarDsNav />
|
||||||
<div className="project-ds-nav-content-and-messages">
|
<div className="project-ds-nav-content-and-messages">
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ function ShowUserInfoModal({
|
|||||||
const user = users[0]
|
const user = users[0]
|
||||||
|
|
||||||
const [activationLink, setActivationLink] = useState<string | null>(null)
|
const [activationLink, setActivationLink] = useState<string | null>(null)
|
||||||
const [copied, setCopied] = useState(false)
|
const [copiedId, setCopiedId] = useState(false)
|
||||||
|
const [copiedActivationLink, setCopiedActivationLink] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!showModal) return
|
if (!showModal) return
|
||||||
@@ -56,22 +57,22 @@ function ShowUserInfoModal({
|
|||||||
})
|
})
|
||||||
}, [showModal, user.id])
|
}, [showModal, user.id])
|
||||||
|
|
||||||
const handleCopy = () => {
|
const markCopied = (setter: React.Dispatch<React.SetStateAction<boolean>>) => {
|
||||||
if (!activationLink) return
|
setter(true)
|
||||||
|
setTimeout(() => setter(false), 1500)
|
||||||
|
}
|
||||||
|
|
||||||
const markCopied = () => {
|
const handleCopy = (text: string, setter: React.Dispatch<React.SetStateAction<boolean>>) => {
|
||||||
setCopied(true)
|
if (!text) return
|
||||||
setTimeout(() => setCopied(false), 1500)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (navigator.clipboard?.writeText) {
|
if (navigator.clipboard?.writeText) {
|
||||||
navigator.clipboard.writeText(activationLink).then(markCopied)
|
navigator.clipboard.writeText(text).then(() => markCopied(setter))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback for older browsers
|
// fallback for older browsers
|
||||||
const tempInput = document.createElement('input')
|
const tempInput = document.createElement('input')
|
||||||
tempInput.value = activationLink
|
tempInput.value = text
|
||||||
tempInput.style.position = 'fixed'
|
tempInput.style.position = 'fixed'
|
||||||
tempInput.style.opacity = '0'
|
tempInput.style.opacity = '0'
|
||||||
document.body.appendChild(tempInput)
|
document.body.appendChild(tempInput)
|
||||||
@@ -79,7 +80,7 @@ function ShowUserInfoModal({
|
|||||||
document.execCommand('copy')
|
document.execCommand('copy')
|
||||||
document.body.removeChild(tempInput)
|
document.body.removeChild(tempInput)
|
||||||
|
|
||||||
markCopied()
|
markCopied(setter)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -95,7 +96,22 @@ function ShowUserInfoModal({
|
|||||||
<>
|
<>
|
||||||
<Card.Header>{t('Account')}</Card.Header>
|
<Card.Header>{t('Account')}</Card.Header>
|
||||||
<Body>
|
<Body>
|
||||||
<InfoRow label={'ID'} value={user.id} />
|
<InfoRow
|
||||||
|
label={'ID'}
|
||||||
|
value={
|
||||||
|
<span
|
||||||
|
style={{ cursor: 'pointer', textDecoration: 'underline' }}
|
||||||
|
onClick={() => handleCopy(user.id, setCopiedId)}
|
||||||
|
>
|
||||||
|
{user.id}
|
||||||
|
{copiedId && (
|
||||||
|
<span className="ms-2 text-success">
|
||||||
|
({t('copied')})
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<InfoRow label={t('email_address')} value={user.email} />
|
<InfoRow label={t('email_address')} value={user.email} />
|
||||||
<InfoRow label={t('first_name')} value={user.firstName || '—'} />
|
<InfoRow label={t('first_name')} value={user.firstName || '—'} />
|
||||||
<InfoRow label={t('last_name')} value={user.lastName || '—'} />
|
<InfoRow label={t('last_name')} value={user.lastName || '—'} />
|
||||||
@@ -111,15 +127,15 @@ function ShowUserInfoModal({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{activationLink && (
|
{activationLink && (
|
||||||
<InfoRow
|
<InfoRow
|
||||||
label={t('activation_link')}
|
label={t('activation_link')}
|
||||||
value={
|
value={
|
||||||
<span
|
<span
|
||||||
style={{ cursor: 'pointer', textDecoration: 'underline' }}
|
style={{ cursor: 'pointer', textDecoration: 'underline' }}
|
||||||
onClick={handleCopy}
|
onClick={() => handleCopy(activationLink, setCopiedActivationLink)}
|
||||||
>
|
>
|
||||||
{activationLink}
|
{activationLink}
|
||||||
{copied && (
|
{copiedActivationLink && (
|
||||||
<span className="ms-2 text-success">
|
<span className="ms-2 text-success">
|
||||||
({t('copied')})
|
({t('copied')})
|
||||||
</span>
|
</span>
|
||||||
@@ -171,4 +187,3 @@ function ShowUserInfoModal({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default ShowUserInfoModal
|
export default ShowUserInfoModal
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user