From 008fcb9dd8a3f8b2c639fa403567158138bcc360 Mon Sep 17 00:00:00 2001 From: Sven van de Scheur Date: Mon, 8 Apr 2024 15:21:43 +0200 Subject: [PATCH] :bug: - fix: various issues while implementing library --- src/components/data/datagrid/datagrid.scss | 3 +- src/components/data/datagrid/datagrid.tsx | 94 +++++++++------ src/components/form/form/form.tsx | 8 +- src/components/form/select/select.tsx | 4 +- src/components/toolbar/toolbar.tsx | 8 +- src/lib/data/attributedata.ts | 22 ++-- src/style/tokens/base.scss | 2 +- src/templates/list/list.tsx | 127 +++++++++++++++++---- 8 files changed, 189 insertions(+), 79 deletions(-) diff --git a/src/components/data/datagrid/datagrid.scss b/src/components/data/datagrid/datagrid.scss index fd3687bf..037806ec 100644 --- a/src/components/data/datagrid/datagrid.scss +++ b/src/components/data/datagrid/datagrid.scss @@ -11,7 +11,6 @@ } &__caption { - padding: var(--spacing-v) var(--spacing-h); text-align: start; } @@ -70,7 +69,7 @@ top: 50%; transform: translate(-50%, -50%); width: 100%; - z-index: 1; + z-index: 1000; .mykn-input { width: 100%; diff --git a/src/components/data/datagrid/datagrid.tsx b/src/components/data/datagrid/datagrid.tsx index a579341b..255bd6b4 100644 --- a/src/components/data/datagrid/datagrid.tsx +++ b/src/components/data/datagrid/datagrid.tsx @@ -6,7 +6,6 @@ import { SerializedFormData, TypedField, formatMessage, - isPrimitive, serializeForm, typedFieldByFields, useIntl, @@ -110,6 +109,9 @@ export type DataGridProps = { attributeData: DataGridProps["objectList"][number], ) => void; + /** Gets called when a row value is edited. */ + onChange?: (event: React.ChangeEvent) => void; + /** Gets called when a row value is edited. */ onEdit?: (rowData: SerializedFormData) => void; @@ -148,10 +150,11 @@ const getRenderableFields = ( fields: Array, objectList: AttributeData[], urlFields: string[], + editable: DataGridProps["editable"], ): TypedField[] => - typedFieldByFields(fields, objectList).filter( - (f) => !urlFields.includes(String(f.name)), - ); + typedFieldByFields(fields, objectList, { + editable: Boolean(editable), + }).filter((f) => !urlFields.includes(String(f.name))); /** * A subset of `PaginatorProps` that act as aliases. @@ -176,7 +179,7 @@ export const DataGrid: React.FC = ({ boolProps, objectList, fields = objectList?.length ? Object.keys(objectList[0]) : [], - editable = Boolean(fields.find((f) => !isPrimitive(f) && f.editable)), + editable = undefined, paginatorProps, showPaginator = Boolean(paginatorProps), pProps, @@ -187,6 +190,7 @@ export const DataGrid: React.FC = ({ urlFields = DEFAULT_URL_FIELDS, labelSelect, labelSelectAll, + onChange, onEdit, onSelect, onSelectionChange, @@ -214,12 +218,6 @@ export const DataGrid: React.FC = ({ [string, "ASC" | "DESC"] | undefined >(); - // Trigger onSelectionChange when selectedState changes. - useEffect(() => { - const dirty = selectedState && selected !== selectedState; - dirty && onSelectionChange?.(selectedState as AttributeData[]); - }, [selectedState]); - // Update selectedState when selected prop changes. useEffect(() => { selected && setSelectedState(selected); @@ -232,7 +230,12 @@ export const DataGrid: React.FC = ({ } }, [sort]); - const renderableFields = getRenderableFields(fields, objectList, urlFields); + const renderableFields = getRenderableFields( + fields, + objectList, + urlFields, + editable, + ); const sortField = sortState?.[0]; const sortDirection = sortState?.[1]; const titleId = title ? `${id}-caption` : undefined; @@ -253,20 +256,22 @@ export const DataGrid: React.FC = ({ const value = allSelected ? [] : renderableRows; setSelectedState(value); onSelect?.(value, !allSelected); + onSelectionChange?.(value); }; const handleSelect = (attributeData: AttributeData) => { const currentlySelected = selectedState || []; + const isAttributeDataCurrentlySelected = currentlySelected.includes(attributeData); - setSelectedState( - isAttributeDataCurrentlySelected - ? [...currentlySelected].filter((a) => a !== attributeData) - : [...currentlySelected, attributeData], - ); + const newSelectedState = isAttributeDataCurrentlySelected + ? [...currentlySelected].filter((a) => a !== attributeData) + : [...currentlySelected, attributeData]; + setSelectedState(newSelectedState); onSelect?.([attributeData], !isAttributeDataCurrentlySelected); + onSelectionChange?.(newSelectedState); }; /** @@ -337,12 +342,12 @@ export const DataGrid: React.FC = ({ amountSelected={selectedState?.length || 0} count={count || 0} dataGridId={id} - editable={editable} + editable={Boolean(renderableFields.find((f) => f.editable))} editingRow={editingState[0]} editingFieldIndex={editingState[1]} - fields={fields} handleSelect={handleSelect} labelSelect={labelSelect || ""} + onChange={onChange} onClick={onClick} onEdit={onEdit} page={page || 1} @@ -350,7 +355,7 @@ export const DataGrid: React.FC = ({ renderableRows={renderableRows} setEditingState={setEditingState} selectable={selectable} - selectedRows={selected || []} + selectedRows={selectedState || []} sortDirection={sortDirection} sortField={sortField} urlFields={urlFields} @@ -458,9 +463,9 @@ export type DataGridBodyProps = { editable: boolean; editingRow: AttributeData | null; editingFieldIndex: number | null; - fields: Array; handleSelect: (attributeData: AttributeData) => void; labelSelect: string; + onChange: DataGridProps["onChange"]; onClick: DataGridProps["onClick"]; onEdit: DataGridProps["onEdit"]; page: number; @@ -488,9 +493,9 @@ export const DataGridBody: React.FC = ({ editable, editingRow, editingFieldIndex, - fields, handleSelect, labelSelect, + onChange, onClick, onEdit, page, @@ -545,8 +550,9 @@ export const DataGridBody: React.FC = ({ editingFieldIndex === renderableFields.indexOf(field) } field={field} - fields={fields} + renderableFields={renderableFields} urlFields={urlFields} + onChange={onChange} onClick={(e, rowData) => { if (editable) { setEditingState([rowData, renderableFields.indexOf(field)]); @@ -675,8 +681,9 @@ export type DataGridContentCellProps = { dataGridId: string; rowData: AttributeData; field: TypedField; - fields: DataGridProps["fields"]; + renderableFields: TypedField[]; urlFields: DataGridProps["urlFields"]; + onChange: DataGridProps["onChange"]; onClick: DataGridProps["onClick"]; onEdit: DataGridProps["onEdit"]; }; @@ -694,9 +701,10 @@ export const DataGridContentCell: React.FC = ({ isEditingRow, isEditingField, field, - fields = [], + renderableFields = [], rowData, urlFields = DEFAULT_URL_FIELDS, + onChange, onClick, onEdit, }) => { @@ -704,7 +712,6 @@ export const DataGridContentCell: React.FC = ({ const fieldEditable = typeof field.editable === "boolean" ? field.editable : editable; - const renderableFields = getRenderableFields(fields, [rowData], urlFields); const fieldIndex = renderableFields.findIndex((f) => f.name === field.name); const urlField = urlFields.find((f) => rowData[f]); const rowUrl = urlField ? rowData[urlField] : null; @@ -753,9 +760,15 @@ export const DataGridContentCell: React.FC = ({ value={(value || "").toString()} form={`${dataGridId}-editable-form`} required={true} - onChange={() => setPristine(false)} + onChange={(e: React.ChangeEvent) => { + setPristine(false); + onChange?.(e); + }} onBlur={(e: React.FocusEvent) => { - const data = serializeForm(e.target.form as HTMLFormElement, true); + const data = Object.assign( + rowData, + serializeForm(e.target.form as HTMLFormElement, true), + ); !pristine && onEdit?.(data); }} /> @@ -784,15 +797,20 @@ export const DataGridContentCell: React.FC = ({ /** * Renders the value according to Value component */ - const renderValue = () => ( - - ); + const renderValue = () => { + // Support label from select + const label = field.options?.find((o) => o.value === value)?.label; + + return ( + + ); + }; return ( = ({ )} aria-description={field2Caption(field.name)} > + {isEditingRow && !isEditingField && renderHiddenInput()} {link && ( onClick?.(e, rowData)}> )} - {isEditingRow && !isEditingField && renderHiddenInput()} {isEditingField && renderFormControl()} {!isEditingField && fieldEditable && renderButton()} {!isEditingField && !fieldEditable && renderValue()} diff --git a/src/components/form/form/form.tsx b/src/components/form/form/form.tsx index 65c49f72..d7568e51 100644 --- a/src/components/form/form/form.tsx +++ b/src/components/form/form/form.tsx @@ -16,7 +16,7 @@ import { forceArray } from "../../../lib/format/array"; import { ucFirst } from "../../../lib/format/string"; import { useIntl } from "../../../lib/i18n/useIntl"; import { Button } from "../../button"; -import { Toolbar, ToolbarItem } from "../../toolbar"; +import { Toolbar, ToolbarItem, ToolbarProps } from "../../toolbar"; import { ErrorMessage } from "../errormessage"; import { FormControl } from "../formcontrol"; import { InputProps } from "../input"; @@ -51,6 +51,9 @@ export type FormProps = React.ComponentProps<"form"> & { /** Whether to show the form actions. */ showActions?: boolean; + /** Props to pass to Toolbar. */ + toolbarProps?: Partial; + /** The submit form label. */ labelSubmit?: string; @@ -90,6 +93,7 @@ export type FormProps = React.ComponentProps<"form"> & { * @param onChange * @param onSubmit * @param showActions + * @param toolbarProps * @param useTypedResults * @param validate * @param validateOnChange @@ -110,6 +114,7 @@ export const Form: React.FC = ({ onChange, onSubmit, showActions = true, + toolbarProps, useTypedResults = false, validate, validateOnChange = false, @@ -237,6 +242,7 @@ export const Form: React.FC = ({ align={secondaryActions.length ? "space-between" : "end"} variant={"transparent"} items={secondaryActions} + {...toolbarProps} >