تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Planning ClickUp Import0:00

(upbeat music) Okay, we're almost done. We're actually at a point where maybe you would say you are done, but I wanna do one more really big feature that's gonna highlight a lot of the different things you can do in Filament, and we're gonna go pretty deep. Okay, so the feature I want to build is, if you see this new feature button, I don't think we should have a new feature button. I think if you want to add a task for the roadmap,

I don't think we should have a new feature button. I think if you want to add a task for the roadmap, it should actually come from my project management tool. That's where everything goes first. And then once I decide I want to maybe tell my customers, I'm thinking about this, I wanna pull it in from there. So what we're gonna do is we're gonna create a custom modal that is gonna hold the table, that's gonna get data from an API, and we're gonna be able to use that data

that's gonna get data from an API, and we're gonna be able to use that data to fill the form to create a feature. So there's a lot of steps there, it's pretty complicated. Let me go to my web.php and show you. So the first thing we need to do is figure out how to use custom content in an action where we mount a modal. The second thing is we need to create a table and put that into that modal, and we're gonna use custom data,

and put that into that modal, and we're gonna use custom data, not an eloquent model, but custom data. Number three, we're gonna fill that table with data from an API, that's the custom data we're gonna use. Then we're gonna create an action to pre-fill the form with the data from the API, and lastly, we create the feature model. So we're gonna get started, but there's one thing we have to do first,

So we're gonna get started, but there's one thing we have to do first, and for 15 videos, we've had this issue where this is not a badge, and I can't believe I've missed it this long. Let's fix it really quickly. So simple, a features table. Here's the status, it's a badge, here's the type, it needs to be a badge, and there we go. Okay, if that's been bothering you for 15 videos,

Creating Import Modal1:47

it needs to be a badge, and there we go. Okay, if that's been bothering you for 15 videos, I truly apologize, but that's fixed. Okay, we gotta get rid of this button and replace it with something else. So that is on the list features class. Here we have the create action, I don't want the create action, I'm gonna create my own action. So I'll do that, we'll call it import from click up.

I'm gonna create my own action. So I'll do that, we'll call it import from click up. Click up, let me show you. Click up is my project management tool, and I use this at my company, and I've created this fake personal space that has a bunch of just random things that an app might have, some of them are bugs, they have different priorities, and so I'm gonna use the API from click up

they have different priorities, and so I'm gonna use the API from click up to get the data out of this system so that we can put it into our table. Okay, so we are importing from click up, we'll give it a label, we don't need to worry about the color, and we're actually not gonna have any action with this action. So the action class, think of that more like a button, this is a way to mount an action.

So the action class, think of that more like a button, this is a way to mount an action. This is what would happen when you submit the action, but we're not submitting an action, we are just wanting to mount a modal. So what we want to do is define the modal content, and we need to define that here. We also want to make sure that the modal submit action does not show up, because like I said, we're not submitting anything here,

that the modal submit action does not show up, because like I said, we're not submitting anything here, and I think that's all we really need, but we have to figure out what are we gonna put in this modal? So the first thing we're gonna want to do is, I've got my resources views here, what do we have? Okay, so I'm just gonna create a new file here, and I'm just gonna call this import table view.blade.php. Okay, so this is just a blade file,

and I'm just gonna call this import table view.blade.php. Okay, so this is just a blade file, which is a div, we can just say hello, and then if we go back to this modal content, we just want to pass in the view of import table view. Okay, so this should work now, I'm going to go to the browser, refresh, I've got import from click up, here's my modal, here's the hello I just had, so just stop right here, if you ever just need a modal to display some content,

Building Custom Data Table4:05

here's the hello I just had, so just stop right here, if you ever just need a modal to display some content, this is how you do it. We don't want to just display content, we want to display a table, so we'll get to that next. If we go back to web.php, we have some custom content in the modal, so that's good. Now we need to create a table. All right, in order to do this, let's go ahead and look at the filament docs.

All right, in order to do this, let's go ahead and look at the filament docs. So the first thing we need to do is render a table in a blade view. This is very similar to what we just did where we rendered a form in a blade view outside the panels. Even though we're currently in the panels, it's still the same concept, so we're just going to create a live wire component, just like any other live wire component,

so we're just going to create a live wire component, just like any other live wire component, and then we're going to follow these instructions to put the table in a blade view. So I'm going to make a live wire component first, artisan make live wire, let's call this click up tasks table, and I want this to be a class. So let's find that in our project, we have the click up tasks table, and this is just a normal old live wire component.

we have the click up tasks table, and this is just a normal old live wire component. We're not using the bolts syntax here, and we do have a view, and I can finish this view really quickly, because I already know this is going to be this table. That's it, if we go back to the docs, you're going to see at the bottom, this is what your live Argus component needs to be. So now we just need to follow these instructions here.

