chrone: sperate client and server to different repos.

This commit is contained in:
a.bouhuolia
2021-09-21 17:13:53 +02:00
parent e011b2a82b
commit 18df5530c7
10015 changed files with 17686 additions and 97524 deletions

View File

@@ -0,0 +1,5 @@
import React from 'react';
export function CellTextSpan({ cell: { value } }) {
return (<span class="cell-text">{ value }</span>)
}

View File

@@ -0,0 +1,36 @@
import React from 'react';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import { DataTable, If } from 'components';
import 'style/components/DataTable/DataTableEditable.scss';
/**
* Editable datatable.
*/
export default function DatatableEditable({
totalRow = false,
actions,
name,
className,
...tableProps
}) {
return (
<div
className={classNames(
CLASSES.DATATABLE_EDITOR,
{
[`${CLASSES.DATATABLE_EDITOR}--${name}`]: name,
},
className,
)}
>
<DataTable {...tableProps} />
<If condition={actions}>
<div className={classNames(CLASSES.DATATABLE_EDITOR_ACTIONS)}>
{actions}
</div>
</If>
</div>
);
}

View File

@@ -0,0 +1,11 @@
export default function TableBody({}) {
return (
<ScrollSyncPane>
<div {...getTableBodyProps()} className="tbody">
<div class="tbody-inner" style={{ minWidth: totalColumnsWidth }}></div>
</div>
</ScrollSyncPane>
);
}

View File

@@ -0,0 +1,100 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import { If } from 'components';
import { Skeleton } from 'components';
import { useAppIntlContext } from 'components/AppIntlProvider';
import TableContext from './TableContext';
import { saveInvoke } from 'utils';
import { isCellLoading } from './utils';
/**
* Table cell.
*/
export default function TableCell({ cell, row, index }) {
const { index: rowIndex, depth, getToggleRowExpandedProps, isExpanded } = row;
const {
props: {
expandToggleColumn,
expandColumnSpace,
expandable,
cellsLoading,
cellsLoadingCoords,
onCellClick,
},
} = useContext(TableContext);
const isExpandColumn = expandToggleColumn === index;
const { skeletonWidthMax = 100, skeletonWidthMin = 40 } = {};
// Application intl context.
const { isRTL } = useAppIntlContext();
// Detarmines whether the current cell is loading.
const cellLoading = isCellLoading(
cellsLoading,
cellsLoadingCoords,
rowIndex,
cell.column.id,
);
if (cellLoading) {
return (
<div
{...cell.getCellProps({
className: classNames(cell.column.className, 'td'),
})}
>
<Skeleton minWidth={skeletonWidthMin} maxWidth={skeletonWidthMax} />
</div>
);
}
// Handle cell click action.
const handleCellClick = (event) => {
saveInvoke(onCellClick, cell, event);
};
return (
<div
{...cell.getCellProps({
className: classNames(cell.column.className, 'td', {
'is-text-overview': cell.column.textOverview,
'clickable': cell.column.clickable,
'align-right': cell.column.align === 'right',
}),
onClick: handleCellClick,
})}
>
<div
className={classNames(
{
'text-overview': cell.column.textOverview,
},
'cell-inner',
)}
style={{
[isRTL ? 'paddingRight' : 'paddingLeft']:
isExpandColumn && expandable
? `${depth * expandColumnSpace}rem`
: '',
}}
>
{
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter
// to build the toggle for expanding a row
}
<If condition={cell.row.canExpand && expandable && isExpandColumn}>
<span {...getToggleRowExpandedProps({ className: 'expand-toggle' })}>
<span
className={classNames({
'arrow-down': isExpanded,
'arrow-right': !isExpanded,
})}
/>
</span>
</If>
{cell.render('Cell')}
</div>
</div>
);
}

View File

@@ -0,0 +1,3 @@
import { createContext } from 'react';
export default createContext();

View File

@@ -0,0 +1,20 @@
import React, { memo } from 'react';
import TableCell from './TableCell';
function TableFastCell({ cell, row, index }) {
return <TableCell cell={cell} row={row} index={index} />;
}
export default memo(TableFastCell, (prevProps, nextProps) => {
if (
prevProps.row.canExpand === nextProps.row.canExpand &&
prevProps.row.isExpanded === nextProps.row.isExpanded &&
prevProps.cell.value === nextProps.cell.value &&
prevProps.cell.maxWidth === nextProps.cell.maxWidth &&
prevProps.cell.width === nextProps.cell.width
) {
return true;
} else {
return false;
}
});

View File

