Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1774: Move translations to translations file #1841

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions administration/src/bp-modules/ErrorHandler.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button, NonIdealState } from '@blueprintjs/core'
import React, { ReactElement } from 'react'
import { useTranslation } from 'react-i18next'

type ErrorHandlerProps = {
title?: string
Expand All @@ -11,13 +12,16 @@ const ErrorHandler = ({
refetch,
title = 'Ein Fehler ist aufgetreten.',
description,
}: ErrorHandlerProps): ReactElement => (
<NonIdealState
icon='error'
title={title}
description={description}
action={<Button onClick={() => refetch()}>Erneut Versuchen</Button>}
/>
)
}: ErrorHandlerProps): ReactElement => {
const { t } = useTranslation('errors')
return (
<NonIdealState
icon='error'
title={title}
description={description}
action={<Button onClick={() => refetch()}>{t('retry')}</Button>}
/>
)
}

export default ErrorHandler
20 changes: 12 additions & 8 deletions administration/src/bp-modules/NavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Alignment, Button, Navbar } from '@blueprintjs/core'
import React, { ReactElement, useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { NavLink } from 'react-router-dom'
import styled from 'styled-components'

Expand All @@ -21,6 +22,7 @@ type Props = {
}

const Navigation = ({ onSignOut }: Props): ReactElement => {
const { t } = useTranslation('misc')
const config = useContext(ProjectConfigContext)
const { region, role } = useContext(WhoAmIContext).me!
const canSeeProjectSettings =
Expand All @@ -31,7 +33,9 @@ const Navigation = ({ onSignOut }: Props): ReactElement => {
<Navbar.Group>
<Navbar.Heading>
<NavLink to='/' style={{ color: 'black', textDecoration: 'none', display: 'block' }}>
<div style={{ flexDirection: 'column' }}>{config.name} Verwaltung</div>
<div style={{ flexDirection: 'column' }}>
{config.name} {t('administration')}
</div>
{!region ? null : (
<span>
{region.prefix} {region.name} {`(${process.env.REACT_APP_VERSION})`}
Expand All @@ -44,41 +48,41 @@ const Navigation = ({ onSignOut }: Props): ReactElement => {
<>
{config.applicationFeature ? (
<NavLink to='/applications'>
<Button minimal icon='form' text='Eingehende Anträge' />
<Button minimal icon='form' text={t('inComingApplications')} />
</NavLink>
) : null}
{config.cardCreation ? (
<NavLink to='/cards'>
<Button minimal icon='id-number' text='Karten erstellen' />
<Button minimal icon='id-number' text={t('createCards')} />
</NavLink>
) : null}
</>
) : null}
{role === Role.ProjectAdmin || role === Role.RegionAdmin ? (
<>
<NavLink to='/users'>
<Button minimal icon='people' text='Benutzer verwalten' />
<Button minimal icon='people' text={t('manageUsers')} />
</NavLink>
{config.cardStatistics.enabled ? (
<NavLink to='/statistics'>
<Button minimal icon='stacked-chart' text='Statistiken' />
<Button minimal icon='stacked-chart' text={t('statistics')} />
</NavLink>
) : null}
</>
) : null}
{role === Role.RegionAdmin && config.applicationFeature ? (
<NavLink to='/region'>
<Button minimal icon='path-search' text='Region verwalten' />
<Button minimal icon='path-search' text={t('manageRegion')} />
</NavLink>
) : null}
{canSeeProjectSettings ? (
<NavLink to='/project'>
<Button minimal icon='projects' text='Projekt verwalten' />
<Button minimal icon='projects' text={t('manageProject')} />
</NavLink>
) : null}
{role === Role.ProjectStoreManager ? (
<NavLink to='/stores'>
<Button minimal icon='shop' text='Akzeptanzpartner verwalten' />
<Button minimal icon='shop' text={t('manageStores')} />
</NavLink>
) : null}
</Navbar.Group>
Expand Down
11 changes: 8 additions & 3 deletions administration/src/bp-modules/PasswordInput.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Button, InputGroup, InputGroupProps2, Label, Tooltip } from '@blueprintjs/core'
import { TFunction } from 'i18next'
import React, { ReactElement, useState } from 'react'
import { useTranslation } from 'react-i18next'

const ShowPasswordButton = ({ hidden, onClick }: { hidden: boolean; onClick: () => void }) => (
const ShowPasswordButton = ({ hidden, onClick, t }: { hidden: boolean; onClick: () => void; t: TFunction }) => (
<Tooltip
content={hidden ? 'Passwort anzeigen' : 'Passwort verstecken'}
content={hidden ? t('showPassword') : t('hidePassword')}
renderTarget={({ isOpen, ref, ...tooltipProps }) => (
<Button ref={ref} {...tooltipProps} minimal icon={hidden ? 'eye-open' : 'eye-off'} onClick={onClick} />
)}
Expand All @@ -18,6 +20,7 @@ const PasswordInput = ({
label: string
setValue: ((value: string) => void) | null
}): ReactElement => {
const { t } = useTranslation('misc')
const [passwordHidden, setPasswordHidden] = useState(true)
return (
<Label>
Expand All @@ -28,7 +31,9 @@ const PasswordInput = ({
type={passwordHidden ? 'password' : 'text'}
onChange={event => setValue?.(event.currentTarget.value)}
readOnly={setValue === null}
rightElement={<ShowPasswordButton hidden={passwordHidden} onClick={() => setPasswordHidden(!passwordHidden)} />}
rightElement={
<ShowPasswordButton hidden={passwordHidden} onClick={() => setPasswordHidden(!passwordHidden)} t={t} />
}
/>
</Label>
)
Expand Down
6 changes: 4 additions & 2 deletions administration/src/bp-modules/UserMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button, Divider, Menu, Popover } from '@blueprintjs/core'
import React, { ReactElement, useContext, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { NavLink, useNavigate } from 'react-router-dom'
import styled from 'styled-components'

Expand Down Expand Up @@ -41,6 +42,7 @@ const RoleInfo = styled.span`

const UserMenu = ({ onSignOut }: UserMenuProps): ReactElement => {
const { role, email } = useContext(WhoAmIContext).me!
const { t } = useTranslation('misc')
const [isOpen, setIsOpen] = useState<boolean>(false)
const navigate = useNavigate()
const signOutAndRedirect = () => {
Expand All @@ -52,9 +54,9 @@ const UserMenu = ({ onSignOut }: UserMenuProps): ReactElement => {
<RoleInfo>Rolle: {roleToText(role)}</RoleInfo>
<Divider style={{ margin: '4px 0px' }} />
<NavLink to='/user-settings'>
<MenuItem minimal icon='settings' text='Benutzereinstellungen' />
<MenuItem minimal icon='settings' text={t('userSettings')} />
</NavLink>
<MenuItem minimal icon='log-out' text='Logout' onClick={signOutAndRedirect} />
<MenuItem minimal icon='log-out' text={t('logout')} onClick={signOutAndRedirect} />
</MenuContent>
)
return (
Expand Down
32 changes: 17 additions & 15 deletions administration/src/bp-modules/applications/ApplicationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Tooltip,
} from '@blueprintjs/core'
import React, { ReactElement, memo, useContext, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled, { css } from 'styled-components'

import getMessageFromApolloError from '../../errors/getMessageFromApolloError'
Expand Down Expand Up @@ -164,116 +165,117 @@
onChange,
}: ApplicationCardProps) => {
const [isExpanded, setIsExpanded] = useState(false)
const { t } = useTranslation('applications')
const { createdDate: createdDateString, jsonValue, id, withdrawalDate, cardCreated } = application
const jsonField: JsonField<'Array'> = JSON.parse(jsonValue)
const config = useContext(ProjectConfigContext)
const baseUrl = `${getApiBaseUrl()}/application/${config.projectId}/${id}`
const appToaster = useAppToaster()
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false)
const [openNoteDialog, setOpenNoteDialog] = useState(false)
const [deleteApplication, { loading }] = useDeleteApplicationMutation({
onError: error => {
const { title } = getMessageFromApolloError(error)
appToaster?.show({ intent: 'danger', message: title })
},
onCompleted: ({ deleted }: { deleted: boolean }) => {
if (deleted) {
onDelete()
} else {
console.error('Delete operation returned false.')
appToaster?.show({ intent: 'danger', message: 'Etwas ist schief gelaufen.' })
appToaster?.show({ intent: 'danger', message: t('errors:unknown') })
}
},
})

const createCardQuery = useMemo(
() => `${config.applicationFeature?.applicationJsonToCardQuery(jsonField)}&applicationIdToMarkAsProcessed=${id}`,
[config.applicationFeature, jsonField, id]
)

const personalData = useMemo(
() => config.applicationFeature?.applicationJsonToPersonalData(jsonField),
[config.applicationFeature, jsonField]
)

return (
<ApplicationViewCard
title={
<div>
<Title>Antrag vom {formatDateWithTimezone(createdDateString, config.timezone)}&emsp;</Title>{' '}
<Title>
{t('applicationFrom')} {formatDateWithTimezone(createdDateString, config.timezone)}&emsp;
</Title>{' '}
{personalData && personalData.forenames !== undefined && personalData.surname !== undefined && (
<CardContentHint>
Name: {personalData.surname}, {personalData.forenames}
{t('name')}: {personalData.surname}, {personalData.forenames}
</CardContentHint>
)}
</div>
}
rightElement={<RightElement jsonField={jsonField} application={application} />}
elevation={1}
icon={withdrawalDate ? <Icon icon='warning-sign' intent='warning' /> : undefined}
collapseProps={{ isOpen: isExpanded, onToggle: () => setIsExpanded(!isExpanded), keepChildrenMounted: true }}
collapsible={!isSelectedForPrint}
$hideInPrintMode={!isSelectedForPrint}>
<SectionCard>
<SectionCardHeader>
<NoteDialogController
application={application}
isOpen={openNoteDialog}
onOpenNoteDialog={setOpenNoteDialog}
onChange={onChange}
/>

{!!withdrawalDate && (
<WithdrawAlert intent='warning'>
Der Antrag wurde vom Antragsteller am {formatDateWithTimezone(withdrawalDate, config.timezone)}{' '}
zurückgezogen. <br />
Bitte löschen Sie den Antrag zeitnah.
{t('withdrawalMessage', { withdrawalDate: formatDateWithTimezone(withdrawalDate, config.timezone) })}
<br />
{t('deleteApplicationSoonPrompt')}
</WithdrawAlert>
)}
</SectionCardHeader>
<JsonFieldView
jsonField={jsonField}
baseUrl={baseUrl}
key={0}
hierarchyIndex={0}
attachmentAccessible
expandedRoot={false}
/>
</SectionCard>
<SectionCard>
<VerificationsView verifications={application.verifications} />
</SectionCard>
<SectionCard>
<ButtonContainer>
<Tooltip
disabled={!!createCardQuery}
content='Es existiert kein passendes Mapping, um aus diesem Antrag das Kartenformular vollständig auszufüllen.'>
<Tooltip disabled={!!createCardQuery} content={t('incompleteMappingTooltip')}>
<PrintAwareAnchorButton
disabled={!createCardQuery}
href={createCardQuery ? `./cards/add${createCardQuery}` : undefined}
icon='id-number'
intent='primary'>
{cardCreated ? 'Karte erneut erstellen' : 'Karte erstellen'}
{cardCreated ? t('createCardAgain') : t('createCard')}
</PrintAwareAnchorButton>
</Tooltip>
<PrintAwareButton onClick={() => setDeleteDialogOpen(true)} intent='danger' icon='trash'>
Antrag löschen
{t('deleteApplication')}
</PrintAwareButton>
<PrintAwareButton onClick={() => printApplicationById(id)} intent='none' icon='print'>
PDF exportieren
{t('exportPdf')}
</PrintAwareButton>
<CollapseIcon icon='chevron-up' onClick={() => setIsExpanded(!isExpanded)} style={{ marginLeft: 'auto' }} />
</ButtonContainer>
<Alert
cancelButtonText='Abbrechen'
confirmButtonText='Antrag löschen'
cancelButtonText={t('cancel')}
confirmButtonText={t('deleteApplication')}
icon='trash'
intent='danger'
isOpen={deleteDialogOpen}
loading={loading}
onCancel={() => setDeleteDialogOpen(false)}
onConfirm={() => deleteApplication({ variables: { applicationId: application.id } })}>
<p>Möchten Sie den Antrag unwiderruflich löschen?</p>
<p>{t('deleteApplicationConfirmationPrompt')}</p>

Check notice on line 278 in administration/src/bp-modules/applications/ApplicationCard.tsx

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Complex Method

ApplicationCard decreases in cyclomatic complexity from 13 to 12, threshold = 10. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
</Alert>
</SectionCard>
</ApplicationViewCard>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { render } from '@testing-library/react'
import React from 'react'

import { renderWithTranslation } from '../../testing/render'
import ApplicationStatusBar from './ApplicationStatusBar'
import { Application } from './ApplicationsOverview'
import { barItems } from './constants'
Expand Down Expand Up @@ -71,7 +71,7 @@ const applications: Application[] = [
describe('ApplicationStatusBar', () => {
const setActiveBarItem = jest.fn()
it('Should show the correct count for all applications', () => {
const { getByTestId } = render(
const { getByTestId } = renderWithTranslation(
<ApplicationStatusBar
applications={applications}
setActiveBarItem={setActiveBarItem}
Expand All @@ -84,7 +84,7 @@ describe('ApplicationStatusBar', () => {
expect(allApplicationsCount).toHaveTextContent('4')
})
it('Should show the correct count for open applications', () => {
const { getByTestId } = render(
const { getByTestId } = renderWithTranslation(
<ApplicationStatusBar
applications={applications}
setActiveBarItem={setActiveBarItem}
Expand All @@ -97,7 +97,7 @@ describe('ApplicationStatusBar', () => {
expect(openApplicationsCount).toHaveTextContent('1')
})
it('Should show the correct count for withdrawed applications', () => {
const { getByTestId } = render(
const { getByTestId } = renderWithTranslation(
<ApplicationStatusBar
applications={applications}
setActiveBarItem={setActiveBarItem}
Expand All @@ -110,7 +110,7 @@ describe('ApplicationStatusBar', () => {
expect(withdrawedApplicationsCount).toHaveTextContent('1')
})
it('Should show the correct count for rejected applications', () => {
const { getByTestId } = render(
const { getByTestId } = renderWithTranslation(
<ApplicationStatusBar
applications={applications}
setActiveBarItem={setActiveBarItem}
Expand All @@ -123,7 +123,7 @@ describe('ApplicationStatusBar', () => {
expect(rejectedApplicationsCount).toHaveTextContent('0')
})
it('Should show the correct count for accepted applications', () => {
const { getByTestId } = render(
const { getByTestId } = renderWithTranslation(
<ApplicationStatusBar
applications={applications}
setActiveBarItem={setActiveBarItem}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { ReactElement } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'

import ApplicationStatusHelpButton from './ApplicationStatusBarHelpButton'
Expand Down Expand Up @@ -60,22 +61,25 @@ const ApplicationStatusBar = ({
activeBarItem,
barItems,
setActiveBarItem,
}: ApplicationStatusBarProps): ReactElement => (
<Container>
<Title>Status</Title>
<ApplicationStatusHelpButton />
<BarItemContainer>
{barItems.map(item => (
<ApplicationStatusBarItem
key={item.title}
count={getApplicationCount(applications, item.status)}
item={item}
setActiveBarItem={setActiveBarItem}
active={item === activeBarItem}
/>
))}
</BarItemContainer>
</Container>
)
}: ApplicationStatusBarProps): ReactElement => {
const { t } = useTranslation('applications')
return (
<Container>
<Title>{t('status')}</Title>
<ApplicationStatusHelpButton />
<BarItemContainer>
{barItems.map(item => (
<ApplicationStatusBarItem
key={item.title}
count={getApplicationCount(applications, item.status)}
item={item}
setActiveBarItem={setActiveBarItem}
active={item === activeBarItem}
/>
))}
</BarItemContainer>
</Container>
)
}

export default ApplicationStatusBar
Loading