Skip to content

Commit

Permalink
Adds utility functions for grabbing attribute types and precisions
Browse files Browse the repository at this point in the history
Mirrors CODAP's  precision for numeric attributes
  • Loading branch information
eireland committed Mar 27, 2024
1 parent 066afa0 commit fe7a7cd
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 11 deletions.
7 changes: 6 additions & 1 deletion src/components/flat-table.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { ITableProps, IValues } from "../types";
import { DraggableTableContainer, DraggagleTableHeader } from "./draggable-table-tags";
import { getAttrPrecisions, getAttrTypes } from "../utils/utils";

import css from "./tables.scss";

Expand All @@ -14,6 +15,8 @@ export const FlatTable = (props: IFlatProps) => {
const {className} = collectionClasses[0];

const titles = collection.attrs.map(attr => attr.title);
const precisions = getAttrPrecisions(collections);
const attrTypes = getAttrTypes(collections);
const orderedItems = items.map(item => {
const orderedItem: IValues = {};
titles.forEach(title => {
Expand Down Expand Up @@ -45,7 +48,9 @@ export const FlatTable = (props: IFlatProps) => {
</tr>
{orderedItems.map((item, index) => {
return (
<tr key={`${index}-${item.id}`}>{mapCellsFromValues(collection.id, `row-${index}`, item)}</tr>
<tr key={`${index}-${item.id}`}>
{mapCellsFromValues(collection.id, `row-${index}`, item, precisions, attrTypes)}
</tr>
);
})}
</tbody>
Expand Down
9 changes: 7 additions & 2 deletions src/components/landscape-view.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { ICollection, IProcessedCaseObj, ITableProps } from "../types";
import { DraggagleTableHeader } from "./draggable-table-tags";
import { getAttrPrecisions, getAttrTypes } from "../utils/utils";

import css from "./tables.scss";

Expand All @@ -12,6 +13,8 @@ export const LandscapeView = (props: ITableProps) => {
const firstRowValues = parentColl.cases.map(caseObj => caseObj.values);
const valueCount = getValueLength(firstRowValues);
const className = getClassName(parentColl.cases[0]);
const precisions = getAttrPrecisions(collections);
const attrTypes = getAttrTypes(collections);
return (
<>
{showHeaders &&
Expand All @@ -22,7 +25,7 @@ export const LandscapeView = (props: ITableProps) => {
{firstRowValues.map(values => mapHeadersFromValues(parentColl.id, "first-row", values))}
</tr>
<tr className={css[className]}>
{firstRowValues.map(values => mapCellsFromValues(parentColl.id, "first-row", values))}
{firstRowValues.map(values => mapCellsFromValues(parentColl.id, "first-row", values, precisions, attrTypes))}
</tr>
<tr className={css[className]}>
{parentColl.cases.map((caseObj) => {
Expand All @@ -46,6 +49,8 @@ export const LandscapeView = (props: ITableProps) => {
const renderColFromCaseObj = (collection: ICollection, caseObj: IProcessedCaseObj, index?: number) => {
const {children, values} = caseObj;
const isFirstIndex = index === 0;
const precisions = getAttrPrecisions(collections);
const attrTypes = getAttrTypes(collections);
if (!children.length) {
const className = getClassName(caseObj);
return (
Expand All @@ -60,7 +65,7 @@ export const LandscapeView = (props: ITableProps) => {
{mapHeadersFromValues(collection.id, `first-row-${index}`, values)}
</tr>
}
<tr>{mapCellsFromValues(collection.id, `row-${index}`, values)}</tr>
<tr>{mapCellsFromValues(collection.id, `row-${index}`, values, precisions, attrTypes)}</tr>
</>
);
} else {
Expand Down
22 changes: 19 additions & 3 deletions src/components/nested-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,27 @@ export const NestedTable = (props: IProps) => {
);
};

const mapCellsFromValues = (collectionId: number, rowKey: string, values: IValues, isParent?: boolean,
resizeCounter?: number, parentLevel?: number) => {
const mapCellsFromValues = (collectionId: number, rowKey: string, values: IValues,
precisions: Record<string, number>, attrTypes: Record<string, string | undefined | null>,
isParent?: boolean, resizeCounter?: number, parentLevel?: number) => {
return Object.keys(values).map((key, index) => {
const val = values[key];
const val = attrTypes[key] === "numeric" ? parseFloat(values[key]) : values[key];
if (typeof val === "string" || typeof val === "number") {
if (typeof val === "number") {
const precision = precisions[key] || 2; // default to 2 decimal places
return (
<DraggagleTableData
collectionId={collectionId}
attrTitle={key}
key={`${rowKey}-${val}-${index}}`}
isParent={isParent}
resizeCounter={resizeCounter}
parentLevel={parentLevel}
>
{val.toFixed(precision)}
</DraggagleTableData>
);
}
return (
<DraggagleTableData
collectionId={collectionId}
Expand Down
14 changes: 11 additions & 3 deletions src/components/portrait-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ import React, { useEffect, useMemo, useRef, useState } from "react";
import { ICollection, IProcessedCaseObj, ITableProps } from "../types";
import { DraggableTableContainer, DroppableTableData, DroppableTableHeader } from "./draggable-table-tags";
import { TableScrollTopContext, useTableScrollTop } from "../hooks/useTableScrollTop";
import { getAttrPrecisions, getAttrTypes } from "../utils/utils";

import css from "./tables.scss";

export type PortraitViewRowProps = {collectionId: number, caseObj: IProcessedCaseObj, index?: null|number,
precisions: Record<string, number>,
attrTypes: Record<string, string | undefined | null>,
isParent: boolean, resizeCounter: number, parentLevel?: number}
& ITableProps;

export const PortraitViewRow = (props: PortraitViewRowProps) => {
const {paddingStyle, mapCellsFromValues, mapHeadersFromValues, showHeaders,
const {paddingStyle, mapCellsFromValues, mapHeadersFromValues, showHeaders, precisions, attrTypes,
getClassName, collectionId, caseObj, index, isParent, resizeCounter, parentLevel} = props;

const {children, values} = caseObj;

if (!children.length) {
return (
<tr>{mapCellsFromValues(collectionId, `row-${index}`, values)}</tr>
<tr>{mapCellsFromValues(collectionId, `row-${index}`, values, precisions, attrTypes)}</tr>
);
} else {
return (
Expand All @@ -31,7 +34,8 @@ export const PortraitViewRow = (props: PortraitViewRowProps) => {
</tr>
}
<tr className={`${css[getClassName(caseObj)]} parent-row`}>
{mapCellsFromValues(collectionId, `parent-row-${index}`, values, isParent, resizeCounter, parentLevel)}
{mapCellsFromValues(collectionId, `parent-row-${index}`, values, precisions, attrTypes,
isParent, resizeCounter, parentLevel)}
<DroppableTableData collectionId={collectionId} style={paddingStyle}>
<DraggableTableContainer collectionId={collectionId}>
<table style={paddingStyle} className={`${css.subTable} ${css[getClassName(children[0])]}`}>
Expand Down Expand Up @@ -104,6 +108,8 @@ export const PortraitView = (props: ITableProps) => {
const {className} = collectionClasses[0];
const firstRowValues = parentColl.cases.map(caseObj => caseObj.values);
const valueCount = getValueLength(firstRowValues);
const precisions = getAttrPrecisions(collections);
const attrTypes = getAttrTypes(collections);

return (
<DraggableTableContainer>
Expand All @@ -122,6 +128,8 @@ export const PortraitView = (props: ITableProps) => {
collectionId={caseObj.collection.id}
caseObj={caseObj}
index={index}
precisions={precisions}
attrTypes={attrTypes}
isParent={true}
resizeCounter={resizeCounter}
parentLevel={0}
Expand Down
5 changes: 3 additions & 2 deletions src/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ export interface ITableProps {
getClassName: (caseObj: IProcessedCaseObj) => string,
selectedDataSet: IDataSet,
collections: Array<ICollection>,
mapCellsFromValues: (collectionId: number, rowKey: string, values: IValues, isParent?: boolean,
resizeCounter?: number, parentLevel?: number) => void,
mapCellsFromValues: (collectionId: number, rowKey: string, values: IValues, precisions: Record<string, number>,
attrTypes: Record<string, string | undefined | null>, isParent?: boolean, resizeCounter?: number,
parentLevel?: number) => void,
mapHeadersFromValues: (collectionId: number, rowKey: string, values: IValues) => void,
getValueLength: (firstRow: Array<IValues>) => number
paddingStyle: Record<string, string>
Expand Down
29 changes: 29 additions & 0 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ICollections } from "../types";

const getAllAttributesFromCollections = (collections: ICollections[]) => {
const attrArray: any[] = [];
collections.forEach((collection: any) => {
attrArray.push(...collection.attrs);
});
return attrArray;
};

export const getAttrPrecisions = (collections: any) => {
const attrs = getAllAttributesFromCollections(collections);
const precisions = attrs.reduce((acc: Record<string, number>, attr: any) => {
const numPrecision = parseInt(attr.precision, 10);
acc[attr.name] = isNaN(numPrecision) ? 2 : numPrecision;
return acc;
}, {});
return precisions;
};

export const getAttrTypes = (collections: any) => {
const attrs = getAllAttributesFromCollections(collections);
const attrTypes = attrs.reduce(
(acc: Record<string, string | null | undefined>, attr: any) => {
acc[attr.name] = attr.type || null;
return acc;
}, {});
return attrTypes;
};

0 comments on commit fe7a7cd

Please sign in to comment.