g1eb / reactjs-calendar-heatmap

React component for d3.js calendar heatmap graph
https://rawgit.com/g1eb/reactjs-calendar-heatmap/master/
MIT License
151 stars 35 forks source link

Trouble to display data in the year mode #12

Open StrockBecca opened 4 years ago

StrockBecca commented 4 years ago

Hi, I really like your chart and wanted to reuse it. I just have a problem when I put overview={'year'} . The data aren't displayed when the page is done loading, I have to go on global mode before going back to the year one in order for my data to be displayed. I didn't have the problem when I tried to put overview={'day'} or overview={'global'} . But I really wished to be able to display the year mode first. thanks :)

g1eb commented 4 years ago

The default view in the demo is the year overview.

Can you share the changes you've made to the source? Maybe you could fork the project and share the link?

StrockBecca commented 4 years ago

Hi, Sure. So as you can see in the picture, the first part in the for is where I organize the data that I got from my api, then I create my chart with these data as well as other informations needed

Capture d’écran 2020-08-25 à 09 22 22

g1eb commented 4 years ago

Thanks for sharing the screenshot, the formatted data looks correct.. although I can't see what heatMapData data looks like. If it's not too much trouble could you upload an example somewhere? Maybe you could fork the project and share the link with me here, or use a jsfiddle or similar? That would help with debugging. Thanks!

StrockBecca commented 4 years ago

Sure I can share an example. It is an array with a bunch of data, but the way I get it from the api doesn't work with the chart so I just reformatted it in a way for it to work. Actually I also had the same problem when I was testing with the exemple you used in the README. Capture d’écran 2020-08-27 à 10 18 47

g1eb commented 4 years ago

sorry about the delay, were you able to get it to work correctly? Let me know if there's a way I can help, I'd appreciate a fork with your data/ or a simple js-fiddle with an example where you get that buggy behavior.

StrockBecca commented 4 years ago

Hi, I wasn't able to make it works. So I tried to start again from the begining and using the following data which doesn't require to use my api call : Capture d’écran 2020-09-01 à 15 33 46 But again I wasn't able to display them in year mode Capture d’écran 2020-09-01 à 15 35 55 I have to click on the arrow button and then on the global graph to correctly display them in the year mode Capture d’écran 2020-09-01 à 15 36 45 I will let you know if I'm able to make it works somehow.

g1eb commented 4 years ago

Thanks, let me know! In the meantime, I'd love to help if you could provide other examples (that I could copy/paste) or what's even better - a link to a cloned fork of the project or something similar I could download and reproduce this issue.

Deveshb15 commented 2 years ago

Hey @StrockBecca, even I'm not able to display the year data, can someone provide me with some sample data to test with, I tried the one in the documentation but it doesn't work:-<

g1eb commented 2 years ago

Hi @Deveshb15 - let me try to help you get some data for testing. In our demo we generate random data for the visualization using this method: https://github.com/g1eb/reactjs-calendar-heatmap/blob/master/index.html#L29

// Initialize random data for the demo
let now = moment().endOf('day').toDate()
let time_ago = moment().startOf('day').subtract(10, 'year').toDate()
let data = d3.timeDays(time_ago, now).map(function (dateElement, index) {
  return {
    date: dateElement,
    details: Array.apply(null, new Array(Math.floor(Math.random() * 15))).map(function(e, i, arr) {
      return {
        'name': 'Project ' + Math.ceil(Math.random() * 10),
        'date': function () {
          let projectDate = new Date(dateElement.getTime())
          projectDate.setHours(Math.floor(Math.random() * 24))
          projectDate.setMinutes(Math.floor(Math.random() * 60))
          return projectDate
        }(),
        'value': 3600 * ((arr.length - i) / 5) + Math.floor(Math.random() * 3600) * Math.round(Math.random() * (index / 365))
      }
    }),
    init: function () {
      this.total = this.details.reduce(function (prev, e) {
        return prev + e.value
      }, 0)
      return this
    }
  }.init()
})

Could you try running the above snippet and see if the generated data works for you?
Let me know if you run into any issues!

graciax452 commented 6 months ago

Hi did you manage to get this to work? I'm facing the same issue and I am not sure what to do as I'm new using react

