Building A Comment System

In this stream, we focused on building a comment system that allowed infinitely nestable responses. It's all done server-side too, so it's SEO friendly!

Published
Jan 29, 22
Duration
2h 24m

Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.

Adocasts

Burlington, KY

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.

0:16

come on show me a picture

0:26

all right there we go now it showed me a picture i want to make sure the stream wasn't just streaming black um

0:32

yeah so i started working on a comment system and then i thought you know why not just uh stream what you're doing

0:39

um it's been a while since i've done this so i haven't gotten much so far uh this is

0:45

the new jaeger co site by the way this is what will be the future

0:50

uh kind of lesson page um so down at the bottom here i haven't

0:55

gotten too much so far so far i'm just printing out the post id along with just a text area there

1:02

and this is what i have going on so far

1:08

so one thing that i know that i want to add is i just closed it but if we look at the

1:14

database so for the comments so far i have an id name post id user id reply to

1:20

state identity body created and updated that but i would like to have in addition to just the post or the

1:30

post id uh and another id that is the parent

1:35

the root parent comment id so that you can nest comments

1:40

and so that i can pull them all down in one tree uh so i want to add that and then i also

1:45

want to add a level so let's go add those in really quick so

1:52

let's create a migration here

2:07

i always forget to put the dash dash table but that's all right it doesn't take long to do that

2:14

comments add root there it is okay so we want to change this from

2:20

create to an altar table uh the table the name there is going to be comments

2:26

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

2:34

integer and then we'll call this root parent id it should this should have a

2:41

parent id too evidently i did not have that in here

2:47

whenever i ported it over or maybe that's what reply 2 was

2:52

yeah that's probably what it was all right so root parent id

2:58

unsigned uh

3:06

id and table comments

3:12

and we'll make that not nullable all right and then we will also want to add a level so integer

3:20

we'll call that level index um not nullable and default that to

3:26

zero okie doke and then down here

3:32

this schema dot altered table

3:38

table and then we want to just drop those columns so i like doing this

3:44

uh what did i do wrong here oh yeah table name

3:50

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

3:55

change in the future it's just easier to visually see that you know what's going on here so root

4:02

parent id and then we'll do another one drop column for level

4:09

index okay so and then i also like to just check and

4:15

make sure um this is my first time using whatever this is this extension so i don't know how to

4:21

check and see what the structure of or even if it can do that but i'd like to check and see what the

4:29

reply where's my comments

4:34

oh i probably got a refresh yeah there we go all right so i want to check and see

4:40

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

4:50

okay i'll probably change that in the future all right so then let's go ahead

4:57

into our comment model i did that backwards but here it

5:04

is and let's add that in here so reply to

5:09

and act column public root parent id

5:15

of type number and then we had a level uh put put the level index after the

5:22

ids right column public level index

5:29

of type number there we go okay so let's go ahead and run that migration so that's in there

5:36

uh there we go

5:42

okie doke and let me go ahead and refresh that make sure that i don't know

5:49

if that updated or not all right we'll just hide that for now all right and then let me go back to

5:55

the lesson page here and we can start stubbing this out a little bit more so

6:01

actually i need to go into the comment component that i have going on

6:06

here so so far this is all that it is it's just a a text field that i'll eventually make

6:11

hidden just wanted to make sure that the post id got pop populated in there okay and then we have just a simple

6:18

form input of type text area so then i will just add a

6:25

button type submit for right now we're just going to do this as a normal

6:31

form action for right now and then later on i'll switch it over to using uh

6:38

uh api requests all right so we'll just have that is that for right now and then we'll do our

6:46

end and submit comments fine for now

6:54

okie doke so if we come back over here we should have a simple

7:00

form here all right go ahead and

7:07

just add a h4 uh font semi bold margin top six

7:18

and that'll work for right now okeydoke so that's what we got going on

7:24

so far we need a way to save it next so we'll go ahead and i don't know if i

7:31

have a comments controller or not oh let's see there we go

7:38

so let me go check and see if i do so yep right there alrighty and let's see we'll want to

7:46

store wrong keyboard shortcut there we go

7:52

and so we're going to want to request response

7:57

yes and probably off

8:02

all right so let's go ahead and

8:08

let's also make and now we'll worry about validation later so const um

8:17

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

8:24

so i need to remember to do that request dot and uh let's see i

8:30

think it's only and we'll do post id and comment

8:35

and then we will await i'm to add a little to do note here to validate

8:44

okay and we'll so we'll do const comment equals away

8:50

comment dot i'll take that imported

8:56

let me go ahead and import it

9:02

models comment there we go

9:09

dot create all right and so

9:15

well let's just switch this to data for right now that'll make things a little bit easier to switch over

9:21

whenever i do add validation and we'll spread that out and then we'll also want to add in

9:27

if there is an authenticated user i think it was called user id

9:33

yes all right so user id is auth

9:39

user id and we'll want to there we go

9:44

all right and then for right now let's just go ahead and return response redirect back

9:51

so response redirect back

9:56

all right so very simplistic to start so let's go to find that route

10:07

route dot and this will be a post

10:13

comments comments controller dot store

10:20

as comments dot store there we go and let's go break that up into our form

10:28

whoops did i just type something i did

10:34

route comment comments dot store

10:40

and then i need to remember to put a name on here

10:47

comment actually i think that's supposed to be body yes so we'll change that to body

10:54

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

11:01

switched that to data so we should be good there and so this should just in this simplistic

11:07

form go ahead and save that into the database so let's go ahead and test it out so we have

11:12

actually let me make sure i have all my null not nullable stuff taken care of here

11:18

id is good post id is good uh state id oh we don't have a default on that do i

11:24

alright i need to figure out remember what that was and then uh an identity

11:31

so that is what i use if there is not a user id uh

11:37

and yeah so we'll need to take care of those two i'm just gonna

11:43

see if let's take a look at the enum see if we have a so we have states

11:49

uh so let's go ahead and import those so import

11:54

states from app enums states and let's

12:02

drop this down into a new line all right and let's give that a state id

12:11

states dot oh yeah all right so this will depend so

12:17

if there's an auth user so auth.user.id

12:22

then just go ahead and make it public otherwise we want it to be

12:29

uh let's see what did i do in review interview probably makes the most sense

12:34

so if it's an unauthenticated user posting an anonymous comment it should go into a

12:40

review state where it needs to be approved first before it goes to being public so that's

12:45

what that's all about and then what was the other one

12:53

identity all right so i i don't remember what i had going on

12:59

for that for authenticated users or and then i had a separate service that

13:05

kind of generated out a unique name um so for right now i'll just do asdf on that just to get stuff saving

13:14

okay so we should now be able to go ahead and this is a test

13:21

it won't display or anything it's not being pulled down with this post or anything like that but oh yeah csrf

13:29

so then we need to uh come into that edge form here

13:35

and add our was it two or three i think it was three

13:41

or csrf field into there

13:47

no evidently it was two there we go all right so now we should be able to do

13:53

this is a test go ahead save that off and got an error

14:02

insert and i need to turn this off but i i was working on the error page

14:09

um oh root parent id yeah i just added that in that needs to be defined too

14:15

okay that should actually be nullable because if it is the

14:21

root then you can't assign it should be its own id but you can't assign it to that

14:29

so this should be nullable after all so let's go ahead and rerun that

14:34

migration

14:44

okay so now that's nullable so we can go ahead and try to resubmit

14:49

so let's do this as a test and there we go all right so it should

14:55

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

15:03

there it is so next thing that we'll want to do is

15:08

to i guess go ahead and get whatever i was doing with the identity rigged back up

15:14

so i'm going to go check out what i was doing for that real quick

15:23

so let's go into controllers http there should be a comments controller

15:31

store [Music] all right let's see identity identity

15:38

service dot takes an ipn agent agent is request headers user agent

15:45

all right so i'm going to go ahead and grab that because i'll probably forget exactly

15:51

what that is and let's go back into the

15:56

comments controller plop that up here with the data that we have so that's just the user agent string

16:01

coming from the headers and then

16:10

oh i guess previously i had the post id and url let me grab the ip address too so that's

16:17

just request.ip i can remember that much all right and then we'll want to grab the identity service

16:24

so

16:30

because i do not remember at all what i had going on there i just know that it was generating out

16:36

a random name for users so let's go back into here app services

16:42

and then i have this identity service here i'm just going to go ahead and grab the raw version of that

16:49

all right and then let's go ahead and make that so

16:57

all right so app services

17:03

identity service and paste that in there all right now i thought that uh see i do have a cache

17:11

service done yes so i just need to import that so um

17:18

i'm surprised that's

17:26

oh it's a promise okay so that changed so i just need to add in a weight here

17:33

and make this async i'll just take that off

17:39

all right there we go and then it looks like i was using a unique names generator

17:45

so let's go ahead and install that

17:57

okay so in essence what this will do is it will

18:03

take in the let's see where's the root at here create so it'll take in the ip and the

