123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- // Data source utils
- /**
- * Extracts unique values of a specified nested property from an array of JSON objects.
- *
- * @param {Array} data - An array of JSON objects from which to extract unique values.
- * @param {string} key - The dot-separated key representing the nested property (e.g., 'source.id').
- * @returns {Array} An array containing the unique values of the specified nested property.
- *
- * @example
- * const data = [
- * {"id": 1, "name": "foo", "source": {"id": 4, "name": "bar"}},
- * {"id": 2, "name": "baz", "source": {"id": 4, "name": "qux"}},
- * {"id": 3, "name": "quux", "source": {"id": 5, "name": "corge"}}
- * ];
- *
- * const key = 'source.id';
- * const uniqueSourceIds = getUniqueValues(data, key);
- * console.log(uniqueSourceIds); // Output: [4, 5]
- */
- export function getUniqueValues(data, key) {
- var lookup = {};
- var items = data;
- var results = [];
- for (var item, i = 0; item = items[i++];) {
- var val = getValueByNestedKey(item, key);
- if (!(val in lookup)) {
- lookup[val] = 1;
- results.push(val);
- }
- }
- return results;
- }
- /**
- * Retrieves the value of a nested property in an object using a dot-separated key.
- *
- * @param {Object} obj - The input JavaScript object from which to retrieve the nested value.
- * @param {string} key - The dot-separated key representing the nested property (e.g., 'source.id').
- * @returns {*} The value of the nested property if found, otherwise, returns undefined.
- *
- * @example
- * const jsonString = '{"id":11,"name":"ajax","subject":"OR","mark":63,"source":{"id":4,"name":"foo"}}';
- * const jsonObject = JSON.parse(jsonString);
- *
- * const key = 'source.id';
- * const sourceId = getValueByNestedKey(jsonObject, key);
- * console.log(sourceId); // Output: 4
- */
- function getValueByNestedKey(obj, key) {
- const keys = key.split('.');
- let value = obj;
- for (const k of keys) {
- if (value[k] === undefined) {
- return undefined; // Property not found
- }
- value = value[k];
- }
- return value;
- }
- // From https://stackoverflow.com/a/49332027/13775459
- function toISOLocal(d) {
- var z = n => ('0' + n).slice(-2);
- var zz = n => ('00' + n).slice(-3);
- var off = d.getTimezoneOffset();
- var sign = off > 0? '-' : '+';
- off = Math.abs(off);
- return d.getFullYear() + '-' +
- z(d.getMonth()+1) + '-' +
- z(d.getDate()) + 'T' +
- z(d.getHours()) + ':' +
- z(d.getMinutes()) + ':' +
- z(d.getSeconds()) + '.' +
- zz(d.getMilliseconds()) +
- sign + z(off/60|0) + ':' + z(off%60);
- }
- // Create a function to convert data to CSV
- export function convertToCSV(data) {
- if (data.length === 0) {
- return "";
- }
- // Extract column names from the first object in the data array
- const columns = Object.keys(data[0]);
- // Create the header row
- const headerRow = columns.join(',') + '\n';
- // Create the data rows
- const dataRows = data.map(row => {
- const rowData = columns.map(col => {
- const value = row[col];
- if (typeof value === 'object' && value !== null) {
- return value.description || '';
- } else if (col === 'event_start' || col === 'belief_time') {
- // Check if the column is a timestamp column
- const timestamp = parseInt(value);
- if (!isNaN(timestamp)) {
- const date = new Date(timestamp); // Convert to Date
- // Format the date in ISO8601 format and localize to the specified timezone
- // return date.toISOString(); // Use this instead of toISOLocal to get UTC instead
- return toISOLocal(date);
- }
- } else if (col === 'belief_horizon') {
- // Check if the column is 'belief_horizon' (duration in ms)
- const durationMs = parseInt(value);
- if (!isNaN(durationMs)) {
- // Check if the duration is zero
- if (durationMs === 0) {
- return 'PT0H';
- }
- // Check if the duration is negative
- const isNegative = durationMs < 0;
- // Calculate absolute duration in seconds
- const absDurationSeconds = Math.abs(durationMs) / 1000;
- // Calculate hours, minutes, and seconds
- const hours = Math.floor(absDurationSeconds / 3600);
- const minutes = Math.floor((absDurationSeconds % 3600) / 60);
- const seconds = Math.floor(absDurationSeconds % 60);
- // Format the duration as ISO8601 duration
- let iso8601Duration = isNegative ? '-PT' : 'PT';
- if (hours > 0) {
- iso8601Duration += hours + 'H';
- }
- if (minutes > 0) {
- iso8601Duration += minutes + 'M';
- }
- if (seconds > 0) {
- iso8601Duration += seconds + 'S';
- }
- return iso8601Duration;
- }
- }
- return value;
- });
- return rowData.join(',');
- });
- // Combine the header row and data rows
- return "data:text/csv;charset=utf-8," + headerRow + dataRows.join('\n');
- }
|