Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Lazyload #25

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@
- Supports exporting chart as a picture or pdf document
- Supports pan and zoom
- Allows user to customize the internal structure for every node
- Allows user to fetch nodes from server and add to chart(lazyload)

## Chart Node

```js
type node = {
id: string
isLeaf?: boolean
defaultExpanded?: boolean
children: node[]
```

you can add other fields to the model.


## Props
<table>
Expand Down Expand Up @@ -103,6 +117,12 @@
<td>0.5</td>
<td>User can zoom the chart at different scales(0.5~7).</td>
</tr>
<tr>
<td>loadData</td>
<td>function</td>
<td></td>
<td>This function takes the node as an argument and returns a Promise. Promise should return a list of child nodes in resolve: (node) => Promise< node[] ></td>
</tr>
</tbody>
</table>

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dabeng/react-orgchart",
"version": "1.0.0",
"version": "1.1.0",
"main": "./dist/ChartContainer.js",
"files": [
"dist",
Expand Down Expand Up @@ -76,4 +76,4 @@
"last 1 safari version"
]
}
}
}
3 changes: 3 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import ExportChart from "./export-chart/export-chart";
import DragDropChart from "./drag-drop-chart/drag-drop-chart";
import EditChart from "./edit-chart/edit-chart";
import EditNode from "./edit-node/edit-node";
import lazyloadChart from "./lazyload/lazyload-chart";
import "./App.css";

const App = () => {
Expand All @@ -19,6 +20,7 @@ const App = () => {
<NavLink to="/default-chart" activeClassName="selected">Deault Chart</NavLink>
<NavLink to="/pan-zoom-chart" activeClassName="selected">Pan & Zoom Chart</NavLink>
<NavLink to="/custom-node-chart" activeClassName="selected">Custom Node Chart</NavLink>
<NavLink to="/lazyload-chart" activeClassName="selected">LazyLoad Chart</NavLink>
<NavLink to="/export-chart" activeClassName="selected">Export Chart</NavLink>
<NavLink to="/drag-drop-chart" activeClassName="selected">Drap & Drop Chart</NavLink>
<NavLink to="/edit-chart" activeClassName="selected">Edit Chart</NavLink>
Expand All @@ -29,6 +31,7 @@ const App = () => {
<Route path="/default-chart" component={DefaultChart} />
<Route path="/pan-zoom-chart" component={PanZoomChart} />
<Route path="/custom-node-chart" component={CustomNodeChart} />
<Route path="/lazyload-chart" component={lazyloadChart} />
<Route path="/export-chart" component={ExportChart} />
<Route path="/drag-drop-chart" component={DragDropChart} />
<Route path="/edit-chart" component={EditChart} />
Expand Down
32 changes: 23 additions & 9 deletions src/components/ChartContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const propTypes = {
collapsible: PropTypes.bool,
multipleSelect: PropTypes.bool,
onClickNode: PropTypes.func,
onClickChart: PropTypes.func
onClickChart: PropTypes.func,
loadData: PropTypes.func
};

const defaultProps = {
Expand Down Expand Up @@ -56,14 +57,15 @@ const ChartContainer = forwardRef(
collapsible,
multipleSelect,
onClickNode,
onClickChart
onClickChart,
loadData
},
ref
) => {

const container = useRef();
const chart = useRef();
const downloadButton = useRef();

const [startX, setStartX] = useState(0);
const [startY, setStartY] = useState(0);
const [transform, setTransform] = useState("");
Expand All @@ -74,8 +76,12 @@ const ChartContainer = forwardRef(
const [download, setDownload] = useState("");

const attachRel = (data, flags) => {
data.relationship =
flags + (data.children && data.children.length > 0 ? 1 : 0);
if (data.isLeaf === undefined) {
data.isLeaf = true;
}

data.relationship = flags + ((data.children && !!data.children.length) || !data.isLeaf ? 1 : 0);

if (data.children) {
data.children.forEach(function(item) {
attachRel(item, "1" + (data.children.length > 1 ? 1 : 0));
Expand All @@ -84,11 +90,17 @@ const ChartContainer = forwardRef(
return data;
};

const [ds, setDS] = useState(datasource);
useEffect(() => {
setDS(datasource);
}, [datasource]);

const [ds, setDS] = useState(datasource);

const onLoadData = async (datasource, children) => {
await dsDigger.updateNode({ ...datasource, children });
setDS({ ...dsDigger.ds });
};

const dsDigger = new JSONDigger(datasource, "id", "children");

const clickChartHandler = event => {
Expand Down Expand Up @@ -212,12 +224,12 @@ const ChartContainer = forwardRef(
orientation: "landscape",
unit: "px",
format: [canvasWidth, canvasHeight]
})
})
: new jsPDF({
orientation: "portrait",
unit: "px",
format: [canvasHeight, canvasWidth]
});
});
doc.addImage(canvas.toDataURL("image/jpeg", 1.0), "JPEG", 0, 0);
doc.save(exportFilename + ".pdf");
};
Expand Down Expand Up @@ -291,7 +303,7 @@ const ChartContainer = forwardRef(
"isAncestorsCollapsed"
);
});
}
},
}));

