BIG-5: feat switching between compact and medium table row size.

This commit is contained in:
a.bouhuolia
2021-09-23 10:37:54 +02:00
parent 9b7382e222
commit e949b1b0c7
13 changed files with 190 additions and 55 deletions

View File

@@ -1,36 +0,0 @@
import React from 'react';
import {
Button,
PopoverInteractionKind,
Popover,
Menu,
MenuItem,
MenuDivider,
Classes
} from '@blueprintjs/core';
import { Icon } from 'components';
export function DashboardRowsHeightButton() {
return (
<Popover
minimal={true}
content={
<Menu>
<MenuDivider title={'Rows height'} />
<MenuItem text="Compact" />
<MenuItem text="Medium" />
</Menu>
}
placement="bottom-start"
modifiers={{
offset: { offset: '0, 4' },
}}
interactionKind={PopoverInteractionKind.CLICK}
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="rows-height" iconSize={16} />}
/>
</Popover>
);
}

View File

@@ -0,0 +1,70 @@
import React from 'react';
import {
Button,
PopoverInteractionKind,
Popover,
Menu,
MenuItem,
MenuDivider,
Classes,
Tooltip,
Position,
} from '@blueprintjs/core';
import clsx from 'classnames';
import { Icon, T } from 'components';
import Style from './style.module.scss';
/**
* Dashboard rows height button control.
*/
export function DashboardRowsHeightButton({ initialValue, value, onChange }) {
const [localSize, setLocalSize] = React.useState(initialValue);
// Handle menu item click.
const handleItemClick = (size) => (event) => {
setLocalSize(size);
onChange && onChange(size, event);
};
// Button icon name.
const btnIcon = `table-row-${localSize}`;
return (
<Popover
minimal={true}
content={
<Menu className={Style.menu}>
<MenuDivider title={<T id={'dashboard.rows_height'} />} />
<MenuItem
onClick={handleItemClick('small')}
text={<T id={'dashboard.row_small'} />}
/>
<MenuItem
onClick={handleItemClick('medium')}
text={<T id={'dashboard.row_medium'} />}
/>
</Menu>
}
placement="bottom-start"
modifiers={{
offset: { offset: '0, 4' },
}}
interactionKind={PopoverInteractionKind.CLICK}
>
<Tooltip
content={<T id={'dashboard.rows_height'} />}
minimal={true}
position={Position.BOTTOM}
>
<Button
className={clsx(Classes.MINIMAL, Style.button)}
icon={<Icon icon={btnIcon} iconSize={16} />}
/>
</Tooltip>
</Popover>
);
}
DashboardRowsHeightButton.defaultProps = {
initialValue: 'medium',
};

View File

@@ -0,0 +1,12 @@
.menu{
:global .bp3-heading{
font-weight: 400;
opacity: 0.5;
font-size: 12px;
}
}
.button{
min-width: 34px;
}

View File