@@ -0,0 +1,36 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import TableContext from './TableContext';
/**
* Table footer.
*/
export default function TableFooter() {
const {
props: { footer },
table: { footerGroups },
} = useContext(TableContext);
// Can't contiunue if the footer is disabled.
if (!footer) { return null; }
return (
<div class="tfooter">
{footerGroups.map((group) => (
<div {...group.getFooterGroupProps({ className: 'tr' })}>
{group.headers.map((column) => (
<div
{...column.getFooterProps({
className: classNames(column.className || '', 'td'),
})}
>
<div className={'cell-inner'}>
{column.render('Footer')}
</div>
</div>
))}
</div>
))}
</div>
);
}

View File

@@ -0,0 +1,101 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import { ScrollSyncPane } from 'react-scroll-sync';
import { If } from 'components';
import TableContext from './TableContext';
import MaterialProgressBar from 'components/MaterialProgressBar';
function TableHeaderCell({ column, index }) {
const {
table: { getToggleAllRowsExpandedProps, isAllRowsExpanded },
props: { expandable, expandToggleColumn },
} = useContext(TableContext);
return (
<div
{...column.getHeaderProps({
className: classNames(column.className || '', 'th', {
'align-right': column.align === 'right',
}),
})}
>
<If condition={expandable && index + 1 === expandToggleColumn}>
<span {...getToggleAllRowsExpandedProps()} className="expand-toggle">
<span
className={classNames({
'arrow-down': isAllRowsExpanded,
'arrow-right': !isAllRowsExpanded,
})}
/>
</span>
</If>
<div
{...column.getSortByToggleProps({
className: classNames('cell-inner', {
'text-overview': column.textOverview,
}),
})}
>
{column.render('Header')}
<If condition={column.isSorted}>
<span
className={classNames(
{
'sort-icon--desc': column.isSortedDesc,
'sort-icon--asc': !column.isSortedDesc,
},
'sort-icon',
)}
></span>
</If>
</div>
{column.canResize && (
<div
{...column.getResizerProps()}
className={`resizer ${column.isResizing ? 'isResizing' : ''}`}
>
<div class="inner-resizer" />
</div>
)}
</div>
);
}
function TableHeaderGroup({ headerGroup }) {
return (
<div {...headerGroup.getHeaderGroupProps()} className="tr">
{headerGroup.headers.map((column, index) => (
<TableHeaderCell key={index} column={column} index={index} />
))}
</div>
);
}
/**
* Table header.
*/
export default function TableHeader() {
const {
table: { headerGroups, page },
props: { TableHeaderSkeletonRenderer, headerLoading, progressBarLoading },
} = useContext(TableContext);
if (headerLoading && TableHeaderSkeletonRenderer) {
return <TableHeaderSkeletonRenderer />;
}
return (
<ScrollSyncPane>
<div className="thead">
{headerGroups.map((headerGroup, index) => (
<TableHeaderGroup key={index} headerGroup={headerGroup} />
))}
<If condition={progressBarLoading}>
<MaterialProgressBar />
</If>
</div>
</ScrollSyncPane>
);
}

View File

@@ -0,0 +1,42 @@
import React, { useContext } from 'react';
import TableContext from './TableContext';
import { Skeleton } from 'components';
function TableHeaderCell({ column }) {
const { skeletonWidthMax = 100, skeletonWidthMin = 40 } = column;
return (
<div
{...column.getHeaderProps({
className: 'th',
})}
>
<Skeleton minWidth={skeletonWidthMin} maxWidth={skeletonWidthMax} />
</div>
);
}
/**
* Table skeleton rows.
*/
export default function TableSkeletonHeader({}) {
const {
table: { headerGroups },
} = useContext(TableContext);
return (
<div class="thead">
{headerGroups.map((headerGroup) => (
<div
{...headerGroup.getHeaderGroupProps({
className: 'tr',
})}
>
{headerGroup.headers.map((column) => (
<TableHeaderCell column={column} />
))}
</div>
))}
</div>
);
}

View File

@@ -0,0 +1,12 @@
import React from 'react';
import { Checkbox } from '@blueprintjs/core';
export default function TableIndeterminateCheckboxHeader({
getToggleAllRowsSelectedProps,
}) {
return (
<div>
<Checkbox {...getToggleAllRowsSelectedProps()} />
</div>
);
}

View File

@@ -0,0 +1,10 @@
import React from 'react';
import { Checkbox } from '@blueprintjs/core';
export default function TableIndeterminateCheckboxRow({ row }) {
return (
<div>
<Checkbox {...row.getToggleRowSelectedProps()} />
</div>
);
}

View File

@@ -0,0 +1,15 @@
import React from 'react';
import { Spinner } from '@blueprintjs/core';
/**
* Table loading component.
*/
export default function TableLoading({
spinnerProps
}) {
return (
<div class="loading">
<Spinner {...spinnerProps} />
</div>
);
}

View File