this is what your live Argus component needs to be. So now we just need to follow these instructions here. We need to use these three traits. So let's go back to our class. We will have those three and we need to import all of them. And now we also have to implement these contracts. So implements has actions, has schemas, and has table, yep, all three of those. And then we just need columns and some data. So for that, what I want to do is go to another page

And then we just need columns and some data. So for that, what I want to do is go to another page in the Filament Docs, this is in the tables, and we have custom data. So here we have a table, and I'm going to copy the records and the columns. So actually I need the entire table methods. So let's just go ahead and grab all of this. We'll put this right here. We need to import the columns.

We'll put this right here. We need to import the columns. I don't think we're gonna use an icon column, so I don't even need to import that. Let's just see how this works. I also need to import the table. And we're gonna go over to our browser and check. We have import from ClickUp, and it's still our hello, because let's go back to the list features.

and it's still our hello, because let's go back to the list features. We have this import table view, and instead of saying hello, we need to actually do our live wire component. So live wire, ClickUp Tasks table. Now if we refresh import from here, we have the table. Okay, so this is the table that we need. There's a couple things that are already not working with this table is you can see this is sortable,

There's a couple things that are already not working with this table is you can see this is sortable, because way back in the beginning, we said we want every column to be sortable by default. Well, Filament doesn't know how to sort just an array of data when it's not an eloquent model. And so we either have to decide to turn this off, which is where we'll start. And then we can also implement our own sorting if we want it to be sortable.

And then we can also implement our own sorting if we want it to be sortable. So let's go back to our ClickUp Tasks table. And in order to fix these, we're not even gonna use these, but just we would go to sortable and pass false. And same thing with the slug, we would say that's false. And the other thing is it shouldn't be searchable either. You have to manually do your search right now. Filament doesn't know what to do with this search.

You have to manually do your search right now. Filament doesn't know what to do with this search. So we would turn that off as well. So searchable, false, and the same thing here. So now if we have this, at least when we look at the table, it's not giving us any kind of indication that we can do anything with it, aside from just look at the data. We probably also don't want this columns here.

aside from just look at the data. We probably also don't want this columns here. So on the table itself, we can just say, column manager is false. And so if I refresh and go here, now we don't have that column manager. So this is a much cleaner table. This is what we want. Eventually what we're gonna do is fill this with the data from the API.

Fetching and Mapping API Data8:45

Eventually what we're gonna do is fill this with the data from the API. And then on this right side, we're gonna have a action based on the row that we've selected to import that. Let's go back to our to-do list in our web.php. We have a table with custom data, great. Now we need to pull that data from the external API. All right, while we're here in web, let's just do a route, get, we'll do click up,

All right, while we're here in web, let's just do a route, get, we'll do click up, and add a closure here. I want to show you how this is going to work. So I'm going to paste in the code that it would take to get a response from the click up API. Again, our click up project management tool is just all of this stuff. So we're gonna get that through the API. And I'm just gonna return to the browser, the JSON here.

So we're gonna get that through the API. And I'm just gonna return to the browser, the JSON here. And I wanna show you what this looks like. So we're gonna go to click up right here. And there we go, we can pretty print this. And it's just giving us our tasks that we're in the list that I've selected. We have a pizza, ipsum, and names, and statuses, and priorities, and all kinds of stuff here. So we're gonna be able to use this data to fill our table.

and statuses, and priorities, and all kinds of stuff here. So we're gonna be able to use this data to fill our table. Now, we do need to kind of transform this. This is a lot of data, and we need to transform it into just the columns that we want to use in our table. And so I'm gonna copy all of this. And I'm gonna go back to my terminal, and I'm gonna use Cloud to help with this. This is a perfect example of a time

and I'm gonna use Cloud to help with this. This is a perfect example of a time where it's nice to use AI. So the first thing I'm gonna do is paste in all the data that I got from here. I have this JSON, paste it. And now I've got a prompt I want to put, create me a wrapper or transform a class. We don't need a DTO right here. If you're familiar with a data transfer object,

We don't need a DTO right here. If you're familiar with a data transfer object, that is when you actually want to pass around this object that represents the data. I don't need an object to represent my data. I just want to transform the JSON object into an array, and I want a collection of it. So I'm kind of giving it some information. I want you to convert it to my feature model. Here's how I use my priority scale.

I want you to convert it to my feature model. Here's how I use my priority scale. And I want the API to use is this click up task mapper to feature attributes array. And that is what I want to feed into my table. So I'm gonna let Cloud help me with this one. Okay, Cloud wants to make a mappers directory that is fine with me. And now it has created my class.

