Using lodash to prepare data for "last day user registration" chart - angularjs

I want to use lodash to prepare data for "last day user registration" chart.
Here is my users array:
{
name: toto,
creationDate: 11/11/2016 11:00:00
},
{
name: tata,
creationDate: 11/11/2016 10:00:00
},
{
name: titi,
creationDate: 09/11/2016 10:00:00
}
I need to create a chart with ChartJS that repesent the users registrations over th last day (24 hours).
If I use groupBy :
var grouped = _.groupBy(users, function (user) {
return moment(user.creationDate).get('hour');
});
I can't have the "empty" hours, when there is no user registration, in the final array.
The aim is to have this (let's say it is 18h o'clock) :
labels = ['18', '17', '16', ... '18']
data = [['1', '1', '12, ... '3']]
Could you please help ?

You can create a defauls object with empty arrays and apply _.defaults:
var hours = _.range(0,24);
var defaultHours = _.zipObject(hours, _.map(hours, function(){return [];}));
_.defaults(grouped, defaultHours);
After that, grouped will hold the values you found, or empty array for hours that had no registrations.

Related

Swift - How do I add a new object to an array inside another object that has a grouping field

I have an array of events of type.
struct Event { var id: UUID, var title: String, var date: Date }
this array is inside another object with an occurrence title
struct Category { var occurs: String, var events: [Event] }
occurs defines if the event.date is before or after Now(), so that i can make Section Headers in a table to show Past and Upcoming sections.
I am only persisting Event(need id for Notification changes).
I am able to save and load data into an array of Category but how do I add a new event and get it into the correct "occurs" array.
Data Example (Event struc has init that assigns the UUID to id. )
[
Category(occurs: "passed", events: [
Event(title: "Yesterday", date: Calendar.current.date(byAdding: .day, value: -1, to: Date())!)
]),
Category(occurs: "upcoming", events: [
Event(title: "Tomorrow", date: Calendar.current.date(byAdding: .day, value: 1, to: Date())!),
Event(title: "Future", date: Calendar.current.date(byAdding: .day, value: 5, to: Date())!)
])
]
Category array is then consumed by a List/ForEach to spit out the Section and Body.
Thanks
First you need a way to figure out if the event has passed or is upcoming. You could add an extension to your Event struct to compute this:
extension Event {
var occurs: String {
let diff = date.timeIntervalSince1970 - Date().timeIntervalSince1970
return diff >= 0 ? "upcoming" : "passed"
}
}
Next you need to find the index of the category that matches the event's occurs value in your data array. You can do this by using the firstIndex method:
let newEvent = Event(
title: "2 hours from now",
date: Calendar.current.date(byAdding: .hour, value: 2, to: Date())!)
let newEventOccurs = newEvent.occurs
if let index = data.firstIndex(where: { $0.occurs == newEventOccurs }) {
data[index].events.append(newEvent)
}
Notice we use an if-let binding because it's possible you don't have a category in your array for the event. In this case, you will want to add the category to your array with the new event.

How to map/filter data correctly with luxon (DateTimeNow) and ReactJs

I would like to explain my problem of the day.
I have a array which looks like this
[{status: "closed",createdAt: "2022-01-13T15:28:25.239Z"},{status: "closed",createdAt: "2022-01-10T15:28:25.239Z"},{status: "open",createdAt: "2021-11-25T15:28:25.239Z"}]
I filter to retrieve only the data with the status "closed"
const countData = data?.filter(
(item) => item.status === "closed"
);
const count = countData?.length;
this works well, it correctly returns the number to me.
I would like to add a new filter with Luxon.
I would like to take the date of today with luxon, and, as a result, display the objects that correspond to this date
const dateNow = DateTime.now().toISO();
console.log(dateNow)
2022-01-13T16:23:44.873+01:00
How can I fix this issue?
If you want to check if a given Luxon DateTime object represent the same day of today, you can use hasSame passing date as second parameter
Return whether this DateTime is in the same unit of time as another DateTime. Higher-order units must also be identical for this function to return true. Note that time zones are ignored in this comparison, which compares the local calendar time. Use DateTime#setZone to convert one of the dates if needed.
In your case, you can have something like the following code:
const DateTime = luxon.DateTime;
const input = [{
status: "closed",
createdAt: "2022-01-13T15:28:25.239Z"
}, {
status: "closed",
createdAt: "2022-01-10T15:28:25.239Z"
}, {
status: "open",
createdAt: "2021-11-25T15:28:25.239Z"
}, {
status: "closed",
createdAt: new Date().toISOString()
}];
const todayItems = input.filter(item => {
return DateTime.fromISO(item.createdAt).hasSame(DateTime.now(), 'day') && item.status == "closed";
});
console.log(todayItems)
<script src="https://cdn.jsdelivr.net/npm/luxon#2.3.0/build/global/luxon.js"></script>
Luxon has a function that let's you get a date at certain point of a parameter that's called startOf. So you can do something like:
const todayDate = DateTime.now().startOf("day");
So your todayDate variable will be your current date, but at 00:00:00 time.
And you can make the transformation of the elements date during your filter function to compare them to todayDate like this:
//Please consider that the example for today was at 2022-01-13
const array = [
{
name: "this is for today",
date: "2022-01-13T15:28:25.239Z"
},
{
name: "this was for yesterday",
date: "2022-01-12T15:28:25.239Z"
}];
const todayDate = DateTime.now().startOf("day");
const todayElements = array.filter((element) => {
return DateTime.fromISO(element.date).startOf("day").equals(todayDate);
});

How can I build some chart with Chart.js and ng2-charts using an array of revenus & budgets per month date as Data source?

I want to build some charts using Chart.js and ng2-charts. I have an array of data (week). I would like to know how to build an array of revenu-values and budget-values according to each date. These values will be shown on the Y-axis of the graph and the X-axis contains the labels ( [01, 02, 03, 04, 05, ..., 31] ) which are the month dates :
week = [
{
date = "2019-03-01",
revenu = 1000,
budget = 800
},
{
date = "2019-03-02",
revenu = 1000,
budget = 800
},
{
date = "2019-03-03",
revenu = 1000,
budget = 800
},
{
date = "2019-03-04",
revenu = 1000,
budget = 800
},
...
];
public monthChartLabels= [01, 02, 03, 04, 05, ..., 31];
public monthChartData = [
{
data: [ ? ] // Array of revenu-values according to each date
},
{
data: [ ? ] // Array of budget-values according to each date
}
];
<canvas
baseChart
[chartType]=" 'line' "
[datasets]="monthChartData"
[labels]="monthChartLabels"
[options]="monthLabels"
[legend]="true"
(chartHover)="onChartHover($event)">
</canvas>
Shalom Eli, you should map your original data to the chart's data arrays: week.map(e => e.revenu) for the revenu dataset, and week.map(e => e.budges) for the budget dataset.
Update
Based on your comment, you want to convert your week array to a map keyed by the day of the month of each record:
week.reduce((acc,v)=> ({
...acc,
[new Date(v.date).getDate()]: v
}), {})
And then use your labels array to fetch each value from this map:
revenuData = labels.map(r => this.weekMap[+r] && this.weekMap[+r].revenu);
budgetData = labels.map(r => this.weekMap[+r] && this.weekMap[+r].budget);
See this updated stackblitz: https://stackblitz.com/edit/ng2-charts-line-template-3dfmxn

how to dynamically remove/add options from/to dropdown using angularjs

On my Angular template there is a set of cascade dropdowns (Country, State, City), an Add button, and a table with Delete button on each row. All the data in the dropdowns is retrieved from asp.net webapi unfiltered at load time. I am trying to do the flowing with filter:
When all the dropdown values are selected, clicking the add button the value will be added to a table below it. The value is hidden (not deleted) from the dropdown.
When clicking the Delete button in the respective table row, it will delete (not hidden) the row. If the deleted City is still in the dropdown, it will be un-hidden.
At the load time, the City dropdown also need to filter out value already in the table.
Each button click will Ajax post to the webapi to update the server database
The table data is an array of objects with 7 fields (id, countryId, country, stateId, state, cityId, city) like below.
[{
id: 1,
level1id: 101,
level1: 'USA',
level2id: 39,
level2: 'California',
level3id: 4210,
level3: 'San Diego'
}, {
id: 19,
level1id: 101,
level1: 'USA',
level2id: 33,
level2: 'Oregon',
level3id: 5905,
level3: 'Portland'
}, {
id: 1,
level1id: 101,
level1: 'USA',
level2id: 690,
level2: 'Washington',
level3id: 1223,
level3: 'Seattle'
}]
After applying the filter Seattle, Portland, and San Diego will be removed from the dropdown.
[{
id: 3521,
city: 'San Francisco'
}, {
id: 5234,
city: 'Los Angeles'
}, {
id: 9792,
city: 'New York'
}, {
id: 8899,
city: 'Chicago'
}]
You could create a custom filter that will receive the original cities array (the one that goes into the drop-downs) and the list of selected cities (the one that goes into the table) and filter the selected cities out of the list of all the cities.
Based on your objects, and assuming level3id is the one you want to filter, you can go with this one:
// This is the custom filter - add it to your model
app.filter('selectedCities', function() {
/**
* This will be the returned filter function
* input is the list of cities that needs to be filtered
* selected is the list of items in the table
*/
return function(input, selected) {
var selected_cities = {}
var output = [];
//first we create hash map with all the selected cities
//This will enable us to locate a selected city in ~O(1)
angular.forEach(selected, function(selected_city) {
selected_cities[selected_city.level3id] = true;
})
/**
* now we go through the cities.
* we check if the city is in the hash of selected cities
* if its not there - we add it to the output
*/
angular.forEach(input, function(city) {
if (!(city.id in selected_cities)) {
output.push(city)
}
})
return output;
}
});
In the drop down you probably have some loop like ng-repeat = "city in cities", and lets say the table data object name is table_selected_data so you can use the filter like this:
ng-repeat = "city in cities | selectedCities:table_selected_data"

How to filter by a specific field in an object array using $filter('filter')

I would like to filter an employee object array using $filter('filter') to filter the results based on an employee's first name field ONLY that can be selected from the drop down/select. Notes that I do NOT want to use the "| filter:" in the ng-repeat".
The difficulty is that the name field is a property of another field called 'details', so I can't details.name like the code below because it will error.
$scope.filteredEmployees = $filter('filter')(employees, {details.name: selectedName });
See below for structure of the employee array object.
How can I tell it to filter the records based on details.name field using $filter('filter')?
Thank you in advance for your help!
Here is the code:
Var selectedName = “An”;
$scope.filteredEmployees = $filter('filter')(employees, {**details.name:** selectedName });
Var employees = [
{
Date: 01/01/2012
details: {
name: ‘An’,
age: 25
}
},
{
Date: 01/01/2012
details: {
name: ‘'Bill',
age: 20
}
}];
//Here is
<select ng-model="selectedName" ng-options="e for e in employees" data-ng-show="employees.length > 0" ng-change="filterEmployees">
<option value="">All Employees</option>
</select><br>
function filterEmployees() {
$scope.filteredEmployees = $filter('filter')(employees, "Joe");
};
The expression can be a map of property-to-filters: where each property in the object maps to a corresponding property within the result set.
$filter('filter')(employees, {name:"Joe"});
Live Demo
Using A Custom Function
If your data is more complex, and you need more advanced filtering, then you can simply pass in a custom predicate function to evaluate whether or not an item should be filtered.
The input of the function takes each item of the array as an argument, and is expected to return false if the item should be excluded from the result set.
var people = [{date:new Date(), details:{
name: 'Josh',
age: 32
}}, {date:new Date(), details:{
name: 'Jonny',
age: 34
}}, {date:new Date(), details:{
name: 'Blake',
age: 28
}}, {date:new Date(), details:{
name: 'David',
age: 35
}}];
$scope.filteredPeople = $filter('filter')(people, function(person){
return /^Jo.*/g.test(person.details.name);
});
Live Demo

Resources