@@ -0,0 +1,21 @@
import React, { useContext } from 'react';
import intl from 'react-intl-universal';
import TableContext from './TableContext';
/**
* Table no-results row text.
*/
export default function TableNoResultsRow() {
const {
props: { noResults },
} = useContext(TableContext);
const noResultText =
noResults || intl.get('there_is_no_results_in_the_table');
return (
<div className={'tr no-results'}>
<div class="td">{noResultText}</div>
</div>
);
}

View File

@@ -0,0 +1,26 @@
import React, { useContext } from 'react';
import TableContext from './TableContext';
/**
* Table page.
*/
export default function TablePage() {
const {
table: { page },
props: {
spinnerProps,
loading,
TableRowsRenderer,
TableLoadingRenderer,
TableNoResultsRowRenderer,
},
} = useContext(TableContext);
if (loading) {
return <TableLoadingRenderer spinnerProps={spinnerProps} />;
}
if (page.length === 0) {
return <TableNoResultsRowRenderer />;
}
return (<TableRowsRenderer />);
}

View File

@@ -0,0 +1,59 @@
import React, { useCallback, useContext } from 'react';
import { If, Pagination } from 'components';
import TableContext from './TableContext';
import { saveInvoke } from 'utils';
/**
* Table pagination.
*/
export default function TablePagination() {
const {
table: {
gotoPage,
setPageSize,
pageCount,
state: { pageIndex, pageSize },
},
props: { pagination, loading, onPaginationChange },
} = useContext(TableContext);
const triggerOnPaginationChange = useCallback((payload) => {
saveInvoke(onPaginationChange, payload)
}, [onPaginationChange]);
// Handles the page changing.
const handlePageChange = useCallback(
({ page, pageSize }) => {
const pageIndex = page - 1;
gotoPage(pageIndex);
triggerOnPaginationChange({ pageIndex, pageSize });
},
[gotoPage, triggerOnPaginationChange],
);
// Handles the page size changing.
const handlePageSizeChange = useCallback(
({ pageSize, page }) => {
const pageIndex = 0;
gotoPage(pageIndex);
setPageSize(pageSize);
triggerOnPaginationChange({ pageIndex, pageSize });
},
[gotoPage, setPageSize, triggerOnPaginationChange],
);
return (
<If condition={pagination && !loading}>
<Pagination
currentPage={pageIndex + 1}
total={pageSize * pageCount}
size={pageSize}
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
/>
</If>
);
}

View File

@@ -0,0 +1,90 @@
import React, { useCallback, useContext } from 'react';
import { ContextMenu } from 'components';
import classNames from 'classnames';
import useContextMenu from 'react-use-context-menu';
import TableContext from './TableContext';
import { saveInvoke, ConditionalWrapper } from 'utils';
/**
* Table row context wrapper.
*/
function TableRowContextMenu({ children, row }) {
// Table context.
const {
props: { ContextMenu: ContextMenuContent },
table,
} = useContext(TableContext);
const [
bindMenu,
bindMenuItem,
useContextTrigger,
{ coords, setVisible, isVisible },
] = useContextMenu();
const [bindTrigger] = useContextTrigger({
collect: () => 'Title',
});
const handleClose = useCallback(() => {
setVisible(false);
}, [setVisible]);
return (
<div class="tr-context" {...bindTrigger}>
{children}
<ContextMenu
bindMenu={bindMenu}
isOpen={isVisible}
coords={coords}
onClosed={handleClose}
>
<ContextMenuContent {...table} row={row} />
</ContextMenu>
</div>
);
}
/**
* Table row.
*/
export default function TableRow({ row, className, style }) {
const {
props: {
TableCellRenderer,
rowClassNames,
ContextMenu: ContextMenuContent,
},
} = useContext(TableContext);
return (
<div
{...row.getRowProps({
className: classNames(
'tr',
{ 'is-expanded': row.isExpanded && row.canExpand },
saveInvoke(rowClassNames, row),
className,
),
style,
})}
>
<ConditionalWrapper
condition={ContextMenuContent}
wrapper={TableRowContextMenu}
row={row}
>
{row.cells.map((cell, index) => (
<TableCellRenderer
key={index}
cell={cell}
row={row}
index={index + 1}
/>
))}
</ConditionalWrapper>
</div>
);
}

View File

@@ -0,0 +1,17 @@
import React, { useContext } from "react";
import TableContext from "./TableContext";
/**
* Table rows.
*/
export default function TableRows() {
const {
table: { prepareRow, page },
props: { TableRowRenderer, TableCellRenderer },
} = useContext(TableContext);
return page.map((row, index) => {
prepareRow(row);
return <TableRowRenderer key={index} row={row} TableCellRenderer={TableCellRenderer} />;
});
}

View File