I can get the example to work but if I send json data I can't seem to get it right. in the decade/ years view the heatmap disappears

image image

<!-- my habit heatmap Component -->
<script type="text/babel">

    class MyApp extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                data: [], // Initialize data as an empty array
                color: '#238DCD',
                overview: 'year',
            };
        }

       componentDidMount() {
fetch('/data')
    .then(response => {
        if (!response.ok) {
            console.error(`Fetch failed with status: ${response.status}`);
            throw new Error('Failed to fetch data');
        }
        return response.json();
    })
    .then(jsonData => {
        console.log('Fetched JSON data:', jsonData); // Log fetched data

        // Create an object to store details grouped by day
        let detailsByDay = {};

        // Loop through the JSON data and group details by day
        jsonData.forEach(dateElement => {
            let date = new Date(dateElement[2]);
            let dayKey = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
            if (!detailsByDay[dayKey]) {
                detailsByDay[dayKey] = [];
            }
            detailsByDay[dayKey].push({
                'name': dateElement[1],
                'date': date,
                'value': dateElement[3]
            });
        });

        // Convert the detailsByDay object into an array of objects
        let data = Object.keys(detailsByDay).map(dayKey => {
            return {
                date: new Date(dayKey),
                details: detailsByDay[dayKey],
                init: function () {
                    this.total = this.details.reduce(function (prev, e) {
                        return prev + e.value;
                    }, 0);
                    return this;
                }
            }.init();
        });

        console.log('Data after transformation:', data); // Log transformed data

        // Set the state with the transformed data
        this.setState({ data: data }, () => {
            console.log('Data in checking set state:', this.state.data); // Log the data after state is set
        });

    })
    .catch(error => {
        console.error('Error fetching data:', error);
        this.setState({ error: 'Error fetching data' });
    });

}

        print(val) {
            console.log(val);
        }

        render() {
console.log('Data in render method:', this.state.data); // Log the data
return (
    <div>
        <h1>Calendar Heatmap</h1>
        {/* Conditional rendering based on whether data is available */}
        {this.state.data.length > 0 ? (
            <CalendarHeatmap
                data={this.state.data}
                color={this.state.color}
                overview={this.state.overview}
                handler={this.print.bind(this)}
            />
        ) : (
            <p>Loading...</p>
        )}
    </div>
);

}

    }

    // Render the App component
    ReactDOM.render(<MyApp />, document.getElementById('root'));

</script>
<script type="text/babel">

  class App extends React.Component {

    constructor(props) {
      super(props)

      // Initialize random data for the demo
      let now = moment().endOf('day').toDate()
      let time_ago = moment().startOf('day').subtract(10, 'year').toDate()
      let data = d3.timeDays(time_ago, now).map(function (dateElement, index) {
        return {
          date: dateElement,
          details: Array.apply(null, new Array(Math.floor(Math.random() * 15))).map(function(e, i, arr) {
            return {
              'name': 'Project ' + Math.ceil(Math.random() * 10),
              'date': function () {
                let projectDate = new Date(dateElement.getTime())
                projectDate.setHours(Math.floor(Math.random() * 24))
                projectDate.setMinutes(Math.floor(Math.random() * 60))
                return projectDate
              }(),
              'value': 3600 * ((arr.length - i) / 5) + Math.floor(Math.random() * 3600) * Math.round(Math.random() * (index / 365))
            }
          }),
          init: function () {
            this.total = this.details.reduce(function (prev, e) {
              return prev + e.value
            }, 0)
            return this
          }
        }.init()
      })

      this.state = {
        data: data,
        color: '#cd2327',
        overview: 'year',
      }
       console.log('example after it:',data);
    }

    print(val) {
      console.log(val)
    }

    render() {
      return (
        <CalendarHeatmap
          data={this.state.data}
          color={this.state.color}
          overview={this.state.overview}
          handler={this.print.bind(this)}>
        </CalendarHeatmap>
      )
    }
  }

  // Render calendar heatmap component
  const container = document.getElementById('broot');
  const broot = ReactDOM.createRoot(container);
  broot.render(<App />)

StrockBecca commented 5 months ago

Hi, sorry but no, I can't remember exactly what the problem was back then but I think it had something to do between react and the type of my data that were just incompatible with this so I decided to drop this and code something else.