Bryant builds an embeddable feedback widget for documentation sites that captures user ratings and comments with a decisive 4-point scale. Watch as he creates a complete system with slick animations and wraps it in an iframe-friendly package, then builds a dashboard to visualize feedback metrics with conditional styling.
Speaker 0: And we're back with another episode of 100 apps, one hundred hours. I'm your host Brian Gillespie here for Directus. And today, we are building a feedback widget. And you know what they say, if it quacks like a duck, it's probably a duck. So we'll see what the duck is going on today.
I've got this amazing hockey jersey that, my brother-in-law gifted me a couple years ago. Rocking that today. So what are we rocking on the build today? We're rocking a feedback widget and I don't often, like, carry over builds from episode to episode. But if you watched the last episode, you probably watched me fail to try and massage a help center template into something that pulls the data remotely, pulls the content remotely from Directus as a CMS instead of local markdown files.
Rectified that issue a little bit off scene. And today, we're gonna carry that same theme. We're gonna be build a feedback widget for the documentation site. So if this is your first go with hundred apps hundred hours, you might wanna go back and watch me fail miserably at that one. Maybe not.
You'll still get value out of this one. You'll be able to follow along. You don't have to watch that one. But the rules are, we have sixty minutes to plan, sixty minutes to build. Well, it's just sixty minutes total.
Plan and build. No more, no less. And then we're gonna use whatever we have at our disposal, which in this case happens to be the last project I was working on. Alright. So let's start the clock and discuss this feedback widget.
Right? What are we actually trying to achieve with this thing? Let's discuss the functionality for this. Right? So functionality wise, basically, I want to track feedback on articles within our help center or documentation.
And can we make this iframeable or, like, a custom element, I dare say? We'll probably start with iframe. Right. So we basically wanna manage our feedback on the articles within our help center or documentation. And to do that, obviously, we're gonna need a back end.
Right? We can statically deploy a website. We could do all of that, but we need somewhere to store this feedback. Directus is gonna make that super simple for us. So what do we have for this specific one?
Actually, let's let's talk about our data model before I dive into that. Right? Always helps to kinda map that out. So we already have an articles collection from the last episode. It has a title.
Each article has a slug, and it has some content. We have categories for those articles as well. I'm not super worried about the categories. What we are going to add to the mix here is a feedback collection or ratings or what I I don't even know. You could call this a million things.
Right? So we wanna give a an objective score, so an actual rating. We wanna have comments. Great. We need to track the article.
Right? So we need to have a connection there. Basically, the nope. That's weird. Okay.
Left is right and right is left. So we had the rating, we had the comments, we got the article. I think that's pretty much all we need or what we're looking for there. Could be wrong. We probably wanna track, like, the URL as well.
Cool. So that's kinda what our data model looks like for this. It shouldn't be anything crazy. We could build, like, a dashboard out of this thing. You know, let's dive in.
Right? So going back to the application, if we take a look, we've got this direct to since then it has categories. Great. Categories contain articles. Each article has a title, a slug, some content.
You know, we can apply tags to it. We didn't really mess around with tags much on the last episode because never got there. Really struggled to adapt that template. But, hey, this is hundred apps, hundred hours. There's only so much you could do in an hour.
And if it goes wrong, it goes wrong. Right? So what are we gonna do first? Let's start working on our back end. You know, you could see this amazing front end I've got here.
Basically, this is our look. This is a really beautiful help center. If you don't agree with me, I'm sorry. But this is this thing is amazing. So we got an article called accessing items.
There's a header for it. There's a title. Here's the markdown editor. We can actually see what that content looks like side by side. Ayo.
It's a markdown editor. This is beautiful. Right? Hit save. Refresh.
Boom. There it is. You know, I probably need to add some padding there. Let's just quickly do that. The designer OCD is kicking in.
Let's just add a little bit of padding here. Of Of course, I'm a huge Tailwind guy. Tailwind nut. Okay. There we go.
Great. Or we could even probably add a divider there. Get a little more separation. View divider or is it u? I'm using the Nuxt UI library.
Yeah. There we go. Alright. So there we go. It's beautiful.
What we wanna do is plop a big giant feedback widget down here at the bottom of this particular article. And I don't know why I took a screenshot of that, but that's what we're gonna do. First thing we wanna do though, at least on the back end, let's separate these tabs. We'll make this giant yeah, I could call this ratings. I'm inclined to just call it feedback.
And, usually, I'm breaking my own convention here where I use, like, plurals for the table or collection names, but, hey, it's feedback. So the this was created on. We could call this the timestamp or, you know, created at. Let's say updated at. K.
Status sort. We don't really need any of that. Do we really care the user that this was created by? You know, if you had users that were logged in on the Directus documentation, you know, maybe you do. Oh, I got those backwards created by created at or updated by.
Gah. Updated by. Gosh. Alright. Not enough coffee this morning, actually.
Alright. So we'll finish the setup of that one. We'll give this a rating, icon, rate. We give it a star, half star, save. Cool.
Now, let's add a rating value. Right? We've got a rating. What do we want to give as far as our ratings? You know, do we wanna go three, four, five?
I'm more inclined to do, like like, four as as far as the rating. Right? So let's set up a new input here. Maybe this is better served as something like a what do we have for this? We have a slider component.
Slider. Slider. There we go. Alright. So the minimum value will say one, the maximum value is four, default value is null.
Do we wanna always show the value? Yes. The step interval is one. We can open advanced field creation mode if we want. And then on the display side of it, we can visualize this as a number of stars.
We could show it in a simple format, or we could just show the actual stars. So we'll do that. Why go with four? To me, I I hate giving people a middle ground. Right?
So if we have bad or let's say, the worst, bad, and then good and great, there's no middle ground. Right? So you gotta get off the fence. We want to add some comments to this. So we'll use just like a text area.
It's a great way to see that content, you know, maybe trim the start and end of that, and save. Right? Now what we need is let's just do the URL. We'll track that. I can add a little link input to the icon to the box, actually.
And then we'll do what else are we gonna do here? We wanna do a relationship back to the article. Alright. So if we look at this feedback, we got like a rating system. Okay.
We can have some comments here. There's a URL. But we probably wanna be able to, you know, see the feedback per article, instead of just by the URL. So what we're gonna do, we'll go to our feedback, and I could do this one of two ways. I can create the relationship inside the feedback, and that's a many to one relationship, or I can go into articles and create a one to many relationship there.
You know, if you are creating the many to one and you do want that, inverse relationship, just make sure you check the boxes appropriately. I'm gonna go to articles. We're just gonna use the one to many relationship here. Let's call this feedback the feedback collection. The foreign key is gonna be article.
So all the feedback, every single rating is gonna belong to an article, a single article. Like, we can't give the same feedback on multiple articles, basically. And we're gonna do the rating, and maybe we show, like, the comments as well for this. We show a link, and maybe this would be better as actually, like, a table as well. So we see the comments when this was created at and any comments.
Okay. We will sort by the ratings. We could sort ascending. So, yes, let's show the worst ones first. Amazing.
Alright. So now we've got feedback. If I go to the feedback collection, you could see we've got the article that it's related to there. And anytime you create that one to many relationship inside Directus, it's going to hide the corresponding mini to one relationship. So we're we're just going to, add that back.
Great. And we probably wanna track, like, the URL here, like a fully qualified URL. This would be great for something like, hey, I've got development and I have production, where obviously you're gonna have different URLs for that. So you could filter that out even though it may be on like the same article locally. Or you could get around that a couple different ways by, you know, not even storing development feedback or, you know, some other type of system.
But now if we go here, I should be able to go in and create feedback on this. You know, hey. This article is not beautiful, sir. And that is gonna be what? API HTTP local host 3,000 API slash accessing, is it two?
Two c's? Accessing items. Right? Great. I've added some feedback.
There it is. Boom. I can see that feedback now. I can see the URL. I can see the article.
We got all of that. Great. But we don't want people to log in to Directus to actually interact with this feedback or leave us feedback. There's our ratings, the stars. Looks that looks really nice.
Right? So what are we gonna do? We're gonna build that on the front end. Right? Cool.
So if we are to interact with our API now, right, I could go in and basically, I could see the articles. I could see feedback and, you you know, I could do something like this in my params where I call fields and I do feedback.asterisk. So this first asterisk will give me all the root level fields. The second one will give me all the second level or the the root level fields for the feedback collection. If I actually save it there actually make that call, feedback.star.
Great. So here I could see the actual ratings. Right? But if I were to actually try to post a rating or anything like that, at least publicly. Right?
If I copy this same URL great. Open an incognito window. I am not even actually getting the info. Alright. I can't see the ratings.
You know, previously, I had set up public permissions for the articles. I can't see the ratings for the feedback. And the reason for that is bada bing bada boom. Quack, quack, quack. Because we have, restrictive permissions, basically.
Whenever you create new collections inside Directus, we don't add permissions for those by default. So we keep that data secure. So what we're gonna do, we'll go into our access policy here and, you know, this might not necessarily be what I would go to production with, but I'm gonna let people create feedback here and, you know, maybe I let them read the ID of the feedback. So as far as field permissions, I don't want them to be able to read our feedback. Maybe just get the ID after they've submitted that.
Right? So we'll let them create feedback and then they can read the feedback of the ID they've created. Now a couple other ways we could do this, you know, if this was like a a static site, you could use like Vercel or Netlify functions that that you could potentially, you know, proxy to the direct us back end. You know, just a a a ton of different ways you could do this and you could have like a a separate role that controls the communication to the direct assistance. But for now, this will work.
This will be fine. We're just gonna let anybody create that feedback. Right? So now let's start in on our feedback component. I'm just gonna create a new component.
We'll call it feedback. Should we call it widget? Love widgets. Who doesn't love widgets? Alright.
So I'm a script script tag first guy. Not sure if you are or not, but alright. So what do we actually need to define our you know, let's let's start with, like, props. Right? What what do we want for our props?
The props are going to be define props. We do want an article ID. That's a that's a great prop to have. We do want to have the URL or should we we should be able to get that, actually. So I think all we actually need here as far as props is an article ID, and then we can get the current URL.
This should be like use request URL from Nuxt. Use request URL. Let's just check their documentation. Use request URL. There's a helper function that returns the URL object working on both client side and user get request URL.
Okay. So there we've got the request URL. Cool. And then, yeah, maybe we'll wanna define our ratings. Right?
Const ratings, ratings map, or something like that. So we'll give a label. I I like using emojis for this. Let's do mad. Maybe we just use a trash can, like value trash.
No. I'm using cursor here as the IDE. I I I like the auto completion for this, basically. Sometimes it's very finicky. Sometimes it's not.
Yeah. It seems like we've come up with a good scale here. Cool. There's our ratings map. What else do we need here?
We probably wanna track some comments. Comments equals ref string. No. That's just gonna be a string. We'll just, leave that as an empty string for now.
And then let's go in and just like build a comments component. Right? And since that we're using cursor, let's just see what the sync can actually do. I'm just gonna hit command l and let's say build a feedback widget with the ratings map. Make it look beautiful.
This is not how I've been prompting this thing, but build the, let's say, the template portion of the feedback widget with the ratings map. Make it look beautiful. Alright. So we can see here it's going through creating some code for us. I think it's using Claude three point five Sonnet here.
There's our submit button. And I've got the Tailwind UI library here. So, you know, we could probably let's let's just see what it comes up with first. Feedback widget, app widget. Oh, no.
That is not the right one. We want to what is going on here? Okay. Maybe we just copy paste this code here. It seems like I need to update the index for this or something like that.
So we'll just copy paste. Great. There's our feedback widget. It's doing something. Obviously, styled with Tailwind.
It's probably not gonna match what we've got, but we'll go to our slug. So here's our actual page. We've got some messy, messy stuff going on here. We are actually using the, Nuxt MDC library to just render this markdown content. And then we're gonna add a new separator.
We'll add this feedback widget, article ID, this page dot ID. Did we even get the page dot ID? Yeah. We should have that page ID. Alright.
So is this beautiful? Yes. Looks beautiful ish. Alright. We could do better.
We could do better than this. Alright. Let's zoom out to, like, hundred percent. Yeah. I just kinda cut off here, the shadows, etcetera.
We don't really want BG whites. And I think the Nuxt UI library has this uCard we could even drop this thing into. There we go. Let's remove all of this. K.
How helpful was this article? Great. So now this is full width. Then we have new buttons. We can remove all of this.
The title here, let's change that to label or no. We'll leave that. U buttons. What happens if we click this? Right?
What? View button. Key equals rating value. We probably need a rating as well. Right?
Rating. Ref number. We'll just leave that set to null to begin with. Number or null. K.
And when we click that yeah. There you go. Cursor. We wanna set the rating equal to the rating dot value. Solid.
There's the rating. Let's see what we get. Refresh. Something broken? Why are we not seeing anything good here?
U buttons. Oh, yeah. U button. Dum dum. There we go.
Alright. So now I could see there's our buttons. Those are not the great looking buttons that I want. So let's do, like, a ghost. Okay.
There we go. And if I just wanted to show this, right, we could do rating. There's our rating. Is that actually gonna show the rating? Rating, rating, rating, rating.
P p tag. Rating is null. Rating is we're using maybe conflicting rating value. There we go. Alright.
So now we can see one, two, three, or four. Great. That's helpful. And then we have our extra comments. You know, let's make this giant text five XL.
Great. We'll give these some padding too. Glass. P two. P four.
Is this gonna give us some padding? Yeah. There we go. Cool. Alright.
Looking great. This is trash. This is great. And let's do some additional cleanup here. So then we have a u form field, I think, is the name of this component, that wraps this, that provides us like a label.
Additional comments. Okay. Looking great. And then we can do a u text area. V model, there's our comments, feedback comments.
We don't need any of this. And then do we actually need we want this to be is block a prop here? It is not. So let's do width equals width full full width. Okay.
Cool. Looking great. And then let's ditch this blue button. That'll be you button. Yeah.
We can leave the type as submit. We'll just clear this out. Let's make that a block level button. Block and size equals x l. Make it a big button.
Alright. And then in this case, I don't know why the overflow is being hidden here. Probably something to do with, like, one of my layouts. Overflow hidden. Yeah.
There it is. Let's just solve for that. Right? Okay. So now we're good here.
Let's add, like, a ring or something if this is selected. And let's do a little bit of cleanup. Right? So if there's no rating, the if if there's a rating value, we're gonna show the additional comments. So by default, this won't show and then it should expand.
Now one of the other libraries that I love to use in my Nuxt projects is called form kit auto animate, auto animate dot form kit. It basically gives us, like, a nice animations and basically like a single line of code. Right? So you add this to your project. They've got a Nuxt module for this.
And now if we go up to our card component, so that's where this is at, and I add this directive, v auto animate watch this. Watch this. What's v if if I got this inside a why is this not working as intended? Maybe because of the structure of the card component. And let's just wrap the inside of this in a div and see if that fixes it.
Div. V auto animate. I don't wanna make a liar out of myself. Oh, there. Yeah.
There we go. Now we got, like, some slick animations. Okay. V f rating dot value. You chose maybe we show, like, the yeah.
You chose four out of four. You know, we could potentially even wrap these. And flex, justify between items baseline. Let's see what that looks like. It shows four out of four.
Great. And then let's add, like, a conditional class. BG gray. No. I I wanna add a ring to this.
Ring two, ring primary, 500. Right. There we go. We've got some additional comets. This is looking nice.
Yeah. Solid. Cool. Looks good. We can submit feedback.
If we actually we're not showing the additional comments, and then we submit the feedback. Right? Right now, this does absolutely nothing. So what we're gonna do, let's add a click. We're gonna submit the feedback, and then we'll go up and actually add a submit feedback function.
Right? So we'll call this an async function because we're gonna be calling the directus API with this. We'll call it submit feedback. And, yeah, we don't really need to pass it any props. We can just pick those up from this widget.
We got the current URL. Cool. Alright. So here's where we're gonna come back and use our direct us SDK. We're gonna do import create item from the Directus SDK.
Great. And we're also going to pull in this Directus plugin from Nuxt app. So, you missed that part on the last episode where we set this up. Basically, I've got this simple Nuxt plug in. It pulls the Directus URL from the Nuxt runtime config, creates a rest client.
There's a bunch of commented stuff here to deal with authentication that we're not handling, and then we provide that back to the directus application. So whenever the, like, the first visit occurs, like, this client gets created, and then we can use that same client throughout the entire Nuxt app here, simple integration with the SDK. Alright. So what we're gonna do, we'll wait for the response. You know, maybe we wanna show like a loading state as well.
So we'll do loading ref equals false. We'll set loading dot value is equal to true. And then we can see that, like, direct us is our cursor here is trying to auto complete this, which I don't like. I don't like that auto complete. We will do this.
So we're gonna call direct us dot request, and then we're gonna pass the method into here. So we're gonna create an item. We're gonna create an item in the feedback collection, and then we're gonna pass the body of that item. So we're gonna pass the URL, which is gonna be current URL. I don't know if that's gonna be value or, you know, let's make sure that's a string.
Then we're gonna pass the rating, which is gonna be rating value dot value. And then we have comments dot value. And we could, you know, potentially wrap this and try catch, just so we could do error handling if we want to. Create item feedback. Yeah.
Okay. Great. And then finally, set the loading value to false. Now I can also pass that loading prop here, And we could even use, like, the view shorthand syntax as well. Okay.
So, let's say disabled unless there's a rating value. If there's no rating value, then this is disabled. Right? So if we haven't picked anything, we can't click the button. Cool.
Alright. So now if we click the button, we could do that. We can add some comments. If I watch the network request tab here, we submit that. We see some data coming back.
We got the ID. There's the payload. Then we can go in and actually check and see whether we got our feedback or not. Cool. Alright.
So what did we miss? We got the URL. We got the rating. The rating sucks. We didn't add any comments.
Okay? We forgot to pass the article. Right? So the article equals the props. Article ID, and that should be required.
Cool. Let's try this one more time. Right? So this is an amazing article. This is amazing, Bryant.
Alright. So there we go. We can see how quick that is. Obviously, that's local. There's our feedback we submitted.
Let's go back to our feedback collection. This is amazing. Bryant, here's our comments. Here's our rating. This looks great.
Alright? There is our feedback widget. We could do a lot to improve this, obviously. But what if we wanted to, like, maybe embed this? Right?
Could we iframe this? You know, Vue is a, like, a good framework for web components. I've not really dove into a lot of, like, the custom elements and, like, web component stuff with Vue. I don't really wanna tackle it on this. That could probably be its own episode.
But what if we put this feedback widget on its own routes and we just try to embed it into other pages? So let's do this. We will create a new route. Let's call it feedback.view. Cool.
We'll initiate, like, the base setup here. And you think I would set up, like, my snippets correctly at this point, but I have not. And then what are we gonna do? We're gonna use the routes, and we're gonna get the article ID. Actually, is it like a use query or we could just call query from this, but I don't think Nuxt provides like a use query.
Let's call the article ID equals route.query. Article ID. K. And then we're gonna just drop this feedback widget in here. It's almost like talking out loud.
This thing knows what I wanna do. And then we should probably pass the blank layout for this because otherwise, if I go here and I go to feedback, we're gonna get the rest of this, like my header and everything else. Right? So then I could go in here and const, no. It's actually define page meta meta layout equals blank.
Does that give us what we want? Cool. Awesome. Alright. Now let's make sure v f article ID to v else, no article ID provided.
So there's no article ID. And then if we do something like this, article ID equals test. Okay. So now we got that. Maybe we want to pass the current URL.
Can an iframe get the current URL? Great question for, great question for AI, I think. Can the can an iframe get the URL of the host? Using JavaScript only works with the same origin policy blah blah blah. Yeah.
So maybe we wanna pass, like, the URL. Cool. Alright. And then that means we may need to adjust our feedback widget just a little bit. So feedback widget.
We can add a URL prop. This could be an optional prop. That'll be a string. And equals URL or props dot URL if that exists or we're gonna use the request URL. Cool.
Cool. Great. Yeah. So now if I try this, this should throw an error coming back from Directus because I'm not using a proper ID. Right?
Unexpected error occurred, and that's because the article ID that I passed here is not correct. Right, because there is no existing article ID there. So we could, you know, do something like making that optional or making that null if there is no article ID, I guess. But, you know, that's not really what we're after here. We just wanna stick this in an iframe.
Alright. Cool. So now let's just open up a new can we do, like, HTML? Yeah. There we go.
Div id app h one. Here's a you know what? Why am I not just relying on AI? Create a sample web page about hundred apps, hundred hours. Not a a Vue app, just a standard HTML five page.
And it is using Tailwind as well, of course. Yes. We'll just copy this guy. There we go. Alright.
This is a weather dashboard. We're just gonna drop this on my desktop, index. HTML, along for the days of index HTML sometimes. Alright. And then how do we get this to open up?
Here's our weather dashboard. Yeah. Who knows? This this is amazing. Now, right, what if we try to add this iframe?
Iframe local host feedback article URL ID blah blah blah. Is this actually gonna work? Okay. That's great. We've got, like, this.
I wish probably do we wanna set a height for this? Do we need to set a height? Height equals, I don't know, 300 px. Okay. So the styling is not necessarily what we need out of this.
MTE four. Refresh. Okay. Cool. In the feedback widget, let's say BG transparent.
Where is that coming from? Where is the white coming from? Where are you coming from, friend? Is that just coming from, like, app dot view or something? No.
The default layout blank. Style dot, let's just do HTML and body, background color equals transparent. There we go. Okay. That gets what we want for the blank.
Now this is looking good. And we can actually embed this. Right? Now, let's set the height to maybe 600 pixels. Give this enough room to expand.
Okay. So now we've got this iframed in here. Will this actually work when we submit feedback? Feedback local host errors are expected. Right?
Because we don't have the proper ID, it's not sending that to direct us correctly. So, you know, maybe we update this widget. Blah blah blah. Undefined props. Article ID or undefined.
Feedback. What are we trying to send? Article is one. Okay. So we are sending an article there.
So if we go into our index.HTML, maybe we just remove this. K. We pass our URL. Page not found. Feedback.
Oh, there you go. No article ID provided. Feedback. Let's just remove that piece. We don't really need that.
Okay. Cool. There it is. There's our widget. We can submit feedback on this.
Cool. There it is. Is this coming through okay? Local host. Yeah.
So there we go. We've got our URL there. Cool. What's what's next? Right?
We need, like, a success state for this thing, and then we could probably call this one gravy. Right? Let's add just like a success state. Success ref equals false. And then success equals true.
And then we go down here and, all of our submit stuff. Right? We're just gonna wrap this in a template. V if no success, v else. Thanks for your feedback.
And you can see why I like cursor. Like, once you get enough of your logic in there, it it does start to, you know, be very helpful as far as auto completion. This is a pretty cool episode. Right? Quack.
Quack. Quack. There we go. We'll hit submit. There you go.
Thanks for your feedback. We're good. You know, we could get even more sophisticated with this as I roll away. We could, you know, potentially, like, add a cookie or something to track whether they submitted this. And if they've already submitted feedback on the article, not let them submit again.
I don't think that's really necessary. Right? Let's use the remaining time that we have to just, like, quickly build, like, a dashboard to see this feedback. So we'll go in, let's call this our feedback dashboard or help center dashboard. Cool.
We'll add insights for this. So we'll just create a new panel for it. Let's show just a list of, like, the total feedback. Right? The field is gonna be ID.
We'll count these. What is the filter gonna be? Do we actually need a filter? No. We don't.
We'll just say total feedback submissions. Great. And boom. Now we get a metric panel that shows us the total number of feedback submissions. Let's add a new one, where we track, like, the average rating.
Right? So I could do this in a metric. Let's see if we can get this meter component, what this will actually show, what it'll look like. So we got the primary field here is gonna be rating or the the field that we're summarizing. We want to average that.
And the max is gonna be four. And there's our color, Filter, Stroke, Medium, Conditional Styles. Yeah. If the is less than or equal to two is red. Let's do, like, yellow for less than or equal to three.
And then, otherwise, maybe this is green? I'm not sure what this is gonna show. Average rating, 60%. Okay. So this is showing, like, a percentage of this.
Right? And that's conditional. So if I go in and I were to I'm not saying you should do this ever, and you'd probably wanna lock down the permissions for this to make it noneditable after the fact. Alright. I go into our help center.
Now we see 85. So I'm guessing the value here Where's that coming in at? Oh, this should be green. Right. Cool.
So, you know, 85%. Probably, the meter is not the best function for that. We should just use the average here. Sort field. We don't really need a sort field for that.
Maximum decimals. Let's go to, like, one decimal. And average rating. Let's see what that comes up of. There we go.
So average rating is 3.4. I can open this up over here. Or can I? Let's do this. There we go.
And then I can blast some feedback. Test. Oh, yeah. You need to actually do an article, though, don't you, Brian? API slash accessing items.
Alright. So now we could blast some feedback on this. This sucks. Boom. Just refresh.
I don't suggest spamming your own help center. But then we could see that score change, obviously, because there are eight total submissions for this thing. Let's keep building out. Right? Maybe we wanna see a list of the individual articles and their feedback.
Can we do that? Like a list of, here's the feedback. And we give a list. We want to show the URL. We wanna show the rating.
And we want to, like, comments are gonna get a bit tricky there, but we can sort by when they were created at. Makes sense to me. We'll sort by descending, so we'll see the new ones first. List of feedback. There it is.
Cool. Again, that designer OCD is kicking in, so let's make this same width. And one of the the finer points about the dashboards here is when you slide them together, the border radius, snaps. So here we can see all the feedback. Great.
I can open this up and see the actual ratings. Let's go in and just solve that. That's going to aggravate me. Like, what I can do here is, I can disable editing for this. So this will control editing from the Directus Studio here.
Now if I wanted to control, like, whether you can update this or not via the API, that would be in the permission settings. You'd probably wanna set that up to where, like, certain team members cannot edit this value. But, now you can see, like, all this is locked down when I open it up inside the studio. And, you know, if I open it here through the dashboard, it's not gonna show either. So it's a great way to do that.
One of the last things that I just wanna showcase here is the ability to add, like, a global variables and global relational variables. So let's just create a global variable called time or date from, and let's make this a time stamp. We'll use, like, a default value of, I don't know, November 1. Daytime, 24 value. DateFrom.
Okay. So we define a key here. Right? This is cool. Define the key.
And obviously I created all these today so I'm not sure how impressive this is going to be. But what I could do here is when I set up like this list of feedback, I could go in and define my filters. So I wanna do createdAt is greater than or is in between, let's say, date from, and let's do dollar sign now. Cool. Dollar sign now.
Okay. If we do November 27, December third as the date from, you know, if I go here, you could see that that is filtered out. And, likewise, I can apply the same filter. Copy raw value. Paste raw value.
Paste raw value. Paste raw value. Paste raw value. And you can see this is just the, these are the standard filter rules inside Directus. You could find all those in the documentation.
And we go back through November. Right. I see a list of all the items, and, obviously, that updates all the different metrics. Right? The other cool thing that I can do is add a relational.
I was trying to combine relational and variable there. So let's call this the the actual article. Right? So I pick an article and let's call this the, let's use the title of the article in our display template for this. Pick an Article.
K. Cool. And this will give us a drop down where we can pick an article. Cool. Great.
There's accessing items. Doesn't do anything though. Right? So we're gonna do the same thing where we add a filter for this. So the article, the should be like article ID equals article.
So because we've defined that that variable here, this is accessible anywhere on this dashboard. Alright. And as soon as I start to add that you can see Article that it adjusts the values that we're seeing. Article ID equals Article. Awesome.
So now I'm only seeing the data that is in this date range and through this specific article. So if I pick WIP, there's nothing there for that one because that one is not published. And now I could see, boom, we have the feedback for our specific article. That's it. This is our amazing feedback widget episode on 100 apps, one hundred hours.
What's more to say? I think this is a a great tutorial, something that, you guys can take away and, could be helpful in a lot of different contexts. So let's call that a win. Eight minutes and thirty seconds left on the clock. Roll the beautiful bean footage as they say.
We'll catch you on the next episode of 100 apps, one hundred hours. We'll see you.