Transcript
Looking for something specific? Feel free to search the page for keywords to find a specific portion of the live stream that interests you most.
come on show me a picture
all right there we go now it showed me a picture i want to make sure the stream wasn't just streaming black um
yeah so i started working on a comment system and then i thought you know why not just uh stream what you're doing
um it's been a while since i've done this so i haven't gotten much so far uh this is
the new jaeger co site by the way this is what will be the future
uh kind of lesson page um so down at the bottom here i haven't
gotten too much so far so far i'm just printing out the post id along with just a text area there
and this is what i have going on so far
so one thing that i know that i want to add is i just closed it but if we look at the
database so for the comments so far i have an id name post id user id reply to
state identity body created and updated that but i would like to have in addition to just the post or the
post id uh and another id that is the parent
the root parent comment id so that you can nest comments
and so that i can pull them all down in one tree uh so i want to add that and then i also
want to add a level so let's go add those in really quick so
let's create a migration here
i always forget to put the dash dash table but that's all right it doesn't take long to do that
comments add root there it is okay so we want to change this from
create to an altar table uh the table the name there is going to be comments
and then instead of all of this fun stuff we can get all of that out of there and let's add in our columns so table dot
integer and then we'll call this root parent id it should this should have a
parent id too evidently i did not have that in here
whenever i ported it over or maybe that's what reply 2 was
yeah that's probably what it was all right so root parent id
unsigned uh
id and table comments
and we'll make that not nullable all right and then we will also want to add a level so integer
we'll call that level index um not nullable and default that to
zero okie doke and then down here
this schema dot altered table
table and then we want to just drop those columns so i like doing this
uh what did i do wrong here oh yeah table name
there we go all right so i like doing the columns one at a time whenever i drop them just in case anything needs to
change in the future it's just easier to visually see that you know what's going on here so root
parent id and then we'll do another one drop column for level
index okay so and then i also like to just check and
make sure um this is my first time using whatever this is this extension so i don't know how to
check and see what the structure of or even if it can do that but i'd like to check and see what the
reply where's my comments
oh i probably got a refresh yeah there we go all right so i want to check and see
what the structure of the reply to is make sure that it's an int and yes so that is the parent id quote unquote um
okay i'll probably change that in the future all right so then let's go ahead
into our comment model i did that backwards but here it
is and let's add that in here so reply to
and act column public root parent id
of type number and then we had a level uh put put the level index after the
ids right column public level index
of type number there we go okay so let's go ahead and run that migration so that's in there
uh there we go
okie doke and let me go ahead and refresh that make sure that i don't know
if that updated or not all right we'll just hide that for now all right and then let me go back to
the lesson page here and we can start stubbing this out a little bit more so
actually i need to go into the comment component that i have going on
here so so far this is all that it is it's just a a text field that i'll eventually make
hidden just wanted to make sure that the post id got pop populated in there okay and then we have just a simple
form input of type text area so then i will just add a
button type submit for right now we're just going to do this as a normal
form action for right now and then later on i'll switch it over to using uh
uh api requests all right so we'll just have that is that for right now and then we'll do our
end and submit comments fine for now
okie doke so if we come back over here we should have a simple
form here all right go ahead and
just add a h4 uh font semi bold margin top six
and that'll work for right now okeydoke so that's what we got going on
so far we need a way to save it next so we'll go ahead and i don't know if i
have a comments controller or not oh let's see there we go
so let me go check and see if i do so yep right there alrighty and let's see we'll want to
store wrong keyboard shortcut there we go
and so we're going to want to request response
yes and probably off
all right so let's go ahead and
let's also make and now we'll worry about validation later so const um
let's see we have the post id and then we have the comment which i didn't give that form and put a name yet
so i need to remember to do that request dot and uh let's see i
think it's only and we'll do post id and comment
and then we will await i'm to add a little to do note here to validate
okay and we'll so we'll do const comment equals away
comment dot i'll take that imported
let me go ahead and import it
models comment there we go
dot create all right and so
well let's just switch this to data for right now that'll make things a little bit easier to switch over
whenever i do add validation and we'll spread that out and then we'll also want to add in
if there is an authenticated user i think it was called user id
yes all right so user id is auth
user id and we'll want to there we go
all right and then for right now let's just go ahead and return response redirect back
so response redirect back
all right so very simplistic to start so let's go to find that route
route dot and this will be a post
comments comments controller dot store
as comments dot store there we go and let's go break that up into our form
whoops did i just type something i did
route comment comments dot store
and then i need to remember to put a name on here
comment actually i think that's supposed to be body yes so we'll change that to body
have that match what it is in the database which means i need to go back over to here and nope i actually don't because i
switched that to data so we should be good there and so this should just in this simplistic
form go ahead and save that into the database so let's go ahead and test it out so we have
actually let me make sure i have all my null not nullable stuff taken care of here
id is good post id is good uh state id oh we don't have a default on that do i
alright i need to figure out remember what that was and then uh an identity
so that is what i use if there is not a user id uh
and yeah so we'll need to take care of those two i'm just gonna
see if let's take a look at the enum see if we have a so we have states
uh so let's go ahead and import those so import
states from app enums states and let's
drop this down into a new line all right and let's give that a state id
states dot oh yeah all right so this will depend so
if there's an auth user so auth.user.id
then just go ahead and make it public otherwise we want it to be
uh let's see what did i do in review interview probably makes the most sense
so if it's an unauthenticated user posting an anonymous comment it should go into a
review state where it needs to be approved first before it goes to being public so that's
what that's all about and then what was the other one
identity all right so i i don't remember what i had going on
for that for authenticated users or and then i had a separate service that
kind of generated out a unique name um so for right now i'll just do asdf on that just to get stuff saving
okay so we should now be able to go ahead and this is a test
it won't display or anything it's not being pulled down with this post or anything like that but oh yeah csrf
so then we need to uh come into that edge form here
and add our was it two or three i think it was three
or csrf field into there
no evidently it was two there we go all right so now we should be able to do
this is a test go ahead save that off and got an error
insert and i need to turn this off but i i was working on the error page
um oh root parent id yeah i just added that in that needs to be defined too
okay that should actually be nullable because if it is the
root then you can't assign it should be its own id but you can't assign it to that
so this should be nullable after all so let's go ahead and rerun that
migration
okay so now that's nullable so we can go ahead and try to resubmit
so let's do this as a test and there we go all right so it should
have saved um we don't have it coming back or anything like that but if we go into the database change this back over to data refresh
there it is so next thing that we'll want to do is
to i guess go ahead and get whatever i was doing with the identity rigged back up
so i'm going to go check out what i was doing for that real quick
so let's go into controllers http there should be a comments controller
store [Music] all right let's see identity identity
service dot takes an ipn agent agent is request headers user agent
all right so i'm going to go ahead and grab that because i'll probably forget exactly
what that is and let's go back into the
comments controller plop that up here with the data that we have so that's just the user agent string
coming from the headers and then
oh i guess previously i had the post id and url let me grab the ip address too so that's
just request.ip i can remember that much all right and then we'll want to grab the identity service
so
because i do not remember at all what i had going on there i just know that it was generating out
a random name for users so let's go back into here app services
and then i have this identity service here i'm just going to go ahead and grab the raw version of that
all right and then let's go ahead and make that so
all right so app services
identity service and paste that in there all right now i thought that uh see i do have a cache
service done yes so i just need to import that so um
i'm surprised that's
oh it's a promise okay so that changed so i just need to add in a weight here
and make this async i'll just take that off
all right there we go and then it looks like i was using a unique names generator
so let's go ahead and install that
okay so in essence what this will do is it will
take in the let's see where's the root at here create so it'll take in the ip and the
user agent um it'll grab whatever the secret is i don't remember
oh okay random byte string um
and then it will attach that onto the user's cache
uh oh it's too early in the morning for this uh let's see
yeah so it's just checking to see whether or not there is already a secret if not then it will create it and then if so it will grab it from the cache and
it will return that back here so this is now async so this needs to be await and then we'll take the crypto we'll
create an md5 hash and that will join in the secret the ip and the user agent
and it will return that back
so then all right what was the call order for that
see so we do create to get an identity and apparently that just returns back the identity doesn't it
okay i wonder this must have been used for
something else generate name unless that's down in here
but i'm not seeing it highlighted okay so let's go back into the comments controller then oh i didn't save
okay so let's go into the comments controller now and i didn't save on the comment model
either there we go okay and let's go ahead and get our identity
so const identity equals a weight identity service dot
create and that will take in the ip and the agent
okay and so now we can replace that here and just get rid of that all
together and since that's going to
be like that we'll put that up there and let's see what was the other thing i need to take care of
you also probably want that root parent id to be provided
if there is one and then we'll type that in here if there is one no that would be on data
so we don't need to do that all right and let's see anything else
reply to pray yeah posted it was coming off the params um
okay all right and then we need to do that
notification service at a later point in time but all right so
should be good let's go ahead and get them coming down a little bit so let's see that's i think
the current lesson page that i have rendering outs here so let's go ahead and
i'm going to do a separate query for this so wait post related
uh do i not have comments defined i probably don't no i don't
oh oh let's see how do i block a user
stop it
all right well hopefully i got all of them people are gonna be
all right well i guess i'll just ignore that go back and delete them later um let's see
surprise there's not like a block option on there it really should be
all right so i need to go to find the comment on here on the on on the post so post model
let's go to find the comment in here scroll down to where we have these
uh so this will be a has many
so put it underneath the other has minis
comment public comments has many
type of comment
i don't think i don't think my auto imports working
oh there we go okay i guess the wrong thing was highlighted all right so that should not be defined
there i won't worry about the inverse right now i don't think we'll ever need it um
so now it should be in here there it is and so we'll get the related comments
we'll go ahead and query it we'll want where the
reply to is null so where
null reply to
i think that would be it um
well no well all right we'll start with that and then we'll do an order by there should
be a created app on there that we will order by descending so that newer comments are
displayed first um and then we'll do
that should really be comments not just comment comments there we go
so that should be coming down onto our
lesson page so
yeah we'll put it in there that'll be small enough to where that won't matter so i'll put it in here um
underneath here so we'll just do a simple ul for right now just to get them listing out
li oh really i guess that would be an ordered list with it
all right and then
oh i need to pass in the comments so be up here
and since it's right off the root we can just pass it in like that and so we'll do an at each
comment in comments this only changed a little bit
in the future but for right now this will work um
and then we'll do a simple just paragraph and
we'll just drop the comment.body on there for right now and we'll do a little h6
with comment dot and i will put the identity
and then i guess it would be
see it's because it has a user id we'll probably want to preload the user so we'll do that so we'll do
comment dot user dot
username otherwise comment.identity all right now we need to go preload that within
here i'm going to go ahead and drop this down so query
we're in all order by let's add our preload into it
and i probably need to oh no there it is i already did define it cool user um
and that should that should that should be it i think
so i should get those displayed okay let me make sure i save this and now let's go back in here and all
right so it looks like it's coming through as a null for the body which shouldn't be right but ah it did save us
an all didn't it okay so then let's see i guess let's check
and make sure that the name on this is getting plopped on there
yep name is body okay
and then i bet you i left it off of the only comments controller not that there we go
yes i lifted his comments so that's why that came through as null so let's go ahead and
delete well let's go ahead and plop a delete button on there we can go ahead and delete real quick
oops so let's go down into back into here
and where we have it listed let's just drop a form method
equals post action equals and then i don't have the
route defined yet so i'll need to do that and form
and then we'll do a
i'm just i'll just manually find this button type of submit
and we'll just do that and then we'll tack on
a hidden input name equals id
value will be comment dot id and there we go all right now let's go
rig up that action and define it on a route so comments controller we'll scroll down to destroy
let's see we're going to want request response
and i won't worry about authorization there for right now we'll just go ahead and get it going
so con oops const um i d
equals request well request only
id and then we will do uh await
comment dot find
yeah let's just go ahead and do a straight up query delete where id
dot delete and then return response and for right now we'll just redirect back
just getting things working on the front end and then getting the crud operations actually working here
we'll worry about changing stuff back to api responses later on so route dot
delete i don't know why i put a space here there we go comments
and then well i guess that ids would normally be in the url instead so let me change that
comments controller dot destroy as
comments and destroy
okay so we'll go ahead and save that let me go back over to here let me change this to a param
so we params don't think we'll need request at that point const
id equals params.id and then let's go back down under here
and change that to match as well okay so we'll want
route comments dot delete we'll want our id
here so comment dot id and then we're going to want query string
uh let me see is it
i think it's underscore method if i remember right delete and am i missing a curly brace
and it will tell me if i am so let's go ahead and try this out
i bet you i am oh cannot find route i bet you i didn't save i did save
oh i named it destroy yeah all right i like that better let's stick with it
there we go and there we are we're back we have this we have our delete button
so if we click on that up always forgetting to see srf all right so let's tack that in here as well csrf
field let's go back and
let me refresh just to make sure that populates and let's try that again and there goes that comment goodbye and
let's try creating so this is a test make sure that the body gets populated now
well that did not seem to work
oh maybe i didn't click the button right all right yeah so there we go now the body's
getting populated and then we should be able to check in the database make sure that we now have a random identity being
populated nope that's not right it should be a string
um not not not like a hashed identity
i think
let's see so that definitely just calls await
identity service dot create which is what i'm doing i copied that over as is
huh oh okay i see i missed this line down here
all right so yeah so if there is no user id then then
that's where i'm calling get by identity that makes sense okay
so we'll come back up into here and
identity is that and i was saving that into what property name comment.name
and i was not saving name if there was a user okay gotcha gotcha
so let's go ahead and tack name onto here too and so we'll do
let's just go ahead and tack user id into a property so we'll come up into here const user id
equals off user id oop there we go
so if user id then we'll make that null otherwise
we'll await identity service dot generate name
oh that must take something i'll get by identity is what i needed to call and that takes the table name and
the identity property okay dot
get by identity which will provide comment dot table for the table name and then the
underlying identity there we go
and wow why the reds quickly string no is not assignable to perimeter
oh okay so just change the stock defined okay
and then was i saving the actual identity before probably right it makes sense too yes
okay so that should now be good so let's go ahead and redelete that comment recreate
it make sure everything's going okay again so let's go back down here delete you
scroll back down to the bottom there's another test
bam and there we go username is right and then if we check in the database we should now have a
proper oh yeah no names all right so let me log
out then and try another comment so i'm gonna go ahead i believe it's gonna plop me back to the login page whenever i log
out oh the homepage okay
no no i don't have that problem working properly okay uh
where would that be
let me turn back off um the errors
uh let's see if i can remember where that is yeah right here let me just set that to true
turn back on the normal debugging errors okay
prepare oh the author block okay oh yeah i was just using the auth user for that wasn't it
all right so i will wrap that up in an if that's the quickest easiest way to go
about it for right now so let's see that was
author card
where are you actually you should be able to drop that directly on author since author is
populated here i think author dot avatar maybe at the very
least it'll be empty because author will be a string so there we go okay so let's
scroll back down and now being an unauthenticated user
on authentic uh wow on off and ticket there we go
test submit that all right it seems to have worked and
oh yeah i'm displaying the identity so instead of the name um so let's switch that to where we are displaying the name
where are you right here so instead of displaying identity display the name
and there we go chimpanzee brandy741 branda
okay regardless unauthenticated users are able to submit an anonymous comment
okay so
let me go ahead and log back in
go back to that page i kind of have a convoluted path to get to that page right now
there we go all right and i guess next let's go ahead and i'm not
going to worry about display i'll worry about that off screen um like how things are rendered out um
but let's go ahead and get a reply to functionality working
uh so that's where things get a little nested so we'll probably want to split this out into a comment form
component so that we can just drop it on and it will
be there so we have to keep writing it over and over again so let's go ahead and
create a new folder within components called
comment we'll move this into here
we'll change this to list
or maybe maybe base yeah base
and because it'll be the base component for the comments and then we'll switch this out
into the form so we'll add a new
one called form dot edge we'll paste that in there
we'll save that come back over to here
add that there what all do we need to provide to that so it definitely needs the post id to
come down with it i should probably have a parent id provided to it if there is one in this case there wouldn't be one
so all we need to do is do the post id here and that's provided as the same as that
so we can just do that and then down here
um i don't want to display this so let's wrap all of this up into a div to
kind of encapsulate every oh whoa wait a minute hold on a minute i've gotta i went and did a ordered list
with an li and i put the looping inside of the li
all right there we go that's more proper and now
we don't need that div we can just use the li okay so we'll do another ordered list
within here i'm gonna put a line break in there just so i can easily see where that is
do a um all right and this is where i want to
change how things are being queried because i want comments to just be
all of the comments and then we'll have this base worry about what should be displayed first and what should be
displayed within so in the comments controller
we or no sorry in the series controller for right now
because this is the page rendering this out eventually i will move this into a service
let's go ahead and get rid of the where null and instead let's change this to
so let's see it shouldn't just be a state check because if the current
user is the one that commented they should be able to see their comment
and so here let me show an example here so if i go into
the current site and if i come into just a random post here
do the first one scroll down and
this is an non-must comment
and i post the comment i should be able to see my not oh i'm logged in it's not very anonymous is
comment logged in log out
i think this still redirects me oh no okay good
that's the behavior i should have on the new site too it takes you back to where you are all right so this is an
anonymous comment
so i should be able to comment that anonymously be able to see it myself so if we just
do a simple state check this won't come back at all because it won't be
public it'll be in review but since i'm the user that commented
um i need to change that that shouldn't
um then i need to be able to see the comment that i left
and i need to be able to see that you know a little warning here so it states that this is pending approval it's not
being publicly displayed right now and i should be able to alter it and delete it if i wish so that's the behavior i would
like to maintain um so
let's try it i'm going to cheat and check and see what exactly i was doing to do that
um it was something with the identity so let's see if we come back into here
that should be probably on
the posts controller on show or maybe it's lessons no
show all right yeah so we're grabbing the
current user agent grabbing the ip it's not the best check but it's good enough
for my simple site
and then this is going to be vastly improved by that parent id so i started out i just went like three layers deep
on the comment system and then anything below that the front end took care of loading additional
which isn't much of a problem but it'd be better to just load them all in
in one go and then have the front end dictate how it should be displayed all right
so back to what i was doing before so all right so we have this simple where
the state is public or where the identity equals the identity up here so all we need to do is grab the create provided the ip
agent so i'm just going to go ahead and copy this line here because it's going to be the same
all right and at that point it would be a lot better
to just go ahead and drop this into a service so let's do that so in here
let's create a file
comment service
get for post or something like that
um i was just let's call it load
yeah yeah all right i'm not gonna worry about naming right now and then this she'll
take in [Music] i guess the post id
for starters and then let's go ahead and copy what we had in the series controller is a good base so
copy u paste that in here
um oh okay so we can go ahead and just drop in the post record as a whole so post of
type post okay and then
that takes care of that so then all we need to do is take care of our aware statements and then return that back so
we can just return directly back from here all right
so let me go back i just over what i had copied from here so let's copy this and paste this into here
i'm going to switch this over to an http service so let's drop this into my http folder
just make it easier i could provide these each time but i don't want to have to remember this
right here the getting the ip address isn't too bad but this i would i would forget now i could extract this out into a service
call that service each time but i'm just not going to worry about it and we'll just extend
wow okay extends
the base http service so now
i should be able to do this oh i need to take the static
keyword off first this dot ctx request and just get that directly within here
and then i need to import the identity service as well
and change this to this dot okay so that should be good
and then down here we need to do our where and i'm going to do this as
a callback so we'll do query
and we'll do dot oh i'm not doing this right
oh yeah no query query there we go dot where
uh this would be state id state not stat state
id is states
or is it status
where is it oh state yeah all right so
what did i call that enum i thought it was states yeah
i guess internally i called it state but i need to change that naming
i also need to change my enums to be in the contracts instead of with an app
okay so states dot
public or where
identity and we can switch that to there
okay so either the state id should be public or the user's identity should match the
comments identity um
and then just order by those descending all right
so that should be good for starters let's go back into here and let's do const comments equals and we're going to
need an instance of our comment service
so i'm going to do at inject
add a constructor public
define the comment service as the argument there so that will be injected and then we'll await this dot comment
service dot get for post and we'll provide it the post
okie dokie so that should be working okay let's go ahead and scope it out let's see what we got
oh i called the um called the yeah i changed the name of the component but i didn't change how i
was using it so let's go back into well i need to save that first and then we'll go back into our lesson page
and update this from just comment to be comment.base there we go
okay so there we go now we have this coming through um
and now we need to add in a reply button and you note that the anonymous comment
is still coming through i'm not sure how i was displaying the um
that the user was the current user i guess
i'll read about that later but you could tell that the fact that we have this here uh means that our or statement is
working within our queries so if we come back into the comment service and we comment this particular portion
out here and we refresh we should not see the chimpanzee yeah so that's gone so our or
statement checking the identity is working and so let's go ahead and add in a reply
button and the reply button should only be there if the user is logged in
yeah that's really the only requirement so the user just needs to be logged in so in order to reply to something you need to be logged in
or i feel like there should be an or statement there because if how do you
respond as an anonymous person
i'm pretty sure i just blocked that all together previously let me go test that out
come down in here testing
bam there's my comment yeah i don't have a reply button at all i don't have a reply button to any of these i have a login to
reply okay i don't know whether or not that's the behavior i want to keep i guess that
makes sense that we don't have an honest person coming out here spamming everybody um
so yeah we'll stick with that behavior i guess so let's go back into our comment
yep base here and we'll do
a sub li and we need to change the way that this
is looping so up at the top here instead of looping over all comments because if you reply to a comment it's going to go
down up into here well we'll do we'll we'll do the reply behavior first and then we'll worry about that actually how about that
so let's add in a button down here that
let's i'm not going to worry about the show right now i'll worry about that later um just get alpine in here and make that nice and easy
but let's go ahead and drop the form in here so at comment form
okay we'll drop the post id in and then we're also going to want to drop the
root parent id and the reply to
id and we could set that up at the top here within the loop so that we can make
things a little cleaner within our template so we can add set i already got the post today taken care
of that's coming from the parent of this component but the root parent id will be the top level
loop comment so that's going to be this comment here so
that will be comment.id and the reply to id will be the
immediate comment so that's going to again for right now it's just going to be
comment.id so reply to comment.id as we get more nested the
reply to will change but the root parent will stay the same
so that should be taken care of now we need to change this form here to accept the root parent id and reply to and plot
them into the form as well so that here it's just right over here i'll just do that
okay and there should be hidden fields so we know that well yeah i'll leave that the same we'll
make it visible just so we can see that it's there for right now and then once we know stuff's working we'll change it
so let's see what was it it was a root parent id value equals
root parent id okay
and then we had another one that was just reply to
ah there we go okay
put a break in there and so now those should be on the form we can also wrap those up in an if
statement um
shouldn't have to though and then we need to check and make sure that the
comments controller is bringing those in so we have the root
parent id being brought in but we also need the reply to okay and then those go directly into the
body or data which we then spread out into the comment and then we'll worry about validation later on
so back to the form everything should be taken care of if we go back to the base
everything should be taken care of so we'll just go ahead and test this out so we have the form being displayed
not very nicely on each one you can see that the ids for the root parent and reply to change for
each comment here that we have and then they are undefined for the root so if we add in a root so another root
comment which should be directed back and we should have in
oh okay so i guess i do need to um actually wrap those in if
so instead of undefined here we will want those to be null
you could probably just actually have that fall back directly in line so within the form here if it's not
provided let's go ahead and just have that fall back to null instead of undefined
or that's delish or yeah
there we go all right there we go now they're null so let's go ahead and test another route
comment submit that up still invalid input syntax right here type integer
all right
let me go ahead and just leave them off altogether it's probably coming up as a string
so let's take this out wrap this up in an if
and if root parent id
reply to yeah type the if statement then it completely
done i mean i did no clue what i was or i couldn't remember what i had just
copied all right there we go so let's go ahead and test that out so if we have a root parent id then it should uh plop it
in otherwise it'll be left off so let me go ahead and refresh make sure that those are there there we go now those are off all together
so if we another root comment
there we go yeah so those were probably coming up as null strings which makes sense
and so there's our another root comment right there
so then if we come into another root comment here and we type in
this should be nested
let's plop that in here and so we'll check in a database but what i expect to happen right now is it should
be listed but it should be at the same level yeah so you can see it right here it's at the same level as all of the
parents it's not within the one that it's actually a response to so let's check and make sure in the database that
the reply to and the root parent id actually populated i'll repair an ids over here yes so
those populated we do need to take care of the level index we'll take care of that here in a second but
the actual behavior that we're looking for is there now all that we need to do is tell our front end how it should
properly list those out so we can actually extract this out into
well let's go ahead and take care of the root level first so what we'll want is we'll want to so comments is just all
comments regardless of what it's a response to so our reply to is within this comments
array so what we want is we want to grab just the root comments and then we'll loop through those first
and then what we'll do is we'll provide in a nested component that is our list here
which will be the exact same as this but we'll pass it in all of the comments as we go and then it will just find the
applicable level within those comments for what's being displayed so here we want at set
root comments and we can grab that off of the comments so comments dot
um filter took me a second there uh so we'll do c
c dot uh let's see this would be reply to
is null so we could just do a not reply to all right and then we'll change this
but actually we'll extract this out into a list component so we'll do a new file
within here called list.edge paste this in here okay
and thinking actually
we can take this out make this even more simplistic because we're going to need that within here
anyway no not necessarily okay let's leave that
at the parent level so let's leave that here and then what we'll do is at
comment dot list so we'll provide it all of the comments and it will also provide it
the what's the best name for this
level comments i don't know um
but you get where i'm coming from so this was just the particular node node comments here why don't we call it
that sure we'll stick for that with that fair
right now and then within here instead of looping over the comments we would loop over the
node comments and we're also going to need to provide
the root parent id as well so that would come from here or no
hmm that would not come from here that would definitely need to be in here because
these are the roots if the level is zero so we'll also want well the level would
be coming off of the database which we haven't taken care of yet
okay so let's not worry about the route right now let's go ahead and make sure that this will work for the
children and then we'll do
child comments will be comments dot filter
um c where c dot reply to
equals comment dot id and then down here we won't need to display this ol unless there are child
comments so at if child comments dot length
then we would want to display that ol and then we'll want to let me not make that mistake again where i put my each
inside of the li at each um to see child
in child comments and each
and let's plop that li back in there actually
so what we want to do is reuse this component so let me go back a level here we don't want that loop to be in here we just want it to be
checking whether or not we have the child comments and then it should just reuse this component so component
list and then what we would do is provide it the
same stuff that the parent level is providing it so we're going to want
we're going to want so okay i forgot one thing at the base
level here we also need the post id to be carried down as well so post id there
post id because the um the form here expects it so we're going to need it at each level and then we're also going to need to
provide the root parent id and then the reply to
or no sorry the ch should just be the
node comments next yeah so node comments would then be the child
comments that we grabbed up above so there we go i believe that should be correct
and then that would just re-render this entire thing for the next level and then to make this a little bit easier to
see let's add a margin left of let's make it decent size let's do eight
so that we can visually see it since things aren't pretty over here oh can i read properties of undefined
reading oh yeah okay uh
oh yeah okay so we also need to provide the comments as a whole here too i don't
know if that's where the air is coming from we don't have a third level so maybe not but
we'll try well okay let me just click on it there we go
okay so that was what the error was cool all right so it might be a little difficult to see
but we have our root level right here so this is the create a root root level comment this is just start a whole
nother comment thread um hey uh
i'm sorry if i mispronounced your name is it roman um no i'm not using bootstrap this is
tailwind i pretty much use tailwind explicitly explicitly anymore
and then i'm just wrapping stuff up in my own custom components so like if we take a look at the input component
i have that within form input so you can see the tailwind stuff is just right here so
i kind of extract out all of the tail and stuff so that it's not bloating everything
um so that that's my approach and then all of this code is up on github uh
at the repository under yeagerco let's see it's github.com
jager hyphen co and then i think it's jaeger dot co yeah so all of the code can be found
here as well um but so this is the root level so you can
see we have oh no sorry this is the root level here because we have the margin left
so this is the root level form and then the root level starts here because that has the margin left on it and then we have
another margin left showing that this is a child of this particular component so that
seems to be working okay uh what we can do is we can test another so
this should be level three so level
one level two level three and post that in there i'm actually gonna add a border left to make it a
little bit even more evident that what level we're on uh so level three so we
have an indent there oop indent there and an indent there so that is indeed level three and is being
shown appropriately let me go ahead and add a margin left on there just to make it a little bit easier to see even more
so margin left or border left sorry border left border
and we'll do gray let's do 300
i'm not using the exact tailwind colors i'm using uh redux radex colors
so the color level is a little bit different so 300 is a lot lighter than tailwind's normal 300 but
all right so there we go so this seems to be working okay
we can go ahead and get rid of these inputs make them hidden so that's going to be inside of the form
so instead of type text we'll change this to type hidden
and hidden that should make things a little bit easier to see all right yeah that's a little bit better
and then we can go ahead and hide the um excuse me
the form behind a reply to button or a reply button
um well before we do that let's go and take care of the
nested level so in order to properly do that
since we already have comments in here there's two ways we could do it we could grab it off of the current
level so like if i go into list here we can grab it off of the current comments but if there are no comments
then it would default to level zero so we could do that we would need to delete all of our comments to make that work which wouldn't be too much of an issue
um or we could just manually pass in each time that we go down a list we increment the level count
not really sure which one which approach i prefer here um
either way we would need to provide it into the form so why don't we go ahead and go with
this so let's do
within the list at level index equals
level index and then default it to zero if one's not provided
um and then we will provide that into the well no actually
because the form for the root is out here
so really that should just that that set should be in there not not out here so let me take that off
and let's provide that into the form instead and really we could make that a hidden
input so input type hidden name level index value equals
let me go ahead and just finish that off there we go level index or zero
and then so we don't need to worry about it at
the root level now because it will just default to that zero i do need to save whatever i change there though
um and then here
ah let's see i'm gonna break this down it's starting to get a little bit
lengthy okay and let's add that in here so
no level index and let's
do what do i want to do here
you would start at a one because then this would be zero now this would be yeah no this would be
zero
but then that would make this need to be one so
no that wouldn't
there all right
because no yeah let's do that so zero
would be for any here one would then be for any inside of there so that
defaulting it to one sounds right to me and then we already have level index defined so we can just take that off put
that here okay
that sounds right to me i'm gonna go ahead and make that a non-hidden component just so that i can
visually easily inspect and make sure that that's what's so let's just change the type text
okay and so we have level zero here which is what we want we have level one there
level two there level so that seems to be working just fine go back to level one one and okay cool
so now what we need to do is persist that um so let's go back up to our comments
controller here and grab that out of here
it's a level index that will get populated within here so that should now be good um and then
next thing that we would want to take care of is editing
well let's go ahead and hide the form first because that way we don't have two forms being shown at the same time
one for editing one for creating a response so
let's see here so we'll take in let's see at the root level here let's
it's going to be need to be in the list and dictated from within here so
we'll need to use a client-side thing wait a minute do i have two indents here i do
i'm not sure how that happened so let's do
trying to think of how alpine is gonna behave if i
instantiate like what is x data
on each li and nest that down i think that would be very
well i think that's how that's intended to be um
why don't we take it out the base here
let's try this first i guess so is the x init or x data i think it's x
data all right and then edit id
no and
yeah i think that that let's stick with that and then
at any point within here that we want to edit it we'll have a edit button so i'm just going to go ahead and
see the students div class flex item center
justify end
all right and we'll put see edit should come before delete so we'll just put a button type
button um click equals
edit id equals and then we're going to need to provide alpine
what level we're at oh no we can hard code that
so okay we'll provide that directly from adonis so we'll do
comment dot id there
okay and we'll do an edit there and then let's go ahead and
duplicate that again and
we'll want some way to
uh asks can we use graphql with adonisj i
think so i think there's a package out there for that i'm not 100 i've never tried so i'm not 100 on that but you can check
packages.js.com it'll have a list of packages that you can search through
let's see if there's i don't know if all of them are listed in here but this will search both
community and um first party
so it doesn't look like there's any listed in here but that doesn't mean that there isn't one um
so i i'm sorry i don't have an answer for that but i do i'm i'm sure that there's a way to
package that in there i just haven't tried
um let's see where was i
so we're gonna want a way to say are you using a or are you trying to create a
comment uh so we'll need like a create id i guess default that to null 2. so we have an
edit and a create id and so if we're editing change the edit id if we're creating
change the create id
and then uh jeno said graphql is not built in
there's a third-party package but last time i checked it was under development constantly changing yeah so
probably still in the works in like a beta state
um okey doke so we have the creativity editor id that
should be set what we will do next is
let's just display whether or not we're at that level so
um let's see let's do let's do
p with x text
eh
i'm trying to think of how how i should display so
we can't pass any of this down through adonis because that's at the
client side at that point so within the form we just need to kind of check whether or not this should
or we could wrap it we could wrap it here and that would yeah let's do that let's wrap it that way everything is
maintained here and we're not doing another check with inform to check and see whether or not a variable
instantiated here or edited here um so we'll do div
v i think it's v show no that's view x show
is uh let's see so this is the reply form so created
id equals and then we can use adonis to just provide what that equality check should
check against so comment dot id
and div and there we go so we'll work on oh need to change that text to
work on reply first so we'll see whether or not this all right looks like we got an error
create id is not all right that might be an old one see if that's still relevant
looks like it is all right i bet you it's not x data i
think it used to be but maybe it's not anymore let me go check i don't use alpine all that much um
al pine js let's see
what is x data hmm what am i doing wrong then
create ids not defined all right so it's on the x show that
it's complaining about it um
okay so it's just it is here
did i name it different is create id is that what the error is coming from did i do created i did create it that's
where they okay so create id there we go let's change that
all right there we go now we got our reply edit that they're not pretty but they're there
so if we tack on reply here boom there's our form if we tack on reply there that form
should go away and there's the form here boom
um i don't intend on doing a payment integration within this particular series that'll be within something
different in the future though i don't have a timetable for it though
but there's a package um i think menzie created uh
for payment integration you can check that out on packages.thomasjs.com i did see that in
here yeah payment it's for stripe uh so you can check that out and it should help you out at least
decently all right so we can hide the level we know that that's working
um all right so where do i here it is so we change that to hidden
and then i can get rid of my little to do here since we've done that it's to did
and then add some spacing to those buttons so that they're not horrible to look
at that's in the list uh so we'll just do space x
three i should space those out decently yeah so that's good for now um
and then we need to do an edit so right now edit's not doing anything response will
should be able to add a cancel button in there too
so we'll just pass that in as a cancel bubble is that how you spell it cancel
i think so cancelable true i don't know good enough for me i'll know what i mean
um so then within the form we will do
at if cancel a bull
uh we'll add in a little cancel button so at button type
but button um
and then the variant
i think i can name those secondary and then i want to change this one too
i think i think that's right um and then we'll do
margin left of three so there's some space in between them so we'll see if that renders stuff in there
what i do unclosed tag yeah i did not close that did i
end and cancel
okay so the root level should not have a cancel button because otherwise how are they gonna leave a
comment if they change their mind but reply should and all right cool
that's kind of what i was going for and then when you click it it should
reset the form and hide the form
which there is no yeah i guess you could just grab the form i don't know if there's a ref that
alpine has off the look but we'll just take care of the viewing for right now so we'll just hide the form on click
so we will want that to be passed in
because at this level we don't want to worry about what exactly is going on whether it's creating or responding we
just want it to handle whatever is provided so here
within let's go ahead and do the same thing here let's drop this down let's start needle a
little long too we will want
on cancel or something of the sort
and we'll want to provide that i don't remember how i do this
i think you provided as a string i did this in the studio portion um
where you pass in a client-side function from the server side
edge uh so let's see let's see uh this should be
a function that well it needs to be a
hold on a minute so it needs to be an alpine function not just any old function
so let's come back up into here maybe we change this to
here for right now i'll just go ahead and just drop this down and we'll do it all in line
so cancel make this a function that
this edit id equals null and this create id
eq create there we go id equals null um
we can also since we only have we will only have one thing um happening at one point in time let's
go ahead and do an edit function okay that will take in the
edit id and what this will do is it will set this it will this dot
cancel so we only want somebody to be able to edit or create show one or the other at any point in
time so that's why i'm calling cancel here to cancel out both the edit and create and then we'll reset this dot
edit id equals edit id and then we will want a reply
we'll call that create actually since reply should be more of a method
for creating um let's see and then we'll take in the create id
spell that right what does that look wrong that's right create id
this dot cancel again and then this dot create id equals
that provided create id okay so now we have these methods that we can
call from within here so instead of this
we will change this to create and then we will use
edge to provide the id that should be provided to the create call whenever that's clicked and then the same thing
going on here for edit so oh missed the bracket or parenthesis
there we go i'm going to go ahead and put a space there just to make that a little bit
more readable i think it's hard to tell what's bracket and what's parentheses there there we go
okay so that should work for that and then down here
i don't remember how i don't know if i used alpine for that in the back end i think it was just a native on click function
but let's try to provide cancel
like that and then i guess since we're in the comment we're in the forum
we're gonna know that we're using alpine here so we can make that judgment call
and then how do i provide that into this here though let me take a look at my button component
where is my button component here's my button component okay so i know if i provide on click
so we could do another uh form of that so on click would be for
a native javascript function if we want to do alpine
we could do at click and then provide it
on at click i don't know
or undefined
we'll stick with that for right now and then um yeah anchor should probably need that
so that should be okay and then we'll go back to the forum
and so we'll do at click sounds horrible and then
that will be yeah we'll
leave it just that so come back up to the list and then we'll
define that on the form so on cancel should now be
at cancel that's what we should define that as
i guess no on cancel there's more right and we'll provide that
cancel so that'll be an alpine function and so we can discern within
here that it should be at click on cancel
i think i did that right we'll see all right we got no
no edge errors so that's that's good so if we reply
to this one and then we hit cancel oh thank goodness that works
hey malek thanks for stopping by um so then we just need to do kind of the
same thing so whenever you submit a comp well it will re-render the page right now so we don't need to worry about that
uh but we will want to do kind of the same thing whenever you click on edit so we're going to need to add an edit form that pre-populates
the current comments data and then pretty much just mimic everything else
so um
we need to go outside of the form back into the list and so this is the reply so i'm going to
add a comment make that a little bit more evident so reply to form
and the edit form probably want that to be above it so edit
comment form div we'll want another x show this will be edit id equals
and then from edge we'll provide the server side comment id into the client side
alpine check there and div
and then we're going to want our form so comment form for the most part we're going to want
the exact same thing
uh no
eh i guess those would all come from the comment itself
so let's go ahead and hard code the hard code those um so that would be comment dot
root parent id reply to
comment that reply to
a post would be comment you won't want that to change post id
and then let's see what else do we have we have level index that's never going to change so we'll have comment dot
level index
i wonder if i should just spread the comment into it for the most part these are one to one
then you got the on cancel so let's go ahead and try that
because then the form itself will pluck everything off of this that it needs so nothing will get provided to the client side that shouldn't be provided
um and then all we need to do is provide cancelable true
on cancel cancel
um and then we need a way to provide it what the action should be so currently
if we take a look at the form it's just going to hard code the store so what we
need to do is tell it whether or not it is editing a comment or whether it's creating a
comment so i guess we could just check whether or not we have a
id that passed through that would since we're spreading the comment out that would take care of it
so we have the entire comment being provided so why don't we do that so
within here we'll do at set action and we'll default this to route
comments dot store so we'll default that to create but then we'll do an if we have an id
then we'll do our end if there set action so we'll overwrite it to be route
comments dot i don't think we have this route created yet but this will be update
and then we'll need to provide the id and then we'll need to provide
method did i spell that right yes okay it's a little bit far away that you look like something else to me um
put yeah okay and then
we will overwrite not the curly braces but just what's inside of here to our action
okay and then all of these should come off of the spreaded post so those should all be just just
fine thank you malik appreciate the compliment
um and then we need to take care of the body so the value should be an empty
string if there is not a body so we can do body and then we also want to get it in case
whenever we do add validation there is an error so we could do
well let's worry about that later because we're also going to need to show it because if we come back to an error it's going
to be hidden anyway so
well we'll go ahead and add it in flash messages get
body um
i think you can do that multi-level no class i i think you can do that
all right anyway so give priority to the flash message if our validation fails then it will plop
what the previous value was within here oh wait a minute
no we do need to change that don't we well check it out based off of the id so yeah all right we won't worry about
that right now we'll need to check that based off of the id to make sure that we're not just plopping that in every single form
um but then we plop it into the one that was actually being edited
so worry about that later we'll need to add a check to see whether or not the current form was for the edited and then
we'll put that in there um all right that was a long circle where
was i uh let's see input form body so yeah okay
so then we should just change this to be if we have an id
update otherwise create probably change that verbage
anyway in the future but we'll leave that as is for right now and i think that should take care of it i think
that's it main thing here is checking whether or not the body actually does populate and
whether or not these here populate correctly and that the action properly goes to an update oh yeah we
need to create that um so let's go into the comments controller first take care of the update action
so here get rid of that comment that doesn't make any sense to do and then let's go down to
update i don't think for this we're going to need edit or show
creator index we don't think we're going to need any of those so we can simplify this controller a little bit
okay and then we're going to want
to get the body data response eventually we'll want off
and params whenever we do authorization checking we'll want auth there
but again i'm gonna go ahead and add a comment here so i don't forget
to do authorization
okay so const data equals request dot only again
we'll worry about validation here later um let's get just get stuff happening first
post id body root
parent well really these things should never change so why don't we just ignore them
right we just ignore them the only thing that really should change is the body whenever you're updating that should be
it and then we'll find the comment so const
comment equals weight comment dot
finder fail actually we can do my lazy man's
authorization here for right now let's do off user assume that we have a user
related so then we are assuming we're restricting updating to
the authenticated user so that they can only update theirs by doing the related off of the user because now the user id
is not going to need to match based off of the authenticated user id so it's what i call my lazy man's authorization
check so we'll start with this and then i'll add in bouncer later on uh so
what is it we're doing comments i don't have that on here all right so let's add that onto our
user so that i can do my lazyman's authorization user
this is going to be has many as well so it has many
comment make sure that i get one that's going to auto import there we go public
comments as many type of
comment and then the property for that is user id so we don't need to worry about defining anything like that there okay
so that should be good now so let me go back in here make sure that the autocomplete is showing it
comments there we go cool and then we could do
where [Music] id is params.id
first or fail so now that we have that first or fail on there oh and then initiate the query
so that we have the first or fail on there if the authenticated user doesn't have a comment matching
their user id where the u where the id is also the param id then it will fail it will throw 404 so that's why it's
kind of a lazy man's authorization check because you're still authorizing the user by querying only the user's
comments but it's not you know the actual authorization that you would want but
it'll work for now um so we have a comment so let's do a wait and we can just do comment dot and emerge in the
body that we're grabbing off of the request body so we'll merge in data that's an object
there and then we'll just call save and that will take care of it and we can return response
redirect back and that's all that we need so let's go ahead and define that route so routes
put this before delete route.put comments the id
comments controller dot update as comments
update and then i'm going to go ahead and put all these comment ones on the same
tab level there we go this makes it a little bit easier to scroll through your things and see what's all grouped uh
together because they're at the same indentation level for the controllers all right so
i think that should work i think we should be all good now so let's go ahead and
try to edit one so let's start with a root one first let's do this this is another test down here and okay so
starting off bad by not having a state for our text area
oh i think i'm plopping the value in there wrong it should go inside
unless this is trying to use alpine oh it is x model value
interesting so looks like the post id didn't go the level id
it was zero anyway uh but yeah it doesn't look like anything populating correctly as i had hoped it would
oh oh it's because we have a nested i bet you unnested no that should still go because this is
being provided um server-side so that should still work as i had hoped it would
so let's take a look and see if there's anything wrong it might not just the spreading might not work as i hoped it
would that might be the issue i'm not sure i haven't tried it before so
it was a try and see if it works thing so it might not i'm talking about this spread right here
where i'm spreading the comment record in um you would think it would work but
maybe not
so i guess let's go ahead and just try providing the post id manually instead of spreading it and see whether or not
it actually goes in there now so let's do com post id comment dot um
post id yeah yes
while i'm at it let's go ahead and make sure the edit is not yeah edit so that should be okay
let's try that then let's see if that populates in the post id within the form so let's scroll all the way back down to
the bottom go back to edit we expected that to be empty but yes so you can see the post id now has a value
so it seems like spreading isn't doing what i had hoped it would it's probably because of the getters um so if we
serialize and then spread i would anticipate that it should work then so
i would assume it's because of the getters so let's go ahead and try cereal eyes
in it i think i spelled that right we'll get rid of that
and let's see if yep there we go okay so let's kind of walk through why serializing there worked so if i were to
come out here and we tack in and inspect on the comment itself on the comment
record you'll see that we have a whole bunch we have kind of a whole
object set here just mapping stuff to lucid so this every
property that we would want to get is within attributes so we could spread the attributes and that should work
but whenever you do your record so comment.id comment.whatever it's using a getter to
grab it off of the attributes but whenever you serialize
it turns it into kind of json format so it gets rid of all of that model data and it just returns back the actual
serialized data here um so like so now
this is coming through as uh snake case
um i think i'm going to change that to be camel case
is that in this project that i did that or is that a different one that was in a different one all right
since the form
yeah we can go ahead and do that all right it doesn't take much to do so i'm going to go back into my github
here and i have a somewhere an adonis camel case naming
strategy example that has app strategies and a camel case naming strategy i'm
just going to go ahead and copy this there we go
come back into here create that structure so app new file
strategies camel case
naming strategy paste that in there
and then i'm going to go ahead and just create a base model so scroll a little bit on accident and i
miss clicked and there we go and let's go ahead and create a base model so we'll do amp base model
ts export default class app
base model extends base model
from adonis and then oh what was it was it
it was naming strategy but did it had if it had a dollar sign before it i can't remember
excuse me in here public static naming strategy okay gotcha
and there we go now i will go ahead and apply that to all of my models so that shouldn't take too long here so just
get rid of that i'm gonna go ahead and define import here import app base
model
okay i'm gonna copy that and then
just tech app on in front of that i was gonna that was debating on it not to do a finder fail for everything or
not to find a phil but uh just just to find oh went the wrong way
there we go and then app
collection scroll to the top plop that in there
app get rid of that okay comment do that once more so
app paste that in there
okay notifications
app paste that all right
post about halfway through
there we go okay
having my own base model will make things a little bit more extendable in the future too if i decide to change anything else globally i can just do it
within that base model and then we'll need to redo going through each model to apply stuff so whoa
there we go two more taxonomy and user
okay
fix that bracketing too okay and last one
amp
all righty there we go so now if we come back and we take a look at the serialized uh
data here need to refresh it's all in camelcase so
i can provide stuff from the model and now whenever i serialize it
the same way and i don't need to worry about whether or not i'm you need to use snake case or camel case within the form
so let's see i don't need that open don't need that open don't need this open
so now if we go back take a look at our form again all right let me get rid of the serialization
i'll see i did that in list didn't i so there we go so we have
comment.serialize so that we get the just the properties that we care about off of this and let's go ahead scroll on
down and now if we hit edit all of that stuff should be populated
off of the comment yeah so we have post id the level is
zero anyway um but then we're also getting this information here
uh and then let's go ahead and check the form so method post comments so the
uh query string isn't getting appended on to set this to a put
um it should be spoofing the um
the method maybe i didn't put that on oh yeah no i didn't put that on right so it needs to be another
object level deep where that we have the query string and then the put okay
and where is that now there it is now you can see it got underscore method equals put on there so
now whenever we actually submit this form adonis will match it to a put route
so let's go ahead and edit this
all right and we'll also want to do that to where that only applies
for the authenticated user we only plop this in if the comment matches the actual user's id
so that we don't plop a whole bunch of unnecessary stuff onto the dom so i'm just going to do take on an
updated here go and try that out so we got redirected back and now you can see boom this dot
updated if we edit there it is we can get rid of it
it should happen again it should be gone there it is we can do that with a nested one so if we edit
this guy here updated
voila and if we go ahead and reply to this comment
i'll tag on a level four within here so that we can check that within the database nice and easy make sure that level is getting appended
on correctly now so this is a response level four so if we take a look at that within the database let's go ahead and
refresh it should be this last one here let me verify that within the body on the level four scroll all the way over
looks like it's uh set to three it should be four
maybe oh no i'm starting at zero right so maybe that is right so zero one two
three okay so okay that's fine it is an index it should start at zero so
we're good there so then we can edit that so it displays correctly now that we have our edit form
working you can see update comment works there now the next thing that would be nice to do is to take this to where it's not
actually resubmitting the whole page again and i think to do that i'm going to try unpoly
but i've never worked with onpoly before i've only seen almond work with it so
i don't want to tread into that water on stream because i feel like i'd just be
reading a bunch of documentation in front of you so i'll try that on my own um
and then we should be able to delete any comment now the delete behavior does need to change so we can take care of
that i guess so right now if i were to delete a comment
first it would fail because it has other like if i were to delete a comment that has children it would fail because i
don't do uh what is it coalescing deletes um
so this one here has a foreign key referencing this one so if i were to try to delete this one the foreign key
restraint here would prevent that from happening and we can go ahead and see that here so if i delete there boom
violates foreign key constraint so what we want to have happen is instead
of if i delete this comment it should not i don't want it to delete the two responses that it has that's not what i
want what i would prefer is that it should just anonymize this comment
completely so it detaches it from the user gets rid of the comment body and it remains keeps everything else in
the tree however if it doesn't have any children then we can go ahead and just delete it out right because we don't need just a
random comment here saying deleted that doesn't help anybody but if there was a conversation going on within it then we want to maintain that
conversation and just nullify out whatever that user's comment was so
let's take a look at that so uh that would be within our comments controller underneath destroy so you can see this
is why we got the foreign key constraint we're just simply trying to delete it without doing any additional child checks or anything like that
so instead of doing this what we will do is we'll want to
completely anonymize it so we'll get rid of the identity we will get rid of the name
and switch the body to just be removed we'll get rid of the user id and i believe keep everything else
how does reddit do it do they keep they keep the name in there don't they
i don't know let me see what my current comment
system does for that would be interesting to see so let me go ahead and
is a test oh i don't want to do this anonymously oh my toasts don't auto
remove
okay let me go in here go down to my comments all right
so this is a test go ahead and comment that in here
let me go ahead and reply this is a reply
reply there oh it's because i'm trying to respond to
myself oh no it did go okay um and then if we delete this guy
boom okay so it does keep the user information it just deletes out the comment and then if the user were to delete
themselves then it would delete out the user too okay so i thought about it more whenever i
created this comment system than i am right now so we'll stick with what i had originally decided
um with the new system so keep the user information just delete
out the comment body and then if the user deletes their account then you would then delete out
the user information from the comment so instead of deleting
we will await er hold on a minute we will const
comment equals and then we don't want to do our lazy man's
authorization checking because if the identity matches an
anonymous comment that user would then be able to delete their comments so not necessarily going to be an auth user
within here so we'll just do a wait comment and we'll worry about authorization later with bouncer
finder fail uh the id or sorry
the id and then await comment dot merge and then what we'll do
is just set the you know body to
deleted and [Music]
let's do that like that and then we won't await that because you don't need to and then we will wait comment dot save there we go looks a
little bit better all right so all we're doing now is just rewriting
the body to deleted um oh wait a minute
and check and see whether or not has children so const has children equals a weight
ah let's see here comment dot
related responses
query
dot where state
state id do i have states within here yes cool
dot
public not archived maybe
yeah let's let's do not archived so we're not
states dot archived and then here in addition to changing
the body change the state id to states dot
archived okay um and then
dot i feel like i should just do a count
here uh let's see i don't do counts all that often so count
try that i guess no taking it oh yeah id
all right i don't remember how this comes back so
let me tinker with a little bit so node ace
rebel let me start a rebel session load models
okay await or let's do const comment let me try it out exactly
how i have it in there and we'll see how it comes back so awaits comment dot
or sorry model uh yeah models dot
comment dot find or fail and then let me go grab the id
of the one that has responses so let's see take a look at the parent id
it would be good to go off of so we have oh no root parent id is changing
that should be the same for all of these so i need to
fix that but looks like six is the one that we want
to grab here so let's grab six
okay const count equals awaits
models dot or sorry we have the let's do comment
dot related responses
dot let me and so we're mimicking what we have right here
so query where not state id equals states.archived which is six so
dot query dot where not state id
equals six hardcoded because i don't have states here and then what is it
okay so we're just going to see how that comes back oh i put it into a variable instead of
just you know let me go ahead and just plop it directly out here there we go
all right so yeah it does
okay so extras and then it should be just count out of there so
all right so let's change this to children and then
we'll do if
if children dot extras dot count
then we'll do that else
oh it's an array oh let's see can i do first
let's see just try this again to get back an object
it doesn't look like it wants to
i did it somewhere to where i just got back the number but i forget what i did and i forget where i did it
but okay so uh let's do let's just grab that out of there
we're just gonna get back one response anyway with the count and then once they do that otherwise we
should be green and clear to go ahead and delete it so await and we'll do what we had before or we
already have the comment here so we just do a weight comment dot and then delete so yeah
all right that's not the prettiest block of code i've ever seen but it'll work for now
so we'll check whether or not we have any responses really this should be the
root parent id so it should check all the way down to stem no
because then if it has a parent and you delete one of the children okay so all right let's stick with this
all right yeah sounds good so let's go ahead and save that and try it out so
let me go ahead and delete my tests on my production site always good to test stuff out in production highly
recommended
and then let's go ahead and try to delete one of these so if we go ahead and try to delete this guy here it should be this button right here
should get back the exact same tree but that comment should now say deleted
and boom there we go so that seems seems to be working good
all right so let's see what's going on with that root parent id um let's go ahead and tack that back to
where we can visually see it nice and easily within the form so form
and let's just change that root parent id from hidden to type text so that we can see it easily compare it at all
levels scroll back down here and i'm not seeing
it maybe that's part of the issue oh the form itself is hidden too so
all right um let's see let's go ahead and get rid of
the x show that should be on
should be on edit id too so let's go and get rid of the x show here um
just get rid of that completely for right now
okay so here it's not provided at all and it should be
i think maybe not no because that is the root okay so
it shouldn't be there but it should be here six seven so let's
see it now it should be six six six but it's going to the immediate
parent so essentially right now is behaving the exact same as reply to so if we looked over at it it's probably
six seven eight and yeah it matches so
um
why
oh well yeah that's why i never got rid of the set on it so all right so from the base are we providing
it no and that makes sense because the loop for the parents is inside of there so
okay so boom um so here we need to check whether or not
it is the route and so for that uh you would check the reply to so if
um comment dot reply to
then it would be should be provided so root
parent id otherwise should be the comment.id
and then we need to make sure that we're providing it to
yeah so it would already be on the record there so we don't worry about there but it is provided here and it is provided here
okay so that should be okay let's go ahead
and see uh we might need to probably need yeah since this is all pulling from the
database already uh we'll need to kind of
oh right i took out the show um where was that it was right here can i
oh no i made a change do i have it oh no all right i'm gonna go
back to where that is all right let me just go ahead and copy it and we'll go forward
all right go back before that paste and now paste there we go okay so let's go ahead and delete out
all of our comments with to be a good chance to test out the deletions again so
well uh on a minute so on the delete are we checking to make sure that all that the children itself
isn't because if i come up to here i would anticipate delete should be hidden because it has already deleted
it's archived but then if we delete these two how would we tell it
to delete this guide too
i guess it would be on the delete check itself you should check the parent too
so here so
if comment dot and here we can actually just do await
comment dot sorry load uh parent
and here we can wrap this up in a nif so if comment dot uh
reply yeah reply to and then that was the if that i was
going to write here so i can get rid of that load in the parent and then
no um yeah if comment parent
dot state id equals states dot archived
then you would delete the parent too of course that would need to happen after you delete the child
so let's
let's all right let's change that so const parent equals
comment dot related parent
query for no just first
okay i think i'm doing that right see
and then down here after you delete the child if parent
dot state id doesn't seem like it wants to
all right so what are you telling me parent is it's a comment or no oh it's promise oh wait
oh wait there we go state id equals
states.archive so if the parent is archive two then we want to await
parent dot delete so that should delete out that parent
too so let's go ahead and test all of that stuff out so we'll delete this guy should go just fine
oh missing model attribute comment.parent expects comment id to exist on
comment model but it is missing and that is because it is reply to
so that is on the parent relationship so let me go into that model
so comment model just
misdefined this let's go to parent local key maybe that needs to be foreign
key
maybe that doesn't need to be foreign maybe i got these mixed up
i don't think i've tried the responses query quite yet or did i is that what i tried in a rebel
yes okay okay yeah no i think both of those should actually be the same because
yeah okay my head was in a different spot whenever i wrote that up yeah that should be the same
okay so now that should work as intended let me make sure i got both of those saved okay there we go
so let's go back try that one more time so let's see we're trying to delete this
whole tree here so let's start at the bottom delete there it goes
and oh all right so that count checks not working as i had hoped because now that's just
gone and deleted the um so let's go ahead and console.log out what it thinks that
count is
and i'm just going to console.log out the extras object we'll see exactly extras there we go
and so i can re-click delete and it should just go through the same structure again um so it should perform the same check so
we should go right back to there uh so let me go ahead and re-click delete there
nothing should change should still just be delete okay check the console log
and oh i'm in rebel uh let me alright let's submit that and exit
all right let's oh no over here all right so yeah it's count and then
it's a string of zero so there is the issue
i should probably a way to get that back as a number but i'm just going to do that like that for right now
i don't feel like looking it up okay so now that should work
and it should not be gone because it doesn't have any children and there it goes we'll do that here we should just
immediately go we shouldn't have to go through the delete step and there it goes and cool yeah it actually deleted the
parent too so that is working as i had hoped okay so now we are all at level zero
back to our root parents not needing the ids um
i guess ideally what would happen is after you create the
comment it should go back in and fill itself in as the root parent because
i mean technically it is the root of itself i'll think about that a little bit more
but so let's take a look at make sure that the root parent id gets populated correctly for responses and that the
level index remains correct because i don't think we gave the level index its proper testing before
so let's go ahead and add a response here testing we can see that the root pair
know is going to be six okay add a response to our prior
response cool so it's still six so that seems like it's going to work okay testing two
and let's add in a third just for chucks and giggles
testing three okay
there we go one two and three if you go into the database here refresh
all of those have six and we have one two and three as the level index
if we respond again to let's say this level here
so we'll do testing a should be six and the level index should be one
so right there it is and let's test that out so the latest one should be six and the level id is
one looking good let's respond to let's respond to this one
testing 2a all right should be displayed at the same level
testing 2a oh oh yeah no i did respond to testing two didn't i so then it should be back
at level three yeah there we go so that is all looking
a okay if we delete this one it should not
delete the parent oh wait i didn't do that check did i
parent it's just checking whether or not it has the parent oh the parent and the state as archive but we also need to
check the parents children to make sure that there's no other children so that would be a sibling's check um
so let's go ahead and just do a preload on there
her with count i guess with count
okay that would be responses
um all right let's only worry about that if
we get to the point where we need to worry about that so down here so awaits
parent dot related yeah
responses dot so at this point we would have already
deleted the um comment before so let's do
query dot count
id const and we'll name the siblings equals
all right not the prettiest block of code you've ever seen here but i will spend some time and clean this up
after i after the stream children dot
extras count oh no not not children uh siblings
okay bam so if not
there we go so if the parent is archived and it does
not have any siblings then we will delete if the parent is archived but it does
have additional siblings to the one that we just deleted then we don't want to delete it
so we have our test case right here so we will delete a sibling
2a so 2 should remain and 3 should remain and there they are and then if we
delete this one two is not deleted so it should remain
and there it is okay let's test this one other way so let's add a sibling to testing and we'll
name this testing 2a so add backer 2a there
all right so here it is and let's delete our testing so now let's leave it with the
parent deleted so let's test it with the parent deleted delete our 2a and then the deleted
should remain because we still have a sibling here so delete 2a
and there's delete and there's 2a now or there's two so if we delete two then deleted should go and we should
only have testing a here
ah perfect cool all right so um
i've been going for about two and a half hours so i think all i will do now is just get the form back to the state that
i had it let's remove these console logs um and we'll call that a day
so go back let's see in the form what did i do oh yeah no i just changed
that to from hidden to text and that should be it should now have a
working it's all server side but it's working a comment system um and then off
stream i will try to figure out how to use unpoly for this and if i figure it out
and i don't get too far with it i will stream this stream that next and then i
intend on streaming also doing um notifications so we will add notifications to this as well
um so it should be a good next stream so let me go ahead and hit edit on that
cancel reply cancel all looks good all right thank you guys so much for watching hopefully
you have a good day see
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!