Skip to content

Commit

Permalink
fix: scorecard form
Browse files Browse the repository at this point in the history
Improvement of the data groups configuration drag and drop
  • Loading branch information
nnkogift committed Sep 10, 2024
1 parent 792baa4 commit f884cfa
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function DataGroupArea() {
<SearchDataItem />
</div>
<h4 className="pl-16">{i18n.t("Groups")}</h4>
<div style={{ maxHeight: "60vh", overflowY: "auto", flex: 1 }}>
<div style={{ maxHeight: "60vh", overflowY: "auto", flex: 1, justifySelf: "stretch" }}>
<DataGroups />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function LinkingContainer({
content={i18n.t(
"Click to configure, drag to rearrange"
)}
key={`group-${groupIndex}-holder-${source}`}
key={`group-${groupIndex}-holder-${source.id}`}
>
<DataSourceHolder
dataHolder={source}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import i18n from "@dhis2/d2-i18n";
import { Button, colors, Tooltip } from "@dhis2/ui";
import { Button, colors, IconDragHandle24, Tooltip } from "@dhis2/ui";
import { IconAdd24, IconChevronDown24 } from "@dhis2/ui-icons";
import React, { useRef, useState } from "react";
import useDataGroupLayout from "../../../../hooks/useDataGroupLayout";
import useDataGroupManage from "../../../../hooks/useDataGroupManage";
import { Accordion, AccordionDetails, AccordionSummary } from "./components/Accordions";
import GroupTitle from "./components/GroupTitle";
import { DataGroupDraggable } from "./components/DataGroupDraggable";
import { isEmpty } from "lodash";
import { LinkingContainer } from "./components/LinkingContainer";
import { DragDropContext, Droppable } from "react-beautiful-dnd";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import DataSourceSelectorModal from "../DataSourceSelectorModal";

export function DataGroup(
{ index, onRemove }: { index: number, onRemove: (index: number) => void }
) {
const {
onDataSourceDelete,
onDataSourceAdd,
group
} = useDataGroupManage({ index });
Expand All @@ -26,102 +25,114 @@ export function DataGroup(
const [openAdd, setOpenAdd] = useState(false);
const summaryRef = useRef();


return (
<DataGroupDraggable id={id}>
<Accordion
onDoubleClick={(event) => event.stopPropagation()}
square
expanded={expanded}
onChange={toggleExpansion}
>
<Tooltip
content={i18n.t(
"Click to {{action}}, drag to rearrange",
{
action:
expanded === id
? i18n.t("collapse")
: i18n.t("expand")
}
)}
>
<AccordionSummary
innerRef={summaryRef}
onClick={(event) => event.stopPropagation()}
expandIcon={
<IconChevronDown24
key={"scorecard-group-expand"}
/>
}
aria-controls={`${id}d-content`}
id={`${id}d--header`}
>
<GroupTitle
index={index}
onDelete={onRemove}
/>
</AccordionSummary>
</Tooltip>
<AccordionDetails>
<div className="column data-holders-area">
{isEmpty(dataHolders) ? (
<div
className="column w-100 text-center center"
style={{ height: 100 }}
<div className="w-100">
<Draggable draggableId={`${id}`} index={index}>
{
(provided) => {

return <Accordion
innerRef={provided.innerRef}
onDoubleClick={(event) => event.stopPropagation()}
square
expanded={expanded}
onChange={toggleExpansion}
>
<Tooltip
content={i18n.t(
"Click to {{action}}, drag to rearrange",
{
action:
expanded === id
? i18n.t("collapse")
: i18n.t("expand")
}
)}
>
<p style={{ color: colors.grey600 }}>
{i18n.t("Add a data source")}
</p>
</div>
) : (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId={`${id}`}>
{(provided: any) => (
<AccordionSummary
{...provided.draggableProps}
{...provided.dragHandleProps}
innerRef={summaryRef}
onClick={(event) => event.stopPropagation()}
expandIcon={
<IconChevronDown24
key={"scorecard-group-expand"}
/>
}
aria-controls={`${id}d-content`}
id={`${id}d--header`}
>
<div style={{ gap: 8 }} className="row align-items-center">
<IconDragHandle24 />
<GroupTitle
index={index}
onDelete={onRemove}
/>
</div>
</AccordionSummary>
</Tooltip>
<AccordionDetails>
<div className="column data-holders-area">
{isEmpty(dataHolders) ? (
<div
className="w-100 "
{...provided.droppableProps}
ref={provided.innerRef}
className="column w-100 text-center center"
style={{ height: 100 }}
>
{dataHolderChunks?.map(
(chunk, i) => (
<LinkingContainer
groupIndex={index}
onDelete={remove}
onUnlink={onUnlink}
onLink={onLink}
chunk={chunk}
key={`${i}-linking-container-${group?.id}`}
/>
)
)}
{provided.placeholder}
<p style={{ color: colors.grey600 }}>
{i18n.t("Add a data source")}
</p>
</div>
) : (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId={`${id}`}>
{(provided: any) => (
<div
className="w-100"
{...provided.droppableProps}
ref={provided.innerRef}
>
{dataHolderChunks?.map(
(chunk, i) => (
<LinkingContainer
groupIndex={index}
onDelete={remove}
onUnlink={onUnlink}
onLink={onLink}
chunk={chunk}
key={`${i}-linking-container-${group?.id}`}
/>
)
)}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
)}
</Droppable>
</DragDropContext>
)}
<div>
<Button
className="scorecard-indicator-add"
dataTest="scorecard-indicator-add"
onClick={() => setOpenAdd(true)}
icon={<IconAdd24 />}
>
{i18n.t("Add Item")}
</Button>
</div>
</div>
{/*{openAdd && (*/}
{/* <DataSourceSelectorModal*/}
{/* disabled={selectedDataSourcesIds}*/}
{/* onSelect={onDataSourceAdd}*/}
{/* onClose={() => setOpenAdd(false)}*/}
{/* open={openAdd}*/}
{/* />*/}
{/*)}*/}
</AccordionDetails>
</Accordion>
</DataGroupDraggable>
<div>
<Button
className="scorecard-indicator-add"
dataTest="scorecard-indicator-add"
onClick={() => setOpenAdd(true)}
icon={<IconAdd24 />}
>
{i18n.t("Add Item")}
</Button>
</div>
</div>
{openAdd && (
<DataSourceSelectorModal
disabled={[]}
onSelect={onDataSourceAdd}
onClose={() => setOpenAdd(false)}
open={openAdd}
/>
)}
</AccordionDetails>
</Accordion>;
}
}
</Draggable>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import i18n from "@dhis2/d2-i18n";
import { Button } from "@dhis2/ui";
import { Button, IconDragHandle24 } from "@dhis2/ui";
import { getDataSourceShortName } from "@scorecard/shared";
import { Avatar } from "@material-ui/core";
import { IconDelete16 } from "@dhis2/ui-icons";
Expand All @@ -13,6 +13,7 @@ export default function DataSource({ dataSource, index, onDelete }: { dataSource
<div className="container-bordered data-source p-8 w-100">
<div className="row space-between align-items-center">
<div className="row align-items-center ">
<IconDragHandle24 />
<Avatar className="data-source avatar">
{getDataSourceShortName(type)}
</Avatar>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function DataSourceHolder({
};
return (
<Draggable draggableId={`${id}`} index={index}>
{(provided: any) => (
{(provided) => (
<div
{...provided.draggableProps}
{...provided.dragHandleProps}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import i18n from "@dhis2/d2-i18n";
import { Button, ButtonStrip, Modal, ModalActions, ModalContent, ModalTitle } from "@dhis2/ui";
import { DataSourceSelector } from "@hisptz/dhis2-ui";
import PropTypes from "prop-types";
import { DataSourceSelector, SelectedDataItem } from "@hisptz/dhis2-ui";
import React, { useState } from "react";

//TODO: Refactor to shared

export default function DataSourceSelectorModal({
onClose,
open,
onSelect,
disabled,
}: any) {
const [selectedItems, setSelectedItems] = useState([]);
onClose,
open,
onSelect,
disabled
}: { onClose: () => void, open: boolean; onSelect: (dataItems: SelectedDataItem[]) => void, disabled: string[] }) {
const [selectedItems, setSelectedItems] = useState<SelectedDataItem[]>([]);

return (
<Modal onClose={onClose} position={"middle"} large hide={!open}>
Expand All @@ -25,7 +22,7 @@ export default function DataSourceSelectorModal({
"dataElement",
"dataSet",
"programIndicator",
"customFunction",
"customFunction"
]}
selected={selectedItems}
disabled={disabled}
Expand All @@ -51,10 +48,3 @@ export default function DataSourceSelectorModal({
</Modal>
);
}

DataSourceSelectorModal.propTypes = {
onClose: PropTypes.func.isRequired,
onSelect: PropTypes.func.isRequired,
disabled: PropTypes.array,
open: PropTypes.bool,
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from "react";
import { DndContext } from "@dnd-kit/core";
import { DataGroupDroppable } from "./components/DataGroup/components/DataGroupDroppable";
import { useDataItemSearchState } from "../../states/searchState";
import { useFieldArray } from "react-hook-form";
import { ScorecardConfig, ScorecardDataGroup } from "@hisptz/dhis2-analytics";
Expand All @@ -11,18 +9,19 @@ import i18n from "@dhis2/d2-i18n";
import { Button } from "@dhis2/ui";
import { IconAdd24 } from "@dhis2/ui-icons";
import { DataGroup } from "./components/DataGroup";
import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd";

export default function DataGroups() {
const [filteredDataGroupIds] = useDataItemSearchState();
const { fields, append, remove } = useFieldArray<ScorecardConfig, "dataSelection.dataGroups">({
const { fields, append, remove, move } = useFieldArray<ScorecardConfig, "dataSelection.dataGroups">({
name: "dataSelection.dataGroups"
});

const onGroupAdd = () => {
append({
id: uid(),
dataHolders: [],
title: i18n.t("Default"),
title: `${i18n.t("Default")} ${fields.length + 1}`,
style: {}
} as ScorecardDataGroup);
};
Expand All @@ -31,22 +30,35 @@ export default function DataGroups() {
return <EmptyDataGroups onGroupAdd={onGroupAdd} />;
}

const onDragEnd = (result: DropResult) => {
const { source, destination } = result;
if (destination) {
move(source.index, destination.index);
}
};

return (
<DndContext>
<DataGroupDroppable>
<div style={{ gap: 24 }} className="column">
<div style={{ flex: 1 }} className="column">
{
fields.map((field, i) => (
<DataGroup onRemove={remove} key={field.id} index={i} />
))
}
</div>
<div style={{ padding: 16 }}>
<Button icon={<IconAdd24 />}>{i18n.t("Add group")}</Button>
</div>
</div>
</DataGroupDroppable>
</DndContext>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId={"group-area"}>
{
(provided) => {

return <div {...provided.droppableProps} ref={provided.innerRef} style={{ gap: 24 }} className="column">
<div style={{ flex: 1 }} className="column">
{
fields.map((field, i) => (
<DataGroup onRemove={remove} key={field.id} index={i} />
))
}
</div>
<div style={{ padding: 16 }}>
<Button onClick={onGroupAdd} icon={<IconAdd24 />}>{i18n.t("Add group")}</Button>
</div>
{provided.placeholder}
</div>;
}
}
</Droppable>
</DragDropContext>
);
}
Loading

0 comments on commit f884cfa

Please sign in to comment.