18:08

user agent um it'll grab whatever the secret is i don't remember

18:15

oh okay random byte string um

18:21

and then it will attach that onto the user's cache

18:26

uh oh it's too early in the morning for this uh let's see

18:35

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

18:42

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

18:48

create an md5 hash and that will join in the secret the ip and the user agent

18:55

and it will return that back

19:01

so then all right what was the call order for that

19:08

see so we do create to get an identity and apparently that just returns back the identity doesn't it

19:14

okay i wonder this must have been used for

19:20

something else generate name unless that's down in here

19:26

but i'm not seeing it highlighted okay so let's go back into the comments controller then oh i didn't save

19:34

okay so let's go into the comments controller now and i didn't save on the comment model

19:40

either there we go okay and let's go ahead and get our identity

19:46

so const identity equals a weight identity service dot

19:55

create and that will take in the ip and the agent

20:01

okay and so now we can replace that here and just get rid of that all

20:06

together and since that's going to

20:14

be like that we'll put that up there and let's see what was the other thing i need to take care of

20:21

you also probably want that root parent id to be provided

20:28

if there is one and then we'll type that in here if there is one no that would be on data

20:34

so we don't need to do that all right and let's see anything else

20:43

reply to pray yeah posted it was coming off the params um

20:50

okay all right and then we need to do that

20:56

notification service at a later point in time but all right so

21:06

should be good let's go ahead and get them coming down a little bit so let's see that's i think

21:12

the current lesson page that i have rendering outs here so let's go ahead and

21:21

i'm going to do a separate query for this so wait post related

21:27

uh do i not have comments defined i probably don't no i don't

21:40

oh oh let's see how do i block a user

21:56

stop it

22:08

all right well hopefully i got all of them people are gonna be

22:20

all right well i guess i'll just ignore that go back and delete them later um let's see

22:29

surprise there's not like a block option on there it really should be

22:46

all right so i need to go to find the comment on here on the on on the post so post model

22:54

let's go to find the comment in here scroll down to where we have these

23:01

uh so this will be a has many

23:07

so put it underneath the other has minis

23:15

comment public comments has many

23:20

type of comment

23:28

i don't think i don't think my auto imports working

23:35

oh there we go okay i guess the wrong thing was highlighted all right so that should not be defined

23:41

there i won't worry about the inverse right now i don't think we'll ever need it um

23:47

so now it should be in here there it is and so we'll get the related comments

23:53

we'll go ahead and query it we'll want where the

24:01

reply to is null so where

24:06

null reply to

24:13

i think that would be it um

24:19

well no well all right we'll start with that and then we'll do an order by there should

24:25

be a created app on there that we will order by descending so that newer comments are

24:32

displayed first um and then we'll do

24:38

that should really be comments not just comment comments there we go

24:45

so that should be coming down onto our

24:52

lesson page so

24:59

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

25:06

underneath here so we'll just do a simple ul for right now just to get them listing out

25:11

li oh really i guess that would be an ordered list with it

25:18

all right and then

25:23

oh i need to pass in the comments so be up here

25:30

and since it's right off the root we can just pass it in like that and so we'll do an at each

25:39

comment in comments this only changed a little bit

25:45

in the future but for right now this will work um

25:53

and then we'll do a simple just paragraph and

25:59

we'll just drop the comment.body on there for right now and we'll do a little h6

26:06

with comment dot and i will put the identity

26:17

and then i guess it would be

26:22

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

26:29

comment dot user dot

26:35

username otherwise comment.identity all right now we need to go preload that within

26:42

here i'm going to go ahead and drop this down so query

26:48

we're in all order by let's add our preload into it

26:54

and i probably need to oh no there it is i already did define it cool user um

27:00

and that should that should that should be it i think

27:05

so i should get those displayed okay let me make sure i save this and now let's go back in here and all

27:12

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

27:18

an all didn't it okay so then let's see i guess let's check

27:25

and make sure that the name on this is getting plopped on there

27:31

yep name is body okay

27:38

and then i bet you i left it off of the only comments controller not that there we go

27:45

yes i lifted his comments so that's why that came through as null so let's go ahead and

27:52

delete well let's go ahead and plop a delete button on there we can go ahead and delete real quick

27:57

oops so let's go down into back into here

28:02

and where we have it listed let's just drop a form method

28:10

equals post action equals and then i don't have the

28:15

route defined yet so i'll need to do that and form

28:22

and then we'll do a

28:27

i'm just i'll just manually find this button type of submit

28:34

and we'll just do that and then we'll tack on

28:39

a hidden input name equals id

28:45

value will be comment dot id and there we go all right now let's go

28:52

rig up that action and define it on a route so comments controller we'll scroll down to destroy

28:59

let's see we're going to want request response

29:05

and i won't worry about authorization there for right now we'll just go ahead and get it going

29:11

so con oops const um i d

29:16

equals request well request only

29:21

id and then we will do uh await

29:29

comment dot find

29:37

yeah let's just go ahead and do a straight up query delete where id

29:44

dot delete and then return response and for right now we'll just redirect back

29:52

just getting things working on the front end and then getting the crud operations actually working here

29:58

we'll worry about changing stuff back to api responses later on so route dot

30:04

delete i don't know why i put a space here there we go comments

30:10

and then well i guess that ids would normally be in the url instead so let me change that

30:17

comments controller dot destroy as

30:23

comments and destroy

30:29

okay so we'll go ahead and save that let me go back over to here let me change this to a param

30:35

so we params don't think we'll need request at that point const

30:42

id equals params.id and then let's go back down under here

30:48

and change that to match as well okay so we'll want

30:56

route comments dot delete we'll want our id

31:01

here so comment dot id and then we're going to want query string

31:08

uh let me see is it

31:15

i think it's underscore method if i remember right delete and am i missing a curly brace

31:22

and it will tell me if i am so let's go ahead and try this out

31:27

i bet you i am oh cannot find route i bet you i didn't save i did save

31:34

oh i named it destroy yeah all right i like that better let's stick with it

31:42

there we go and there we are we're back we have this we have our delete button

31:48

so if we click on that up always forgetting to see srf all right so let's tack that in here as well csrf

31:56

field let's go back and

32:02

let me refresh just to make sure that populates and let's try that again and there goes that comment goodbye and

32:08

let's try creating so this is a test make sure that the body gets populated now

32:17

well that did not seem to work

32:22

oh maybe i didn't click the button right all right yeah so there we go now the body's

32:27

getting populated and then we should be able to check in the database make sure that we now have a random identity being

32:33

populated nope that's not right it should be a string

32:40

um not not not like a hashed identity

32:47

i think

32:55

let's see so that definitely just calls await

33:01

identity service dot create which is what i'm doing i copied that over as is

33:07

huh oh okay i see i missed this line down here

33:16

all right so yeah so if there is no user id then then

33:22

that's where i'm calling get by identity that makes sense okay

33:31

so we'll come back up into here and

33:36

identity is that and i was saving that into what property name comment.name

33:48

and i was not saving name if there was a user okay gotcha gotcha

33:54

so let's go ahead and tack name onto here too and so we'll do

34:02

let's just go ahead and tack user id into a property so we'll come up into here const user id

34:08

equals off user id oop there we go

34:13

so if user id then we'll make that null otherwise

34:18

we'll await identity service dot generate name

34:26

oh that must take something i'll get by identity is what i needed to call and that takes the table name and

34:33

the identity property okay dot

34:38

get by identity which will provide comment dot table for the table name and then the

34:45

underlying identity there we go

34:52

and wow why the reds quickly string no is not assignable to perimeter

34:58

oh okay so just change the stock defined okay

35:05

and then was i saving the actual identity before probably right it makes sense too yes

35:12

okay so that should now be good so let's go ahead and redelete that comment recreate

35:18

it make sure everything's going okay again so let's go back down here delete you

35:24

scroll back down to the bottom there's another test

35:32

bam and there we go username is right and then if we check in the database we should now have a

35:38

proper oh yeah no names all right so let me log

35:44

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

35:50

out oh the homepage okay

35:56

no no i don't have that problem working properly okay uh

36:02

where would that be

36:09

let me turn back off um the errors

36:16

uh let's see if i can remember where that is yeah right here let me just set that to true

36:22

turn back on the normal debugging errors okay

36:29

prepare oh the author block okay oh yeah i was just using the auth user for that wasn't it

36:34

all right so i will wrap that up in an if that's the quickest easiest way to go

36:39

about it for right now so let's see that was

36:46

author card

36:53

where are you actually you should be able to drop that directly on author since author is

36:59

populated here i think author dot avatar maybe at the very

37:06

least it'll be empty because author will be a string so there we go okay so let's

37:13

scroll back down and now being an unauthenticated user

37:19

on authentic uh wow on off and ticket there we go

37:25

test submit that all right it seems to have worked and

37:31

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

37:40

where are you right here so instead of displaying identity display the name

37:46

and there we go chimpanzee brandy741 branda

37:53

