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:
Philip Molares 2023-10-30 12:23:24 +01:00
parent 8884bbb428
commit f701f8d05f
52 changed files with 239 additions and 352 deletions

View file

@ -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>

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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

View file

@ -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>
)
}

View file

@ -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,25 +65,27 @@ 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}
onHide={onHide}
animation={true}
{...testId('commonModal')}
dialogClassName={concatCssClasses(additionalClasses)}
size={modalSize}>
<Modal.Header closeButton={!!showCloseButton}>
<Modal.Title>
<UiIcon icon={titleIcon} nbsp={true} />
{titleElement}
</Modal.Title>
{additionalTitleElement ?? <Fragment />}
</Modal.Header>
{children}
</Modal>
</ShowIf>
<Modal
{...cypressId(props)}
show={show}
onHide={onHide}
animation={true}
{...testId('commonModal')}
dialogClassName={concatCssClasses(additionalClasses)}
size={modalSize}>
<Modal.Header closeButton={!!showCloseButton}>
<Modal.Title>
<UiIcon icon={titleIcon} nbsp={true} />
{titleElement}
</Modal.Title>
{additionalTitleElement ?? <Fragment />}
</Modal.Header>
{children}
</Modal>
)
}

View file

@ -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>

View file

@ -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])

View file

@ -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}>
<PagerItem key={0} index={0} onClick={setPageIndex} />
<Pagination.Ellipsis disabled />
</ShowIf>
{correctedLowerPageIndex > 0 && (
<>
<PagerItem key={0} index={0} onClick={setPageIndex} />
<Pagination.Ellipsis disabled />
</>
)}
{paginationItemsBefore}
<Pagination.Item active>{correctedPageIndex + 1}</Pagination.Item>
{paginationItemsAfter}
<ShowIf condition={correctedUpperPageIndex < lastPageIndex}>
<Pagination.Ellipsis disabled />
<PagerItem key={lastPageIndex} index={lastPageIndex} onClick={setPageIndex} />
</ShowIf>
{correctedUpperPageIndex < lastPageIndex && (
<>
<Pagination.Ellipsis disabled />
<PagerItem key={lastPageIndex} index={lastPageIndex} onClick={setPageIndex} />
</>
)}
</Pagination>
)
}

View file

@ -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')}

View file

@ -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>
`;

View file

@ -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()
})
})

View file

@ -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
}

View file

@ -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>
)
}

View file

@ -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,15 +35,13 @@ 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}`}
icon={IconPencil}
className={'text-primary text-decoration-none mx-1'}
title={linkTitle}
/>
</ShowIf>
<InternalLink
text={''}
href={`/n/${noteDetails.primaryAddress}`}
icon={IconPencil}
className={'text-primary text-decoration-none mx-1'}
title={linkTitle}
/>
</span>
</div>
<div className={'col-md'}>&nbsp;</div>

View file

@ -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,41 +37,43 @@ 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 />
<ItalicButton />
<UnderlineButton />
<StrikethroughButton />
<SubscriptButton />
<SuperscriptButton />
<HighlightButton />
</ButtonGroup>
<ButtonGroup className={'mx-1 flex-wrap'}>
<HeaderLevelButton />
<CodeFenceButton />
<QuotesButton />
<UnorderedListButton />
<OrderedListButton />
<CheckListButton />
</ButtonGroup>
<ButtonGroup className={'mx-1 flex-wrap'}>
<LinkButton />
<ImageLinkButton />
<UploadImageButton />
</ButtonGroup>
<ButtonGroup className={'mx-1 flex-wrap'}>
<TablePickerButton />
<HorizontalLineButton />
<CollapsibleBlockButton />
<CommentButton />
<Suspense fallback={<Fragment />}>
<EmojiPickerButton />
</Suspense>
</ButtonGroup>
</ButtonToolbar>
</ShowIf>
<ButtonToolbar className={concatCssClasses(styles.toolbar, 'my-1')}>
<ButtonGroup className={'mx-1 flex-wrap'}>
<BoldButton />
<ItalicButton />
<UnderlineButton />
<StrikethroughButton />
<SubscriptButton />
<SuperscriptButton />
<HighlightButton />
</ButtonGroup>
<ButtonGroup className={'mx-1 flex-wrap'}>
<HeaderLevelButton />
<CodeFenceButton />
<QuotesButton />
<UnorderedListButton />
<OrderedListButton />
<CheckListButton />
</ButtonGroup>
<ButtonGroup className={'mx-1 flex-wrap'}>
<LinkButton />
<ImageLinkButton />
<UploadImageButton />
</ButtonGroup>
<ButtonGroup className={'mx-1 flex-wrap'}>
<TablePickerButton />
<HorizontalLineButton />
<CollapsibleBlockButton />
<CommentButton />
<Suspense fallback={<Fragment />}>
<EmojiPickerButton />
</Suspense>
</ButtonGroup>
</ButtonToolbar>
)
}

