merge feature/tables-split

This commit is contained in:
Chika 2021-09-01 09:38:16 +03:00
parent 9fdb540ede
commit 9439c39f5b
11 changed files with 148 additions and 72 deletions

View File

@ -6,7 +6,7 @@ import {
withValue,
} from 'client/hocs/Calculation';
import { ElementType } from 'core/types/Calculation/Store/elements';
import { omit } from 'lodash';
import { pick } from 'lodash';
import elementsActions from './elements/actions';
import elementsComponents from './elements/components';
import elementsComputedValues from './elements/computedValues';
@ -23,7 +23,7 @@ export function buildElement(elementName, elementProps = {}) {
case ElementType.Table: {
return withTable(Component)({
name: elementName,
...omit(tables[elementName], ['columns', 'rows', 'options']),
...pick(tables[elementName], ['options', 'callbacks', 'params']),
});
}
case ElementType.Action: {

View File

@ -14,7 +14,7 @@ const { PERIODS_NUMBER } = valuesConstants;
const columns: TableColumn[] = [
{
name: 'paymentRelation',
title: 'Соотношение платежа',
title: '% платежа',
Component: InputNumber,
props: {
min: '0.01',
@ -124,8 +124,10 @@ const callbacks: TableColumnCallbacks = {
};
const features: TableColumnFeatures = {
numerize: {
columnTitle: 'Номер платежа',
numerize: true,
split: {
rowsNumber: 12,
columnsNumber: 3,
},
};

View File

@ -37,9 +37,7 @@ const columns: TableColumn[] = [
];
const features: TableColumnFeatures = {
numerize: {
columnTitle: 'Номер',
},
numerize: true,
};
const params = { features };

View File

@ -1,13 +1,16 @@
import colors from 'client/UIKit/colors';
import { Box } from 'client/UIKit/grid';
import mq from 'client/UIKit/mq';
import { pick } from 'lodash';
import { toJS } from 'mobx';
import { useMemo } from 'react';
import styled from 'styled-components';
const TableWrapper = styled(Box)`
const TableStyles = styled(Box)`
overflow-x: auto;
table {
width: 100%;
${mq.laptop`
width: 100%;
overflow-x: none;
`}
table-layout: fixed;
@ -59,56 +62,132 @@ const TableWrapper = styled(Box)`
}
`;
const TablesGrid = styled(Box)`
display: ${props => props.split && 'grid'};
grid-template-columns: 1fr;
${mq.laptop`
grid-gap: 10px;
grid-template-columns: repeat(${props =>
props?.split?.columnsNumber || '2'}, 1fr);
`}
`;
function buildHead(features, columns) {
return () => (
<thead>
<tr>
{features?.numerize && <th>{features.numerize.columnTitle || '#'}</th>}
{columns.map(column => (
<th key={column.name}>{column.title}</th>
))}
</tr>
</thead>
);
}
function buildBody(
tableName,
features,
rows,
columnsProps,
withTableValue,
partNumber,
rowsNumber,
) {
return () => (
<tbody>
{rows.map((row, rowIndex) => {
const partRowIndex = rowIndex + partNumber * rowsNumber;
return (
<tr key={row.name}>
{features?.numerize && <td>{partRowIndex + 1}</td>}
{Object.keys(row).map(propName => {
const CellComponent = columnsProps[propName].Component;
const Cell = withTableValue(CellComponent)({
tableName,
rowIndex: partRowIndex,
propName,
...columnsProps[propName].props,
});
return (
<td key={propName}>
<Cell />
</td>
);
})}
</tr>
);
})}
</tbody>
);
}
const useColumnsProps = columns =>
useMemo(
() =>
columns.reduce((acc, col) => {
acc[col.name] = pick(col, ['Component', 'props']);
return acc;
}, {}),
[columns],
);
const useSplit = (split, rows) => {
return useMemo(() => {
if (!split) {
return {
partsNumber: 1,
};
}
const { rowsNumber } = split;
if (rows?.length) {
return { partsNumber: Math.ceil(rows?.length / rowsNumber), rowsNumber };
}
}, [rows?.length]);
};
const Table = ({
name: tableName,
columns,
rows,
columns,
params: { features },
withTableValue,
}) => {
return (
<TableWrapper>
<table>
<thead>
<tr>
{features && features.numerize && (
<th>{features.numerize.columnTitle || '#'}</th>
)}
{columns.map(({ title }, ci) => {
return <th key={ci}>{title}</th>;
})}
</tr>
</thead>
<tbody>
{rows.map((row, ri) => {
const rowProps = Object.keys(row);
return (
<tr key={ri}>
{features && features.numerize && <td>{ri + 1}</td>}
{rowProps.map((rowPropName, ki) => {
const columnIndex = columns.findIndex(
c => c.name === rowPropName,
);
const { Component } = columns[columnIndex];
const Element = withTableValue(Component)({
tableName,
rowIndex: ri,
propName: rowPropName,
...columns[columnIndex].props,
});
return (
<td key={ki}>
<Element />
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</TableWrapper>
);
const split = useSplit(features?.split, rows);
const rowsNumber = features?.split?.rowsNumber || rows?.length;
const columnsProps = useColumnsProps(columns);
const Head = buildHead(features, columns);
const tables = useMemo(() => {
let tables = [];
for (const partNumber of Array.from(Array(split.partsNumber).keys())) {
const a = 0 + rowsNumber * partNumber;
const b = rowsNumber + rowsNumber * partNumber;
const rowsPart = toJS(rows).slice(a, b);
const Body = buildBody(
tableName,
features,
rowsPart,
columnsProps,
withTableValue,
partNumber,
rowsNumber,
);
tables.push(
<TableStyles key={partNumber.toString()}>
<table>
<Head />
<Body />
</table>
</TableStyles>,
);
}
return tables;
}, [rows.length]);
return <TablesGrid split={features?.split}>{tables}</TablesGrid>;
};
export default Table;

View File

@ -31,7 +31,7 @@ const withTableValue = callbacks => Component => ({
tableName,
rowIndex,
propName,
columnCallback: callbacks && callbacks[propName],
columnCallback: callbacks?.[propName],
});
const { status } = useTableStatus({ tableName, rowIndex, propName });
const { validateStatus, message } = useTableValidation({

View File

@ -2,8 +2,8 @@ import { useStores } from '../useStores';
export const useOptions = elementName => {
const { calculationStore } = useStores();
const options = calculationStore.options[elementName] || [];
const filter = calculationStore.filters[elementName];
const options = calculationStore?.options?.[elementName] || [];
const filter = calculationStore?.filters?.[elementName];
return {
options: filter ? filter(options) : options,
@ -13,11 +13,9 @@ export const useOptions = elementName => {
export const useTableOptions = ({ tableName, rowIndex, propName }) => {
const { calculationStore } = useStores();
const options =
(calculationStore.tables[tableName].options &&
calculationStore.tables[tableName].options[propName]) ||
[];
calculationStore?.tables?.[tableName]?.options?.[propName] || [];
const filter =
calculationStore.tables[tableName].rows[rowIndex][propName].filter;
calculationStore?.tables?.[tableName]?.rows?.[rowIndex]?.[propName]?.filter;
return {
options: filter ? filter(options) : options,

View File

@ -91,7 +91,8 @@ export const useTableValidation = ({
const { calculationStore } = useStores();
const validationStatus =
calculationStore.tables[tableName].rows[rowIndex][propName]?.validation;
calculationStore?.tables?.[tableName]?.rows?.[rowIndex]?.[propName]
?.validation;
useEffect(() => {
setValidation(validationStatus);
}, [validationStatus]);

View File

@ -44,8 +44,8 @@ export const useTableValue = ({
const [currentValue, setCurrentValue] = useState(undefined);
//get row value from store
const targetTable = calculationStore.tables[tableName];
const sourceValue = targetTable.rows[rowIndex][propName].value;
const targetTable = calculationStore?.tables?.[tableName];
const sourceValue = targetTable?.rows?.[rowIndex]?.[propName]?.value;
useEffect(() => {
if (sourceValue !== undefined) {
setCurrentValue(sourceValue);

View File

@ -12,7 +12,10 @@ const tablesActions = {
getTableRowValues(tableName, rowIndex, paramName) {
let values = {};
const row = this.tables[tableName].rows[rowIndex];
const row = this?.tables?.[tableName]?.rows?.[rowIndex];
if (!row) {
return values;
}
const keys = Object.keys(row);
let overridedValue;
@ -41,7 +44,7 @@ const tablesActions = {
setTableRows(tableName, startIndex, override) {
return rows => {
if (this.tables[tableName] && this.tables[tableName].rows)
if (this?.tables[tableName]?.rows)
for (
let i = startIndex, j = 0;
i < startIndex + rows.length;

View File

@ -15,7 +15,6 @@ import {
TableNames,
TableProps,
TableValuesNames,
TCellCallback,
} from './tables';
import { ResultValuesNames, TValue, TValues, ValuesNames } from './values';
@ -111,10 +110,8 @@ interface ICalculationTables {
override?: boolean,
) => ({
options,
callbacks,
}: {
options?: TableProps<(IBaseOption & TCRMEntity)[]>;
callbacks?: TableProps<TCellCallback>;
}) => void;
}

View File

@ -51,9 +51,7 @@ export type TableColumn = {
};
export type TableColumnFeatures = {
numerize?: {
columnTitle?: string;
};
[feature: string]: any;
};
export type TableParams = {