okay regardless unauthenticated users are able to submit an anonymous comment

38:02

okay so

38:08

let me go ahead and log back in

38:17

go back to that page i kind of have a convoluted path to get to that page right now

38:22

there we go all right and i guess next let's go ahead and i'm not

38:28

going to worry about display i'll worry about that off screen um like how things are rendered out um

38:33

but let's go ahead and get a reply to functionality working

38:39

uh so that's where things get a little nested so we'll probably want to split this out into a comment form

38:47

component so that we can just drop it on and it will

38:52

be there so we have to keep writing it over and over again so let's go ahead and

39:00

create a new folder within components called

39:07

comment we'll move this into here

39:15

we'll change this to list

39:20

or maybe maybe base yeah base

39:26

and because it'll be the base component for the comments and then we'll switch this out

39:33

into the form so we'll add a new

39:39

one called form dot edge we'll paste that in there

39:44

we'll save that come back over to here

39:51

add that there what all do we need to provide to that so it definitely needs the post id to

39:58

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

40:04

so all we need to do is do the post id here and that's provided as the same as that

40:09

so we can just do that and then down here

40:22

um i don't want to display this so let's wrap all of this up into a div to

40:28

kind of encapsulate every oh whoa wait a minute hold on a minute i've gotta i went and did a ordered list

40:35

with an li and i put the looping inside of the li

40:42

all right there we go that's more proper and now

40:48

we don't need that div we can just use the li okay so we'll do another ordered list

40:53

within here i'm gonna put a line break in there just so i can easily see where that is

40:59

do a um all right and this is where i want to

41:04

change how things are being queried because i want comments to just be

41:09

all of the comments and then we'll have this base worry about what should be displayed first and what should be

41:15

displayed within so in the comments controller

41:21

we or no sorry in the series controller for right now

41:27

because this is the page rendering this out eventually i will move this into a service

41:35

let's go ahead and get rid of the where null and instead let's change this to

41:46

so let's see it shouldn't just be a state check because if the current

41:52

user is the one that commented they should be able to see their comment

41:58

and so here let me show an example here so if i go into

42:05

the current site and if i come into just a random post here

42:10

do the first one scroll down and

42:16

this is an non-must comment

42:22

and i post the comment i should be able to see my not oh i'm logged in it's not very anonymous is

42:29

comment logged in log out

42:35

i think this still redirects me oh no okay good

42:40

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

42:47

anonymous comment

42:52

so i should be able to comment that anonymously be able to see it myself so if we just

42:58

do a simple state check this won't come back at all because it won't be

43:03

public it'll be in review but since i'm the user that commented

43:10

um i need to change that that shouldn't

43:18

um then i need to be able to see the comment that i left

43:23

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

43:29

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

43:35

like to maintain um so

43:45

let's try it i'm going to cheat and check and see what exactly i was doing to do that

43:52

um it was something with the identity so let's see if we come back into here

43:58

that should be probably on

44:04

the posts controller on show or maybe it's lessons no

44:10

show all right yeah so we're grabbing the

44:16

current user agent grabbing the ip it's not the best check but it's good enough

44:21

for my simple site

44:27

and then this is going to be vastly improved by that parent id so i started out i just went like three layers deep

44:34

on the comment system and then anything below that the front end took care of loading additional

44:40

which isn't much of a problem but it'd be better to just load them all in

44:48

in one go and then have the front end dictate how it should be displayed all right

44:55

so back to what i was doing before so all right so we have this simple where

45:00

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

45:07

agent so i'm just going to go ahead and copy this line here because it's going to be the same

45:15

all right and at that point it would be a lot better

45:20

to just go ahead and drop this into a service so let's do that so in here

45:27

let's create a file

45:33

comment service

45:47

get for post or something like that

45:54

um i was just let's call it load

46:03

yeah yeah all right i'm not gonna worry about naming right now and then this she'll

46:08

take in [Music] i guess the post id

46:14

for starters and then let's go ahead and copy what we had in the series controller is a good base so

46:19

copy u paste that in here

46:27

um oh okay so we can go ahead and just drop in the post record as a whole so post of

46:33

type post okay and then

46:39

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

46:45

we can just return directly back from here all right

46:50

so let me go back i just over what i had copied from here so let's copy this and paste this into here

47:07

i'm going to switch this over to an http service so let's drop this into my http folder

47:14

just make it easier i could provide these each time but i don't want to have to remember this

47:20

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

47:26

call that service each time but i'm just not going to worry about it and we'll just extend

47:32

wow okay extends

47:37

the base http service so now

47:43

i should be able to do this oh i need to take the static

47:48

keyword off first this dot ctx request and just get that directly within here

47:54

and then i need to import the identity service as well

48:00

and change this to this dot okay so that should be good

48:06

and then down here we need to do our where and i'm going to do this as

48:12

a callback so we'll do query

48:19

and we'll do dot oh i'm not doing this right

48:25

oh yeah no query query there we go dot where

48:31

uh this would be state id state not stat state

48:37

id is states

48:44

or is it status

48:55

where is it oh state yeah all right so

49:01

what did i call that enum i thought it was states yeah

49:07

i guess internally i called it state but i need to change that naming

49:14

i also need to change my enums to be in the contracts instead of with an app

49:19

okay so states dot

49:24

public or where

49:32

identity and we can switch that to there

49:39

okay so either the state id should be public or the user's identity should match the

49:45

comments identity um

49:51

and then just order by those descending all right

50:00

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

50:08

need an instance of our comment service

50:13

so i'm going to do at inject

50:19

add a constructor public

50:30

define the comment service as the argument there so that will be injected and then we'll await this dot comment

50:37

service dot get for post and we'll provide it the post

50:44

okie dokie so that should be working okay let's go ahead and scope it out let's see what we got

50:50

oh i called the um called the yeah i changed the name of the component but i didn't change how i

50:56

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

51:03

and update this from just comment to be comment.base there we go

51:08

okay so there we go now we have this coming through um

51:14

and now we need to add in a reply button and you note that the anonymous comment

51:20

is still coming through i'm not sure how i was displaying the um

51:29

that the user was the current user i guess

51:36

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

51:43

working within our queries so if we come back into the comment service and we comment this particular portion

51:48

out here and we refresh we should not see the chimpanzee yeah so that's gone so our or

51:55

statement checking the identity is working and so let's go ahead and add in a reply

52:01

button and the reply button should only be there if the user is logged in

52:10

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

52:16

or i feel like there should be an or statement there because if how do you

52:22

respond as an anonymous person

52:29

i'm pretty sure i just blocked that all together previously let me go test that out

52:35

come down in here testing

52:41

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

52:48

reply okay i don't know whether or not that's the behavior i want to keep i guess that

52:54

makes sense that we don't have an honest person coming out here spamming everybody um

53:02

so yeah we'll stick with that behavior i guess so let's go back into our comment

53:10

yep base here and we'll do

53:15

a sub li and we need to change the way that this

53:22

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

53:28

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

53:34

so let's add in a button down here that

53:40

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

53:46

but let's go ahead and drop the form in here so at comment form

53:53

okay we'll drop the post id in and then we're also going to want to drop the

54:00

root parent id and the reply to

54:06

id and we could set that up at the top here within the loop so that we can make

54:12

things a little cleaner within our template so we can add set i already got the post today taken care

54:17

of that's coming from the parent of this component but the root parent id will be the top level

54:25

loop comment so that's going to be this comment here so

54:30

that will be comment.id and the reply to id will be the

54:36

immediate comment so that's going to again for right now it's just going to be

54:41

comment.id so reply to comment.id as we get more nested the

54:48

reply to will change but the root parent will stay the same

54:53

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

54:59

them into the form as well so that here it's just right over here i'll just do that

55:05

okay and there should be hidden fields so we know that well yeah i'll leave that the same we'll

55:11

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

55:17

so let's see what was it it was a root parent id value equals

55:25

root parent id okay

55:31

and then we had another one that was just reply to

55:43

ah there we go okay

55:49

put a break in there and so now those should be on the form we can also wrap those up in an if

55:55

statement um

56:01

shouldn't have to though and then we need to check and make sure that the

56:07

comments controller is bringing those in so we have the root

56:13

parent id being brought in but we also need the reply to okay and then those go directly into the

56:20

body or data which we then spread out into the comment and then we'll worry about validation later on

56:26

so back to the form everything should be taken care of if we go back to the base

56:31

everything should be taken care of so we'll just go ahead and test this out so we have the form being displayed

56:38

not very nicely on each one you can see that the ids for the root parent and reply to change for

56:44

each comment here that we have and then they are undefined for the root so if we add in a root so another root

56:53

comment which should be directed back and we should have in

57:01

oh okay so i guess i do need to um actually wrap those in if

57:06

so instead of undefined here we will want those to be null

57:12

you could probably just actually have that fall back directly in line so within the form here if it's not

57:18

provided let's go ahead and just have that fall back to null instead of undefined

57:24

