Skip to content

Commit

Permalink
[WIP] Feature/multi drag dimensions (#206)
Browse files Browse the repository at this point in the history
* remove original sorting implementation

* add react-beautiful-dnd

* move all highlighted items to correct position in correct order

* add number indicator showing how many items will be moved

* fix sorting edge cases

* looking better with ghost items

* first attempt at a cloned element of the dragging item

* multi-drag with cloned item placeholder

* remove old sorting package no longer used

* Make sure box can expand when dragging multiple when list length is just one item less than causing scroll

* move components around to create an ItemSelector component - will be moved to d2-ui

* move toggler to ItemSelector

* separate package for shared code

* need the css file for the item selector

* less hardcoding of styles so component can be more universal

* add some tests

* add watch script

* move files around and use shared colors file

* remove duplicate colors file

* shorthand notation

* fix tests

* update snapshot

* refactoring

* refactoring in ItemSelector

* Ensure caching of ou dialog content while remounting pe and dx

* add tests for DialogManager

* Add tests for UnselectedItems

* add tests for the ItemSelector component

* merge and test fixes
  • Loading branch information
jenniferarnesen authored and janhenrikoverland committed Feb 27, 2019
1 parent de00b4f commit 7744517
Show file tree
Hide file tree
Showing 59 changed files with 4,308 additions and 1,662 deletions.
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = {
'<rootDir>/config/jest/fileTransform.js',
},
transformIgnorePatterns: [
'node_modules/(?!(lodash-es|@dhis2/d2-ui-[a-z-]+)/)',
'node_modules/(?!(lodash-es|analytics-shared|@dhis2/d2-ui-[a-z-]+)/)',
],
moduleFileExtensions: ['js', 'jsx'],
moduleDirectories: ['node_modules'],
Expand Down
15 changes: 3 additions & 12 deletions packages/app/i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2019-01-21T11:22:11.007Z\n"
"PO-Revision-Date: 2019-01-21T11:22:11.007Z\n"
"POT-Creation-Date: 2019-02-27T09:12:48.095Z\n"
"PO-Revision-Date: 2019-02-27T09:12:48.095Z\n"

msgid "Rename successful"
msgstr ""
Expand Down Expand Up @@ -35,21 +35,12 @@ msgstr ""
msgid "Period"
msgstr ""

msgid "Selected Data"
msgstr ""

msgid "Deselect All"
msgstr ""

msgid "Select All"
msgid "Search dimensions"
msgstr ""

msgid "Remove"
msgstr ""

msgid "Search dimensions"
msgstr ""

msgid "Dimension recommended with selected data"
msgstr ""

Expand Down
2 changes: 1 addition & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@
"prop-types": "^15.6.1",
"raf": "3.4.0",
"react": "^16.6.0",
"react-beautiful-dnd": "^10.0.4",
"react-dev-utils": "^5.0.2",
"react-dom": "^16.6.0",
"react-redux": "^5.1.0",
"react-sortable-hoc": "^0.8.3",
"redux": "^4.0.0",
"redux-actions": "^2.2.1",
"redux-logger": "^3.0.6",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { colors } from '../../../modules/colors';
import { colors } from 'analytics-shared';

export default {
arrowDown: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import debounce from 'lodash-es/debounce';
import keyBy from 'lodash-es/keyBy';
import isEqual from 'lodash-es/isEqual';

import { ItemSelector } from 'analytics-shared';
import DataTypes from './DataTypesSelector';
import Groups from './Groups';
import FilterField from '../FilterField';
import UnselectedItems from '../UnselectedItems';
import SelectedItems from '../SelectedItems';

import {
apiFetchGroups,
apiFetchAlternatives,
} from '../../../../api/dimensions';
import { sGetUiItemsByDimension } from '../../../../reducers/ui';
import { sGetSettingsDisplayNameProperty } from '../../../../reducers/settings';
import { sGetMetadata } from '../../../../reducers/metadata';

import {
acRemoveUiItems,
Expand All @@ -38,7 +38,6 @@ import {
import { FIXED_DIMENSIONS } from '../../../../modules/fixedDimensions';

import { styles } from './styles/DataDimension.style';
import '../styles/Dialog.css';

const dxId = FIXED_DIMENSIONS.dx.id;

Expand Down Expand Up @@ -219,43 +218,62 @@ export class DataDimension extends Component {
render = () => {
const groups = this.state.groups[this.state.dataType] || [];

const filterZone = () => {
return (
<div>
<DataTypes
currentDataType={this.state.dataType}
onDataTypeChange={this.onDataTypeChange}
/>
<Groups
dataType={this.state.dataType}
groups={groups}
groupId={this.state.groupId}
onGroupChange={this.onGroupChange}
onDetailChange={this.onDetailChange}
detailValue={this.state.groupDetail}
/>
<FilterField
text={this.state.filterText}
onFilterTextChange={this.onFilterTextChange}
onClearFilter={this.onClearFilter}
/>
</div>
);
};

const unselected = {
items: this.state.items,
onSelect: this.selectDataDimensions,
filterText: this.state.filterText,
requestMoreItems: this.requestMoreItems,
};

const selectedItems = this.props.selectedItems.map(i => {
return {
id: i,
name: this.props.metadata[i].name,
};
});

const selected = {
items: selectedItems,
dialogId: dxId,
onDeselect: this.deselectDataDimensions,
onReorder: this.setUiItems,
};

return (
<Fragment>
<DialogTitle>{i18n.t('Data')}</DialogTitle>
<DialogContent style={styles.dialogContent}>
<div style={styles.dialogContainer}>
<DataTypes
currentDataType={this.state.dataType}
onDataTypeChange={this.onDataTypeChange}
/>
<Groups
dataType={this.state.dataType}
groups={groups}
groupId={this.state.groupId}
onGroupChange={this.onGroupChange}
onDetailChange={this.onDetailChange}
detailValue={this.state.groupDetail}
/>
<FilterField
text={this.state.filterText}
onFilterTextChange={this.onFilterTextChange}
onClearFilter={this.onClearFilter}
/>
<UnselectedItems
className="data-dimension"
items={this.state.items}
onSelect={this.selectDataDimensions}
filterText={this.state.filterText}
requestMoreItems={this.requestMoreItems}
/>
</div>
<SelectedItems
className="data-dimension"
items={this.props.selectedItems}
dialogId={dxId}
onDeselect={this.deselectDataDimensions}
onReorder={this.setUiItems}
/>
<ItemSelector
itemClassName="data-dimension"
unselected={unselected}
selected={selected}
>
{filterZone()}
</ItemSelector>
</DialogContent>
</Fragment>
);
Expand All @@ -278,6 +296,7 @@ DataDimension.defaultProps = {
const mapStateToProps = state => ({
selectedItems: sGetUiItemsByDimension(state, dxId),
displayNameProp: sGetSettingsDisplayNameProperty(state),
metadata: sGetMetadata(state),
});

export default connect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,4 @@ export const styles = {
dialogContent: {
display: 'flex',
},
dialogContainer: {
paddingRight: 55,
},
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { colors } from '../../../../../modules/colors';
import { colors } from 'analytics-shared';

export const styles = {
container: {
border: `1px solid ${colors.greyLight}`,
display: 'flex',
flexFlow: 'column',
height: 53,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { colors } from '../../../../../modules/colors';
import { colors } from 'analytics-shared';

export const styles = {
container: {
border: `1px solid ${colors.greyLight}`,
display: 'flex',
height: '53px',
width: '420px',
borderBottom: '0px',
borderRight: '0px',
borderLeft: '0px',
paddingTop: '5px',
},
groupContainer: {
Expand All @@ -15,7 +16,6 @@ export const styles = {
width: 'inherit',
minWidth: '316px',
paddingLeft: '5px',
paddingRight: '5px',
},
titleText: {
color: colors.greyDark,
Expand Down
111 changes: 59 additions & 52 deletions packages/app/src/components/DimensionsPanel/Dialogs/DialogManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,19 @@ import {
sGetUiActiveModalDialog,
} from '../../../reducers/ui';
import { sGetDimensions } from '../../../reducers/dimensions';

import { apiFetchRecommendedIds } from '../../../api/dimensions';

import { FIXED_DIMENSIONS } from '../../../modules/fixedDimensions';

const dxId = FIXED_DIMENSIONS.dx.id;
const peId = FIXED_DIMENSIONS.pe.id;
const ouId = FIXED_DIMENSIONS.ou.id;

export const fixedDialogs = {
[dxId]: <DataDimension />,
[ouId]: <OrgUnitDimension />,
[peId]: <PeriodDimension />,
};

export const defaultState = {
mounted: [],
};
const ouDialogContent = <OrgUnitDimension />;

export class DialogManager extends Component {
state = defaultState;
state = {
onMounted: false,
};

componentDidUpdate = prevProps => {
const shouldFetchIds =
Expand All @@ -54,13 +46,8 @@ export class DialogManager extends Component {
this.fetchRecommended();
}

if (
this.props.dialogId &&
!this.state.mounted.includes(this.props.dialogId)
) {
this.setState({
mounted: [...this.state.mounted, this.props.dialogId],
});
if (this.props.dialogId === ouId && !this.state.ouMounted) {
this.setState({ ouMounted: true });
}
};

Expand All @@ -73,53 +60,73 @@ export class DialogManager extends Component {
this.props.setRecommendedIds(ids);
}, 1000);

renderDialogContent = () => (
<Fragment>
{Object.keys(FIXED_DIMENSIONS).map(dimensionId => {
return this.state.mounted.includes(dimensionId) ? (
<div
key={dimensionId}
style={{
display:
dimensionId === this.props.dialogId
? 'block'
: 'none',
}}
>
{fixedDialogs[dimensionId]}
</div>
) : null;
})}
{this.props.dialogId &&
!Object.keys(FIXED_DIMENSIONS).includes(
this.props.dialogId
) && (
// The OU content is persisted as mounted in order
// to cache the org unit tree data
renderPersistedContent = () => {
if (this.state.ouMounted) {
return (
<div
key={ouId}
style={{
display:
ouId === this.props.dialogId ? 'block' : 'none',
}}
>
{ouDialogContent}
</div>
);
}

return null;
};

renderDialogContent = () => {
const { dialogId } = this.props;
const dynamicContent = () => {
if (dialogId === dxId) {
return <DataDimension />;
}

if (dialogId === peId) {
return <PeriodDimension />;
}

if (!Object.keys(FIXED_DIMENSIONS).includes(dialogId)) {
return (
<DynamicDimension
dialogId={this.props.dialogId}
dialogTitle={
this.props.dimensions[this.props.dialogId].name
}
dialogId={dialogId}
dialogTitle={this.props.dimensions[dialogId].name}
/>
)}
</Fragment>
);
);
}
return null;
};

return (
<Fragment>
{this.renderPersistedContent()}
{dialogId && dynamicContent()}
</Fragment>
);
};

render() {
const { dialogId } = this.props;
const keepMounted = !dialogId || dialogId === ouId;

return (
<Dialog
data-test="dialog-manager"
open={!!this.props.dialogId}
open={!!dialogId}
onClose={() => this.props.closeDialog(null)}
maxWidth="lg"
disableEnforceFocus
keepMounted
keepMounted={keepMounted}
>
{this.renderDialogContent()}
<DialogActions>
<HideButton />
{this.props.dialogId && (
<AddToLayoutButton dialogId={this.props.dialogId} />
)}
{dialogId && <AddToLayoutButton dialogId={dialogId} />}
</DialogActions>
</Dialog>
);
Expand Down
Loading

0 comments on commit 7744517

Please sign in to comment.