that is fine with me. And now it has created my class. I'm just going to let it decide what it wants to do. We'll look at it in a minute. It's running pint just to make sure it's formatted properly, okay? And here are the mappings it says that it has. It looks like this table is missing like name and description, but it says it's there. Let's just look at the code it generated and see.

and description, but it says it's there. Let's just look at the code it generated and see. We have the click up task mapper. And so if I have my two feature attributes array, it does look like it's giving me my name and description. And all these kinds of things that I care about. Let's see what else it generated. It's mapping the status from the systems and the type and the priority. So all of that is good.

and the type and the priority. So all of that is good. And now what I'm trying to find is where I pass in the response. Okay, so this is a static function. Many two feature attributes array. And this is where I pass in the response. Let's see if I go to web.php. Instead of returning this, I'm going to return click up task mapper here.

Instead of returning this, I'm going to return click up task mapper here. And then I'm gonna pass in the JSON that came from the API. All right, let's go back to the browser refresh and pretty print this. And this looks a lot better. So we've got name, description. This data is now in a format that I can actually use for my table.

This data is now in a format that I can actually use for my table. I don't really love many two feature attributes array. This is to me a pretty awful name. Let's rename this. Say get array of feature attributes. Oh, I think that's better. Okay, so if I go back to my click up tasks table. So this is the data here. So we have a method.

So this is the data here. So we have a method. And all we need to do is delete all of this stuff. We're gonna return an array and we just need this click up task mapper, get array of feature attributes. And we just need to get the data from the API here. So let's go back to our web.php. And this is the response here. And so we'll say response JSON.

And this is the response here. And so we'll say response JSON. Okay, let's see if this works first. We need to import the HTTP facade. Oh, and the last thing before we actually test this out is we want to change the columns. So we had name and I don't know that we want the description. It's gonna be really long in here. Let's say the priority.

It's gonna be really long in here. Let's say the priority. Now let's just see if this works before we go any farther. We're gonna go back to admin features import from click up. And yeah, we've got our data in the table now. Okay, so we need a little bit more data just to decide if we want to import it. Let's do another text column for, let's go back to our mapper and look at what we get here.

let's go back to our mapper and look at what we get here. We might want the type and the priority. Probably just those two. So let's do type or we already have priority. We can get the status as well. And these are probably badges. All right, let's cancel this. Let's import from click up again. Okay, so we've got our data now in the table

Import Action Prefills Form15:20

Let's import from click up again. Okay, so we've got our data now in the table from the external data source. Let's go back here. So we did get that. So now we want to create an action to mount a form pre-filled with the data from the API. So we don't have all the data we need from click up. There's a few things. Remember, we were estimating how long it would take

There's a few things. Remember, we were estimating how long it would take and that data is not coming through the API. So we have to not just create the record immediately, but fill the form, let you complete the rest of the form and then we'll create that new feature model. So let's go back to the table and we need to add something else here. So we're just going to say record actions. A record action is just what it sounds like.

So we're just going to say record actions. A record action is just what it sounds like. It's an action that happens on one specific record within the table. So we're going to create an action here. We'll call it import record from click up. And what we need to do here is not an action or we will need to do an action, but the first thing we need to do is actually we need to create a form

but the first thing we need to do is actually we need to create a form which you use the schema method to do that. And we have that. We have the feature form, configure. And if we just put three dots here, that's going to pass in the schema from this closure into this closure. And then we want to fill the form. So we'll do fill form.

And then we want to fill the form. So we'll do fill form. So we're going to have the record here, which is an array. And we're just going to return that array. So whatever you return from this fill form method is going to fill whatever is in this schema. And then here, we do want to create a new feature model with the data. So this actually might work as well. Now this action, we would want the data, not the record.

So this actually might work as well. Now this action, we would want the data, not the record. It's the data coming from the form. So we'll do that. And let's go refresh this page. All right, we've got one of them. Let's just grab the, I don't know, activity audit logs. Sure. Okay, so we clicked import. Well, this data is it mounted another action.

Okay, so we clicked import. Well, this data is it mounted another action. It pre-filled it with all the data that came from the ClickUp API. It's set my priority, chose feature. We have my pizza ipsum. We have not filled this out. So if I try to submit this, it's not going to work. So let's just say it's going to take 30 days. We don't need to add any milestones

So let's just say it's going to take 30 days. We don't need to add any milestones and I'm going to submit. Okay, and we're getting an error here. And this one, so there's a, we have our rich editor and the rich editor has a method that is looking for a record to be a model, but our records and our table are arrays. So we need to fix that. Let's go back to our code.

So we need to fix that. Let's go back to our code. Okay, let's make this a long closure. So this is going to, allow us to kind of work with this a little bit more. So we need to import the filament schema class. We need to make it look a little nicer and we want to return. And so, instead of these three dots, we have the schema here.