or that's delish or yeah

57:29

there we go all right there we go now they're null so let's go ahead and test another route

57:36

comment submit that up still invalid input syntax right here type integer

57:44

all right

57:54

let me go ahead and just leave them off altogether it's probably coming up as a string

58:01

so let's take this out wrap this up in an if

58:08

and if root parent id

58:24

reply to yeah type the if statement then it completely

58:29

done i mean i did no clue what i was or i couldn't remember what i had just

58:34

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

58:40

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

58:47

so if we another root comment

58:54

there we go yeah so those were probably coming up as null strings which makes sense

59:00

and so there's our another root comment right there

59:09

so then if we come into another root comment here and we type in

59:15

this should be nested

59:20

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

59:26

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

59:31

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

59:37

the reply to and the root parent id actually populated i'll repair an ids over here yes so

59:44

those populated we do need to take care of the level index we'll take care of that here in a second but

59:50

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

59:55

properly list those out so we can actually extract this out into

1:00:05

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

1:00:12

comments regardless of what it's a response to so our reply to is within this comments

1:00:18

array so what we want is we want to grab just the root comments and then we'll loop through those first

1:00:24

and then what we'll do is we'll provide in a nested component that is our list here

1:00:29

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

1:00:36

applicable level within those comments for what's being displayed so here we want at set

1:00:42

root comments and we can grab that off of the comments so comments dot

1:00:48

um filter took me a second there uh so we'll do c

1:00:54

c dot uh let's see this would be reply to

1:00:59

is null so we could just do a not reply to all right and then we'll change this

1:01:06

but actually we'll extract this out into a list component so we'll do a new file

1:01:13

within here called list.edge paste this in here okay

1:01:20

and thinking actually

1:01:26

we can take this out make this even more simplistic because we're going to need that within here

1:01:32

anyway no not necessarily okay let's leave that

1:01:37

at the parent level so let's leave that here and then what we'll do is at

1:01:42

comment dot list so we'll provide it all of the comments and it will also provide it

1:01:51

the what's the best name for this

1:02:07

level comments i don't know um

1:02:14

but you get where i'm coming from so this was just the particular node node comments here why don't we call it

1:02:20

that sure we'll stick for that with that fair

1:02:26

right now and then within here instead of looping over the comments we would loop over the

1:02:31

node comments and we're also going to need to provide

1:02:37

the root parent id as well so that would come from here or no

1:02:43

hmm that would not come from here that would definitely need to be in here because

1:02:48

these are the roots if the level is zero so we'll also want well the level would

1:02:54

be coming off of the database which we haven't taken care of yet

1:03:05

okay so let's not worry about the route right now let's go ahead and make sure that this will work for the

1:03:11

children and then we'll do

1:03:18

child comments will be comments dot filter

1:03:23

um c where c dot reply to

1:03:28

equals comment dot id and then down here we won't need to display this ol unless there are child

1:03:36

comments so at if child comments dot length

1:03:45

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

1:03:50

inside of the li at each um to see child

1:03:57

in child comments and each

1:04:02

and let's plop that li back in there actually

1:04:07

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

1:04:14

checking whether or not we have the child comments and then it should just reuse this component so component

1:04:19

list and then what we would do is provide it the

1:04:25

same stuff that the parent level is providing it so we're going to want

1:04:32

we're going to want so okay i forgot one thing at the base

1:04:38

level here we also need the post id to be carried down as well so post id there

1:04:45

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

1:04:52

provide the root parent id and then the reply to

1:05:00

or no sorry the ch should just be the

1:05:06

node comments next yeah so node comments would then be the child

1:05:11

comments that we grabbed up above so there we go i believe that should be correct

1:05:19

and then that would just re-render this entire thing for the next level and then to make this a little bit easier to

1:05:24

see let's add a margin left of let's make it decent size let's do eight

1:05:30

so that we can visually see it since things aren't pretty over here oh can i read properties of undefined

1:05:36

reading oh yeah okay uh

1:05:50

oh yeah okay so we also need to provide the comments as a whole here too i don't

1:05:55

know if that's where the air is coming from we don't have a third level so maybe not but

1:06:01

we'll try well okay let me just click on it there we go

1:06:06

okay so that was what the error was cool all right so it might be a little difficult to see

1:06:12

but we have our root level right here so this is the create a root root level comment this is just start a whole

1:06:18

nother comment thread um hey uh

1:06:24

i'm sorry if i mispronounced your name is it roman um no i'm not using bootstrap this is

1:06:30

tailwind i pretty much use tailwind explicitly explicitly anymore

1:06:38

and then i'm just wrapping stuff up in my own custom components so like if we take a look at the input component

1:06:43

i have that within form input so you can see the tailwind stuff is just right here so

1:06:50

i kind of extract out all of the tail and stuff so that it's not bloating everything

1:06:57

um so that that's my approach and then all of this code is up on github uh

1:07:02

at the repository under yeagerco let's see it's github.com

1:07:08

jager hyphen co and then i think it's jaeger dot co yeah so all of the code can be found

1:07:14

here as well um but so this is the root level so you can

1:07:20

see we have oh no sorry this is the root level here because we have the margin left

1:07:26

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

1:07:32

another margin left showing that this is a child of this particular component so that

1:07:37

seems to be working okay uh what we can do is we can test another so

1:07:44

this should be level three so level

1:07:50

one level two level three and post that in there i'm actually gonna add a border left to make it a

1:07:57

little bit even more evident that what level we're on uh so level three so we

1:08:02

have an indent there oop indent there and an indent there so that is indeed level three and is being

1:08:08

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

1:08:14

so margin left or border left sorry border left border

1:08:19

and we'll do gray let's do 300

1:08:27

i'm not using the exact tailwind colors i'm using uh redux radex colors

1:08:33

so the color level is a little bit different so 300 is a lot lighter than tailwind's normal 300 but

1:08:41

all right so there we go so this seems to be working okay

1:08:47

we can go ahead and get rid of these inputs make them hidden so that's going to be inside of the form

1:08:56

so instead of type text we'll change this to type hidden

1:09:04

and hidden that should make things a little bit easier to see all right yeah that's a little bit better

1:09:10

and then we can go ahead and hide the um excuse me

1:09:16

the form behind a reply to button or a reply button

1:09:22

um well before we do that let's go and take care of the

1:09:28

nested level so in order to properly do that

1:09:34

since we already have comments in here there's two ways we could do it we could grab it off of the current

1:09:39

level so like if i go into list here we can grab it off of the current comments but if there are no comments

1:09:46

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

1:09:52

um or we could just manually pass in each time that we go down a list we increment the level count

1:10:01

not really sure which one which approach i prefer here um

1:10:12

either way we would need to provide it into the form so why don't we go ahead and go with

1:10:21

this so let's do

1:10:26

within the list at level index equals

1:10:32

level index and then default it to zero if one's not provided

1:10:37

um and then we will provide that into the well no actually

1:10:48

because the form for the root is out here

1:10:56

so really that should just that that set should be in there not not out here so let me take that off

1:11:03

and let's provide that into the form instead and really we could make that a hidden

1:11:09

input so input type hidden name level index value equals

1:11:17

let me go ahead and just finish that off there we go level index or zero

1:11:24

and then so we don't need to worry about it at

1:11:29

the root level now because it will just default to that zero i do need to save whatever i change there though

1:11:35

um and then here

1:11:41

ah let's see i'm gonna break this down it's starting to get a little bit

1:11:46

lengthy okay and let's add that in here so

1:11:54

no level index and let's

1:12:06

do what do i want to do here

1:12:14

you would start at a one because then this would be zero now this would be yeah no this would be

1:12:20

zero

1:12:27

but then that would make this need to be one so

1:12:47

no that wouldn't

1:12:54

there all right

1:13:09

because no yeah let's do that so zero

1:13:16

would be for any here one would then be for any inside of there so that

1:13:24

defaulting it to one sounds right to me and then we already have level index defined so we can just take that off put

1:13:31

that here okay

1:13:37

that sounds right to me i'm gonna go ahead and make that a non-hidden component just so that i can

1:13:43

visually easily inspect and make sure that that's what's so let's just change the type text

1:13:51

okay and so we have level zero here which is what we want we have level one there

1:13:56

level two there level so that seems to be working just fine go back to level one one and okay cool

1:14:05

so now what we need to do is persist that um so let's go back up to our comments

1:14:12

controller here and grab that out of here

1:14:19

it's a level index that will get populated within here so that should now be good um and then

1:14:29

next thing that we would want to take care of is editing

1:14:36

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

1:14:42

one for editing one for creating a response so

1:14:49

let's see here so we'll take in let's see at the root level here let's

1:14:56

it's going to be need to be in the list and dictated from within here so

1:15:04

we'll need to use a client-side thing wait a minute do i have two indents here i do

1:15:11

i'm not sure how that happened so let's do

1:15:19

trying to think of how alpine is gonna behave if i

1:15:24

instantiate like what is x data