View file

@ -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>
)

View file

@ -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>

View file

@ -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} />

View file

@ -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'}

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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>
)
}

View file

@ -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' />

View file

@ -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}>
<Trans i18nKey={'editor.modal.shareLink.slidesDescription'} />
<NoteUrlField type={LinkType.SLIDESHOW} />
</ShowIf>
<ShowIf condition={noteFrontmatter.type === NoteType.DOCUMENT}>
<Trans i18nKey={'editor.modal.shareLink.viewOnlyDescription'} />
<NoteUrlField type={LinkType.DOCUMENT} />
</ShowIf>
{noteFrontmatter.type === NoteType.SLIDE && (
<>
<Trans i18nKey={'editor.modal.shareLink.slidesDescription'} />
<NoteUrlField type={LinkType.SLIDESHOW} />
</>
)}
{noteFrontmatter.type === NoteType.DOCUMENT && (
<>
<Trans i18nKey={'editor.modal.shareLink.viewOnlyDescription'} />
<NoteUrlField type={LinkType.DOCUMENT} />
</>
)}
</Modal.Body>
</CommonModal>
)

View file

@ -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>

View file

@ -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>

View file

@ -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>
)

View file

@ -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>
)
}

View file

@ -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>

View file

@ -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}>
<ModifierKey />
<span> + </span>
</ShowIf>
{showModifierKey && (
<>
<ModifierKey />
<span> + </span>
</>
)}
<ShowIf condition={showAltKey}>
<AltKey />
<span> + </span>
</ShowIf>
{showAltKey && (
<>
<AltKey />
<span> + </span>
</>
)}
<kbd>{functionKeyCode.toUpperCase()}</kbd>
</span>

View file

@ -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>

View file

@ -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}>
<Dropdown.Divider />
<DeleteNoteItem onConfirm={onDeleteNote} noteTitle={title} />
</ShowIf>
{userExists && (
<>
<Dropdown.Divider />
<DeleteNoteItem onConfirm={onDeleteNote} noteTitle={title} />
</>
)}
</Dropdown.Menu>
</Dropdown>
)

View file

@ -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>

View file

@ -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}

View file

@ -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>
<Link href={loginLink} passHref={true}>
<Button title={buttonTitle} {...cypressId('sign-in-button')} variant={variant || 'success'} {...props}>
<Trans i18nKey='login.signIn' />
</Button>
</Link>
)
}

View file

@ -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>
)
}

View file

@ -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>
)

View file

@ -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>
)

View file

@ -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>
)

View file

@ -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}>
<hr className={'m-0'} />
<LocalRegisterCardBody />
</ShowIf>
{frontendConfig.allowRegister && (
<>
<hr className={'m-0'} />
<LocalRegisterCardBody />
</>
)}
</Card>
)
}

View file

@ -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,20 +112,25 @@ 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']}`}>
<span>
<Trans i18nKey={'renderer.clickShield.previewHoverText'} values={hoverTextTranslationValues} />
</span>
{icon}
<span className={`${styles['click-shield']} d-inline-block ratio ratio-16x9`} onClick={doShowChildren}>
{previewBackground}
<span className={`${styles['preview-hover']}`}>
<span>
<Trans i18nKey={'renderer.clickShield.previewHoverText'} values={hoverTextTranslationValues} />
</span>
{icon}
</span>
</ShowIf>
</span>
</span>
)
}

View file

@ -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>

View file

@ -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>
)

View file

@ -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>
</>
)
}

View file

@ -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>
)
}

View file

@ -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`}

View file

@ -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>
)

View file

@ -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>
)

View file

@ -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`}

View file

@ -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>