And so, instead of these three dots, we have the schema here. So this is exactly what we just had. This is kind of the long form of those three dots. I always forget what that's called. But for this schema, we need to pass in what model we're actually trying to create here. So if we do a model and we do the feature model here, I believe this is going to fix the error. So now, as the record is being passed in

I believe this is going to fix the error. So now, as the record is being passed in through the different closures within filament, it's going to know that we're talking about the feature model as opposed to just the array that we have from the API data source. That might not make a lot of sense to you and it's getting really deep into like filament internals. But again, basically the form just needs to know what am I creating here?

But again, basically the form just needs to know what am I creating here? And this tells the form what it's about to create. If we go back here and try one more time, we're going to import from click up, I don't know, dark mode support. Let's try that one. Now we have all of our data filled. It's going to take 15 days and we click submit. And there we go.

It's going to take 15 days and we click submit. And there we go. So it worked. If we search here for dark mode support, there it is. So we were actually able to get the data out of click up into our system. And I mean, that's pretty cool. Okay, so we were able to integrate with an external API, give ourselves a nice UI to find the data we want from there, pull it in, find the one we want, import it,

give ourselves a nice UI to find the data we want from there, pull it in, find the one we want, import it, and then fill our database with this external data. Like that's pretty cool and very powerful and didn't take a whole lot of work. So pretty excited where we ended up here. I think the only other thing I'd like to do is maybe clean this up as we finish up here. These are not sortable yet. This is not searchable.

Caching, Sorting, Searching20:41

These are not sortable yet. This is not searchable. You probably will want to do that if you're using these tables with custom data. So let's just implement those features and we'll call it a day. Okay, so let's figure out sorting and searching. The first thing is it's probably gonna be easier to sort and search if we get a collection instead of an array. Records can take either a collection or an array,

to sort and search if we get a collection instead of an array. Records can take either a collection or an array, so it's gonna be easier for us to do that. I don't know, maybe we add a new method here for static function, get collection of feature attributes. So that will probably work. Let's go ahead and change this to get collection of feature attributes. It's not returning an array anymore. Let's just not type in and refresh import from click up.

It's not returning an array anymore. Let's just not type in and refresh import from click up. All right, so that's all still working. Okay, so now we have a collection. We need to start searching and sorting on it. One thing is every single time we make any update, we're going back and hitting this API to get the data and we should really cache it. So let's do that now. Let's create a tasks variable

So let's do that now. Let's create a tasks variable and we'll use the layer of all cache facade. We'll remember this, the key will be tasks from click up. We're gonna have it stay for five minutes and then we have a callback and we just need to return this. Okay, so now that we're caching it, I think we're just gonna call JSON here. And then so this is the task.

I think we're just gonna call JSON here. And then so this is the task. So I think if we just pass in tasks, this should work. Let's check, we're gonna refresh import from click up. And yeah, now we're getting that again. And if I click the button, it happens immediately because now we have the data and the cache. So that's good. And now if we sort or search, we're again gonna be able to do it a lot faster.

And now if we sort or search, we're again gonna be able to do it a lot faster. Let's change this records to a long closure. This is going to be our collection. And then we're gonna do something with it and then we're gonna return that collection. Now in this closure here, we can pass in some of the things. Well, let me show you in the filament docs. So if we look for sorting, you can see here that we can pass in a sort column

So if we look for sorting, you can see here that we can pass in a sort column in a sort direction. And then when the sort column is filled, then we can use the collection to sort it. So first let's get this here. Okay, so we're passing in the sort column and the sort direction. And then when the sort column is filled, we're gonna call sort by.

And then when the sort column is filled, we're gonna call sort by. So we have the collection right here. And when the sort column is filled, we're going to sort it by the column in the direction that's selected here. So let's go back to the front end and let's see if this is working. I'm gonna import from click up. And now all that is nothing to sort.

I'm gonna import from click up. And now all that is nothing to sort. There we go. The bug and feature that's sorting. If we want the name to be sortable, we have to allow it to be sortable. Let's try that. Import from click up, name, there we go. So this is sorting nicely and we can implement searching as well.

So this is sorting nicely and we can implement searching as well. And so in order to do searching as well, we're also going to have a string for search. And then we have when the search is filled, we're going to check if the string contains that in the item. So let's go back here. Let's close it, try again. And if I do CSV, there we go.

Let's close it, try again. And if I do CSV, there we go. So searching is now working as well. So it is a little complicated. Honestly, I get tripped up with this when I use it a lot. I have to reference the docs. I usually have Claude help me get the syntax correct. But once you have it working, you can actually have your own table that behaves almost exactly like a filament eloquent table,

you can actually have your own table that behaves almost exactly like a filament eloquent table, except the data is coming from an API or some external source and not eloquent.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