bumbeishvili / org-chart

Highly customizable org chart. Integrations available for Angular, React, Vue
https://stackblitz.com/edit/web-platform-o5t1ha
MIT License
928 stars 330 forks source link

How can make some nodes with different styles (compact or non-compact) #319

Open parsasaei opened 1 year ago

parsasaei commented 1 year ago

I used d3 OrgChart and implemented my code as below:

d3.json(
     url.href
).then((dataFlattened) => {
    modes = modes.map(element => { if (element.checked) { element.checked = false; } else { element.checked = true; } return element; });
    const mappedData = dataFlattened.map((d) => {
        const width = Math.round(Math.random() * 50 + 300);
        const height = Math.round(Math.random() * 20 + 130);
        const cornerShape = ['ORIGINAL', 'ROUNDED', 'CIRCLE'][
            Math.round(Math.random() * 2)
        ];
        const nodeImageWidth = 100;
        const nodeImageHeight = 100;
        const centerTopDistance = 0;
        const centerLeftDistance = 0;
        const expanded = false; //d.id=="O-6"

        const titleMarginLeft = nodeImageWidth / 2 + 20 + centerLeftDistance;
        const contentMarginLeft = width / 2 + 25;
        return {
            nodeId: d.nodeId ,
            nodeName: d.name,
            parentNodeId: d.nodeParentId ,
            nodeLevel: d.level,
            width: width,
            height: height,
            borderWidth: 1,
            borderRadius: 5,
            borderColor: {
                red: 15,
                green: 140,
                blue: 121,
                alpha: 1,
            },
            backgroundColor: {
                red: 51,
                green: 182,
                blue: 208,
                alpha: 1,
            },
            nodeImage: {
                url: d.imageUrl,
                width: nodeImageWidth,
                height: nodeImageHeight,
                centerTopDistance: centerTopDistance,
                centerLeftDistance: centerLeftDistance,
                cornerShape: cornerShape,
                shadow: false,
                borderWidth: 0,
                borderColor: {
                    red: 19,
                    green: 123,
                    blue: 128,
                    alpha: 1,
                },
            },
            nodeIcon: {
                icon: 'http://example.com/p/ddd',
                size: 30,
            },
            template: `<div id="position-${d.nodeId}" position-id="${d.nodeId}" level="${d.level}" class="position-level" style="direction:rtl;padding-right:20px;">
                  <div style="margin-left:${titleMarginLeft}px;
                              margin-top:10px;
                              font-size:15px;
                              font-weight:bold;
                         ">${d.name}</div>
                 <div style="margin-left:${titleMarginLeft}px;
                              margin-top:3px;
                              font-size:11px;
                              max-width:235px;
                         ">${d.positionName}</div>

                 <div style="margin-left:${titleMarginLeft}px;
                              margin-top:3px;
                              font-size:11px;
                         ">${d.unit?.value || 'Unit'}</div>

                 <div style="
                             margin-top:15px;
                             font-size:11px;
                             position:absolute;
                             bottom:15px;
                            ">
                      <div>${d.office}</div>
                      <div style="position:relative;font-size:11px;top:10px;text-align:right;padding-right:2px;">${d.area}</div>
                 </div>
              </div>`,
            connectorLineColor: {
                red: 220,
                green: 189,
                blue: 207,
                alpha: 1,
            },
            connectorLineWidth: 5,
            dashArray: '',
            expanded: false
        };
    });
    //root = mappedData;
    ////console.log(root);
    chart = new d3.OrgChart()
                  .container('.chart-container')
                  .data(mappedData)
                  .nodeWidth((n) => 375)
                  .nodeHeight((n) => 120)
                  //.childrenMargin((node) => node.Y = 130)
                  //.childrenMargin((node) => 60)
                  //.compactMarginBetween((d) => 50)
                  //.siblingsMargin((d) => 100)
                  .siblingsMargin(node => 20)
                  .childrenMargin(node => 150)
                  .neighbourMargin((n1, n2) => 80)
                  .compactMarginBetween(node => 50)
                  .compactMarginPair(node => 100)
                  .nodeContent((d) => {
                      //console.log(d);
                      return `<div class="outer-wrapper" style="margin-top:-30px;position:relative;padding-top:0px;background-color:none;width:${d.width - 70}px;height:${d.height}px">
                          <img style="position:absolute;top:0;border: 1px solid #cdcdcd;" width="120" height="120" src="${d.data.nodeImage.url}" onerror="this.style.opacity='0'"/>
                          <div class="template-wrapper"  style="margin-top:30px;height: 120px;border: 1px solid #cdcdcd;border-radius:2px;color:000000;background-color:#FFFFFF;width:${d.width}px;  height:${d.height}px">
                              <div style="margin-left:-30px;padding-top:2px">${d.data.template}</div>
                          </div>
                          <div style="position: relative;color: #FFFFFF;margin-top: -27px;margin-left: 1px;background: #ffffff3d;width: 118px;padding-left: 3px;font-size: 8px;text-shadow: -1px 0 black, 0 1px black,1px 0 black, 0 -1px black;"> ${d.data._totalSubordinates} Subordinates <br/> ${d.data._directSubordinates} Direct</div>
                          </div>
                          `;
                  })
    .compact(false)
    .render();
    chart.data().sort(function (a, b) {
        // Check if node a has an expand button
        var aHasExpandButton = (a._totalSubordinates) ? 1 : 0;

        // Check if node b has an expand button
        var bHasExpandButton = (b._totalSubordinates) ? 1 : 0;

        // Compare the presence of expand buttons
        //if (aHasExpandButton !== bHasExpandButton) {
        //    return bHasExpandButton - aHasExpandButton;
        //}

        // If expand buttons are the same, compare the node names
        //|| (a.nodeName.localeCompare(b.nodeName))
        return (bHasExpandButton - aHasExpandButton);
    });
    chart.render();

I want to active some nodes on compact style with checking some flags and some other nodes have non-compact style like below: OrgChart How can to do like this 👆🏻?

bumbeishvili commented 1 year ago

Hi, as commented on Observable it's not possible to do it directly.

We'll have to reimplement

This function https://github.com/bumbeishvili/org-chart/blob/94023f15884cc64b3e8c80e09bc29b7edaf948ee/src/d3-org-chart.js#L757

And this function https://github.com/bumbeishvili/org-chart/blob/94023f15884cc64b3e8c80e09bc29b7edaf948ee/src/d3-org-chart.js#L798

To be able to accommodate that layout

parsasaei commented 1 year ago

@bumbeishvili Thank you. I couldn't find how to pass root element to calculateCompactFlexDimensions function. Can you give me a simple example with using pure javascript? I used d3-org-chart2.js

bumbeishvili commented 1 year ago

@parsasaei I think you have to copy and change the source code itself

parsasaei commented 1 year ago

@parsasaei I think you have to copy and change the source code itself

@bumbeishvili No I don't changed the source, I used the source, used in this example links in here: https://www.npmjs.com/package/d3-org-chart

bumbeishvili commented 1 year ago

I mean, you will need to use and modify the source code itself (it's just a single class), instead of loading the chart from NPM, otherwise I can't see how it can be implemented. Even then, it won't be easy