1:15:30

on each li and nest that down i think that would be very

1:15:35

well i think that's how that's intended to be um

1:15:54

why don't we take it out the base here

1:16:06

let's try this first i guess so is the x init or x data i think it's x

1:16:14

data all right and then edit id

1:16:22

no and

1:16:29

yeah i think that that let's stick with that and then

1:16:35

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

1:16:42

see the students div class flex item center

1:16:50

justify end

1:16:56

all right and we'll put see edit should come before delete so we'll just put a button type

1:17:02

button um click equals

1:17:08

edit id equals and then we're going to need to provide alpine

1:17:14

what level we're at oh no we can hard code that

1:17:19

so okay we'll provide that directly from adonis so we'll do

1:17:26

comment dot id there

1:17:34

okay and we'll do an edit there and then let's go ahead and

1:17:41

duplicate that again and

1:17:48

we'll want some way to

1:17:55

uh asks can we use graphql with adonisj i

1:18:00

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

1:18:07

packages.js.com it'll have a list of packages that you can search through

1:18:15

let's see if there's i don't know if all of them are listed in here but this will search both

1:18:21

community and um first party

1:18:27

so it doesn't look like there's any listed in here but that doesn't mean that there isn't one um

1:18:35

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

1:18:42

package that in there i just haven't tried

1:18:51

um let's see where was i

1:18:56

so we're gonna want a way to say are you using a or are you trying to create a

1:19:02

comment uh so we'll need like a create id i guess default that to null 2. so we have an

1:19:08

edit and a create id and so if we're editing change the edit id if we're creating

1:19:15

change the create id

1:19:20

and then uh jeno said graphql is not built in

1:19:26

there's a third-party package but last time i checked it was under development constantly changing yeah so

1:19:31

probably still in the works in like a beta state

1:19:38

um okey doke so we have the creativity editor id that

1:19:45

should be set what we will do next is

1:19:53

let's just display whether or not we're at that level so

1:19:58

um let's see let's do let's do

1:20:05

p with x text

1:20:11

eh

1:20:20

i'm trying to think of how how i should display so

1:20:26

we can't pass any of this down through adonis because that's at the

1:20:32

client side at that point so within the form we just need to kind of check whether or not this should

1:20:37

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

1:20:43

maintained here and we're not doing another check with inform to check and see whether or not a variable

1:20:49

instantiated here or edited here um so we'll do div

1:20:54

v i think it's v show no that's view x show

1:21:00

is uh let's see so this is the reply form so created

1:21:06

id equals and then we can use adonis to just provide what that equality check should

1:21:14

check against so comment dot id

1:21:19

and div and there we go so we'll work on oh need to change that text to

1:21:26

work on reply first so we'll see whether or not this all right looks like we got an error

1:21:33

create id is not all right that might be an old one see if that's still relevant

1:21:38

looks like it is all right i bet you it's not x data i

1:21:45

think it used to be but maybe it's not anymore let me go check i don't use alpine all that much um

1:21:53

al pine js let's see

1:21:58

what is x data hmm what am i doing wrong then

1:22:04

create ids not defined all right so it's on the x show that

1:22:10

it's complaining about it um

1:22:25

okay so it's just it is here

1:22:38

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

1:22:44

where they okay so create id there we go let's change that

1:22:53

all right there we go now we got our reply edit that they're not pretty but they're there

1:22:59

so if we tack on reply here boom there's our form if we tack on reply there that form

1:23:04

should go away and there's the form here boom

1:23:13

um i don't intend on doing a payment integration within this particular series that'll be within something

1:23:21

different in the future though i don't have a timetable for it though

1:23:28

but there's a package um i think menzie created uh

1:23:35

for payment integration you can check that out on packages.thomasjs.com i did see that in

1:23:40

here yeah payment it's for stripe uh so you can check that out and it should help you out at least

1:23:47

decently all right so we can hide the level we know that that's working

1:23:55

um all right so where do i here it is so we change that to hidden

1:24:01

and then i can get rid of my little to do here since we've done that it's to did

1:24:07

and then add some spacing to those buttons so that they're not horrible to look

1:24:14

at that's in the list uh so we'll just do space x

1:24:21

three i should space those out decently yeah so that's good for now um

1:24:28

and then we need to do an edit so right now edit's not doing anything response will

1:24:34

should be able to add a cancel button in there too

1:24:44

so we'll just pass that in as a cancel bubble is that how you spell it cancel

1:24:51

i think so cancelable true i don't know good enough for me i'll know what i mean

1:24:57

um so then within the form we will do

1:25:03

at if cancel a bull

1:25:08

uh we'll add in a little cancel button so at button type

1:25:14

but button um

1:25:19

and then the variant

1:25:26

i think i can name those secondary and then i want to change this one too

1:25:36

i think i think that's right um and then we'll do

1:25:44

margin left of three so there's some space in between them so we'll see if that renders stuff in there

1:25:52

what i do unclosed tag yeah i did not close that did i

1:25:58

end and cancel

1:26:06

okay so the root level should not have a cancel button because otherwise how are they gonna leave a

1:26:12

comment if they change their mind but reply should and all right cool

1:26:18

that's kind of what i was going for and then when you click it it should

1:26:23

reset the form and hide the form

1:26:30

which there is no yeah i guess you could just grab the form i don't know if there's a ref that

1:26:36

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

1:26:43

so we will want that to be passed in

1:26:48

because at this level we don't want to worry about what exactly is going on whether it's creating or responding we

1:26:54

just want it to handle whatever is provided so here

1:27:00

within let's go ahead and do the same thing here let's drop this down let's start needle a

1:27:06

little long too we will want

1:27:12

on cancel or something of the sort

1:27:20

and we'll want to provide that i don't remember how i do this

1:27:31

i think you provided as a string i did this in the studio portion um

1:27:38

where you pass in a client-side function from the server side

1:27:43

edge uh so let's see let's see uh this should be

1:27:49

a function that well it needs to be a

1:27:55

hold on a minute so it needs to be an alpine function not just any old function

1:28:01

so let's come back up into here maybe we change this to

1:28:07

here for right now i'll just go ahead and just drop this down and we'll do it all in line

1:28:15

so cancel make this a function that

1:28:20

this edit id equals null and this create id

1:28:26

eq create there we go id equals null um

1:28:36

we can also since we only have we will only have one thing um happening at one point in time let's

1:28:42

go ahead and do an edit function okay that will take in the

1:28:48

edit id and what this will do is it will set this it will this dot

1:28:54

cancel so we only want somebody to be able to edit or create show one or the other at any point in

1:29:01

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

1:29:07

edit id equals edit id and then we will want a reply

1:29:16

we'll call that create actually since reply should be more of a method

1:29:22

for creating um let's see and then we'll take in the create id

1:29:28

spell that right what does that look wrong that's right create id

1:29:35

this dot cancel again and then this dot create id equals

1:29:41

that provided create id okay so now we have these methods that we can

1:29:48

call from within here so instead of this

1:29:53

we will change this to create and then we will use

1:29:58

edge to provide the id that should be provided to the create call whenever that's clicked and then the same thing

1:30:04

going on here for edit so oh missed the bracket or parenthesis

1:30:10

there we go i'm going to go ahead and put a space there just to make that a little bit

1:30:15

more readable i think it's hard to tell what's bracket and what's parentheses there there we go

1:30:23

okay so that should work for that and then down here

1:30:32

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

1:30:40

but let's try to provide cancel

1:30:47

like that and then i guess since we're in the comment we're in the forum

1:30:53

we're gonna know that we're using alpine here so we can make that judgment call

1:30:59

and then how do i provide that into this here though let me take a look at my button component

1:31:05

where is my button component here's my button component okay so i know if i provide on click

1:31:14

so we could do another uh form of that so on click would be for

1:31:19

a native javascript function if we want to do alpine

1:31:26

we could do at click and then provide it

1:31:33

on at click i don't know

1:31:41

or undefined

1:31:47

we'll stick with that for right now and then um yeah anchor should probably need that

1:31:54

so that should be okay and then we'll go back to the forum

1:31:59

and so we'll do at click sounds horrible and then

1:32:05

that will be yeah we'll

1:32:11

leave it just that so come back up to the list and then we'll

1:32:16

define that on the form so on cancel should now be

1:32:22

at cancel that's what we should define that as

1:32:27

i guess no on cancel there's more right and we'll provide that

1:32:34

cancel so that'll be an alpine function and so we can discern within

1:32:42

here that it should be at click on cancel

1:32:49

i think i did that right we'll see all right we got no

1:32:54

no edge errors so that's that's good so if we reply

1:32:59

to this one and then we hit cancel oh thank goodness that works

1:33:06

hey malek thanks for stopping by um so then we just need to do kind of the

1:33:12

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

1:33:17

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

1:33:23

the current comments data and then pretty much just mimic everything else

1:33:30

so um

1:33:35

we need to go outside of the form back into the list and so this is the reply so i'm going to

