Best way to update multiple attributes in nested state? - javascript

Just before I go about having to learn Redux or use Immer, I was wondering if anyone knew of a simple way to do this. I checked the React docs but I must be making a mistake somewhere, and need new sets of eyes on this.
I've got a users array of objects that is set to state {i.e. users, setUsers) , where each user object that has nested within it posts and concerts. Here's an example of one of them:
{
"id": 305,
"username": "L0V3MUSIC",
"email": "kanisha.hansen#bayer.co",
"posts": [
{
"id": 129,
"body": "PLEASE EMAIL IF YOU HAVE 4 TICKETS ALTOGETHER! MY DAUGHTERS LOVE HER -- THX ",
"for_sale": false,
"tickets": 4,
"concert_id": 51,
"user_id": 305
}
],
"concerts": [
{
"id": 51,
"date": "2023-07-22T00:00:00.000Z",
"location": "Brooklyn Steel",
"image": "https://i.imgur.com/SmFrzTC.jpg",
"artist_id": 37
}
]
},
I've also got concerts state holding an array of objects with the same information also and in the same way as above with users.
{
"id": 51,
"date": "2023-07-22T00:00:00.000Z",
"location": "Brooklyn Steel",
"image": "https://i.imgur.com/SmFrzTC.jpg",
"artist_id": 37,
"artist": {
"id": 37,
"name": "Adele",
"image": "https://i.imgur.com/zmGbfKS.jpg",
"genre": "Pop"
},
"posts": [
{
"id": 123,
"body": "2 tickets, $100 total OBO -- CHEAPEST YOU'LL EVER FIND FOR ADELE!!",
"for_sale": true,
"tickets": 2,
"concert_id": 51,
"user_id": 289
},
{
"id": 124,
"body": "3 tickets, $400 total OBO!",
"for_sale": true,
"tickets": 3,
"concert_id": 51,
"user_id": 289
},
{
"id": 129,
"body": "PLEASE EMAIL IF YOU HAVE 4 TICKETS ALTOGETHER! MY DAUGHTERS LOVE HER -- THX ",
"for_sale": false,
"tickets": 4,
"concert_id": 51,
"user_id": 305
}
],
"users": [
{
"id": 289,
"username": "onlineguy1",
"email": "su#cronin.name"
},
{
"id": 305,
"username": "L0V3MUSIC",
"email": "kanisha.hansen#bayer.co"
}
]
},
My issue is that I want to update a post that a user enters. I'd like to iterate either through users or through concerts, as I'm not sure which is best just yet given that both are 'symmetrical' in a sense. I don't want to have a posts state object though as I'm being graded on my ability to access users through concerts, and concerts through users.
currentUser is just the user that is currently logged in, and who would be the author of the created post. What I've tried to do a bunch of different ways is this: (here's my latest iteration)
if (response.status >= 200 && response.status <= 299) {
response.json().then((createdPost) => {
console.log('createdPost: ', createdPost);
const updatedPosts = currentUser.posts.map((eachPost) => {
if (eachPost.id === createdPost.id) {
return createdPost;
} else {
return eachPost;
}
});
console.log('updatedPosts: ', updatedPosts);
setCurrentUser(...currentUser, currentUser.posts: updatedPosts)
// FIGURE OUT HOW TO UPDATE THE STATE OF THE ABOVE
// THEN MAP THROUGH USERS AND UPDATE THAT USER WITH CURRENTUSER INSTEAD
});
setError([]);
setSuccess('Your post has been created!');
setSubmitted(true);
} else {
What I have above is updating the currentUser's posts and have an updated collection of the currentUser's post, and then ideally update the users state itself with this currentUser (and his updated posts) replacing currentUser (and his now outdated posts, given that they don't include the newly created post). But I've managed to confuse myself through the nesting and mapping and staring at this too long.
Is there a concise way to go about either updating the posts altogether then iterating through the user then updating users state, in a way that doesn't require redux or a plugin? Or is there a better way to go about handling this entirely? I'm assuming for sure that I'm being sloppy in getting this done so I'll take any steps in the right direction

Related

Get Custom label of people participating with my page through messenger

I am building a dashboard so I can easily view how many people currently have a specific label in my facebook messenger. I'm just developing this for my page that I'm admin at, so it's only for this one page.
The final result is this:
Label 1 - 38 People
Label 2 - 82 People
Label 3 - 47 People
First I get the participants using this endpoints: {page-id}/conversations?fields=participants
I get this sample:
{
"data": [
{
"participants": {
"data": [
{
"name": "Particiapnt's name",
"id": "<psid>"
},
{
"name": "My Page Name",
"id": "<my-pageid>"
}
]
},
"id": "<thread-id>"
}
]
}
Now when I use participants id (psid) to get custom labels using this endpint: /custom_labels
I get this error:
{
"error": {
"message": "Unsupported get request. Object with ID 'xxxxx' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api",
"type": "GraphMethodException",
"code": 100,
"error_subcode": 33,
"fbtrace_id": "A5kFh5U-xSMB83ZnQrbzEfy"
}
}
Please help.

How to model the rows in getData() since i have nested JSON data?

I want to display these fields :name, age, addresses_id, addresses_city, addresses_primary for each person into data studio.
My JSON data
{
"data": [
{
"name": "Lio",
"age": 30,
"addresses": [
{
"id": 7834,
"city": "ML",
"primary": 1
},
{
"id": 5034,
"city": "MM",
"primary": 1
}
]
},
{
"name": "Kali",
"age": 41,
"addresses": [
{
"id": 3334,
"city": "WK",
"primary": 1
},
{
"id": 1730,
"city": "DC",
"primary": 1
}
]
},
...
]
}
there is no problem if i don't render the addresses field
return {
schema: requestedFields.build(),
rows: rows
};
//rows:
/*
"rows": [
{
"values": ["Lio", 30]
},
{
"values": ["Kali", 41]
},
...
]
*/
The problem is
I'm not able to model the nested JSON data in Google Data Studio. I
have the problem exactly in the "addresses" field.
Could anyone tell me what format should be for the rows in this case?
As you already know, for each name of your dataset, you clearly have more than one row (one person has multiple addresses). Data Studio only accepts a single data for each field, since arrays are not supported at all. So you need to work on this.
There are some ways to solve this, but always keep in mind that:
getSchema() should return all available fields for your connector (the order doesn't really matter, since Data Studio always sort alphabetically the available fields)
getData() should return a list of values. But here the order is relevant: it should be the same as the parameter passed to getData() (which means the results should be dynamic, sometimes you'll return all values, sometimes not, and the order may change).
Solution 1: Return multiple rows per record
Since you can produce multiple rows for each name, just do it.
To achieve this, your field definition (=getSchema()) should include fields address_id, address_city and address_primary (you can also add address_order if you need to know the position of the address in the list).
Supposing getData() is called with all fields in the same order they were discribed, rows array should look like this:
"rows": [
{
"values": ["Lio", 30, "7834", "ML", 1]
},
{
"values": ["Lio", 30, "5034", "MM", 1]
},
{
"values": ["Kali", 41, "3334", "WK", 1]
},
{
"values": ["Kali", 41, "1730", "DC", 1]
},
...
]
IMO, this is the best solution for your data.
Solution 2: Return one address only, ignoring others
If you prefer one row per person, you can get one of the addresses and display only it (usually the main/primary address, or the first one).
To achieve this, your field definition (=getSchema()) should include fields address_id, address_city and address_primary.
Supposing getData() is called with all fields in the same order they were discribed, rows array should look like this:
"rows": [
{
"values": ["Lio", 30, "7834", "ML", 1]
},
{
"values": ["Kali", 41, "3334", "WK", 1]
},
...
]
Solution 3: Return all addresses, serialized in a field
This is helpful if you really need all information but do not want a complex scheme.
Just create a field called addresses in your field definition (=getSchema()) and write the JSON there as a string (or any other format you want).
Supposing getData() is called with all fields in the same order they were discribed, rows array should look like this:
"rows": [
{
"values": ["Lio", 30, "[{\"id\": 7834, \"city\": "ML", \"primary\": 1}, {\"id\": 5034, \"city\": \"MM\", \"primary\": 1}]"]
},
{
"values": ["Kali", 41, "[{\"id\": 3334, \"city\": \"WK\", \"primary\": 1}, {\"id\": 1730, \"city\": \"DC\", \"primary\": 1}]"]
},
...
]
This solution may appear senseless, but it is possible to interact with this data later in DataStudio using REGEX if really needed.
Solution 4: Create a different field for each address
If you're sure all records has a maximum number of addresses (in you example, both names have 2 addresses, for example), you can create multiple fields.
Your field definition (=getSchema()) should include fields address_id1, address_city1, address_primary1, address_id2, ... address_primaryN.
I wouldn't explain how rows should look like in this situation, but it is not hard to guess with the other examples.

Requesting info out of DISCORD API INVITES

I would like to know how can i request this two values from the https://discord.com/api/v8/invites/, getting the first channel's name and the name of the guild.
Cause im looking foward to do so every invite sent in a channel must have a specific word in the guild name it is from and a specific word as first channel, otherwise it will get deleted.
I would appreciate some help since im new to this a docs got me really confused. Thanks!
If you try using the API, (this example uses unblock)
You get this response:
{
"code": "unblock",
"guild": {
"id": "419123358698045453",
"name": "TitaniumNetwork",
"splash": "86378b9059a3fe6d7a76d126c3c4b678",
"banner": "86378b9059a3fe6d7a76d126c3c4b678",
"description": null,
"icon": "870e49b4cd8fce8063b7bda48e33aa46",
"features": ["COMMUNITY", "WELCOME_SCREEN_ENABLED", "VANITY_URL", "ANIMATED_ICON", "BANNER", "PREVIEW_ENABLED", "INVITE_SPLASH", "MEMBER_VERIFICATION_GATE_ENABLED", "NEWS"],
"verification_level": 4,
"vanity_url_code": "unblock",
"welcome_screen": {
"description": "We are an organization revolving around proxies, armed with a mission for the protection of freedom and privacy rights to be normalized.",
"welcome_channels": [{
"channel_id": "738967801460686889",
"description": "Read the rules.",
"emoji_id": "709447784536866869",
"emoji_name": "verif"
}, {
"channel_id": "796606512407511060",
"description": "Join some discussions!",
"emoji_id": "766746158546026547",
"emoji_name": "infernal"
}, {
"channel_id": "743646448721068092",
"description": "Talk about tech!",
"emoji_id": "779561163293196288",
"emoji_name": "abraded"
}, {
"channel_id": "769716455230668820",
"description": "Be ready for feedback!",
"emoji_id": "574816517989072897",
"emoji_name": "TitaniumNetwork"
}]
}
},
"channel": {
"id": "738967801460686889",
"name": "rules",
"type": 0
}
}
It's a simple matter of parsing the JSON.

Get the list of users that liked a post

A friend of mine decided to run a sweepstakes on Instagram without giving much thought to how to get the full list of users that liked a post. He's saying he can just pick a random user from the available/visible list, but that wouldn't be fair, so I decided to step in.
The post in question, currently, has 1.4k likes.
First, I created a tiny script in JS to view, scroll down (to populate the list) and finally get the users that liked the post. This was troublesome to create, but it works. Then I realized I could not view all the users. While there are 1.4k users, I could only list 675 of them.
In the name of fairness, this is not enough. So I started digging more and examined the HTTP Requests made by the (Instagram) post page to the Instagram Graph API to load more users. This is what the URL looks like:
https://www.instagram.com/graphql/query/?query_id=SOME_ID&variables={\"shortcode\":\"SHORTCODE\",\"first\":20}
When I make a request to this URL, I get the following:
{
"data": {
"shortcode_media": {
"id": "SOME_ID",
"shortcode": "SHORTCODE",
"edge_liked_by": {
"count": 675,
"page_info": {
"has_next_page": false,
"end_cursor": "AQBPkM1xm2XgBx8ZQ8lR6GDsFAvQBx_Eqxg2NnTXN-GUPGhlpUa9_10UoMcJ6xNcIH4"
},
"edges": [{
"node": {
"id": "", // value omitted intentionally
"username": "", // value omitted intentionally
"full_name": "", // value omitted intentionally
"profile_pic_url": "", // value omitted intentionally
"is_verified": false,
"followed_by_viewer": false,
"requested_by_viewer": false
}
},
...
There's this ["edge_liked_by"]["count"] property and it is set to 675. I'm guessing this is a server-side restriction. When I increase the "first" parameter in the URL and make it greater than 675, it still returns 675 users.
Can I overcome this restriction and get the full list in any way?
Update: I've just tried the same thing with comments. The post has 11.8k comments and this is what the request returns:
{
"data": {
"shortcode_media": {
"edge_media_to_comment": {
"count": 11809,
"page_info": {
"has_next_page": true,
"end_cursor": "AQBV53OxNFkaHwJ6xjgHmlI-hwtpHCEeButMmGLwZJ_sjdyUy49gY_WZo1iH_aRcuAFOCzfrKPEktMaQLRjFVAsmQTincJpr4ZTITbTT1BZkJQ"
},
"edges": [{
"node": {
"id": "",
"text": "",
"created_at": ,
"owner": {
"id": "",
"profile_pic_url": "",
"username": ""
}
}
},
...
The exact count of the comments is 11809 and the request listed first 10259, but there's a next page. So I requested the next page and this is it:
{
"data": {
"shortcode_media": {
"edge_media_to_comment": {
"count": 11809,
"page_info": {
"has_next_page": false,
"end_cursor": null
},
"edges": [{
"node": {
"id": "",
"text": "",
"created_at": ,
"owner": {
"id": "",
"profile_pic_url": "",
"username": ""
}
}
},
...
This time it didn't return the remaining 1550 (11809 - 10259) users, but just 356 of them. And there's no next page. So there seems to be some inconsistencies. (Perhaps, there's a privacy issue that prevents some users to be listed?)

Populate AngularJS {{expression}} within ng-repeat using a second array

I'm completely rebuilding my website (originally hacked together with Wordpress) using Laravel and AngularJS. It's been a massive learning experience and I think I'm nearly there but for one problem.
On my site 'schemes' (or courses) are made up of 'units' which are made up of 'lessons'. Retrieving this data is fine, using Eloquent I retrieve valid JSON like this made up example...
[
{
"id": "1", //Scheme Id
"title": "Sports",
"description": "This is a Sports course!",
"units": [
{
"id": "1",
"title": "Tennis",
"lessons": [
{
"id": "6",
"title": "Serving"
},
{
"id": "7",
"title": "Hitting the ball with top-spin"
}
]
},
{
"id": "2",
"title": "Athletics",
"lessons": [
{
"id": "1",
"title": "Long Jump"
},
{
"id": "2",
"title": "Hurdling Technique"
}
]
},
{
"id": "4",
"title": "Golf",
"lessons": [
{
"id": "4",
"title": "Pitching"
},
{
"id": "5",
"title": "Putting"
}
]
}
]
}
....
]
Separately I have a simple array of completed lesson ids for a particular user like this...
[2, 6, 8, 9] ///User has completed lessons with ids of 2,6,8 and 9
In my view I'm using nested ng-repeat loops like so...
...
<div ng-controller="SchemesController">
<div ng-repeat="scheme in schemes">
<h1>{{scheme.title}}</h1>
<div ng-repeat="unit in scheme.units">
<h3>{{unit.title}}</h3>
<div ng-repeat="lesson in unit.lessons">
<div>{{lesson.title}}: {{status}}</div>
</div>
</div>
</div>
</div><!--[end of ng-controller="SchemesController"]-->
....
SchemesController (v simple!) looks like this...
var app = angular.module('schemesApp', []);
app.controller('SchemesController', function($scope){
$scope.schemes=jsonData;
});
The problem is I have no idea how to populate the {{status}} field which I want to state simply 'Complete' or 'Incomplete. I investigated whether I could somehow add this info to my original array like this...
"lessons": [
{
"id": "6",
"title": "Serving",
"status": "Complete" //populated somehow
},
{
"id": "7",
"title": "Hitting the ball with top-spin",
}
]
but I got nowhere slowly. Is there a way to do this (I've played around with underscore.js and felt this could help?).
Or do I populate {{status}} from creating and calling a javascript function?!?
ANY help that anyone could offer would be incredible. I'm a school teacher and for some sadistic reason I find a bit of programming/web design a fun use of my spare time so I apologise if this is a stupid question. THANKS in advance!!!
btw if anyone has a better 'title' for this question then please let me know.
I'm assuming you don't need to persist the status back to the database...
This is where you're having the problem:
<div>{{lesson.title}}: {{status}}</div>
You really don't need to store the status in your data model, because it's just used for presentation purposes.
Let's say your array of completed lessons is defined like this:
$scope.completedLessons = [1, 2, 3, 4, 5] // Or however you'd assign it
You need to create a function in your scope like this:
$scope.isLessonCompleted = function(lessonId) {
return $scope.completedLessons.indexOf(lessonId) > -1;
};
Then you need to change the html from above to this:
<div>{{lesson.title}}: {{isLessonCompleted(lesson.id) && 'Complete' || 'Incomplete'}}</div>
If lessons are also a model and each lesson should have a status, which isn't a column/field in your table but is something you'll add logic to determine, you could add a custom model accessor by adding the following to your models/Lesson.php:
// Append custom accessor attributes
protected $appends = ['status'];
public function getStatusAttribute() {
// Add logic here
return 'Complete';
}
This way, when you use Eloquent to retrieve your data, you'll also see a status attribute as part of the object, so you could then access it as usual $lesson->status (PHP) or lesson.status (JS).
For more information, see the official Laravel documentation on accessors and mutators

Categories

Resources