Skip to content

Commit

Permalink
Grid component (#1118)
Browse files Browse the repository at this point in the history
Co-authored-by: Ole Martin Handeland <git@olemartin.org>
Co-authored-by: Magnus Revheim Martinsen <mrmartinsen.96@gmail.com>
  • Loading branch information
3 people authored Apr 26, 2023
1 parent a8fd222 commit a94c75a
Show file tree
Hide file tree
Showing 48 changed files with 936 additions and 88 deletions.
75 changes: 73 additions & 2 deletions schemas/json/layout/layout.schema.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"type": "string",
"title": "Type",
"description": "The component type.",
"enum": ["AddressComponent", "AttachmentList", "Button", "Checkboxes", "Custom", "Datepicker", "Dropdown", "FileUpload", "FileUploadWithTag", "Group", "Header", "Image", "Input", "InstanceInformation", "InstantiationButton", "Likert","List", "MultipleSelect", "NavigationButtons", "NavigationBar", "Panel", "Paragraph", "PrintButton", "RadioButtons", "Summary", "TextArea"]
"enum": ["AddressComponent", "AttachmentList", "Button", "Checkboxes", "Custom", "Datepicker", "Dropdown", "FileUpload", "FileUploadWithTag", "Grid", "Group", "Header", "Image", "Input", "InstanceInformation", "InstantiationButton", "Likert","List", "MultipleSelect", "NavigationButtons", "NavigationBar", "Panel", "Paragraph", "PrintButton", "RadioButtons", "Summary", "TextArea"]
},
"required": {
"title": "Required",
Expand Down Expand Up @@ -130,6 +130,7 @@
{ "if": {"properties": {"type": { "const": "Dropdown"}}}, "then": { "$ref": "#/definitions/selectionComponents"}},
{ "if": {"properties": {"type": { "const": "FileUpload"}}}, "then": { "$ref": "#/definitions/fileUploadComponent"}},
{ "if": {"properties": {"type": { "const": "FileUploadWithTag"}}}, "then": { "$ref": "#/definitions/fileUploadWithTagComponent"}},
{ "if": {"properties": {"type": { "const": "Grid"}}}, "then": { "$ref": "#/definitions/gridComponent"}},
{ "if": {"properties": {"type": { "const": "Group"}}}, "then": { "$ref": "#/definitions/groupComponent"}},
{ "if": {"properties": {"type": { "const": "Image"}}}, "then": { "$ref": "#/definitions/imageComponent"}},
{ "if": {"properties": {"type": { "const": "Input"}}}, "then": { "$ref": "#/definitions/inputComponent"}},
Expand Down Expand Up @@ -452,6 +453,71 @@
}
}
},
"gridComponent": {
"properties": {
"rows": {
"title": "Rows",
"description": "An array of rows to be rendered in the grid.",
"type": "array",
"items": {
"$ref": "#/definitions/gridRow"
}
}
},
"required": ["rows"]
},
"gridRow": {
"properties": {
"header": {
"title": "Header?",
"description": "A boolean indicating if the row should be a header row",
"type": "boolean",
"default": false
},
"readOnly": {
"title": "Read only?",
"description": "A boolean indicating if the row should be a read only row (yellow background)",
"type": "boolean",
"default": false
},
"cells": {
"title": "Grid row cells",
"description": "An array of cells to be rendered in the row",
"type": "array",
"items": {
"anyOf": [
{ "$ref": "#/definitions/gridCellText" },
{ "$ref": "#/definitions/gridCellComponent" },
{ "$ref": "#/definitions/tableColumnOptions" },
{ "type": "null", "title": "Empty cell" }
]
}
}
},
"required": ["cells"]
},
"gridCellText": {
"properties": {
"text": {
"title": "Text",
"description": "The text or text resource ID to be rendered in the cell",
"type": "string"
}
},
"$ref": "#/definitions/tableColumnOptions",
"required": ["text"]
},
"gridCellComponent": {
"properties": {
"component": {
"title": "Component ID",
"description": "The ID of the component to be rendered in the cell",
"type": "string"
}
},
"$ref": "#/definitions/tableColumnOptions",
"required": ["component"]
},
"groupComponent": {
"properties": {
"children": {
Expand Down Expand Up @@ -626,7 +692,12 @@
"description": "Width of cell in % or 'auto'. Defaults to 'auto'",
"type": "string",
"pattern": "^([0-9]{1,2}%|100%|auto)$"
},
}
},
"$ref": "#/definitions/tableColumnTextOptions"
},
"tableColumnTextOptions": {
"properties": {
"alignText": {
"title": "Align Text",
"description": "Choose text alignment between 'left', 'center', or 'right' for text in table cells. Defaults to 'left' for text and 'right' for numbers.",
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useCommaSeparatedOptionsToText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { ISelectionComponent } from 'src/layout/layout';
export function useCommaSeparatedOptionsToText(component: ISelectionComponent, value: string) {
const textResources = useAppSelector((state) => state.textResources.resources);
const optionList = useOptionList(component);
const split = value.split(',');
const split = value.split(',').filter((value) => !!value.trim());
const out: { [key: string]: string } = {};
split?.forEach((part) => {
const textKey = optionList.find((option) => option.value === part)?.label || '';
Expand Down
4 changes: 4 additions & 0 deletions src/layout/Address/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ export class Address extends FormComponent<'AddressComponent'> {
const data = this.useDisplayData(targetNode);
return <SummaryItemSimple formDataAsString={data} />;
}

canRenderInTable(): boolean {
return false;
}
}
4 changes: 4 additions & 0 deletions src/layout/AttachmentList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ export class AttachmentList extends PresentationComponent<'AttachmentList'> {
renderWithLabel(): boolean {
return false;
}

canRenderInTable(): boolean {
return false;
}
}
16 changes: 13 additions & 3 deletions src/layout/Checkboxes/CheckboxesContainerComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export const CheckboxContainerComponent = ({
language,
handleDataChange,
getTextResource,
getTextResourceAsString,
overrideDisplay,
}: ICheckboxContainerProps) => {
const {
id,
Expand Down Expand Up @@ -103,6 +105,8 @@ export const CheckboxContainerComponent = ({
</span>
);

const hideLabel = overrideDisplay?.renderedInTable === true && calculatedOptions.length === 1;

return fetchingOptions ? (
<AltinnSpinner />
) : (
Expand All @@ -115,9 +119,14 @@ export const CheckboxContainerComponent = ({
compact={false}
disabled={readOnly}
onChange={(values) => handleChange(values)}
legend={labelText}
legend={overrideDisplay?.renderLegend === false ? null : labelText}
description={textResourceBindings?.description && getTextResource(textResourceBindings.description)}
error={!isValid}
fieldSetProps={{
'aria-label': overrideDisplay?.renderedInTable
? getTextResourceAsString(textResourceBindings?.title)
: undefined,
}}
helpText={textResourceBindings?.help && getTextResource(textResourceBindings.help)}
variant={
shouldUseRowLayout({
Expand All @@ -131,9 +140,10 @@ export const CheckboxContainerComponent = ({
name: option.value,
checkboxId: `${id}-${option.label.replace(/\s/g, '-')}`,
checked: selected.includes(option.value),
label: getTextResource(option.label),
hideLabel,
label: hideLabel ? getTextResourceAsString(option.label) : getTextResource(option.label),
description: getTextResource(option.description),
helpText: getTextResource(option.helpText),
helpText: option.helpText && getTextResource(option.helpText),
}))}
/>
</div>
Expand Down
5 changes: 2 additions & 3 deletions src/layout/Checkboxes/MultipleChoiceSummary.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from 'react';

import { render as rtlRender } from '@testing-library/react';

import { MultipleChoiceSummary } from 'src/layout/Checkboxes/MultipleChoiceSummary';
import { renderWithProviders } from 'src/testUtils';
import type { IMultipleChoiceSummaryProps } from 'src/layout/Checkboxes/MultipleChoiceSummary';

describe('MultipleChoiceSummary', () => {
Expand All @@ -17,7 +16,7 @@ function render(props: Partial<IMultipleChoiceSummaryProps> = {}) {
formData: { 'some-key': 'This is a text', 'some-other-key': 'This is another text' },
};

return rtlRender(
return renderWithProviders(
<MultipleChoiceSummary
{...defaultProps}
{...props}
Expand Down
48 changes: 33 additions & 15 deletions src/layout/Checkboxes/MultipleChoiceSummary.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React from 'react';

import { Grid, List, ListItem, ListItemText, makeStyles } from '@material-ui/core';
import { Grid, List, ListItem, ListItemText, makeStyles, Typography } from '@material-ui/core';

import { useAppSelector } from 'src/hooks/useAppSelector';
import { getLanguageFromKey } from 'src/language/sharedLanguage';

export interface IMultipleChoiceSummaryProps {
formData: { [key: string]: string };
Expand All @@ -22,31 +25,46 @@ const useStyles = makeStyles({
fontSize: '1.125rem',
},
},
emptyField: {
fontStyle: 'italic',
fontSize: '1rem',
lineHeight: 1.6875,
},
});

export function MultipleChoiceSummary({ formData }: IMultipleChoiceSummaryProps) {
const classes = useStyles();
const language = useAppSelector((state) => state.language.language);

return (
<Grid
item
xs={12}
data-testid={'multiple-choice-summary'}
>
<List classes={{ root: classes.list }}>
{Object.keys(formData).map((key) => (
<ListItem
key={key}
classes={{ root: classes.listItem }}
>
<ListItemText
id={key}
primaryTypographyProps={{ classes: { root: classes.data } }}
primary={formData[key]}
/>
</ListItem>
))}
</List>
{Object.keys(formData).length === 0 ? (
<Typography
variant='body1'
className={classes.emptyField}
>
{getLanguageFromKey('general.empty_summary', language || {})}
</Typography>
) : (
<List classes={{ root: classes.list }}>
{Object.keys(formData).map((key) => (
<ListItem
key={key}
classes={{ root: classes.listItem }}
>
<ListItemText
id={key}
primaryTypographyProps={{ classes: { root: classes.data } }}
primary={formData[key]}
/>
</ListItem>
))}
</List>
)}
</Grid>
);
}
15 changes: 14 additions & 1 deletion src/layout/Datepicker/DatepickerComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,15 @@ class AltinnMomentUtils extends MomentUtils {
// We dont use the built-in validation for the 3rd party component, so it is always empty string
const emptyString = '';

export function DatepickerComponent({ node, language, formData, handleDataChange, isValid }: IDatepickerProps) {
export function DatepickerComponent({
node,
language,
formData,
handleDataChange,
isValid,
overrideDisplay,
getTextResourceAsString,
}: IDatepickerProps) {
const classes = useStyles();
const { minDate, maxDate, format, timeStamp = true, readOnly, required, id, textResourceBindings } = node.item;

Expand Down Expand Up @@ -183,6 +191,11 @@ export function DatepickerComponent({ node, language, formData, handleDataChange
'aria-describedby': `description-${id}`,
}),
}}
inputProps={{
'aria-label': overrideDisplay?.renderedInTable
? getTextResourceAsString(textResourceBindings?.title)
: undefined,
}}
DialogProps={{ className: classes.dialog }}
PopoverProps={{ className: classes.dialog }}
FormHelperTextProps={{
Expand Down
6 changes: 5 additions & 1 deletion src/layout/Dropdown/DropdownComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ export function DropdownComponent({
formData,
handleDataChange,
isValid,
overrideDisplay,
getTextResourceAsString,
}: IDropdownProps) {
const { optionsId, preselectedOptionIndex, id, readOnly, mapping, source } = node.item;
const { optionsId, preselectedOptionIndex, id, readOnly, mapping, source, textResourceBindings } = node.item;
const language = useAppSelector((state) => state.language.language);
const textResources = useAppSelector((state) => state.textResources.resources);
const options = useGetOptions({ optionsId, mapping, source })?.filter(duplicateOptionFilter);
Expand Down Expand Up @@ -75,6 +76,9 @@ export function DropdownComponent({
value: option.value,
})) || []
}
aria-label={
overrideDisplay?.renderedInTable ? getTextResourceAsString(textResourceBindings?.title) : undefined
}
/>
)}
</>
Expand Down
4 changes: 4 additions & 0 deletions src/layout/FileUpload/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ export class FileUpload extends FormComponent<'FileUpload'> {
renderSummary({ targetNode }: SummaryRendererProps<'FileUpload'>): JSX.Element | null {
return <AttachmentSummaryComponent targetNode={targetNode} />;
}

canRenderInTable(): boolean {
return false;
}
}
4 changes: 4 additions & 0 deletions src/layout/FileUploadWithTag/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ export class FileUploadWithTag extends FormComponent<'FileUploadWithTag'> {
renderSummary({ targetNode }: SummaryRendererProps<'FileUploadWithTag'>): JSX.Element | null {
return <AttachmentWithTagSummaryComponent targetNode={targetNode} />;
}

canRenderInTable(): boolean {
return false;
}
}
Loading

0 comments on commit a94c75a

Please sign in to comment.