1:33:42

add a comment make that a little bit more evident so reply to form

1:33:50

and the edit form probably want that to be above it so edit

1:33:55

comment form div we'll want another x show this will be edit id equals

1:34:02

and then from edge we'll provide the server side comment id into the client side

1:34:08

alpine check there and div

1:34:14

and then we're going to want our form so comment form for the most part we're going to want

1:34:19

the exact same thing

1:34:25

uh no

1:34:30

eh i guess those would all come from the comment itself

1:34:36

so let's go ahead and hard code the hard code those um so that would be comment dot

1:34:41

root parent id reply to

1:34:47

comment that reply to

1:34:53

a post would be comment you won't want that to change post id

1:34:59

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

1:35:04

level index

1:35:11

i wonder if i should just spread the comment into it for the most part these are one to one

1:35:16

then you got the on cancel so let's go ahead and try that

1:35:25

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

1:35:32

um and then all we need to do is provide cancelable true

1:35:39

on cancel cancel

1:35:45

um and then we need a way to provide it what the action should be so currently

1:35:50

if we take a look at the form it's just going to hard code the store so what we

1:35:56

need to do is tell it whether or not it is editing a comment or whether it's creating a

1:36:01

comment so i guess we could just check whether or not we have a

1:36:07

id that passed through that would since we're spreading the comment out that would take care of it

1:36:12

so we have the entire comment being provided so why don't we do that so

1:36:19

within here we'll do at set action and we'll default this to route

1:36:27

comments dot store so we'll default that to create but then we'll do an if we have an id

1:36:34

then we'll do our end if there set action so we'll overwrite it to be route

1:36:41

comments dot i don't think we have this route created yet but this will be update

1:36:47

and then we'll need to provide the id and then we'll need to provide

1:36:54

method did i spell that right yes okay it's a little bit far away that you look like something else to me um

1:37:04

put yeah okay and then

1:37:10

we will overwrite not the curly braces but just what's inside of here to our action

1:37:16

okay and then all of these should come off of the spreaded post so those should all be just just

1:37:23

fine thank you malik appreciate the compliment

1:37:29

um and then we need to take care of the body so the value should be an empty

1:37:35

string if there is not a body so we can do body and then we also want to get it in case

1:37:42

whenever we do add validation there is an error so we could do

1:37:49

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

1:37:55

to be hidden anyway so

1:38:00

well we'll go ahead and add it in flash messages get

1:38:05

body um

1:38:12

i think you can do that multi-level no class i i think you can do that

1:38:23

all right anyway so give priority to the flash message if our validation fails then it will plop

1:38:29

what the previous value was within here oh wait a minute

1:38:35

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

1:38:41

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

1:38:47

um but then we plop it into the one that was actually being edited

1:38:52

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

1:38:58

we'll put that in there um all right that was a long circle where

1:39:04

was i uh let's see input form body so yeah okay

1:39:10

so then we should just change this to be if we have an id

1:39:16

update otherwise create probably change that verbage

1:39:21

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

1:39:26

that's it main thing here is checking whether or not the body actually does populate and

1:39:32

whether or not these here populate correctly and that the action properly goes to an update oh yeah we

1:39:38

need to create that um so let's go into the comments controller first take care of the update action

1:39:44

so here get rid of that comment that doesn't make any sense to do and then let's go down to

1:39:50

update i don't think for this we're going to need edit or show

1:39:57

creator index we don't think we're going to need any of those so we can simplify this controller a little bit

1:40:03

okay and then we're going to want

1:40:08

to get the body data response eventually we'll want off

1:40:14

and params whenever we do authorization checking we'll want auth there

1:40:21

but again i'm gonna go ahead and add a comment here so i don't forget

1:40:27

to do authorization

1:40:33

okay so const data equals request dot only again

1:40:39

we'll worry about validation here later um let's get just get stuff happening first

1:40:45

post id body root

1:40:50

parent well really these things should never change so why don't we just ignore them

1:40:56

right we just ignore them the only thing that really should change is the body whenever you're updating that should be

1:41:02

it and then we'll find the comment so const

1:41:08

comment equals weight comment dot

1:41:13

finder fail actually we can do my lazy man's

1:41:19

authorization here for right now let's do off user assume that we have a user

1:41:24

related so then we are assuming we're restricting updating to

1:41:31

the authenticated user so that they can only update theirs by doing the related off of the user because now the user id

1:41:37

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

1:41:43

check so we'll start with this and then i'll add in bouncer later on uh so

1:41:50

what is it we're doing comments i don't have that on here all right so let's add that onto our

1:41:57

user so that i can do my lazyman's authorization user

1:42:02

this is going to be has many as well so it has many

1:42:09

comment make sure that i get one that's going to auto import there we go public

1:42:15

comments as many type of

1:42:21

comment and then the property for that is user id so we don't need to worry about defining anything like that there okay

1:42:27

so that should be good now so let me go back in here make sure that the autocomplete is showing it

1:42:35

comments there we go cool and then we could do

1:42:41

where [Music] id is params.id

1:42:47

first or fail so now that we have that first or fail on there oh and then initiate the query

1:42:56

so that we have the first or fail on there if the authenticated user doesn't have a comment matching

1:43:02

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

1:43:09

kind of a lazy man's authorization check because you're still authorizing the user by querying only the user's

1:43:14

comments but it's not you know the actual authorization that you would want but

1:43:20

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

1:43:27

body that we're grabbing off of the request body so we'll merge in data that's an object

1:43:33

there and then we'll just call save and that will take care of it and we can return response

1:43:38

redirect back and that's all that we need so let's go ahead and define that route so routes

1:43:47

put this before delete route.put comments the id

1:43:53

comments controller dot update as comments

1:43:59

update and then i'm going to go ahead and put all these comment ones on the same

1:44:04

tab level there we go this makes it a little bit easier to scroll through your things and see what's all grouped uh

1:44:09

together because they're at the same indentation level for the controllers all right so

1:44:16

i think that should work i think we should be all good now so let's go ahead and

1:44:22

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

1:44:31

starting off bad by not having a state for our text area

1:44:38

oh i think i'm plopping the value in there wrong it should go inside

1:44:43

unless this is trying to use alpine oh it is x model value

1:44:50

interesting so looks like the post id didn't go the level id

1:44:55

it was zero anyway uh but yeah it doesn't look like anything populating correctly as i had hoped it would

1:45:05

oh oh it's because we have a nested i bet you unnested no that should still go because this is

1:45:12

being provided um server-side so that should still work as i had hoped it would

1:45:18

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

1:45:23

would that might be the issue i'm not sure i haven't tried it before so

1:45:31

it was a try and see if it works thing so it might not i'm talking about this spread right here

1:45:36

where i'm spreading the comment record in um you would think it would work but

1:45:42

maybe not

1:45:48

so i guess let's go ahead and just try providing the post id manually instead of spreading it and see whether or not

1:45:53

it actually goes in there now so let's do com post id comment dot um

1:45:59

post id yeah yes

1:46:05

while i'm at it let's go ahead and make sure the edit is not yeah edit so that should be okay

1:46:11

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

1:46:16

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

1:46:24

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

1:46:29

serialize and then spread i would anticipate that it should work then so

1:46:35

i would assume it's because of the getters so let's go ahead and try cereal eyes

1:46:41

in it i think i spelled that right we'll get rid of that

1:46:49

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

1:46:56

come out here and we tack in and inspect on the comment itself on the comment

1:47:03

record you'll see that we have a whole bunch we have kind of a whole

1:47:10

object set here just mapping stuff to lucid so this every

1:47:15

property that we would want to get is within attributes so we could spread the attributes and that should work

1:47:22

but whenever you do your record so comment.id comment.whatever it's using a getter to

1:47:28

grab it off of the attributes but whenever you serialize

1:47:34

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

1:47:40

serialized data here um so like so now

1:47:46

this is coming through as uh snake case

1:47:52

um i think i'm going to change that to be camel case

1:47:59

is that in this project that i did that or is that a different one that was in a different one all right

1:48:09

since the form

1:48:15

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

1:48:22

here and i have a somewhere an adonis camel case naming

1:48:28

strategy example that has app strategies and a camel case naming strategy i'm

1:48:35

just going to go ahead and copy this there we go

1:48:40

come back into here create that structure so app new file

1:48:48

strategies camel case

1:48:53

naming strategy paste that in there

1:48:59

and then i'm going to go ahead and just create a base model so scroll a little bit on accident and i

1:49:05

miss clicked and there we go and let's go ahead and create a base model so we'll do amp base model

1:49:12

ts export default class app

1:49:18

base model extends base model

1:49:25

from adonis and then oh what was it was it

1:49:30

it was naming strategy but did it had if it had a dollar sign before it i can't remember

1:49:38

excuse me in here public static naming strategy okay gotcha

1:49:53

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

1:50:01

get rid of that i'm gonna go ahead and define import here import app base

1:50:09

model

1:50:15