return (
Expand All @@ -318,6 +330,8 @@ const ChartContainer = forwardRef(
multipleSelect={multipleSelect}
changeHierarchy={changeHierarchy}
onClickNode={onClickNode}
loadData={loadData}
onLoadData={onLoadData}
/>
</ul>
</div>
Expand Down
1 change: 0 additions & 1 deletion src/components/ChartNode.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

.orgchart ul {
padding-left: 0;
text-align: center;
Expand Down
104 changes: 64 additions & 40 deletions src/components/ChartNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ const propTypes = {
collapsible: PropTypes.bool,
multipleSelect: PropTypes.bool,
changeHierarchy: PropTypes.func,
onClickNode: PropTypes.func
onClickNode: PropTypes.func,
loadData: PropTypes.func,
onLoadData: PropTypes.func,
};

const defaultProps = {
Expand All @@ -26,14 +28,15 @@ const ChartNode = ({
collapsible,
multipleSelect,
changeHierarchy,
onClickNode
onClickNode,
loadData,
onLoadData
}) => {
const node = useRef();

const [isChildrenCollapsed, setIsChildrenCollapsed] = useState(false);
const [isChildrenCollapsed, setIsChildrenCollapsed] = useState(!datasource.defaultExpanded);
const [topEdgeExpanded, setTopEdgeExpanded] = useState();
const [rightEdgeExpanded, setRightEdgeExpanded] = useState();
const [bottomEdgeExpanded, setBottomEdgeExpanded] = useState();
const [bottomEdgeExpanded, setBottomEdgeExpanded] = useState(datasource.defaultExpanded);
const [leftEdgeExpanded, setLeftEdgeExpanded] = useState();
const [allowedDrop, setAllowedDrop] = useState(false);
const [selected, setSelected] = useState(false);
Expand Down Expand Up @@ -148,10 +151,21 @@ const ChartNode = ({
toggleAncestors(e.target.closest("li"));
};

const bottomEdgeClickHandler = e => {
const addChildrenHandler = children => {
onLoadData(datasource, children);
setIsChildrenCollapsed(false);
setBottomEdgeExpanded(true);
};

const bottomEdgeClickHandler = async e => {
e.stopPropagation();
setIsChildrenCollapsed(!isChildrenCollapsed);
setBottomEdgeExpanded(!bottomEdgeExpanded);
if (loadData && !!!datasource.children) {
const children = await loadData(datasource);
addChildrenHandler(children);
} else {
setIsChildrenCollapsed(!isChildrenCollapsed);
setBottomEdgeExpanded(!bottomEdgeExpanded);
}
};

const toggleSiblings = actionNode => {
Expand Down Expand Up @@ -235,6 +249,11 @@ const ChartNode = ({
);
};

const setCollapse = collapse => {
setIsChildrenCollapsed(collapse);
setBottomEdgeExpanded(!collapse);
};

return (
<li className="oc-hierarchy">
<div
Expand All @@ -251,30 +270,33 @@ const ChartNode = ({
onMouseLeave={removeArrows}
>
{NodeTemplate ? (
<NodeTemplate nodeData={datasource} />
<NodeTemplate
nodeData={datasource}
setCollapse={setCollapse}
addChildren={addChildrenHandler}
/>
) : (
<>
<div className="oc-heading">
{datasource.relationship &&
datasource.relationship.charAt(2) === "1" && (
<i className="oci oci-leader oc-symbol" />
)}
{datasource.name}
</div>
<div className="oc-content">{datasource.title}</div>
</>
)}
<>
<div className="oc-heading">
{datasource.relationship &&
datasource.relationship.charAt(2) === "1" && (
<i className="oci oci-leader oc-symbol" />
)}
{datasource.name}
</div>
<div className="oc-content">{datasource.title}</div>
</>
)}
{collapsible &&
datasource.relationship &&
datasource.relationship.charAt(0) === "1" && (
<i
className={`oc-edge verticalEdge topEdge oci ${
topEdgeExpanded === undefined
className={`oc-edge verticalEdge topEdge oci ${topEdgeExpanded === undefined
? ""
: topEdgeExpanded
? "oci-chevron-down"
: "oci-chevron-up"
}`}
? "oci-chevron-down"
: "oci-chevron-up"
}`}
onClick={topEdgeClickHandler}
/>
)}
Expand All @@ -283,23 +305,23 @@ const ChartNode = ({
datasource.relationship.charAt(1) === "1" && (
<>
<i
className={`oc-edge horizontalEdge rightEdge oci ${
rightEdgeExpanded === undefined
className={`oc-edge horizontalEdge rightEdge oci
${rightEdgeExpanded === undefined
? ""
: rightEdgeExpanded
? "oci-chevron-left"
: "oci-chevron-right"
}`}
? "oci-chevron-left"
: "oci-chevron-right"
}`}
onClick={hEdgeClickHandler}
/>
<i
className={`oc-edge horizontalEdge leftEdge oci ${
leftEdgeExpanded === undefined
className={`oc-edge horizontalEdge leftEdge oci
${leftEdgeExpanded === undefined
? ""
: leftEdgeExpanded
? "oci-chevron-right"
: "oci-chevron-left"
}`}
? "oci-chevron-right"
: "oci-chevron-left"
}`}
onClick={hEdgeClickHandler}
/>
</>
Expand All @@ -308,13 +330,13 @@ const ChartNode = ({
datasource.relationship &&
datasource.relationship.charAt(2) === "1" && (
<i
className={`oc-edge verticalEdge bottomEdge oci ${
bottomEdgeExpanded === undefined
className={`oc-edge verticalEdge bottomEdge oci
${bottomEdgeExpanded === undefined
? ""
: bottomEdgeExpanded
? "oci-chevron-up"
: "oci-chevron-down"
}`}
? "oci-chevron-up"
: "oci-chevron-down"
}`}
onClick={bottomEdgeClickHandler}
/>
)}
Expand All @@ -332,6 +354,8 @@ const ChartNode = ({
multipleSelect={multipleSelect}
changeHierarchy={changeHierarchy}
onClickNode={onClickNode}
loadData={loadData}
onLoadData={onLoadData}
/>
))}
</ul>
Expand Down
4 changes: 2 additions & 2 deletions src/custom-node-chart/custom-node-chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const CustomNodeChart = () => {
const ds = {
id: "n1",
name: "Lao Lao",
title: "general manager",
title: "general manager",
children: [
{ id: "n2", name: "Bo Miao", title: "department manager" },
{
Expand Down Expand Up @@ -40,4 +40,4 @@ const CustomNodeChart = () => {
return <OrganizationChart datasource={ds} chartClass="myChart" NodeTemplate={MyNode}/>;
};

export default CustomNodeChart;
export default CustomNodeChart;
2 changes: 1 addition & 1 deletion src/custom-node-chart/my-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ const MyNode = ({ nodeData }) => {

MyNode.propTypes = propTypes;

export default MyNode;
export default MyNode;
Loading