Skip to content

Commit 9344cda

Browse files
authored
Merge pull request #1485 from navikt/feature/translations-filter-on-empty-rows
Feature/translations filter on empty rows
2 parents 79ddf76 + 042b8e5 commit 9344cda

13 files changed

+202
-45
lines changed

packages/bygger/cypress/e2e/form-translations.spec.cy.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe('Form translations', () => {
1212
);
1313
});
1414

15-
describe('When there are no unsaved translations', () => {
15+
describe('When there are no unsaved global translations translations', () => {
1616
beforeEach(() => {
1717
cy.intercept('GET', '/api/translations', (req) => req.reply([])).as('getGlobalTranslations');
1818
cy.visit('/forms/tst123456/oversettelser');
@@ -42,6 +42,23 @@ describe('Form translations', () => {
4242
cy.wait('@getGlobalTranslations');
4343
});
4444

45+
it('filters translation rows with missing translations', () => {
46+
cy.findByText('Gitar').should('be.visible');
47+
cy.findByText('Trommer').should('be.visible');
48+
cy.findByText('Piano').should('be.visible');
49+
cy.findByText('Trekkspill').should('be.visible');
50+
cy.findByRole('checkbox', { name: 'Vis kun manglende oversettelser' }).should('exist');
51+
cy.findByRole('checkbox', { name: 'Vis kun manglende oversettelser' }).click();
52+
cy.findByText('Gitar').should('not.exist');
53+
cy.findByText('Trommer').should('not.exist');
54+
cy.findByText('Piano').should('not.exist');
55+
cy.findByText('Trekkspill').should('not.exist');
56+
57+
// Partial translations should not be filtered out
58+
cy.findByText('Dine opplysninger').should('be.visible');
59+
cy.findByText('Ja').should('be.visible');
60+
});
61+
4562
it('updates existing translation, adds new translation and adds global override', () => {
4663
cy.intercept('POST', '/api/forms/tst123456/translations', (req) => req.reply(201, req.body)).as(
4764
'postTranslation',

packages/bygger/cypress/e2e/global-translations.spec.cy.ts

+13
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@ describe('Global translations', () => {
1111
});
1212

1313
describe('Skjematekster', () => {
14+
it('filters on rows with missing translations', () => {
15+
cy.findByText('Ny').should('be.visible');
16+
cy.findByText('Nyere').should('be.visible');
17+
cy.findByText('Abc').should('be.visible');
18+
cy.findByText('Hei').should('be.visible');
19+
cy.findByRole('checkbox', { name: 'Vis kun manglende oversettelser' }).should('exist');
20+
cy.findByRole('checkbox', { name: 'Vis kun manglende oversettelser' }).click();
21+
cy.findByText('Ny').should('not.exist');
22+
cy.findByText('Nyere').should('not.exist');
23+
cy.findByText('Abc').should('not.exist');
24+
cy.findByText('Hei').should('be.visible');
25+
});
26+
1427
it('does not update translations if no changes', () => {
1528
cy.findByRole('button', { name: 'Lagre' }).click();
1629
cy.findByText('Ingen endringer oppdaget. Oversettelser ble ikke lagret.').should('be.visible');

packages/bygger/cypress/fixtures/form123456-translations.json

+66
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,71 @@
5353
"en": "Hello",
5454
"changedAt": null,
5555
"changedBy": null
56+
},
57+
{
58+
"id": 6,
59+
"key": "Bor du i Norge?",
60+
"revision": 1,
61+
"globalTranslationId": null,
62+
"nb": "Bor du i Norge?",
63+
"nn": "Bor du i Noreg?",
64+
"en": "Do you live in Norway?",
65+
"changedAt": null,
66+
"changedBy": null
67+
},
68+
{
69+
"id": 7,
70+
"key": "Nav sender svar på søknad og annen kommunikasjon til din folkeregistrerte adresse. \n<br>\nDu kan <a href=\"https://www.skatteetaten.no/person/folkeregister/flytte/endre-postadresse/\" target=\"_blank\">sjekke og endre din folkeregistrerte adresse på skatteetatens nettsider (åpnes i et nytt vindu).</a>\nHvis du ønsker å motta kommunikasjon fra Nav på en annen adresse enn din folkeregistrerte adresse, kan du bruke lenken ovenfor til å oppgi en postadresse i Folkeregisteret.\nDu finner også papirskjema for å endre postadresse på samme siden hos Skatteetaten.",
71+
"revision": 4,
72+
"globalTranslationId": null,
73+
"nb": "Nav sender svar på søknad og annen kommunikasjon til din folkeregistrerte adresse. \n<br>\nDu kan <a href=\"https://www.skatteetaten.no/person/folkeregister/flytte/endre-postadresse/\" target=\"_blank\">sjekke og endre din folkeregistrerte adresse på skatteetatens nettsider (åpnes i et nytt vindu).</a>\nHvis du ønsker å motta kommunikasjon fra Nav på en annen adresse enn din folkeregistrerte adresse, kan du bruke lenken ovenfor til å oppgi en postadresse i Folkeregisteret.\nDu finner også papirskjema for å endre postadresse på samme siden hos Skatteetaten.",
74+
"nn": "Nav sender svar på søknad og annen kommunikasjon til din folkeregistrerte adresse. \n<br>\nDu kan <a href=\"https://www.skatteetaten.no/person/folkeregister/flytte/endre-postadresse/\" target=\"_blank\">sjekke og endre din folkeregistrerte adresse på skatteetatens nettsider (åpnes i et nytt vindu).</a>\nHvis du ønsker å motta kommunikasjon fra Nav på en annen adresse enn din folkeregistrerte adresse, kan du bruke lenken ovenfor til å oppgi en postadresse i Folkeregisteret.\nDu finner også papirskjema for å endre postadresse på samme siden hos Skatteetaten.",
75+
"en": "",
76+
"changedAt": null,
77+
"changedBy": null
78+
},
79+
{
80+
"id": 8,
81+
"key": "Gitar",
82+
"revision": 2,
83+
"globalTranslationId": null,
84+
"nb": "Gitar",
85+
"nn": "Gitar (nn)",
86+
"en": "Guitar",
87+
"changedAt": null,
88+
"changedBy": null
89+
},
90+
{
91+
"id": 9,
92+
"key": "Trommer",
93+
"revision": 1,
94+
"globalTranslationId": null,
95+
"nb": "Trommer",
96+
"nn": "Trommer (nn)",
97+
"en": "Drums",
98+
"changedAt": null,
99+
"changedBy": null
100+
},
101+
{
102+
"id": 10,
103+
"key": "Trekkspill",
104+
"revision": 1,
105+
"globalTranslationId": null,
106+
"nb": "Trekkspill",
107+
"nn": "Trekkspel",
108+
"en": "Accordion",
109+
"changedAt": null,
110+
"changedBy": null
111+
},
112+
{
113+
"id": 11,
114+
"key": "Piano",
115+
"revision": 1,
116+
"globalTranslationId": null,
117+
"nb": "Piano",
118+
"nn": "Piano (nn)",
119+
"en": "Piano (en)",
120+
"changedAt": null,
121+
"changedBy": null
56122
}
57123
]

packages/bygger/cypress/fixtures/formsApiGlobalTranslations.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"changedBy": "Testesen, Test",
88
"revision": 4,
99
"nb": "Ny",
10-
"nn": "Ny",
10+
"nn": "Ny (nn)",
1111
"en": "New",
1212
"publishedAt": null,
1313
"publishedBy": null

packages/bygger/src/translations/components/NewTranslationRow.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Table, TextField } from '@navikt/ds-react';
22
import { useEditGlobalTranslations } from '../../context/translations/EditGlobalTranslationsContext';
3-
import useTranslationTableStyles from './styles';
3+
import { useTranslationTableStyles } from './styles';
44

55
const NewTranslationRow = () => {
66
const { newTranslation, updateNewTranslation, errors } = useEditGlobalTranslations();

packages/bygger/src/translations/components/TranslationDisplayCell.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { PadlockLockedIcon } from '@navikt/aksel-icons';
22
import { Table } from '@navikt/ds-react';
33
import { InnerHtml, htmlUtils } from '@navikt/skjemadigitalisering-shared-components';
4-
import useTranslationTableStyles from './styles';
4+
import { useTranslationTableStyles } from './styles';
55

66
interface Props {
77
text?: string;

packages/bygger/src/translations/components/TranslationRow.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { FormsApiTranslation, formsApiTranslations, TranslationLang } from '@nav
44
import { useEffect, useMemo, useState } from 'react';
55
import { TranslationError } from '../../context/translations/utils/errorUtils';
66
import { getInputHeightInRows } from '../utils/translationsUtils';
7-
import useTranslationTableStyles from './styles';
87
import TranslationDisplayCell from './TranslationDisplayCell';
98
import TranslationInput from './TranslationInput';
9+
import { useTranslationTableStyles } from './styles';
1010

1111
interface Props<Translation extends FormsApiTranslation> {
1212
translation: Translation;

packages/bygger/src/translations/components/TranslationTable.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { SortState, Table } from '@navikt/ds-react';
22
import { SkeletonList } from '@navikt/skjemadigitalisering-shared-components';
33
import { ReactNode } from 'react';
4-
import useTranslationTableStyles from './styles';
4+
import { useTranslationTableStyles } from './styles';
55

66
const defaultColumns = [
77
{ key: 'nb', label: 'Bokmål' },
@@ -15,6 +15,7 @@ interface Props {
1515
sort?: SortState;
1616
onSortChange?: (sortkey: string) => void;
1717
loading?: boolean;
18+
stickyHeaderClassname?: string;
1819
children?: ReactNode[];
1920
}
2021

@@ -24,6 +25,7 @@ const TranslationTable = ({
2425
sort,
2526
onSortChange,
2627
loading = false,
28+
stickyHeaderClassname,
2729
children,
2830
}: Props) => {
2931
const styles = useTranslationTableStyles();
@@ -34,7 +36,7 @@ const TranslationTable = ({
3436

3537
return (
3638
<Table className={styles.table} sort={sort} onSortChange={onSortChange}>
37-
<Table.Header className={styles.header}>
39+
<Table.Header className={stickyHeaderClassname}>
3840
<Table.Row>
3941
{columns.map((column) => (
4042
<Table.ColumnHeader

packages/bygger/src/translations/components/UnusedTranslationRow.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Button, Table } from '@navikt/ds-react';
22
import { FormsApiTranslation, formsApiTranslations } from '@navikt/skjemadigitalisering-shared-domain';
33
import { useState } from 'react';
44
import TranslationDisplayCell from './TranslationDisplayCell';
5-
import useTranslationTableStyles from './styles';
5+
import { useTranslationTableStyles } from './styles';
66

77
interface Props {
88
translation: FormsApiTranslation;

packages/bygger/src/translations/components/UnusedTranslations.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ReadMore } from '@navikt/ds-react';
22
import { FormsApiTranslation } from '@navikt/skjemadigitalisering-shared-domain';
33
import TranslationTable, { defaultColumns } from './TranslationTable';
44
import UnusedTranslationRow from './UnusedTranslationRow';
5+
import { useStickyStyles } from './styles';
56

67
interface Props {
78
translations?: FormsApiTranslation[];
@@ -10,6 +11,7 @@ interface Props {
1011
}
1112

1213
const UnusedTranslations = ({ translations, onRemove, showKeys = false }: Props) => {
14+
const stickyStyles = useStickyStyles();
1315
const columns = showKeys ? [{ key: 'key', label: 'Nøkkel' }, ...defaultColumns] : defaultColumns;
1416

1517
if (!translations || translations.length === 0) {
@@ -18,7 +20,11 @@ const UnusedTranslations = ({ translations, onRemove, showKeys = false }: Props)
1820

1921
return (
2022
<ReadMore header={`Se alle ubrukte oversettelser (${translations.length})`}>
21-
<TranslationTable columns={columns} actionColumn={{ key: 'deleteButton', label: '' }}>
23+
<TranslationTable
24+
columns={columns}
25+
actionColumn={{ key: 'deleteButton', label: '' }}
26+
stickyHeaderClassname={stickyStyles.unusedTranslations}
27+
>
2228
{translations.map((translation) => (
2329
<UnusedTranslationRow
2430
key={translation.key}

packages/bygger/src/translations/components/styles.ts

+22-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
11
import { makeStyles } from '@navikt/skjemadigitalisering-shared-components';
22

3+
const sticky = {
4+
position: 'sticky',
5+
top: '0',
6+
backgroundColor: 'var(--a-bg-default)',
7+
zIndex: '10000',
8+
};
9+
const useStickyStyles = makeStyles({
10+
filterRow: {
11+
...sticky,
12+
top: '9.5rem',
13+
},
14+
unusedTranslations: {
15+
...sticky,
16+
top: '8.5rem',
17+
},
18+
mainTable: {
19+
...sticky,
20+
top: '12.5rem',
21+
},
22+
});
23+
324
const useTranslationTableStyles = makeStyles({
425
table: {
526
marginBottom: '4rem',
627
},
7-
header: {
8-
position: 'sticky',
9-
top: '8.5rem',
10-
backgroundColor: 'var(--a-bg-default)',
11-
zIndex: '10000',
12-
},
1328
column: {
1429
width: '12rem',
1530
maxWidth: '12rem',
@@ -28,4 +43,4 @@ const useTranslationTableStyles = makeStyles({
2843
},
2944
});
3045

31-
export default useTranslationTableStyles;
46+
export { useStickyStyles, useTranslationTableStyles };

packages/bygger/src/translations/form/FormTranslationsTable.tsx

+33-14
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1-
import { SortState } from '@navikt/ds-react';
1+
import { SortState, Switch } from '@navikt/ds-react';
22
import { listSort } from '@navikt/skjemadigitalisering-shared-components';
33
import { FormsApiFormTranslation } from '@navikt/skjemadigitalisering-shared-domain';
44
import { useMemo, useState } from 'react';
55
import { useEditFormTranslations } from '../../context/translations/EditFormTranslationsContext';
66
import TranslationRow from '../components/TranslationRow';
77
import TranslationTable from '../components/TranslationTable';
8+
import { useStickyStyles } from '../components/styles';
89

910
interface Props {
1011
translations: FormsApiFormTranslation[] | undefined;
1112
loading?: boolean;
1213
}
1314

1415
const FormTranslationsTable = ({ translations, loading = false }: Props) => {
16+
const [isFilterChecked, setIsFilterChecked] = useState(false);
1517
const [sortState, setSortState] = useState<SortState>();
1618
const { updateTranslation, errors, editState } = useEditFormTranslations();
19+
const stickyStyles = useStickyStyles();
1720

1821
const handleSort = (sortKey: string) => {
1922
setSortState((currentState) => {
@@ -25,22 +28,38 @@ const FormTranslationsTable = ({ translations, loading = false }: Props) => {
2528
});
2629
};
2730

31+
const filteredRows = useMemo<FormsApiFormTranslation[] | undefined>(() => {
32+
return isFilterChecked ? translations?.filter((row) => !row.nn || !row.en) : translations;
33+
}, [isFilterChecked, translations]);
34+
2835
const sortedRows = useMemo<FormsApiFormTranslation[] | undefined>(() => {
29-
return translations?.slice().sort(listSort.getLocaleComparator(sortState?.orderBy, sortState?.direction));
30-
}, [translations, sortState?.orderBy, sortState?.direction]);
36+
return filteredRows?.slice().sort(listSort.getLocaleComparator(sortState?.orderBy, sortState?.direction));
37+
}, [filteredRows, sortState?.orderBy, sortState?.direction]);
3138

3239
return (
33-
<TranslationTable loading={loading || !sortedRows} sort={sortState} onSortChange={handleSort}>
34-
{sortedRows?.map((row) => (
35-
<TranslationRow
36-
key={row.key}
37-
translation={row}
38-
updateTranslation={updateTranslation}
39-
errors={errors}
40-
editState={editState}
41-
/>
42-
))}
43-
</TranslationTable>
40+
<>
41+
<div className={stickyStyles.filterRow}>
42+
<Switch checked={isFilterChecked} onChange={(event) => setIsFilterChecked(event.target.checked)}>
43+
Vis kun manglende oversettelser
44+
</Switch>
45+
</div>
46+
<TranslationTable
47+
loading={loading || !sortedRows}
48+
sort={sortState}
49+
onSortChange={handleSort}
50+
stickyHeaderClassname={stickyStyles.mainTable}
51+
>
52+
{sortedRows?.map((row) => (
53+
<TranslationRow
54+
key={row.key}
55+
translation={row}
56+
updateTranslation={updateTranslation}
57+
errors={errors}
58+
editState={editState}
59+
/>
60+
))}
61+
</TranslationTable>
62+
</>
4463
);
4564
};
4665

0 commit comments

Comments
 (0)