okay i'm gonna copy that and then

1:50:23

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

1:50:28

not to find a phil but uh just just to find oh went the wrong way

1:50:35

there we go and then app

1:50:41

collection scroll to the top plop that in there

1:50:46

app get rid of that okay comment do that once more so

1:50:55

app paste that in there

1:51:01

okay notifications

1:51:06

app paste that all right

1:51:12

post about halfway through

1:51:19

there we go okay

1:51:38

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

1:51:44

within that base model and then we'll need to redo going through each model to apply stuff so whoa

1:51:51

there we go two more taxonomy and user

1:52:00

okay

1:52:07

fix that bracketing too okay and last one

1:52:14

amp

1:52:20

all righty there we go so now if we come back and we take a look at the serialized uh

1:52:25

data here need to refresh it's all in camelcase so

1:52:31

i can provide stuff from the model and now whenever i serialize it

1:52:36

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

1:52:48

so let's see i don't need that open don't need that open don't need this open

1:52:56

so now if we go back take a look at our form again all right let me get rid of the serialization

1:53:02

i'll see i did that in list didn't i so there we go so we have

1:53:07

comment.serialize so that we get the just the properties that we care about off of this and let's go ahead scroll on

1:53:14

down and now if we hit edit all of that stuff should be populated

1:53:20

off of the comment yeah so we have post id the level is

1:53:26

zero anyway um but then we're also getting this information here

1:53:32

uh and then let's go ahead and check the form so method post comments so the

1:53:40

uh query string isn't getting appended on to set this to a put

1:53:46

um it should be spoofing the um

1:53:52

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

1:53:58

object level deep where that we have the query string and then the put okay

1:54:10

and where is that now there it is now you can see it got underscore method equals put on there so

1:54:16

now whenever we actually submit this form adonis will match it to a put route

1:54:22

so let's go ahead and edit this

1:54:30

all right and we'll also want to do that to where that only applies

1:54:36

for the authenticated user we only plop this in if the comment matches the actual user's id

1:54:42

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

1:54:48

updated here go and try that out so we got redirected back and now you can see boom this dot

1:54:55

updated if we edit there it is we can get rid of it

1:55:01

it should happen again it should be gone there it is we can do that with a nested one so if we edit

1:55:06

this guy here updated

1:55:14

voila and if we go ahead and reply to this comment

1:55:23

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

1:55:28

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

1:55:34

refresh it should be this last one here let me verify that within the body on the level four scroll all the way over

1:55:43

looks like it's uh set to three it should be four

1:55:48

maybe oh no i'm starting at zero right so maybe that is right so zero one two

1:55:55

three okay so okay that's fine it is an index it should start at zero so

1:56:00

we're good there so then we can edit that so it displays correctly now that we have our edit form

1:56:05

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

1:56:11

actually resubmitting the whole page again and i think to do that i'm going to try unpoly

1:56:17

but i've never worked with onpoly before i've only seen almond work with it so

1:56:24

i don't want to tread into that water on stream because i feel like i'd just be

1:56:29

reading a bunch of documentation in front of you so i'll try that on my own um

1:56:35

and then we should be able to delete any comment now the delete behavior does need to change so we can take care of

1:56:40

that i guess so right now if i were to delete a comment

1:56:46

first it would fail because it has other like if i were to delete a comment that has children it would fail because i

1:56:53

don't do uh what is it coalescing deletes um

1:57:00

so this one here has a foreign key referencing this one so if i were to try to delete this one the foreign key

1:57:06

restraint here would prevent that from happening and we can go ahead and see that here so if i delete there boom

1:57:12

violates foreign key constraint so what we want to have happen is instead

1:57:18

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

1:57:24

want what i would prefer is that it should just anonymize this comment

1:57:30

completely so it detaches it from the user gets rid of the comment body and it remains keeps everything else in

1:57:36

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

1:57:42

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

1:57:49

conversation and just nullify out whatever that user's comment was so

1:57:57

let's take a look at that so uh that would be within our comments controller underneath destroy so you can see this

1:58:04

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

1:58:12

so instead of doing this what we will do is we'll want to

1:58:19

completely anonymize it so we'll get rid of the identity we will get rid of the name

1:58:28

and switch the body to just be removed we'll get rid of the user id and i believe keep everything else

1:58:39

how does reddit do it do they keep they keep the name in there don't they

1:58:45

i don't know let me see what my current comment

1:58:51

system does for that would be interesting to see so let me go ahead and

1:58:58

is a test oh i don't want to do this anonymously oh my toasts don't auto

1:59:04

remove

1:59:11

okay let me go in here go down to my comments all right

1:59:17

so this is a test go ahead and comment that in here

1:59:23

let me go ahead and reply this is a reply

1:59:30

reply there oh it's because i'm trying to respond to

1:59:36

myself oh no it did go okay um and then if we delete this guy

1:59:44

boom okay so it does keep the user information it just deletes out the comment and then if the user were to delete

1:59:50

themselves then it would delete out the user too okay so i thought about it more whenever i

1:59:56

created this comment system than i am right now so we'll stick with what i had originally decided

2:00:02

um with the new system so keep the user information just delete

2:00:08

out the comment body and then if the user deletes their account then you would then delete out

2:00:13

the user information from the comment so instead of deleting

2:00:20

we will await er hold on a minute we will const

2:00:25

comment equals and then we don't want to do our lazy man's

2:00:31

authorization checking because if the identity matches an

2:00:36

anonymous comment that user would then be able to delete their comments so not necessarily going to be an auth user

2:00:44

within here so we'll just do a wait comment and we'll worry about authorization later with bouncer

2:00:52

finder fail uh the id or sorry

2:00:58

the id and then await comment dot merge and then what we'll do

2:01:05

is just set the you know body to

2:01:12

deleted and [Music]

2:01:20

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

2:01:27

little bit better all right so all we're doing now is just rewriting

2:01:32

the body to deleted um oh wait a minute

2:01:38

and check and see whether or not has children so const has children equals a weight

2:01:46

ah let's see here comment dot

2:01:51

related responses

2:01:57

query

2:02:03

dot where state

2:02:08

state id do i have states within here yes cool

2:02:14

dot

2:02:23

public not archived maybe

2:02:31

yeah let's let's do not archived so we're not

2:02:37

states dot archived and then here in addition to changing

2:02:42

the body change the state id to states dot

2:02:49

archived okay um and then

2:02:56

dot i feel like i should just do a count

2:03:02

here uh let's see i don't do counts all that often so count

2:03:08

try that i guess no taking it oh yeah id

2:03:16

all right i don't remember how this comes back so

2:03:23

let me tinker with a little bit so node ace

2:03:28

rebel let me start a rebel session load models

2:03:34

okay await or let's do const comment let me try it out exactly

2:03:39

how i have it in there and we'll see how it comes back so awaits comment dot

2:03:45

or sorry model uh yeah models dot

2:03:51

comment dot find or fail and then let me go grab the id

2:03:57

of the one that has responses so let's see take a look at the parent id

2:04:03

it would be good to go off of so we have oh no root parent id is changing

2:04:09

that should be the same for all of these so i need to

2:04:14

fix that but looks like six is the one that we want

2:04:20

to grab here so let's grab six

2:04:26

okay const count equals awaits

2:04:33

models dot or sorry we have the let's do comment

2:04:38

dot related responses

2:04:44

dot let me and so we're mimicking what we have right here

2:04:50

so query where not state id equals states.archived which is six so

2:04:56

dot query dot where not state id

2:05:03

equals six hardcoded because i don't have states here and then what is it

2:05:08

count.id

2:05:14

okay so we're just going to see how that comes back oh i put it into a variable instead of

2:05:19

just you know let me go ahead and just plop it directly out here there we go

2:05:26

all right so yeah it does

2:05:32

okay so extras and then it should be just count out of there so

2:05:38

all right so let's change this to children and then

2:05:44

we'll do if

2:05:49

if children dot extras dot count

2:05:57

then we'll do that else

2:06:06

oh it's an array oh let's see can i do first

2:06:12

let's see just try this again to get back an object

2:06:18

it doesn't look like it wants to

2:06:27

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

2:06:34

but okay so uh let's do let's just grab that out of there

2:06:40

we're just gonna get back one response anyway with the count and then once they do that otherwise we

2:06:46

should be green and clear to go ahead and delete it so await and we'll do what we had before or we

2:06:52

already have the comment here so we just do a weight comment dot and then delete so yeah

2:06:58

all right that's not the prettiest block of code i've ever seen but it'll work for now

2:07:06

so we'll check whether or not we have any responses really this should be the

2:07:12

root parent id so it should check all the way down to stem no

2:07:17

because then if it has a parent and you delete one of the children okay so all right let's stick with this

2:07:23

all right yeah sounds good so let's go ahead and save that and try it out so

2:07:30

let me go ahead and delete my tests on my production site always good to test stuff out in production highly

2:07:36

recommended

2:07:41

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

2:07:48