@@ -0,0 +1,44 @@
import React, { useContext } from 'react';
import TableContext from './TableContext';
import { Skeleton } from 'components';
/**
* Table header cell.
*/
function TableHeaderCell({ column }) {
const { skeletonWidthMax = 100, skeletonWidthMin = 40 } = column;
return (
<div
{...column.getHeaderProps({
className: 'td',
})}
>
<Skeleton minWidth={skeletonWidthMin} maxWidth={skeletonWidthMax} />
</div>
);
}
/**
* Table skeleton rows.
*/
export default function TableSkeletonRows({}) {
const {
table: { headerGroups },
} = useContext(TableContext);
const skeletonRows = 10;
return Array.from({ length: skeletonRows }).map(() => {
return headerGroups.map((headerGroup) => (
<div
{...headerGroup.getHeaderGroupProps({
className: 'tr',
})}
>
{headerGroup.headers.map((column) => (
<TableHeaderCell column={column} />
))}
</div>
));
});
}

View File

@@ -0,0 +1,21 @@
import React, { useContext } from 'react';
import { ScrollSyncPane } from 'react-scroll-sync';
import TableContext from './TableContext';
export default function TableTBody({
children
}) {
const {
table: { getTableBodyProps }
} = useContext(TableContext);
return (
<ScrollSyncPane>
<div {...getTableBodyProps()} className="tbody">
<div class="tbody-inner">
{ children }
</div>
</div>
</ScrollSyncPane>
);
}

View File

@@ -0,0 +1,67 @@
import React, { useContext } from 'react';
import { WindowScroller, AutoSizer, List } from 'react-virtualized';
import { CLASSES } from 'common/classes';
import TableContext from './TableContext';
/**
* Table virtualized list row.
*/
function TableVirtualizedListRow({
index,
isScrolling,
isVisible,
style,
}) {
const {
table: { page, prepareRow },
props: { TableRowRenderer },
} = useContext(TableContext);
const row = page[index];
prepareRow(row);
return (<TableRowRenderer row={row} style={style} />);
}
/**
* Table virtualized list rows.
*/
export default function TableVirtualizedListRows() {
const {
table: { page },
props: { vListrowHeight, vListOverscanRowCount },
} = useContext(TableContext);
// Dashboard content pane.
const dashboardContentPane = React.useMemo(()=> document.querySelector(
`.${CLASSES.DASHBOARD_CONTENT_PANE}`,
), []);
const rowRenderer = React.useCallback(({ key, ...args }) => (
<TableVirtualizedListRow {...args} key={key} />
), []);
return (
<WindowScroller scrollElement={dashboardContentPane}>
{({ height, isScrolling, onChildScroll, scrollTop }) => (
<AutoSizer disableHeight>
{({ width }) => (
<List
autoHeight={true}
className={'List'}
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
overscanRowCount={vListOverscanRowCount}
rowCount={page.length}
rowHeight={vListrowHeight}
rowRenderer={rowRenderer}
scrollTop={scrollTop}
width={width}
/>
)}
</AutoSizer>
)}
</WindowScroller>
);
}

View File

@@ -0,0 +1,35 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import { ScrollSync } from 'react-scroll-sync';
import TableContext from './TableContext';
/**
* Table wrapper.
*/
export default function TableWrapper({ children }) {
const {
table: { getTableProps },
props: { sticky, pagination, loading, expandable, virtualizedRows, className },
} = useContext(TableContext);
return (
<div
className={classNames('bigcapital-datatable', className, {
'has-sticky': sticky,
'has-pagination': pagination,
'is-expandable': expandable,
'is-loading': loading,
'has-virtualized-rows': virtualizedRows,
})}
>
<ScrollSync>
<div
{...getTableProps({ style: { minWidth: 'none' } })}
className="table"
>
{children}
</div>
</ScrollSync>
</div>
);
}

View File

@@ -0,0 +1,35 @@
import React from 'react';
export const isCellLoading = (loading, cellsCoords, rowIndex, columnId) => {
if (!loading) {
return false;
}
return !cellsCoords
? true
: cellsCoords.some(
(cellCoord) => cellCoord[0] === rowIndex && cellCoord[1] === columnId,
);
};
export const useResizeObserver = (state, callback) => {
// This Ref will contain the id of the column being resized or undefined
const columnResizeRef = React.useRef();
React.useEffect(() => {
// We are interested in calling the resize event only when "state.columnResizing?.isResizingColumn" changes from
// a string to undefined, because it indicates that it WAS resizing but it no longer is.
if (
state.columnResizing &&
!state.columnResizing?.isResizingColumn &&
columnResizeRef.current
) {
// Trigger resize event
callback(
columnResizeRef.current,
state.columnResizing.columnWidths[columnResizeRef.current],
state.columnResizing,
);
}
columnResizeRef.current = state.columnResizing?.isResizingColumn;
}, [callback, state.columnResizing]);
};