Skip to content
Draft
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
23 changes: 23 additions & 0 deletions src/codegen/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,29 @@ const common = {
),
ITableColumnFormatting: () => new CG.obj().additionalProperties(CG.common('ITableColumnProperties')),
ITableColumnProperties: () =>
new CG.obj(
new CG.prop(
'width',
new CG.str()
.optional({ default: 'auto' })
.setTitle('Width')
.setDescription("Width of cell in % or 'auto'. Defaults to 'auto'")
.setPattern(/^([0-9]{1,2}%|100%|auto)$/),
),
new CG.prop('alignText', CG.common('ITableColumnsAlignText').optional()),
new CG.prop('textOverflow', CG.common('ITableColumnsTextOverflow').optional()),
)
.setTitle('Column options')
.setDescription('Options for the row/column')
.addExample({
width: 'auto',
alignText: 'left',
textOverflow: {
lineWrap: true,
maxHeight: 2,
},
}),
ITableColumnPropertiesWithHidden: () =>
new CG.obj(
new CG.prop(
'width',
Expand Down
4 changes: 4 additions & 0 deletions src/language/texts/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,10 @@ export function en() {
'config_error.group_no_deletion_strategy': 'When you have set group, you must also set deletionStrategy.',
'config_error.soft_delete_no_checked': 'When you have set deletionStrategy to soft, you must also set "checked".',
'config_error.hard_delete_with_checked': 'When you have set deletionStrategy to hard, you cannot set "checked".',
'config_error.grid_diff_cell_columns':
'There is a difference in number of cells({0}) on row {1} and the number of columns({2}). Make sure the rows have correct number of cells({2}).',
'config_error.grid_column_option_cell':
'You have a columnOption configuration on both cell and columns property. Please use the column property instead.',
'version_error.version_mismatch': 'Version mismatch',
'version_error.version_mismatch_message':
'This version of the app frontend is not compatible with the version of the backend libraries you are using. Update to the latest version of the packages and try again.',
Expand Down
5 changes: 5 additions & 0 deletions src/language/texts/nb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,11 @@ export function nb() {
'config_error.group_no_deletion_strategy': 'Når du har satt group må du også sette deletionStrategy.',
'config_error.soft_delete_no_checked': 'Når du har satt deletionStrategy til soft må du også sette "checked".',
'config_error.hard_delete_with_checked': 'Når du har satt deletionStrategy til hard kan du ikke sette "checked".',
'config_error.grid_diff_cell_columns':
'Det er forskjell i antall celler({0}) på rad {1} og antall kolonner({2}). Sørg for at alle rader har korrekt antall celler({2}).',
'config_error.grid_column_option_cell':
'"columnOption"-konfigurasjon er spesifisert både på "cell" og på "columns" egenskapene. Vennligst bruk "columns" egenskapen.',

'version_error.version_mismatch': 'Versjonsfeil',
'version_error.version_mismatch_message':
'Denne versjonen av app frontend er ikke kompatibel med den versjonen av backend-bibliotekene du bruker. Oppdater til nyeste versjon av pakkene og prøv igjen.',
Expand Down
4 changes: 4 additions & 0 deletions src/language/texts/nn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ export function nn() {
'config_error.group_no_deletion_strategy': 'Når du har sett group, må du også setje deletionStrategy.',
'config_error.soft_delete_no_checked': 'Når du har sett deletionStrategy til soft, må du også setje checked.',
'config_error.hard_delete_with_checked': 'Når du har sett deletionStrategy til hard, kan du ikkje setje checked.',
'config_error.grid_diff_cell_columns':
'Det er forskjell i talet på celler({0}) på rad {1} og talet på kolonnar({2}). Sørg for at alle rader har korrekt tal på celler({2}).',
'config_error.grid_column_option_cell':
'"columnOption"-konfigurasjon er spesifisert både på "cell" og på "columns" eigenskapane. Ver vennleg og bruk "columns" eigenskapen.',
'version_error.version_mismatch': 'Versjonsfeil',
'version_error.version_mismatch_message':
'Denne versjonen av app frontend er ikkje kompatibel med den versjonen av backend-biblioteka du brukar. Oppdater til nyaste versjon av pakkane og prøv igjen.',
Expand Down
41 changes: 33 additions & 8 deletions src/layout/Grid/GridComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,17 @@ import { useIsHidden } from 'src/utils/layout/hidden';
import { useLabel } from 'src/utils/layout/useLabel';
import { useItemFor, useItemWhenType } from 'src/utils/layout/useNodeItem';
import type { PropsFromGenericComponent } from 'src/layout';
import type { GridCell, GridRow, ITableColumnFormatting, ITableColumnProperties } from 'src/layout/common.generated';
import type {
GridCell,
GridRow,
ITableColumnFormatting,
ITableColumnProperties,
ITableColumnPropertiesWithHidden,
} from 'src/layout/common.generated';

export function RenderGrid(props: PropsFromGenericComponent<'Grid'>) {
const { baseComponentId } = props;
const { rows, textResourceBindings, labelSettings } = useItemWhenType(baseComponentId, 'Grid');
const { rows, textResourceBindings, labelSettings, columns } = useItemWhenType(baseComponentId, 'Grid');
const { title, description, help } = textResourceBindings ?? {};
const columnSettings: ITableColumnFormatting = {};
const isMobile = useIsMobile();
Expand Down Expand Up @@ -68,6 +74,7 @@ export function RenderGrid(props: PropsFromGenericComponent<'Grid'>) {
)}
<GridRowsRenderer
rows={rows}
columns={columns}
isNested={isNested}
mutableColumnSettings={columnSettings}
/>
Expand All @@ -78,12 +85,13 @@ export function RenderGrid(props: PropsFromGenericComponent<'Grid'>) {

interface GridRowsProps {
rows: GridRow[];
columns?: ITableColumnProperties[] | undefined;
extraCells?: GridCell[];
isNested: boolean;
mutableColumnSettings: ITableColumnFormatting;
}

export function GridRowsRenderer({ rows, extraCells = [], isNested, mutableColumnSettings }: GridRowsProps) {
export function GridRowsRenderer({ rows, columns, extraCells = [], isNested, mutableColumnSettings }: GridRowsProps) {
const batches: { type: 'header' | 'body'; rows: GridRow[] }[] = [];

for (const row of rows) {
Expand All @@ -106,6 +114,7 @@ export function GridRowsRenderer({ rows, extraCells = [], isNested, mutableColum
{batch.rows.map((row, rowIdx) => (
<GridRowRenderer
key={rowIdx}
columns={columns}
row={{ ...row, cells: [...row.cells, ...extraCells] }}
isNested={isNested}
mutableColumnSettings={mutableColumnSettings}
Expand All @@ -120,9 +129,10 @@ export function GridRowsRenderer({ rows, extraCells = [], isNested, mutableColum

interface GridRowProps extends Omit<GridRowsProps, 'rows'> {
row: GridRow;
columns?: ITableColumnProperties[] | undefined;
}

function GridRowRenderer({ row, isNested, mutableColumnSettings }: GridRowProps) {
function GridRowRenderer({ row, columns, isNested, mutableColumnSettings }: GridRowProps) {
const rowHidden = useIsGridRowHidden(row);
if (rowHidden) {
return null;
Expand All @@ -137,14 +147,17 @@ function GridRowRenderer({ row, isNested, mutableColumnSettings }: GridRowProps)
[css.fullWidthCellFirst]: isFirst && !isNested,
[css.fullWidthCellLast]: isLast && !isNested,
});

if (row.header && cell && 'columnOptions' in cell && cell.columnOptions) {
// eslint-disable-next-line react-compiler/react-compiler
mutableColumnSettings[cellIdx] = cell.columnOptions;
}

if (cell && columns && columns[cellIdx]) {
mutableColumnSettings[cellIdx] = { ...mutableColumnSettings[cellIdx], ...columns[cellIdx] }; //TODO: På sikt fjerne muligheten til å konfigurere på celle nivå.
}

if (isGridCellText(cell) || isGridCellLabelFrom(cell)) {
let textCellSettings: ITableColumnProperties = mutableColumnSettings[cellIdx]
let textCellSettings: ITableColumnPropertiesWithHidden = mutableColumnSettings[cellIdx]
? structuredClone(mutableColumnSettings[cellIdx])
: {};
textCellSettings = { ...textCellSettings, ...cell };
Expand Down Expand Up @@ -202,7 +215,7 @@ function GridRowRenderer({ row, isNested, mutableColumnSettings }: GridRowProps)

interface CellProps {
className?: string;
columnStyleOptions?: ITableColumnProperties;
columnStyleOptions?: ITableColumnPropertiesWithHidden;
isHeader?: boolean;
rowReadOnly?: boolean;
}
Expand All @@ -229,6 +242,10 @@ function CellWithComponent({
const isHidden = useIsHidden(baseComponentId);
const CellComponent = isHeader ? Table.HeaderCell : Table.Cell;

if (columnStyleOptions?.hidden === true) {
return;
}

if (!isHidden) {
const columnStyles = columnStyleOptions && getColumnStyles(columnStyleOptions);
return (
Expand Down Expand Up @@ -257,6 +274,10 @@ function CellWithText({ children, className, columnStyleOptions, help, isHeader
const { elementAsString } = useLanguage();
const CellComponent = isHeader ? Table.HeaderCell : Table.Cell;

if (columnStyleOptions?.hidden === true) {
return;
}

return (
<CellComponent
className={cn(css.tableCellFormatting, className)}
Expand Down Expand Up @@ -290,14 +311,18 @@ function CellWithLabel({ className, columnStyleOptions, labelFrom, isHeader = fa
const help = trb && 'help' in trb ? trb.help : undefined;
const description = trb && 'description' in trb && typeof trb.description === 'string' ? trb.description : undefined;
const CellComponent = isHeader ? Table.HeaderCell : Table.Cell;
const labelId = useIndexedId(labelFrom);
if (columnStyleOptions?.hidden === true) {
return;
}

return (
<CellComponent
className={cn(css.tableCellFormatting, className)}
style={columnStyles}
>
<LabelContent
id={useIndexedId(labelFrom)}
id={labelId}
label={title}
required={required}
help={help}
Expand Down
39 changes: 39 additions & 0 deletions src/layout/Grid/GridLayoutValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useEffect } from 'react';
import type { JSX } from 'react';

import { useLanguage } from 'src/features/language/useLanguage';
import { NodesInternal } from 'src/utils/layout/NodesContext';
import type { NodeValidationProps } from 'src/layout/layout';

export function GridLayoutValidator(props: NodeValidationProps<'Grid'>): JSX.Element | null {
const { intermediateItem, externalItem } = props;
const rows = externalItem?.rows;
const columns = externalItem?.columns;

const { langAsString } = useLanguage();
const addError = NodesInternal.useAddError();

useEffect(() => {
let error: string | null = null;

if (Array.isArray(rows)) {
for (const [i, row] of rows.entries()) {
if (Array.isArray(row?.cells) && Array.isArray(columns) && row.cells.length !== columns?.length) {
error = langAsString(`config_error.grid_diff_cell_columns`, [row.cells.length, i + 1, columns?.length]);
}
for (const [_, cell] of row.cells.entries()) {
if (cell?.columnOptions && columns) {
error = langAsString('config_error.grid_column_option_cell');
}
}
}
}

if (error) {
addError(error, intermediateItem.id, 'node');
window.logErrorOnce(`Validation error for '${intermediateItem.id}': ${error}`);
}
}, [addError, columns, columns?.length, intermediateItem.id, langAsString, rows]);

return null;
}
1 change: 1 addition & 0 deletions src/layout/Grid/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const Config = new CG.component({
),
);
})
.addProperty(new CG.prop('columns', new CG.arr(CG.common('ITableColumnPropertiesWithHidden')).optional()))
.addProperty(new CG.prop('rows', CG.common('GridRows')))
.extends(CG.common('LabeledComponentProps'))
.extendTextResources(CG.common('TRBLabel'));
24 changes: 22 additions & 2 deletions src/layout/Grid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import type { ErrorObject } from 'ajv';
import { claimGridRowsChildren } from 'src/layout/Grid/claimGridRowsChildren';
import { GridDef } from 'src/layout/Grid/config.def.generated';
import { RenderGrid } from 'src/layout/Grid/GridComponent';
import { GridLayoutValidator } from 'src/layout/Grid/GridLayoutValidator';
import { GridSummary } from 'src/layout/Grid/GridSummary';
import { GridSummaryComponent } from 'src/layout/Grid/GridSummaryComponent';
import { EmptyChildrenBoundary } from 'src/layout/Summary2/isEmpty/EmptyChildrenContext';
import type { PropsFromGenericComponent } from 'src/layout';
import type { CompExternalExact } from 'src/layout/layout';
import type { ChildClaimerProps, SummaryRendererProps } from 'src/layout/LayoutComponent';
import type { CompExternalExact, NodeValidationProps } from 'src/layout/layout';
import type { ChildClaimerProps, ExprResolver, SummaryRendererProps } from 'src/layout/LayoutComponent';
import type { Summary2Props } from 'src/layout/Summary2/SummaryComponent2/types';

export class Grid extends GridDef {
Expand Down Expand Up @@ -41,6 +42,25 @@ export class Grid extends GridDef {
claimGridRowsChildren(props, props.item.rows);
}

evalExpressions(props: ExprResolver<'Grid'>) {
const { item, evalBool } = props;

if (item.columns) {
for (const column in item.columns) {
item.columns[column].hidden = evalBool(item.columns[column].hidden, false);
}
}

return {
...this.evalDefaultExpressions(props),
columns: item.columns ? item.columns : undefined,
};
}

renderLayoutValidators(props: NodeValidationProps<'Grid'>): JSX.Element | null {
return <GridLayoutValidator {...props} />;
}

/**
* Override layout validation to validate grid cells individually
*/
Expand Down
2 changes: 1 addition & 1 deletion src/layout/RepeatingGroup/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export const Config = new CG.component({
),
),
)
.extends(CG.common('ITableColumnProperties'))
.extends(CG.common('ITableColumnPropertiesWithHidden'))
.exportAs('IGroupColumnFormatting'),
)
.addExample({
Expand Down
Loading