mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 03:06:31 -05:00
refactor: remove show-if in favour of conditionals
This prevents a problem where show-if can trigger an error if a value is checked to exist with it. Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
parent
8884bbb428
commit
f701f8d05f
52 changed files with 239 additions and 352 deletions
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
import { AuthProviderType } from '../../../api/config/types'
|
||||
import { Redirect } from '../../../components/common/redirect'
|
||||
import { ShowIf } from '../../../components/common/show-if/show-if'
|
||||
import { LandingLayout } from '../../../components/landing-layout/landing-layout'
|
||||
import { ProfileAccessTokens } from '../../../components/profile-page/access-tokens/profile-access-tokens'
|
||||
import { ProfileAccountManagement } from '../../../components/profile-page/account-management/profile-account-management'
|
||||
|
@ -35,9 +34,7 @@ const ProfilePage: NextPage = () => {
|
|||
<Row className='h-100 flex justify-content-center'>
|
||||
<Col lg={6}>
|
||||
<ProfileDisplayName />
|
||||
<ShowIf condition={userProvider === (AuthProviderType.LOCAL as string)}>
|
||||
<ProfileChangePassword />
|
||||
</ShowIf>
|
||||
{userProvider === (AuthProviderType.LOCAL as string) && <ProfileChangePassword />}
|
||||
<ProfileAccessTokens />
|
||||
<ProfileAccountManagement />
|
||||
</Col>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import styles from '../application-loader.module.scss'
|
||||
import { LoadingAnimation } from './loading-animation'
|
||||
import type { ReactElement } from 'react'
|
||||
|
@ -27,9 +26,7 @@ export const LoadingScreen: React.FC<LoadingScreenProps> = ({ errorMessage }) =>
|
|||
<LoadingAnimation error={!!errorMessage} />
|
||||
</span>
|
||||
</div>
|
||||
<ShowIf condition={!!errorMessage}>
|
||||
<Alert variant={'danger'}>{errorMessage}</Alert>
|
||||
</ShowIf>
|
||||
{errorMessage !== undefined && <Alert variant={'danger'}>{errorMessage}</Alert>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { Logger } from '../../../../utils/logger'
|
||||
import { UiIcon } from '../../icons/ui-icon'
|
||||
import { ShowIf } from '../../show-if/show-if'
|
||||
import { CopyToClipboardButton } from '../copy-to-clipboard-button/copy-to-clipboard-button'
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import { Button, FormControl, InputGroup } from 'react-bootstrap'
|
||||
|
@ -54,13 +53,13 @@ export const CopyableField: React.FC<CopyableFieldProps> = ({ content, shareOrig
|
|||
<InputGroup.Text>
|
||||
<CopyToClipboardButton variant={'outline-secondary'} content={content} />
|
||||
</InputGroup.Text>
|
||||
<ShowIf condition={sharingSupported}>
|
||||
{sharingSupported && (
|
||||
<InputGroup.Text>
|
||||
<Button variant='secondary' title={'Share'} onClick={doShareAction}>
|
||||
<UiIcon icon={IconShare} />
|
||||
</Button>
|
||||
</InputGroup.Text>
|
||||
</ShowIf>
|
||||
)}
|
||||
</InputGroup>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { Logger } from '../../../../utils/logger'
|
||||
import { ShowIf } from '../../show-if/show-if'
|
||||
import type { ReactElement, RefObject } from 'react'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { Overlay, Tooltip } from 'react-bootstrap'
|
||||
|
@ -64,12 +63,8 @@ export const useCopyOverlay = (
|
|||
<Overlay target={clickComponent} show={showState !== SHOW_STATE.HIDDEN} placement='top'>
|
||||
{(props) => (
|
||||
<Tooltip id={`copied_${tooltipId}`} {...props}>
|
||||
<ShowIf condition={showState === SHOW_STATE.ERROR}>
|
||||
<Trans i18nKey={'copyOverlay.error'} />
|
||||
</ShowIf>
|
||||
<ShowIf condition={showState === SHOW_STATE.SUCCESS}>
|
||||
<Trans i18nKey={'copyOverlay.success'} />
|
||||
</ShowIf>
|
||||
{showState === SHOW_STATE.ERROR && <Trans i18nKey={'copyOverlay.error'} />}
|
||||
{showState === SHOW_STATE.SUCCESS && <Trans i18nKey={'copyOverlay.success'} />}
|
||||
</Tooltip>
|
||||
)}
|
||||
</Overlay>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
@ -7,7 +7,6 @@ import { concatCssClasses } from '../../../utils/concat-css-classes'
|
|||
import type { PropsWithDataTestId } from '../../../utils/test-id'
|
||||
import { testId } from '../../../utils/test-id'
|
||||
import { UiIcon } from '../icons/ui-icon'
|
||||
import { ShowIf } from '../show-if/show-if'
|
||||
import styles from './icon-button.module.scss'
|
||||
import React, { useMemo } from 'react'
|
||||
import type { ButtonProps } from 'react-bootstrap'
|
||||
|
@ -52,9 +51,7 @@ export const IconButton: React.FC<IconButtonProps> = ({
|
|||
<span className={`${styles['icon-part']}`}>
|
||||
<UiIcon size={iconSize} icon={icon} className={'icon'} />
|
||||
</span>
|
||||
<ShowIf condition={!!children}>
|
||||
<span className={`${styles['text-part']}`}>{children}</span>
|
||||
</ShowIf>
|
||||
{children !== undefined && <span className={`${styles['text-part']}`}>{children}</span>}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import type { PropsWithDataCypressId } from '../../../utils/cypress-attribute'
|
|||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { testId } from '../../../utils/test-id'
|
||||
import { UiIcon } from '../icons/ui-icon'
|
||||
import { ShowIf } from '../show-if/show-if'
|
||||
import type { PropsWithChildren, ReactElement } from 'react'
|
||||
import React, { Fragment, useMemo } from 'react'
|
||||
import { Modal } from 'react-bootstrap'
|
||||
|
@ -66,8 +65,11 @@ export const CommonModal: React.FC<PropsWithChildren<CommonModalProps>> = ({
|
|||
return titleI18nKey !== undefined ? <Trans i18nKey={titleI18nKey} /> : <span>{title}</span>
|
||||
}, [titleI18nKey, title])
|
||||
|
||||
if (!show) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<ShowIf condition={show}>
|
||||
<Modal
|
||||
{...cypressId(props)}
|
||||
show={show}
|
||||
|
@ -85,6 +87,5 @@ export const CommonModal: React.FC<PropsWithChildren<CommonModalProps>> = ({
|
|||
</Modal.Header>
|
||||
{children}
|
||||
</Modal>
|
||||
</ShowIf>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import { createNoteWithPrimaryAlias } from '../../../api/notes'
|
||||
import { testId } from '../../../utils/test-id'
|
||||
import { UiIcon } from '../icons/ui-icon'
|
||||
import { ShowIf } from '../show-if/show-if'
|
||||
import React, { useCallback, useEffect } from 'react'
|
||||
import { Alert, Button } from 'react-bootstrap'
|
||||
import {
|
||||
|
@ -85,9 +84,7 @@ export const CreateNonExistingNoteHint: React.FC<CreateNonExistingNoteHintProps>
|
|||
className='mx-2'
|
||||
onClick={onClickHandler}
|
||||
{...testId('createNoteButton')}>
|
||||
<ShowIf condition={returnState.loading}>
|
||||
<UiIcon icon={IconArrowRepeat} className={'me-2'} spin={true} />
|
||||
</ShowIf>
|
||||
{returnState.loading && <UiIcon icon={IconArrowRepeat} className={'me-2'} spin={true} />}
|
||||
<Trans i18nKey={'noteLoadingBoundary.createNote.create'} />
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,6 @@ import { Logger } from '../../../utils/logger'
|
|||
import { LoadingScreen } from '../../application-loader/loading-screen/loading-screen'
|
||||
import { CommonErrorPage } from '../../error-pages/common-error-page'
|
||||
import { CustomAsyncLoadingBoundary } from '../async-loading-boundary/custom-async-loading-boundary'
|
||||
import { ShowIf } from '../show-if/show-if'
|
||||
import { CreateNonExistingNoteHint } from './create-non-existing-note-hint'
|
||||
import { useLoadNoteFromServer } from './hooks/use-load-note-from-server'
|
||||
import type { PropsWithChildren } from 'react'
|
||||
|
@ -59,9 +58,9 @@ export const NoteLoadingBoundary: React.FC<PropsWithChildren<NoteIdProps>> = ({
|
|||
<CommonErrorPage
|
||||
titleI18nKey={`${errorI18nKeyPrefix}.title`}
|
||||
descriptionI18nKey={`${errorI18nKeyPrefix}.description`}>
|
||||
<ShowIf condition={error instanceof ApiError && error.statusCode === 404}>
|
||||
{error instanceof ApiError && error.statusCode === 404 && (
|
||||
<CreateNonExistingNoteHint onNoteCreated={loadNoteFromServer} noteId={noteId} />
|
||||
</ShowIf>
|
||||
)}
|
||||
</CommonErrorPage>
|
||||
)
|
||||
}, [error, loadNoteFromServer, noteId])
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../show-if/show-if'
|
||||
import { PagerItem } from './pager-item'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import { Pagination } from 'react-bootstrap'
|
||||
|
@ -70,17 +69,21 @@ export const PagerPagination: React.FC<PaginationProps> = ({
|
|||
|
||||
return (
|
||||
<Pagination dir='ltr'>
|
||||
<ShowIf condition={correctedLowerPageIndex > 0}>
|
||||
{correctedLowerPageIndex > 0 && (
|
||||
<>
|
||||
<PagerItem key={0} index={0} onClick={setPageIndex} />
|
||||
<Pagination.Ellipsis disabled />
|
||||
</ShowIf>
|
||||
</>
|
||||
)}
|
||||
{paginationItemsBefore}
|
||||
<Pagination.Item active>{correctedPageIndex + 1}</Pagination.Item>
|
||||
{paginationItemsAfter}
|
||||
<ShowIf condition={correctedUpperPageIndex < lastPageIndex}>
|
||||
{correctedUpperPageIndex < lastPageIndex && (
|
||||
<>
|
||||
<Pagination.Ellipsis disabled />
|
||||
<PagerItem key={lastPageIndex} index={lastPageIndex} onClick={setPageIndex} />
|
||||
</ShowIf>
|
||||
</>
|
||||
)}
|
||||
</Pagination>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
@ -19,7 +19,6 @@ import type {
|
|||
SetScrollStateMessage
|
||||
} from '../../render-page/window-post-message-communicator/rendering-message'
|
||||
import { CommunicationMessageType } from '../../render-page/window-post-message-communicator/rendering-message'
|
||||
import { ShowIf } from '../show-if/show-if'
|
||||
import { WaitSpinner } from '../wait-spinner/wait-spinner'
|
||||
import { useEffectOnRenderTypeChange } from './hooks/use-effect-on-render-type-change'
|
||||
import { useForceRenderPageUrlOnIframeLoadCallback } from './hooks/use-force-render-page-url-on-iframe-load-callback'
|
||||
|
@ -176,9 +175,7 @@ export const RendererIframe: React.FC<RendererIframeProps> = ({
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<ShowIf condition={!rendererReady && showWaitSpinner}>
|
||||
<WaitSpinner />
|
||||
</ShowIf>
|
||||
{!rendererReady && showWaitSpinner && <WaitSpinner />}
|
||||
<iframe
|
||||
style={{ height: `${frameHeight}px` }}
|
||||
{...cypressId('documentIframe')}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ShowIf does not render child if condition is false 1`] = `<div />`;
|
||||
|
||||
exports[`ShowIf renders child if condition is true 1`] = `
|
||||
<div>
|
||||
test
|
||||
</div>
|
||||
`;
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from './show-if'
|
||||
import { render } from '@testing-library/react'
|
||||
|
||||
describe('ShowIf', () => {
|
||||
it('renders child if condition is true', () => {
|
||||
const view = render(<ShowIf condition={true}>test</ShowIf>)
|
||||
expect(view.container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('does not render child if condition is false', () => {
|
||||
const view = render(<ShowIf condition={false}>test</ShowIf>)
|
||||
expect(view.container).toMatchSnapshot()
|
||||
})
|
||||
})
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
export interface ShowIfProps {
|
||||
condition: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the children if the condition is met.
|
||||
*
|
||||
* @param children The children to show if the condition is met.
|
||||
* @param condition If the children should be shown
|
||||
*/
|
||||
export const ShowIf: React.FC<PropsWithChildren<ShowIfProps>> = ({ children, condition }) => {
|
||||
return condition ? <Fragment>{children}</Fragment> : null
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useTranslatedText } from '../../../hooks/common/use-translated-text'
|
||||
import { ShowIf } from '../show-if/show-if'
|
||||
import styles from './user-avatar.module.scss'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useAvatarUrl } from './hooks/use-avatar-url'
|
||||
|
@ -64,9 +63,7 @@ export const UserAvatar: React.FC<UserAvatarProps> = ({
|
|||
height={imageSize}
|
||||
width={imageSize}
|
||||
/>
|
||||
<ShowIf condition={showName}>
|
||||
<span className={`ms-2 me-1 ${styles['user-line-name']}`}>{displayName}</span>
|
||||
</ShowIf>
|
||||
{showName && <span className={`ms-2 me-1 ${styles['user-line-name']}`}>{displayName}</span>}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import { useApplicationState } from '../../hooks/common/use-application-state'
|
||||
import { useTranslatedText } from '../../hooks/common/use-translated-text'
|
||||
import { InternalLink } from '../common/links/internal-link'
|
||||
import { ShowIf } from '../common/show-if/show-if'
|
||||
import { NoteInfoLineCreatedAt } from '../editor-page/sidebar/specific-sidebar-entries/note-info-sidebar-menu/note-info-line/note-info-line-created-at'
|
||||
import { NoteInfoLineUpdatedBy } from '../editor-page/sidebar/specific-sidebar-entries/note-info-sidebar-menu/note-info-line/note-info-line-updated-by'
|
||||
import styles from './document-infobar.module.scss'
|
||||
|
@ -36,7 +35,6 @@ export const DocumentInfobar: React.FC = () => {
|
|||
</div>
|
||||
<span className={'ms-auto'}>
|
||||
{noteDetails.viewCount} <Trans i18nKey={'views.readOnly.viewCount'} />
|
||||
<ShowIf condition={true}>
|
||||
<InternalLink
|
||||
text={''}
|
||||
href={`/n/${noteDetails.primaryAddress}`}
|
||||
|
@ -44,7 +42,6 @@ export const DocumentInfobar: React.FC = () => {
|
|||
className={'text-primary text-decoration-none mx-1'}
|
||||
title={linkTitle}
|
||||
/>
|
||||
</ShowIf>
|
||||
</span>
|
||||
</div>
|
||||
<div className={'col-md'}> </div>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { useMayEdit } from '../../../../hooks/common/use-may-edit'
|
||||
import { concatCssClasses } from '../../../../utils/concat-css-classes'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import { BoldButton } from './buttons/bold-button'
|
||||
import { CheckListButton } from './buttons/check-list-button'
|
||||
import { CodeFenceButton } from './buttons/code-fence-button'
|
||||
|
@ -38,8 +37,11 @@ const EmojiPickerButton = React.lazy(() => import('./emoji-picker/emoji-picker-b
|
|||
export const ToolBar: React.FC = () => {
|
||||
const mayEdit = useMayEdit()
|
||||
|
||||
if (!mayEdit) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<ShowIf condition={mayEdit}>
|
||||
<ButtonToolbar className={concatCssClasses(styles.toolbar, 'my-1')}>
|
||||
<ButtonGroup className={'mx-1 flex-wrap'}>
|
||||
<BoldButton />
|
||||
|
@ -73,6 +75,5 @@ export const ToolBar: React.FC = () => {
|
|||
</Suspense>
|
||||
</ButtonGroup>
|
||||
</ButtonToolbar>
|
||||
</ShowIf>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { cypressId } from '../../../../../utils/cypress-attribute'
|
||||
import { Logger } from '../../../../../utils/logger'
|
||||
import { ShowIf } from '../../../../common/show-if/show-if'
|
||||
import { acceptedMimeTypes } from '../../../../common/upload-image-mimetypes'
|
||||
import { UploadInput } from '../../../../common/upload-input'
|
||||
import { useCodemirrorReferenceContext } from '../../../change-content-context/codemirror-reference-context'
|
||||
|
@ -47,14 +46,14 @@ export const UploadImageButton: React.FC = () => {
|
|||
return (
|
||||
<Fragment>
|
||||
<ToolbarButton i18nKey={'uploadImage'} icon={IconUpload} onClick={buttonClick}>
|
||||
<ShowIf condition={!!codeMirror}>
|
||||
{codeMirror !== undefined && (
|
||||
<UploadInput
|
||||
onLoad={onUploadImage}
|
||||
allowedFileTypes={acceptedMimeTypes}
|
||||
onClickRef={clickRef}
|
||||
{...cypressId('toolbar.uploadImage.input')}
|
||||
/>
|
||||
</ShowIf>
|
||||
)}
|
||||
</ToolbarButton>
|
||||
</Fragment>
|
||||
)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { concatCssClasses } from '../../../../utils/concat-css-classes'
|
||||
import { UiIcon } from '../../../common/icons/ui-icon'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import type { SidebarEntryProps } from '../types'
|
||||
import styles from './sidebar-button.module.scss'
|
||||
import type { PropsWithChildren } from 'react'
|
||||
|
@ -51,11 +50,11 @@ export const SidebarButton: React.FC<PropsWithChildren<SidebarEntryProps>> = ({
|
|||
className={concatCssClasses(styles.button, className, { [styles.hide]: hide })}
|
||||
disabled={disabled}
|
||||
{...props}>
|
||||
<ShowIf condition={!!icon}>
|
||||
{icon !== undefined && (
|
||||
<span className={`sidebar-button-icon ${styles.icon}`}>
|
||||
<UiIcon icon={icon} />
|
||||
</span>
|
||||
</ShowIf>
|
||||
)}
|
||||
<span className={concatCssClasses(styles.text, { [styles.disabled]: disabled })}>{children}</span>
|
||||
</button>
|
||||
</OverlayTrigger>
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { UiIcon } from '../../../common/icons/ui-icon'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import styles from './sidebar-menu-info-entry.module.css'
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import React from 'react'
|
||||
|
@ -32,9 +31,7 @@ export const SidebarMenuInfoEntry: React.FC<PropsWithChildren<SidebarMenuInfoEnt
|
|||
|
||||
return (
|
||||
<div className={`d-flex flex-row align-items-center p-1 ${styles['entry']}`}>
|
||||
<ShowIf condition={icon !== undefined}>
|
||||
<UiIcon icon={icon} className={'mx-2'} size={1.25} />
|
||||
</ShowIf>
|
||||
{icon !== undefined && <UiIcon icon={icon} className={'mx-2'} size={1.25} />}
|
||||
<div className={'d-flex flex-column px-1'}>
|
||||
<span className={styles['title']}>
|
||||
<Trans i18nKey={titleI18nKey} />
|
||||
|
|
|
@ -10,7 +10,6 @@ import { useTranslatedText } from '../../../../../../hooks/common/use-translated
|
|||
import { updateMetadata } from '../../../../../../redux/note-details/methods'
|
||||
import { testId } from '../../../../../../utils/test-id'
|
||||
import { UiIcon } from '../../../../../common/icons/ui-icon'
|
||||
import { ShowIf } from '../../../../../common/show-if/show-if'
|
||||
import { useUiNotifications } from '../../../../../notifications/ui-notification-boundary'
|
||||
import React, { useCallback } from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
|
@ -51,7 +50,7 @@ export const AliasesListEntry: React.FC<AliasesListEntryProps> = ({ alias }) =>
|
|||
<li className={'list-group-item d-flex flex-row justify-content-between align-items-center'}>
|
||||
{alias.name}
|
||||
<div>
|
||||
<ShowIf condition={alias.primaryAlias}>
|
||||
{alias.primaryAlias && (
|
||||
<Button
|
||||
className={'me-2 text-warning'}
|
||||
variant='light'
|
||||
|
@ -60,8 +59,8 @@ export const AliasesListEntry: React.FC<AliasesListEntryProps> = ({ alias }) =>
|
|||
{...testId('aliasIsPrimary')}>
|
||||
<UiIcon icon={IconStar} />
|
||||
</Button>
|
||||
</ShowIf>
|
||||
<ShowIf condition={!alias.primaryAlias}>
|
||||
)}
|
||||
{!alias.primaryAlias && (
|
||||
<Button
|
||||
className={'me-2'}
|
||||
variant='light'
|
||||
|
@ -71,7 +70,7 @@ export const AliasesListEntry: React.FC<AliasesListEntryProps> = ({ alias }) =>
|
|||
{...testId('aliasButtonMakePrimary')}>
|
||||
<UiIcon icon={IconStarFill} />
|
||||
</Button>
|
||||
</ShowIf>
|
||||
)}
|
||||
<Button
|
||||
variant='light'
|
||||
className={'text-danger'}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { FileContentFormat, readFile } from '../../../../utils/read-file'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import { UploadInput } from '../../../common/upload-input'
|
||||
import { useChangeEditorContentCallback } from '../../change-content-context/use-change-editor-content-callback'
|
||||
import { SidebarButton } from '../sidebar-button/sidebar-button'
|
||||
|
@ -54,14 +53,14 @@ export const ImportMarkdownSidebarEntry: React.FC = () => {
|
|||
disabled={!changeEditorContent}>
|
||||
<Trans i18nKey={'editor.import.file'} />
|
||||
</SidebarButton>
|
||||
<ShowIf condition={!!changeEditorContent}>
|
||||
{changeEditorContent !== undefined && (
|
||||
<UploadInput
|
||||
onLoad={onImportMarkdown}
|
||||
{...cypressId('menu-import-markdown-input')}
|
||||
allowedFileTypes={'.md, text/markdown, text/plain'}
|
||||
onClickRef={clickRef}
|
||||
/>
|
||||
</ShowIf>
|
||||
)}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { useApplicationState } from '../../../../../../hooks/common/use-application-state'
|
||||
import { cypressId } from '../../../../../../utils/cypress-attribute'
|
||||
import { ShowIf } from '../../../../../common/show-if/show-if'
|
||||
import { useEditorReceiveHandler } from '../../../../../render-page/window-post-message-communicator/hooks/use-editor-receive-handler'
|
||||
import type { OnWordCountCalculatedMessage } from '../../../../../render-page/window-post-message-communicator/rendering-message'
|
||||
import { CommunicationMessageType } from '../../../../../render-page/window-post-message-communicator/rendering-message'
|
||||
|
@ -42,12 +41,8 @@ export const NoteInfoLineWordCount: React.FC<NoteInfoLineWordCountProps> = ({ vi
|
|||
|
||||
return (
|
||||
<SidebarMenuInfoEntry titleI18nKey={'editor.noteInfo.wordCount'} icon={IconAlignStart}>
|
||||
<ShowIf condition={wordCount === null}>
|
||||
<Trans i18nKey={'common.loading'} />
|
||||
</ShowIf>
|
||||
<ShowIf condition={wordCount !== null}>
|
||||
<span {...cypressId('document-info-word-count')}>{wordCount}</span>
|
||||
</ShowIf>
|
||||
{wordCount === null && <Trans i18nKey={'common.loading'} />}
|
||||
{wordCount !== null && <span {...cypressId('document-info-word-count')}>{wordCount}</span>}
|
||||
</SidebarMenuInfoEntry>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import { removeUserPermission, setUserPermission } from '../../../../../../api/p
|
|||
import { getUser } from '../../../../../../api/users'
|
||||
import { useApplicationState } from '../../../../../../hooks/common/use-application-state'
|
||||
import { setNotePermissionsFromServer } from '../../../../../../redux/note-details/methods'
|
||||
import { ShowIf } from '../../../../../common/show-if/show-if'
|
||||
import { UserAvatarForUser } from '../../../../../common/user-avatar/user-avatar-for-user'
|
||||
import { useUiNotifications } from '../../../../../notifications/ui-notification-boundary'
|
||||
import type { PermissionDisabledProps } from './permission-disabled.prop'
|
||||
|
@ -18,6 +17,7 @@ import React, { useCallback, useMemo } from 'react'
|
|||
import { useAsync } from 'react-use'
|
||||
import { PermissionInconsistentAlert } from './permission-inconsistent-alert'
|
||||
import { useGetSpecialPermissions } from './hooks/use-get-special-permissions'
|
||||
import { AsyncLoadingBoundary } from '../../../../../common/async-loading-boundary/async-loading-boundary'
|
||||
|
||||
export interface PermissionEntryUserProps {
|
||||
entry: NoteUserPermissionEntry
|
||||
|
@ -87,7 +87,7 @@ export const PermissionEntryUser: React.FC<PermissionEntryUserProps & Permission
|
|||
}
|
||||
|
||||
return (
|
||||
<ShowIf condition={!loading && !error}>
|
||||
<AsyncLoadingBoundary loading={loading} error={error} componentName={'PermissionEntryUser'}>
|
||||
<li className={'list-group-item d-flex flex-row justify-content-between align-items-center'}>
|
||||
<UserAvatarForUser user={value} />
|
||||
<div className={'d-flex flex-row align-items-center'}>
|
||||
|
@ -103,6 +103,6 @@ export const PermissionEntryUser: React.FC<PermissionEntryUserProps & Permission
|
|||
/>
|
||||
</div>
|
||||
</li>
|
||||
</ShowIf>
|
||||
</AsyncLoadingBoundary>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import type { RevisionMetadata } from '../../../../../../api/revisions/types'
|
||||
import { UiIcon } from '../../../../../common/icons/ui-icon'
|
||||
import { ShowIf } from '../../../../../common/show-if/show-if'
|
||||
import { UserAvatarForUser } from '../../../../../common/user-avatar/user-avatar-for-user'
|
||||
import { WaitSpinner } from '../../../../../common/wait-spinner/wait-spinner'
|
||||
import { useUiNotifications } from '../../../../../notifications/ui-notification-boundary'
|
||||
|
@ -72,10 +71,8 @@ export const RevisionListEntry: React.FC<RevisionListEntryProps> = ({ active, on
|
|||
</span>
|
||||
<span className={'d-flex flex-row my-1 align-items-center'}>
|
||||
<UiIcon icon={IconPerson} className={'mx-2'} />
|
||||
<ShowIf condition={revisionAuthors.loading}>
|
||||
<WaitSpinner />
|
||||
</ShowIf>
|
||||
<ShowIf condition={!revisionAuthors.error && !revisionAuthors.loading}>{revisionAuthors.value}</ShowIf>
|
||||
{revisionAuthors.loading && <WaitSpinner />}
|
||||
{!revisionAuthors.error && !revisionAuthors.loading && revisionAuthors.value}
|
||||
</span>
|
||||
<span>
|
||||
<UiIcon icon={IconPersonPlus} className='mx-2' />
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import { useApplicationState } from '../../../../../../hooks/common/use-application-state'
|
||||
import type { ModalVisibilityProps } from '../../../../../common/modals/common-modal'
|
||||
import { CommonModal } from '../../../../../common/modals/common-modal'
|
||||
import { ShowIf } from '../../../../../common/show-if/show-if'
|
||||
import { LinkType, NoteUrlField } from './note-url-field'
|
||||
import { NoteType } from '@hedgedoc/commons'
|
||||
import React from 'react'
|
||||
|
@ -32,14 +31,18 @@ export const ShareModal: React.FC<ModalVisibilityProps> = ({ show, onHide }) =>
|
|||
<Modal.Body>
|
||||
<Trans i18nKey={'editor.modal.shareLink.editorDescription'} />
|
||||
<NoteUrlField type={LinkType.EDITOR} />
|
||||
<ShowIf condition={noteFrontmatter.type === NoteType.SLIDE}>
|
||||
{noteFrontmatter.type === NoteType.SLIDE && (
|
||||
<>
|
||||
<Trans i18nKey={'editor.modal.shareLink.slidesDescription'} />
|
||||
<NoteUrlField type={LinkType.SLIDESHOW} />
|
||||
</ShowIf>
|
||||
<ShowIf condition={noteFrontmatter.type === NoteType.DOCUMENT}>
|
||||
</>
|
||||
)}
|
||||
{noteFrontmatter.type === NoteType.DOCUMENT && (
|
||||
<>
|
||||
<Trans i18nKey={'editor.modal.shareLink.viewOnlyDescription'} />
|
||||
<NoteUrlField type={LinkType.DOCUMENT} />
|
||||
</ShowIf>
|
||||
</>
|
||||
)}
|
||||
</Modal.Body>
|
||||
</CommonModal>
|
||||
)
|
||||
|
|
|
@ -10,7 +10,6 @@ import { ActiveIndicator } from '../active-indicator'
|
|||
import styles from './user-line.module.scss'
|
||||
import React, { useMemo } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { ShowIf } from '../../../../../common/show-if/show-if'
|
||||
import { Incognito as IconIncognito } from 'react-bootstrap-icons'
|
||||
import { useTranslatedText } from '../../../../../../hooks/common/use-translated-text'
|
||||
|
||||
|
@ -48,9 +47,7 @@ export const UserLine: React.FC<UserLineProps> = ({ username, displayName, activ
|
|||
<div className={`${styles['user-line-color-indicator']} ${createCursorCssClass(color)}`} />
|
||||
{avatar}
|
||||
<div className={'ms-auto d-flex align-items-center gap-1 h-100'}>
|
||||
<ShowIf condition={!username}>
|
||||
<IconIncognito title={guestUserTitle} size={'16px'} className={'text-muted'} />
|
||||
</ShowIf>
|
||||
{!username && <IconIncognito title={guestUserTitle} size={'16px'} className={'text-muted'} />}
|
||||
{own ? (
|
||||
<span className={'px-1'}>
|
||||
<Trans i18nKey={'editor.onlineStatus.you'}></Trans>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { useKeyboardShortcuts } from './hooks/use-keyboard-shortcuts'
|
||||
import { DividerButtonsShift, SplitDivider } from './split-divider/split-divider'
|
||||
import styles from './splitter.module.scss'
|
||||
|
@ -140,7 +139,7 @@ export const Splitter: React.FC<SplitterProps> = ({ additionalContainerClassName
|
|||
className={`flex-fill flex-row d-flex ${additionalContainerClassName || ''}${
|
||||
resizingInProgress ? ' ' + styles.resizing : ''
|
||||
}`}>
|
||||
<ShowIf condition={resizingInProgress}>
|
||||
{resizingInProgress && (
|
||||
<div
|
||||
className={styles['move-overlay']}
|
||||
onTouchMove={onMove}
|
||||
|
@ -148,7 +147,7 @@ export const Splitter: React.FC<SplitterProps> = ({ additionalContainerClassName
|
|||
onTouchCancel={onStopResizing}
|
||||
onTouchEnd={onStopResizing}
|
||||
onMouseUp={onStopResizing}></div>
|
||||
</ShowIf>
|
||||
)}
|
||||
<div className={styles['left']} style={{ width: `calc(${adjustedRelativeSplitValue}% - 5px)` }}>
|
||||
<div className={styles['inner']}>{left}</div>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { concatCssClasses } from '../../../utils/concat-css-classes'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import styles from './table-of-contents.module.scss'
|
||||
import { useBuildReactDomFromTocAst } from './use-build-react-dom-from-toc-ast'
|
||||
import type { TocAst } from '@hedgedoc/markdown-it-plugins'
|
||||
|
@ -32,9 +31,7 @@ export const TableOfContents: React.FC<TableOfContentsProps> = ({ ast, maxDepth
|
|||
|
||||
return (
|
||||
<div className={concatCssClasses(styles.toc, className)}>
|
||||
<ShowIf condition={ast.children.length === 0}>
|
||||
<Trans i18nKey={'editor.infoToc'} />
|
||||
</ShowIf>
|
||||
{ast.children.length === 0 && <Trans i18nKey={'editor.infoToc'} />}
|
||||
{tocTree}
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { JumpAnchor } from '../../markdown-renderer/extensions/link-replacer/jump-anchor'
|
||||
import { tocSlugify } from './toc-slugify'
|
||||
import type { TocAst } from '@hedgedoc/markdown-it-plugins'
|
||||
|
@ -42,14 +41,12 @@ const buildReactDomFromTocAst = (
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<ShowIf condition={toc.level > 0}>
|
||||
{toc.level > 0 && (
|
||||
<JumpAnchor href={headlineUrl} title={rawName} jumpTargetId={slug.slice(1)}>
|
||||
{rawName}
|
||||
</JumpAnchor>
|
||||
</ShowIf>
|
||||
<ShowIf condition={children.length > 0}>
|
||||
<ul>{children}</ul>
|
||||
</ShowIf>
|
||||
)}
|
||||
{children.length > 0 && <ul>{children}</ul>}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../common/show-if/show-if'
|
||||
import { LandingLayout } from '../landing-layout/landing-layout'
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import React from 'react'
|
||||
|
@ -35,11 +34,11 @@ export const CommonErrorPage: React.FC<PropsWithChildren<CommonErrorPageProps>>
|
|||
<h1>
|
||||
<Trans i18nKey={titleI18nKey} />
|
||||
</h1>
|
||||
<ShowIf condition={!!descriptionI18nKey}>
|
||||
{descriptionI18nKey !== undefined && (
|
||||
<h3>
|
||||
<Trans i18nKey={descriptionI18nKey} />
|
||||
</h3>
|
||||
</ShowIf>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
</LandingLayout>
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { AltKey } from './alt-key'
|
||||
import { ModifierKey } from './modifier-key'
|
||||
import React from 'react'
|
||||
|
@ -39,15 +38,19 @@ export const ShortcutLine: React.FC<ShortcutLineProps> = ({
|
|||
<Trans i18nKey={functionNameI18nKey} />
|
||||
</span>
|
||||
<span>
|
||||
<ShowIf condition={showModifierKey}>
|
||||
{showModifierKey && (
|
||||
<>
|
||||
<ModifierKey />
|
||||
<span> + </span>
|
||||
</ShowIf>
|
||||
</>
|
||||
)}
|
||||
|
||||
<ShowIf condition={showAltKey}>
|
||||
{showAltKey && (
|
||||
<>
|
||||
<AltKey />
|
||||
<span> + </span>
|
||||
</ShowIf>
|
||||
</>
|
||||
)}
|
||||
|
||||
<kbd>{functionKeyCode.toUpperCase()}</kbd>
|
||||
</span>
|
||||
|
|
|
@ -11,7 +11,6 @@ import { useFrontendConfig } from '../../common/frontend-config-context/use-fron
|
|||
import { TranslatedExternalLink } from '../../common/links/translated-external-link'
|
||||
import type { CommonModalProps } from '../../common/modals/common-modal'
|
||||
import { CommonModal } from '../../common/modals/common-modal'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import React, { useMemo } from 'react'
|
||||
import { Modal } from 'react-bootstrap'
|
||||
|
||||
|
@ -46,20 +45,20 @@ export const VersionInfoModal: React.FC<CommonModalProps> = ({ onHide, show }) =
|
|||
<Modal.Body>
|
||||
<CopyableField content={backendVersion} />
|
||||
<div className='d-flex justify-content-between mt-3'>
|
||||
<ShowIf condition={!!links.sourceCode}>
|
||||
{links.sourceCode !== undefined && (
|
||||
<TranslatedExternalLink
|
||||
i18nKey={'landing.versionInfo.sourceCode'}
|
||||
className={'btn btn-primary d-block mb-2'}
|
||||
href={links.sourceCode}
|
||||
/>
|
||||
</ShowIf>
|
||||
<ShowIf condition={!!links.issues}>
|
||||
)}
|
||||
{links.issues !== undefined && (
|
||||
<TranslatedExternalLink
|
||||
i18nKey={'landing.versionInfo.issueTracker'}
|
||||
className={'btn btn-primary d-block mb-2'}
|
||||
href={links.issues}
|
||||
/>
|
||||
</ShowIf>
|
||||
)}
|
||||
</div>
|
||||
</Modal.Body>
|
||||
</CommonModal>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import { HistoryEntryOrigin } from '../../../api/history/types'
|
||||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { UiIcon } from '../../common/icons/ui-icon'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { DeleteNoteItem } from './delete-note-item'
|
||||
import styles from './entry-menu.module.scss'
|
||||
import { RemoveNoteEntryItem } from './remove-note-entry-item'
|
||||
|
@ -60,27 +59,29 @@ export const EntryMenu: React.FC<EntryMenuProps> = ({
|
|||
<Trans i18nKey='landing.history.menu.recentNotes' />
|
||||
</Dropdown.Header>
|
||||
|
||||
<ShowIf condition={origin === HistoryEntryOrigin.LOCAL}>
|
||||
{origin === HistoryEntryOrigin.LOCAL && (
|
||||
<Dropdown.Item disabled>
|
||||
<UiIcon icon={IconLaptop} className='mx-2' />
|
||||
<Trans i18nKey='landing.history.menu.entryLocal' />
|
||||
</Dropdown.Item>
|
||||
</ShowIf>
|
||||
)}
|
||||
|
||||
<ShowIf condition={origin === HistoryEntryOrigin.REMOTE}>
|
||||
{origin === HistoryEntryOrigin.REMOTE && (
|
||||
<Dropdown.Item disabled>
|
||||
<UiIcon icon={IconCloud} className='mx-2' />
|
||||
<Trans i18nKey='landing.history.menu.entryRemote' />
|
||||
</Dropdown.Item>
|
||||
</ShowIf>
|
||||
)}
|
||||
|
||||
<RemoveNoteEntryItem onConfirm={onRemoveFromHistory} noteTitle={title} />
|
||||
|
||||
{/* TODO Check permissions (ownership) before showing option for delete (https://github.com/hedgedoc/hedgedoc/issues/5036)*/}
|
||||
<ShowIf condition={userExists}>
|
||||
{userExists && (
|
||||
<>
|
||||
<Dropdown.Divider />
|
||||
<DeleteNoteItem onConfirm={onDeleteNote} noteTitle={title} />
|
||||
</ShowIf>
|
||||
</>
|
||||
)}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
)
|
||||
|
|
|
@ -8,7 +8,6 @@ import { useApplicationState } from '../../../hooks/common/use-application-state
|
|||
import { useTranslatedText } from '../../../hooks/common/use-translated-text'
|
||||
import { importHistoryEntries, setHistoryEntries } from '../../../redux/history/methods'
|
||||
import { UiIcon } from '../../common/icons/ui-icon'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { useUiNotifications } from '../../notifications/ui-notification-boundary'
|
||||
import { ClearHistoryButton } from './clear-history-button'
|
||||
import { ExportHistoryButton } from './export-history-button'
|
||||
|
@ -89,13 +88,13 @@ export const HistoryToolbar: React.FC = () => {
|
|||
<div className={'me-1 mb-1'}>
|
||||
<HistoryRefreshButton />
|
||||
</div>
|
||||
<ShowIf condition={userExists}>
|
||||
{userExists && (
|
||||
<div className={'me-1 mb-1'}>
|
||||
<Button variant={'secondary'} title={uploadAllButtonTitle} onClick={onUploadAllToRemote}>
|
||||
<UiIcon icon={IconCloudUpload} />
|
||||
</Button>
|
||||
</div>
|
||||
</ShowIf>
|
||||
)}
|
||||
<div className={'me-1 mb-1'}>
|
||||
<HistoryViewModeToggleButton />
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
@ -29,7 +29,7 @@ export const IntroCustomContent: React.FC = () => {
|
|||
<AsyncLoadingBoundary loading={loading || !value} error={error} componentName={'custom intro content'}>
|
||||
<RendererIframe
|
||||
frameClasses={'w-100 overflow-y-hidden'}
|
||||
markdownContentLines={value as string[]}
|
||||
markdownContentLines={value ?? []}
|
||||
rendererType={RendererType.SIMPLE}
|
||||
adaptFrameHeightToContent={true}
|
||||
showWaitSpinner={true}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import { useTranslatedText } from '../../../hooks/common/use-translated-text'
|
||||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { useFrontendConfig } from '../../common/frontend-config-context/use-frontend-config'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import Link from 'next/link'
|
||||
import React, { useMemo } from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
|
@ -39,13 +38,15 @@ export const SignInButton: React.FC<SignInButtonProps> = ({ variant, ...props })
|
|||
}, [authProviders, pathname])
|
||||
const buttonTitle = useTranslatedText('login.signIn')
|
||||
|
||||
if (authProviders.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<ShowIf condition={authProviders.length > 0}>
|
||||
<Link href={loginLink} passHref={true}>
|
||||
<Button title={buttonTitle} {...cypressId('sign-in-button')} variant={variant || 'success'} {...props}>
|
||||
<Trans i18nKey='login.signIn' />
|
||||
</Button>
|
||||
</Link>
|
||||
</ShowIf>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../../../../../common/show-if/show-if'
|
||||
import { DropdownHeader } from '../dropdown-header'
|
||||
import { TranslatedDropdownItem } from '../translated-dropdown-item'
|
||||
import type { ReactElement } from 'react'
|
||||
|
@ -29,15 +28,15 @@ export const LegalSubmenu: React.FC = (): null | ReactElement => {
|
|||
<Fragment>
|
||||
<Dropdown.Divider />
|
||||
<DropdownHeader i18nKey={'appbar.help.legal.header'} />
|
||||
<ShowIf condition={!!specialUrls.privacy}>
|
||||
{specialUrls.privacy !== undefined && (
|
||||
<TranslatedDropdownItem href={specialUrls.privacy} i18nKey={'appbar.help.legal.privacy'} />
|
||||
</ShowIf>
|
||||
<ShowIf condition={!!specialUrls.termsOfUse}>
|
||||
)}
|
||||
{specialUrls.termsOfUse !== undefined && (
|
||||
<TranslatedDropdownItem href={specialUrls.termsOfUse} i18nKey={'appbar.help.legal.termsOfUse'} />
|
||||
</ShowIf>
|
||||
<ShowIf condition={!!specialUrls.imprint}>
|
||||
)}
|
||||
{specialUrls.imprint !== undefined && (
|
||||
<TranslatedDropdownItem href={specialUrls.imprint} i18nKey={'appbar.help.legal.imprint'} />
|
||||
</ShowIf>
|
||||
)}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { useTranslatedText } from '../../../../../hooks/common/use-translated-text'
|
||||
import { UiIcon } from '../../../../common/icons/ui-icon'
|
||||
import { ShowIf } from '../../../../common/show-if/show-if'
|
||||
import type { TOptions } from 'i18next'
|
||||
import React from 'react'
|
||||
import { Dropdown } from 'react-bootstrap'
|
||||
|
@ -36,9 +35,7 @@ export const TranslatedDropdownItem: React.FC<TranslatedDropdownItemProps> = ({
|
|||
|
||||
return (
|
||||
<Dropdown.Item {...props} title={title} className={'d-flex align-items-center'}>
|
||||
<ShowIf condition={!!icon}>
|
||||
<UiIcon icon={icon} className={'me-2'} />
|
||||
</ShowIf>
|
||||
{icon !== undefined && <UiIcon icon={icon} className={'me-2'} />}
|
||||
<span>{title}</span>
|
||||
</Dropdown.Item>
|
||||
)
|
||||
|
|
|
@ -9,7 +9,6 @@ import { useMayEdit } from '../../../../../hooks/common/use-may-edit'
|
|||
import { useNoteTitle } from '../../../../../hooks/common/use-note-title'
|
||||
import { useTranslatedText } from '../../../../../hooks/common/use-translated-text'
|
||||
import { UiIcon } from '../../../../common/icons/ui-icon'
|
||||
import { ShowIf } from '../../../../common/show-if/show-if'
|
||||
import React from 'react'
|
||||
import { Lock as IconLock } from 'react-bootstrap-icons'
|
||||
|
||||
|
@ -23,11 +22,11 @@ export const NoteTitleElement: React.FC = () => {
|
|||
|
||||
return (
|
||||
<span className={'m-0 text-truncate'}>
|
||||
<ShowIf condition={!isWriteable}>
|
||||
{!isWriteable && (
|
||||
<span className={'text-secondary me-2'}>
|
||||
<UiIcon icon={IconLock} className={'me-2'} title={readOnlyLabel} />
|
||||
</span>
|
||||
</ShowIf>
|
||||
)}
|
||||
{noteTitle}
|
||||
</span>
|
||||
)
|
||||
|
|
|
@ -11,7 +11,6 @@ import { HistoryButton } from '../../layout/app-bar/app-bar-elements/help-dropdo
|
|||
import { useFrontendConfig } from '../../common/frontend-config-context/use-frontend-config'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { GuestAccessLevel } from '../../../api/config/types'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
|
||||
/**
|
||||
* Renders the card with the options for not logged-in users.
|
||||
|
@ -35,11 +34,11 @@ export const GuestCard: React.FC = () => {
|
|||
<NewNoteButton />
|
||||
<HistoryButton />
|
||||
</div>
|
||||
<ShowIf condition={guestAccessLevel !== GuestAccessLevel.CREATE}>
|
||||
{guestAccessLevel !== GuestAccessLevel.CREATE && (
|
||||
<div className={'text-muted mt-2 small'}>
|
||||
<Trans i18nKey={'login.guest.noteCreationDisabled'} />
|
||||
</div>
|
||||
</ShowIf>
|
||||
)}
|
||||
</Card.Body>
|
||||
</Card>
|
||||
)
|
||||
|
|
|
@ -10,7 +10,6 @@ import { useFrontendConfig } from '../../common/frontend-config-context/use-fron
|
|||
import { AuthProviderType } from '../../../api/config/types'
|
||||
import { LocalLoginCardBody } from './local-login-card-body'
|
||||
import { LocalRegisterCardBody } from './register/local-register-card-body'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
|
||||
/**
|
||||
* Shows the card that processes local logins and registers.
|
||||
|
@ -29,10 +28,12 @@ export const LocalLoginCard: React.FC = () => {
|
|||
return (
|
||||
<Card>
|
||||
<LocalLoginCardBody />
|
||||
<ShowIf condition={frontendConfig.allowRegister}>
|
||||
{frontendConfig.allowRegister && (
|
||||
<>
|
||||
<hr className={'m-0'} />
|
||||
<LocalRegisterCardBody />
|
||||
</ShowIf>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import type { PropsWithDataCypressId } from '../../../../utils/cypress-attribute'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { Logger } from '../../../../utils/logger'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import { ProxyImageFrame } from '../../extensions/image/proxy-image-frame'
|
||||
import styles from './click-shield.module.scss'
|
||||
import type { Property } from 'csstype'
|
||||
|
@ -113,10 +112,16 @@ export const ClickShield: React.FC<ClickShieldProps> = ({
|
|||
[hoverIcon]
|
||||
)
|
||||
|
||||
if (showChildren) {
|
||||
return (
|
||||
<span className={containerClassName} {...cypressId(props['data-cypress-id'])}>
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={containerClassName} {...cypressId(props['data-cypress-id'])}>
|
||||
<ShowIf condition={showChildren}>{children}</ShowIf>
|
||||
<ShowIf condition={!showChildren}>
|
||||
<span className={`${styles['click-shield']} d-inline-block ratio ratio-16x9`} onClick={doShowChildren}>
|
||||
{previewBackground}
|
||||
<span className={`${styles['preview-hover']}`}>
|
||||
|
@ -126,7 +131,6 @@ export const ClickShield: React.FC<ClickShieldProps> = ({
|
|||
{icon}
|
||||
</span>
|
||||
</span>
|
||||
</ShowIf>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import { cypressId } from '../../utils/cypress-attribute'
|
||||
import { Logger } from '../../utils/logger'
|
||||
import { UiIcon } from '../common/icons/ui-icon'
|
||||
import { ShowIf } from '../common/show-if/show-if'
|
||||
import styles from './notifications.module.scss'
|
||||
import type { UiNotification } from './types'
|
||||
import { useUiNotifications } from './ui-notification-boundary'
|
||||
|
@ -106,9 +105,7 @@ export const UiNotificationToast: React.FC<UiNotificationProps> = ({ notificatio
|
|||
{...cypressId('notification-toast')}>
|
||||
<Toast.Header>
|
||||
<strong className='me-auto'>
|
||||
<ShowIf condition={!!notification.icon}>
|
||||
<UiIcon icon={notification.icon} className={'me-1'} />
|
||||
</ShowIf>
|
||||
{notification.icon !== undefined && <UiIcon icon={notification.icon} className={'me-1'} />}
|
||||
<Trans i18nKey={notification.titleI18nKey} tOptions={notification.titleI18nOptions} />
|
||||
</strong>
|
||||
<small>{formattedCreatedAtDate}</small>
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { getAccessTokenList } from '../../../api/tokens'
|
||||
import type { AccessToken } from '../../../api/tokens/types'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { useUiNotifications } from '../../notifications/ui-notification-boundary'
|
||||
import { AccessTokenCreationForm } from './access-token-creation-form/access-token-creation-form'
|
||||
import { AccessTokenListEntry } from './access-token-list-entry'
|
||||
|
@ -58,14 +57,10 @@ export const ProfileAccessTokens: React.FC = () => {
|
|||
<Trans i18nKey='profile.accessTokens.infoDev' />
|
||||
</p>
|
||||
<hr />
|
||||
<ShowIf condition={accessTokens.length === 0}>
|
||||
<Trans i18nKey='profile.accessTokens.noTokens' />
|
||||
</ShowIf>
|
||||
{accessTokens.length === 0 && <Trans i18nKey='profile.accessTokens.noTokens' />}
|
||||
<ListGroup>{tokensDom}</ListGroup>
|
||||
<hr />
|
||||
<ShowIf condition={accessTokens.length < 200}>
|
||||
<AccessTokenCreationForm onUpdateList={refreshAccessTokens} />
|
||||
</ShowIf>
|
||||
{accessTokens.length < 200 && <AccessTokenCreationForm onUpdateList={refreshAccessTokens} />}
|
||||
</Card.Body>
|
||||
</Card>
|
||||
)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
import { useFrontendConfig } from '../common/frontend-config-context/use-frontend-config'
|
||||
import { TranslatedExternalLink } from '../common/links/translated-external-link'
|
||||
import { ShowIf } from '../common/show-if/show-if'
|
||||
import React from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
|
||||
|
@ -16,21 +15,25 @@ export const RegisterInfos: React.FC = () => {
|
|||
useTranslation()
|
||||
const specialUrls = useFrontendConfig().specialUrls
|
||||
|
||||
if (specialUrls.termsOfUse === undefined && specialUrls.privacy === undefined) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<ShowIf condition={!!specialUrls.termsOfUse || !!specialUrls.privacy}>
|
||||
<>
|
||||
<Trans i18nKey='login.register.infoTermsPrivacy' />
|
||||
<ul>
|
||||
<ShowIf condition={!!specialUrls.termsOfUse}>
|
||||
{specialUrls.termsOfUse !== undefined && (
|
||||
<li>
|
||||
<TranslatedExternalLink i18nKey='appbar.help.legal.termsOfUse' href={specialUrls.termsOfUse ?? ''} />
|
||||
</li>
|
||||
</ShowIf>
|
||||
<ShowIf condition={!!specialUrls.privacy}>
|
||||
)}
|
||||
{specialUrls.privacy !== undefined && (
|
||||
<li>
|
||||
<TranslatedExternalLink i18nKey='appbar.help.legal.privacy' href={specialUrls.privacy ?? ''} />
|
||||
</li>
|
||||
</ShowIf>
|
||||
)}
|
||||
</ul>
|
||||
</ShowIf>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { TableOfContentsMarkdownExtension } from '../../../../extensions/essential-app-extensions/table-of-contents/table-of-contents-markdown-extension'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import { useExtensionEventEmitterHandler } from '../../../markdown-renderer/hooks/use-extension-event-emitter'
|
||||
import styles from './markdown-document.module.scss'
|
||||
import { WidthBasedTableOfContents } from './width-based-table-of-contents'
|
||||
|
@ -22,9 +21,7 @@ export const DocumentTocSidebar: React.FC<DocumentTocSidebarProps> = ({ width, b
|
|||
|
||||
return (
|
||||
<div className={styles.side}>
|
||||
<ShowIf condition={!!tocAst}>
|
||||
<WidthBasedTableOfContents tocAst={tocAst as TocAst} baseUrl={baseUrl} width={width} />
|
||||
</ShowIf>
|
||||
{tocAst !== undefined && <WidthBasedTableOfContents tocAst={tocAst} baseUrl={baseUrl} width={width} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { AsyncLoadingBoundary } from '../../../components/common/async-loading-boundary/async-loading-boundary'
|
||||
import { ShowIf } from '../../../components/common/show-if/show-if'
|
||||
import { WaitSpinner } from '../../../components/common/wait-spinner/wait-spinner'
|
||||
import type { CodeProps } from '../../../components/markdown-renderer/replace-components/code-block-component-replacer'
|
||||
import { useEffectWithCatch } from '../../../hooks/common/use-effect-with-catch'
|
||||
|
@ -49,9 +48,9 @@ export const AbcFrame: React.FC<CodeProps> = ({ code }) => {
|
|||
|
||||
return (
|
||||
<AsyncLoadingBoundary loading={loading || !abcLib} error={!!loadingError} componentName={'abc.js'}>
|
||||
<ShowIf condition={!!renderError}>
|
||||
{renderError !== undefined && (
|
||||
<TranslatedApplicationErrorAlert errorI18nKey={'editor.embeddings.abcJs.errorWhileRendering'} />
|
||||
</ShowIf>
|
||||
)}
|
||||
<div
|
||||
ref={container}
|
||||
className={`${styles['abcjs-score']} bg-white text-black svg-container`}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import fontStyles from '../../../../global-styles/variables.module.scss'
|
||||
import { AsyncLoadingBoundary } from '../../../components/common/async-loading-boundary/async-loading-boundary'
|
||||
import { ShowIf } from '../../../components/common/show-if/show-if'
|
||||
import type { CodeProps } from '../../../components/markdown-renderer/replace-components/code-block-component-replacer'
|
||||
import { useDarkModeState } from '../../../hooks/dark-mode/use-dark-mode-state'
|
||||
import { Logger } from '../../../utils/logger'
|
||||
|
@ -71,9 +70,7 @@ export const FlowChart: React.FC<CodeProps> = ({ code }) => {
|
|||
|
||||
return (
|
||||
<AsyncLoadingBoundary loading={loading || !flowchartLib} componentName={'flowchart.js'} error={!!libLoadingError}>
|
||||
<ShowIf condition={syntaxError}>
|
||||
<TranslatedApplicationErrorAlert errorI18nKey={'renderer.flowchart.invalidSyntax'} />
|
||||
</ShowIf>
|
||||
{syntaxError && <TranslatedApplicationErrorAlert errorI18nKey={'renderer.flowchart.invalidSyntax'} />}
|
||||
<div ref={diagramRef} {...testId('flowchart')} className={'text-center'} />
|
||||
</AsyncLoadingBoundary>
|
||||
)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { AsyncLoadingBoundary } from '../../../components/common/async-loading-boundary/async-loading-boundary'
|
||||
import { ShowIf } from '../../../components/common/show-if/show-if'
|
||||
import type { CodeProps } from '../../../components/markdown-renderer/replace-components/code-block-component-replacer'
|
||||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { Logger } from '../../../utils/logger'
|
||||
|
@ -59,9 +58,7 @@ export const GraphvizFrame: React.FC<CodeProps> = ({ code }) => {
|
|||
|
||||
return (
|
||||
<AsyncLoadingBoundary loading={isLibLoading || !graphvizImport} componentName={'graphviz'} error={libLoadingError}>
|
||||
<ShowIf condition={!!error}>
|
||||
<ApplicationErrorAlert className={'text-wrap'}>{error}</ApplicationErrorAlert>
|
||||
</ShowIf>
|
||||
{error !== undefined && <ApplicationErrorAlert className={'text-wrap'}>{error}</ApplicationErrorAlert>}
|
||||
<div className={'svg-container'} {...cypressId('graphviz')} ref={container} />
|
||||
</AsyncLoadingBoundary>
|
||||
)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../../../components/common/show-if/show-if'
|
||||
import type { CodeProps } from '../../../components/markdown-renderer/replace-components/code-block-component-replacer'
|
||||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { Logger } from '../../../utils/logger'
|
||||
|
@ -65,9 +64,7 @@ export const MermaidChart: React.FC<CodeProps> = ({ code }) => {
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<ShowIf condition={!!error}>
|
||||
<ApplicationErrorAlert className={'text-wrap'}>{error?.message}</ApplicationErrorAlert>
|
||||
</ShowIf>
|
||||
{error !== undefined && <ApplicationErrorAlert className={'text-wrap'}>{error?.message}</ApplicationErrorAlert>}
|
||||
<div
|
||||
{...cypressId('mermaid-frame')}
|
||||
className={`text-center ${styles['mermaid']} bg-dark text-black`}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { AsyncLoadingBoundary } from '../../../components/common/async-loading-boundary/async-loading-boundary'
|
||||
import { ShowIf } from '../../../components/common/show-if/show-if'
|
||||
import type { CodeProps } from '../../../components/markdown-renderer/replace-components/code-block-component-replacer'
|
||||
import { Logger } from '../../../utils/logger'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
|
@ -59,9 +58,9 @@ export const VegaLiteChart: React.FC<CodeProps> = ({ code }) => {
|
|||
|
||||
return (
|
||||
<AsyncLoadingBoundary loading={libLoading || !vegaEmbed} error={libLoadingError} componentName={'Vega Lite'}>
|
||||
<ShowIf condition={!!renderingError}>
|
||||
{renderingError !== undefined && (
|
||||
<TranslatedApplicationErrorAlert errorI18nKey={'renderer.vega-lite.errorJson'} />
|
||||
</ShowIf>
|
||||
)}
|
||||
<div className={'text-center'}>
|
||||
<div ref={diagramContainer} />
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue