graphieros / vue-data-ui

A user-empowering data visualization Vue 3 components library for eloquent data storytelling
https://vue-data-ui.graphieros.com/
MIT License
267 stars 13 forks source link

VueUiSparkbar - Unable to have multiple dataset with individual target value #54

Closed lucaspmarra closed 3 weeks ago

lucaspmarra commented 3 weeks ago

I would like to know if the approach of obtaining a target value for each item in the dataset is on the radar. Currently, only one config JSON is used for all the datasets present, which limits the use of this graph.

Example:

[
  {
    "activity": "dragon riding",
    "total_reservations_today": 350,
    "capacity_today": 800,
  },
 {
    "activity": "spell casting",
    "total_reservations_today": 600,
    "capacity_today": 1200,
  },
]

For this to work, I need to pass a single config to the component, selecting a global target... in other words, in terms of usability, this breaks a correct KPI.

Using a javascript map, I can create a config and a dataset for each object in the array, but I can't use the respective config.

const activity_data_today = computed(() => {
  // Mock data
  const data = ref([
    {
      activity: "dragon riding",
      total_reservations_today: 350,
      capacity_today: 800,
    },
    {
      activity: "potion brewing",
      total_reservations_today: 450,
      capacity_today: 1000,
      capacity_week: 1800
    },
    {
      activity: "wand dueling",
      total_reservations_today: 200,
      capacity_today: 500,
    },
    {
      activity: "spell casting",
      total_reservations_today: 600,
      capacity_today: 1200,
    },
    {
      activity: "broom flying",
      total_reservations_today: 150,
      capacity_today: 300,
    },
    {
      activity: "magic herbology",
      total_reservations_today: 320,
      capacity_today: 700,
    },
    {
      activity: "enchanted archery",
      total_reservations_today: 280,
      capacity_today: 600,
    }
  ]);

  if (data.length === 0) {
    return {
      config: {},
      dataset: []
    };
  }

  const config = data.map(item => ({
    style: {
      backgroundColor:  '#5B5959FF',
      fontFamily: 'inherit',
      layout: {
        independant: true,
        percentage: false,
        target: item.capacity_today
      },
      gutter: {
        backgroundColor: '#444444',
        opacity: 100
      },
      bar: {
        gradient: {
          show: true,
          intensity: 0,
          underlayerColor: '#5B5959FF'
        }
      },
      gap: 4,
      animation: {
        show: true,
        animationFrames: 60
      },
      labels: {
        fontSize: 16,
        name: {
          position: 'top',
          width: '100%',
          color:  '#FFFFFF',
          bold: true
        },
        value: {
          show: true,
          bold: true
        }
      }
    }
  }));

  console.log('activity_data_today config: ', config);  // here I can check config's for each object

  const dataset = data.map((item, index) => ({
    name: item.activity,
    value: item.total_reservations_today,
    rounding: 1,
  }));

  console.log('activity_data_today dataset: ', dataset); // here I can check dataset's for each object

  const groupedDataset = groupBy(dataset, 'name');

  const summedDataset = mapValues(groupedDataset, group => ({
    name: group[0].name,
    value: sumBy(group, 'value'),
    rounding: 1
  }));

  const summedDatasetArray = values(summedDataset);

  return {
    config: config,  // Assuming I can pass array of configs
    dataset: summedDatasetArray
  };
});

But for it to work, I need to change the return code to return the first item in the index:

 return {
    config: config[0],
    dataset: summedDatasetArray
  };

So all the items in the dataset will have the same config and respectively the same target.

graphieros commented 3 weeks ago

Hi @lucaspmarra

You can upgrade to v2.2.74 which adds an optional datapoint target attribute. Hope it helps simplify the approach for your use case.

Cheers