@@ -196,6 +196,7 @@ export default function DataTable(props) {
DataTable.defaultProps = {
pagination: false,
size: 'medium',
spinnerProps: { size: 30 },
expandToggleColumn: 1,

View File

@@ -9,7 +9,15 @@ import TableContext from './TableContext';
export default function TableWrapper({ children }) {
const {
table: { getTableProps },
props: { sticky, pagination, loading, expandable, virtualizedRows, className },
props: {
sticky,
pagination,
loading,
expandable,
virtualizedRows,
className,
size,
},
} = useContext(TableContext);
return (
@@ -20,6 +28,7 @@ export default function TableWrapper({ children }) {
'is-expandable': expandable,
'is-loading': loading,
'has-virtualized-rows': virtualizedRows,
[`table-size--${size}`]: size,
})}
>
<ScrollSync>

View File

@@ -17,6 +17,7 @@ import {
If,
DashboardActionViewsList,
DashboardFilterButton,
DashboardRowsHeightButton
} from 'components';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
@@ -165,6 +166,9 @@ function AccountsActionsBar({
icon={<Icon icon="file-import-16" iconSize={16} />}
text={<T id={'import'} />}
/>
<NavbarDivider />
<DashboardRowsHeightButton />
<NavbarDivider />
<Switch
labelElement={<T id={'inactive'} />}
defaultChecked={accountsInactiveMode}

View File

@@ -9,7 +9,7 @@ import {
Switch,
Alignment,
} from '@blueprintjs/core';
import { FormattedMessage as T } from 'components';
import { DashboardRowsHeightButton, FormattedMessage as T } from 'components';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import Icon from 'components/Icon';
import {
@@ -25,8 +25,10 @@ import { useRefreshItems } from 'hooks/query/items';
import withItems from 'containers/Items/withItems';
import withItemsActions from './withItemsActions';
import withAlertActions from 'containers/Alert/withAlertActions';
import withSettings from '../Settings/withSettings';
import { compose } from 'utils';
import withSettingsActions from '../Settings/withSettingsActions';
/**
* Items actions bar.
@@ -42,6 +44,12 @@ function ItemsActionsBar({
// #withAlertActions
openAlert,
// #withSettings
itemsTableSize,
// #withSettingsActions
addSetting,
}) {
// Items list context.
const { itemsViews, fields } = useItemsListContext();
@@ -72,10 +80,14 @@ function ItemsActionsBar({
const checked = event.target.checked;
setItemsTableState({ inactiveMode: checked });
};
// Handle refresh button click.
const handleRefreshBtnClick = () => {
refresh();
};
// Handle table row size change.
const handleTableRowSizeChange = (size) => {
addSetting('items', 'tableSize', size);
};
return (
<DashboardActionsBar>
@@ -131,6 +143,12 @@ function ItemsActionsBar({
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<NavbarDivider />
<DashboardRowsHeightButton
initialValue={itemsTableSize}
onChange={handleTableRowSizeChange}
/>
<NavbarDivider />
<Switch
labelElement={<T id={'inactive'} />}
defaultChecked={itemsInactiveMode}
@@ -150,11 +168,15 @@ function ItemsActionsBar({
}
export default compose(
withSettingsActions,
withItems(({ itemsSelectedRows, itemsTableState }) => ({
itemsSelectedRows,
itemsInactiveMode: itemsTableState.inactiveMode,
itemsFilterRoles: itemsTableState.filterRoles,
})),
withSettings(({ itemsSettings }) => ({
itemsTableSize: itemsSettings.tableSize,
})),
withItemsActions,
withAlertActions,
)(ItemsActionsBar);

View File

@@ -10,11 +10,11 @@ import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
import { TABLES } from 'common/tables';
import withItems from 'containers/Items/withItems';
import withItemsActions from 'containers/Items/withItemsActions';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import withSettings from '../Settings/withSettings';
import { useItemsListContext } from './ItemsListProvider';
import { useItemsTableColumns, ItemsActionMenuList } from './components';
@@ -37,8 +37,8 @@ function ItemsDataTable({
// #withDrawerActions
openDrawer,
// #withItems
itemsTableState,
// #withSettings
itemsTableSize,
// #ownProps
tableProps,
@@ -146,6 +146,7 @@ function ItemsDataTable({
onCellClick={handleCellClick}
initialColumnsWidths={initialColumnsWidths}
onColumnResizing={handleColumnResizing}
size={itemsTableSize}
payload={{
onDeleteItem: handleDeleteItem,
onEditItem: handleEditItem,
@@ -167,5 +168,7 @@ export default compose(
withAlertsActions,
withDrawerActions,
withDialogActions,
withItems(({ itemsTableState }) => ({ itemsTableState })),
withSettings(({ itemsSettings }) => ({
itemsTableSize: itemsSettings.tableSize,
})),
)(ItemsDataTable);

View File

@@ -2,11 +2,13 @@ import { connect } from 'react-redux';
import {
FetchOptions,
submitOptions,
addSettings
} from 'store/settings/settings.actions';
export const mapDispatchToProps = (dispatch) => ({
requestSubmitOptions: (form) => dispatch(submitOptions({ form })),
requestFetchOptions: () => dispatch(FetchOptions({})),
addSetting: (group, key, value) => dispatch(addSettings(group, key, value)),
});
export default connect(null, mapDispatchToProps);

View File

@@ -446,25 +446,36 @@ export default {
},
'universal-search': {
path: [
'M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z'
'M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z',
],
viewBox: '0 0 20 20',
},
"arrow-down-24": {
path: [
'M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z',
],
'arrow-down-24': {
path: ['M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z'],
viewBox: '0 0 24 24',
},
"arrow-up-24": {
path: [
'M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z'
],
'arrow-up-24': {
path: ['M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z'],
viewBox: '0 0 24 24',
},
"caret-right-16": {
'caret-right-16': {
path: [
'M11 8c0-.15-.07-.28-.17-.37l-4-3.5A.495.495 0 006 4.5v7a.495.495 0 00.83.37l4-3.5c.1-.09.17-.22.17-.37z'
'M11 8c0-.15-.07-.28-.17-.37l-4-3.5A.495.495 0 006 4.5v7a.495.495 0 00.83.37l4-3.5c.1-.09.17-.22.17-.37z',
],
viewBox: '0 0 16 16',
},
'table-row-small': {
path: [
'M15,2.5v2a.5.5,0,0,1-.5.5h-13a.5.5,0,0,1-.5-.5v-2A.51.51,0,0,1,1.49,2h13A.5.5,0,0,1,15,2.5Z',
'M1,7.51A.51.51,0,0,1,1.49,7h13a.51.51,0,0,1,0,1h-13A.51.51,0,0,1,1,7.51Z',
'M1,10.5a.5.5,0,0,1,.5-.5h13a.5.5,0,0,1,0,1h-13A.5.5,0,0,1,1,10.5Z',
'M15,13.5a.5.5,0,0,1-.5.51h-13a.51.51,0,0,1,0-1h13A.5.5,0,0,1,15,13.5Z',
],
viewBox: '0 0 16 16',
},
'table-row-medium': {
path: [
'M15,3V7a1,1,0,0,1-1,1H2A1,1,0,0,1,1,7V3A1,1,0,0,1,2,2H14A1,1,0,0,1,15,3ZM1.48,11h13a.5.5,0,0,0,0-1h-13a.5.5,0,0,0,0,1Zm13,2h-13a.51.51,0,0,0,0,1h13a.51.51,0,0,0,0-1Z',
],
viewBox: '0 0 16 16',
},

View File

@@ -36,4 +36,11 @@ export const setSettings = (settings) => {
type: t.SETTING_SET,
options: settings,
};
}
export const addSettings = (group, key, value) => {
return {
type: t.SETTING_ADD,
payload: { group, key, value }
};
}

View File

@@ -1,5 +1,8 @@
import { camelCase } from 'lodash';
import { createReducer } from '@reduxjs/toolkit';
import storage from 'redux-persist/lib/storage';
import { persistReducer, purgeStoredState } from 'redux-persist';
import t from 'store/types';
const initialState = {
@@ -11,10 +14,21 @@ const initialState = {
bills: {},
billPayments: {},
salesEstimates: {},
items: {
tableSize: 'medium',
},
},
};
export default createReducer(initialState, {
const STORAGE_KEY = 'bigcapital:settings';
const PRESIST_CONFIG = {
key: STORAGE_KEY,
whitelist: ['data'],
storage,
};
const reducerInstance = createReducer(initialState, {
[t.SETTING_SET]: (state, action) => {
const { options } = action;
const _data = {
@@ -32,4 +46,19 @@ export default createReducer(initialState, {
});
state.data = _data;
},
[t.SETTING_ADD]: (state, action) => {
const { group, key, value } = action.payload;
const newData = {
...state.data,
[group]: {
...state.data[group],
[key]: value,
},
};
state.data = newData;
},
});
export default persistReducer(PRESIST_CONFIG, reducerInstance);

View File

@@ -2,4 +2,5 @@ export default {
SETTING_LIST_SET: 'SETTING_LIST_SET',
CLEAR_OPTIONS_FORM_ERRORS: 'CLEAR_OPTIONS_FORM_ERRORS',
SETTING_SET: 'SETTING_SET',
SETTING_ADD: 'SETTING_ADD',
};