should get back the exact same tree but that comment should now say deleted

2:07:54

and boom there we go so that seems seems to be working good

2:08:01

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

2:08:06

where we can visually see it nice and easily within the form so form

2:08:11

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

2:08:17

levels scroll back down here and i'm not seeing

2:08:22

it maybe that's part of the issue oh the form itself is hidden too so

2:08:31

all right um let's see let's go ahead and get rid of

2:08:36

the x show that should be on

2:08:41

should be on edit id too so let's go and get rid of the x show here um

2:08:46

just get rid of that completely for right now

2:08:53

okay so here it's not provided at all and it should be

2:08:59

i think maybe not no because that is the root okay so

2:09:05

it shouldn't be there but it should be here six seven so let's

2:09:11

see it now it should be six six six but it's going to the immediate

2:09:16

parent so essentially right now is behaving the exact same as reply to so if we looked over at it it's probably

2:09:22

six seven eight and yeah it matches so

2:09:28

um

2:09:36

why

2:09:46

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

2:09:52

it no and that makes sense because the loop for the parents is inside of there so

2:09:59

okay so boom um so here we need to check whether or not

2:10:05

it is the route and so for that uh you would check the reply to so if

2:10:12

um comment dot reply to

2:10:17

then it would be should be provided so root

2:10:23

parent id otherwise should be the comment.id

2:10:33

and then we need to make sure that we're providing it to

2:10:40

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

2:10:47

okay so that should be okay let's go ahead

2:10:53

and see uh we might need to probably need yeah since this is all pulling from the

2:10:58

database already uh we'll need to kind of

2:11:04

oh right i took out the show um where was that it was right here can i

2:11:10

oh no i made a change do i have it oh no all right i'm gonna go

2:11:16

back to where that is all right let me just go ahead and copy it and we'll go forward

2:11:23

all right go back before that paste and now paste there we go okay so let's go ahead and delete out

2:11:28

all of our comments with to be a good chance to test out the deletions again so

2:11:37

well uh on a minute so on the delete are we checking to make sure that all that the children itself

2:11:44

isn't because if i come up to here i would anticipate delete should be hidden because it has already deleted

2:11:50

it's archived but then if we delete these two how would we tell it

2:11:56

to delete this guide too

2:12:02

i guess it would be on the delete check itself you should check the parent too

2:12:08

so here so

2:12:17

if comment dot and here we can actually just do await

2:12:25

comment dot sorry load uh parent

2:12:37

and here we can wrap this up in a nif so if comment dot uh

2:12:43

reply yeah reply to and then that was the if that i was

2:12:49

going to write here so i can get rid of that load in the parent and then

2:12:58

no um yeah if comment parent

2:13:04

dot state id equals states dot archived

2:13:13

then you would delete the parent too of course that would need to happen after you delete the child

2:13:21

so let's

2:13:28

let's all right let's change that so const parent equals

2:13:36

comment dot related parent

2:13:44

query for no just first

2:13:51

okay i think i'm doing that right see

2:13:56

and then down here after you delete the child if parent

2:14:04

dot state id doesn't seem like it wants to

2:14:11

all right so what are you telling me parent is it's a comment or no oh it's promise oh wait

2:14:17

oh wait there we go state id equals

2:14:23

states.archive so if the parent is archive two then we want to await

2:14:29

parent dot delete so that should delete out that parent

2:14:35

too so let's go ahead and test all of that stuff out so we'll delete this guy should go just fine

2:14:41

oh missing model attribute comment.parent expects comment id to exist on

2:14:48

comment model but it is missing and that is because it is reply to

2:14:53

so that is on the parent relationship so let me go into that model

2:15:00

so comment model just

2:15:05

misdefined this let's go to parent local key maybe that needs to be foreign

2:15:12

key

2:15:20

maybe that doesn't need to be foreign maybe i got these mixed up

2:15:27

i don't think i've tried the responses query quite yet or did i is that what i tried in a rebel

2:15:35

yes okay okay yeah no i think both of those should actually be the same because

2:15:41

yeah okay my head was in a different spot whenever i wrote that up yeah that should be the same

2:15:46

okay so now that should work as intended let me make sure i got both of those saved okay there we go

2:15:52

so let's go back try that one more time so let's see we're trying to delete this

2:15:57

whole tree here so let's start at the bottom delete there it goes

2:16:04

and oh all right so that count checks not working as i had hoped because now that's just

2:16:10

gone and deleted the um so let's go ahead and console.log out what it thinks that

2:16:15

count is

2:16:26

and i'm just going to console.log out the extras object we'll see exactly extras there we go

2:16:33

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

2:16:39

we should go right back to there uh so let me go ahead and re-click delete there

2:16:44

nothing should change should still just be delete okay check the console log

2:16:50

and oh i'm in rebel uh let me alright let's submit that and exit

2:16:58

all right let's oh no over here all right so yeah it's count and then

2:17:03

it's a string of zero so there is the issue

2:17:14

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

2:17:19

i don't feel like looking it up okay so now that should work

2:17:25

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

2:17:31

immediately go we shouldn't have to go through the delete step and there it goes and cool yeah it actually deleted the

2:17:38

parent too so that is working as i had hoped okay so now we are all at level zero

2:17:44

back to our root parents not needing the ids um

2:17:53

i guess ideally what would happen is after you create the

2:18:01

comment it should go back in and fill itself in as the root parent because

2:18:06

i mean technically it is the root of itself i'll think about that a little bit more

2:18:12

but so let's take a look at make sure that the root parent id gets populated correctly for responses and that the

2:18:17

level index remains correct because i don't think we gave the level index its proper testing before

2:18:22

so let's go ahead and add a response here testing we can see that the root pair

2:18:28

know is going to be six okay add a response to our prior

2:18:35

response cool so it's still six so that seems like it's going to work okay testing two

2:18:42

and let's add in a third just for chucks and giggles

2:18:49

testing three okay

2:18:56

there we go one two and three if you go into the database here refresh

2:19:01

all of those have six and we have one two and three as the level index

2:19:07

if we respond again to let's say this level here

2:19:14

so we'll do testing a should be six and the level index should be one

2:19:21

so right there it is and let's test that out so the latest one should be six and the level id is

2:19:27

one looking good let's respond to let's respond to this one

2:19:36

testing 2a all right should be displayed at the same level

2:19:42

testing 2a oh oh yeah no i did respond to testing two didn't i so then it should be back

2:19:48

at level three yeah there we go so that is all looking

2:19:54

a okay if we delete this one it should not

2:20:00

delete the parent oh wait i didn't do that check did i

2:20:06

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

2:20:11

check the parents children to make sure that there's no other children so that would be a sibling's check um

2:20:23

so let's go ahead and just do a preload on there

2:20:28

her with count i guess with count

2:20:33

okay that would be responses

2:20:40

um all right let's only worry about that if

2:20:46

we get to the point where we need to worry about that so down here so awaits

2:20:53

parent dot related yeah

2:20:58

responses dot so at this point we would have already

2:21:03

deleted the um comment before so let's do

2:21:11

query dot count

2:21:19

id const and we'll name the siblings equals

2:21:27

all right not the prettiest block of code you've ever seen here but i will spend some time and clean this up

2:21:34

after i after the stream children dot

2:21:39

extras count oh no not not children uh siblings

2:21:45

okay bam so if not

2:21:51

there we go so if the parent is archived and it does

2:21:57

not have any siblings then we will delete if the parent is archived but it does

2:22:03

have additional siblings to the one that we just deleted then we don't want to delete it

2:22:08

so we have our test case right here so we will delete a sibling

2:22:16

2a so 2 should remain and 3 should remain and there they are and then if we

2:22:22

delete this one two is not deleted so it should remain

2:22:27

and there it is okay let's test this one other way so let's add a sibling to testing and we'll

2:22:35

name this testing 2a so add backer 2a there

2:22:42

all right so here it is and let's delete our testing so now let's leave it with the

2:22:47

parent deleted so let's test it with the parent deleted delete our 2a and then the deleted

2:22:54

should remain because we still have a sibling here so delete 2a

2:23:00

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

2:23:06

only have testing a here

2:23:12

ah perfect cool all right so um

2:23:18

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

2:23:24

i had it let's remove these console logs um and we'll call that a day

2:23:30

so go back let's see in the form what did i do oh yeah no i just changed

2:23:36

that to from hidden to text and that should be it should now have a

2:23:43

working it's all server side but it's working a comment system um and then off

2:23:48

stream i will try to figure out how to use unpoly for this and if i figure it out

2:23:54

and i don't get too far with it i will stream this stream that next and then i

2:24:00

intend on streaming also doing um notifications so we will add notifications to this as well

2:24:07

um so it should be a good next stream so let me go ahead and hit edit on that

2:24:13

cancel reply cancel all looks good all right thank you guys so much for watching hopefully

2:24:18

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.

robot comment bubble

Be the first to Comment!

Playing Next Lesson In
seconds