Context entities in a query
First steps in Wasp-lang coming from PHP
Trying to get to know Wasp-lang I'm working on a job list, where users can post jobs. So in entity Job i have userId and User as relation.
Passing the user entity with the job in the getJobs query
query getJobs {
fn: import { getJobs } from "@src/server/queries.js",
entities: [Job, User]
}
I tried to inlcude the user but I'm not sure how I can use this in a result. I can show the job.userId but not the related user object for example user.username.
export const getJobs: GetJobs<void, Job[]> = async (args, context) => {
return context.entities.Job.findMany({
orderBy: { id: 'asc' },
include: {
user: true,
}
})
![No description](https://cdn.answeroverflow.com/1240036869933236294/Screenshot_2024-05-14_220257.png)
![No description](https://cdn.answeroverflow.com/1240036870252138568/Screenshot_2024-05-14_215859.png)
8 Replies
Hi @Start2Panic. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
In Wasp, you can use the
context.entities
object to access the entities you've specified in your query declaration. In your case, you've specified Job
and User
entities. However, the User
entity is not directly used in the query function, but it's related to the Job
entity.
Your getJobs
query function seems correct. You are using Prisma's findMany
function to get all jobs and including the related user data in the result with include: { user: true }
.
Here is your query function:
This function should return an array of Job
objects, each with a nested User
object. You should be able to access the user's username for each job with job.user.username
.
If you are not able to access the user's username, it might be due to how you are trying to access it in your frontend code. Make sure you are correctly accessing the nested user object in each job.
For more information, you can refer to the following sources:
- Using Entities in Queries (https://wasp-lang.dev/docs/data-model/operations/queries#using-entities-in-queries)
- Implementing Queries (https://wasp-lang.dev/docs/data-model/operations/queries#implementing-queries)
- Example of a Query (https://wasp-lang.dev/docs/data-model/operations/queries#example-1)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Start2Panic, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?Hey @kapa.ai
In the frontend I call JobList in a table:
<table className="min-w-full text-left text-sm font-light">
<thead className="border-b font-medium dark:border-neutral-500">
<tr>
<th scope="col" className="px-6 py-4">#</th>
<th scope="col" className="px-6 py-4">Descrption</th>
<th scope="col" className="px-6 py-4">Created on</th>
<th scope="col" className="px-6 py-4">Created by</th>
<th scope="col" className="px-6 py-4">Status</th>
<th scope="col" className="px-6 py-4">Urgent</th>
<th></th>
</tr>
</thead>
{jobs && <JobsList jobs={jobs} />}
{isLoading && 'Loading...'}
{error && 'Error: ' + error}
</table>
This JobList returns the table body of jobs :
const JobsList = ({ jobs }: { jobs: Job[] }) => {
if (!jobs?.length) return <div>No Jobs</div>
return (
<tbody>
{jobs.map((job, idx) => (
<JobsView job={job} key={idx} />
))}
</tbody>
)
}
Let me check the knowledge base for you. One moment! :books:
----------------------
In your
JobsList
component, you are mapping over the jobs
array and rendering a JobsView
component for each job. If you want to display the user's username for each job, you need to pass the user data to the JobsView
component and then use it there.
Here is an example of how you can do it:
In this example, job.user.username
is used to display the username of the user who created the job. This assumes that your Job
type includes a user
field of type User
, and that User
type has a username
field.
Please note that this is just an example and you might need to adjust it according to your actual data structure and requirements.
For more information, you can refer to the following sources:
- Invoking the Query On the Frontend (https://wasp-lang.dev/docs/tutorial/queries#invoking-the-query-on-the-frontend)
- Working with Queries (https://wasp-lang.dev/docs/data-model/operations/queries#working-with-queries)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Start2Panic, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?Hey @kapa.ai ,
These are my JobsView and JobsList, how do I pass the user data to the JobsView from the JobsList?
const JobsView = ({ job }: { job: Job }) => {
var formattedCreatedAt = job.createdAt.toISOString(); // Example format: "2024-05-10T09:55:24.000Z"
var Urgent = job.isUrgent ? 'Yes' : 'No'; var Status = job.isDone ? 'Done' : 'Open'; return ( <tr className={Urgent === 'Yes' ? 'border-b border-red-200 bg-red-100' : 'text-neutral-800 border-b dark:border-neutral-500'}> <td className="whitespace-nowrap px-6 py-4 font-medium">{job.id}</td> <td className="whitespace-nowrap px-6 py-4">{job.description}</td> <td className="whitespace-nowrap px-6 py-4">{formattedCreatedAt}</td> <td className="whitespace-nowrap px-6 py-4">{job.userId}</td> <td className="whitespace-nowrap px-6 py-4">{Status}</td> <td className={Urgent === 'Yes' ? 'bg-red-500 whitespace-nowrap px-6 py-4"' : 'whitespace-nowrap px-6 py-4"'} >{Urgent}</td> <td className="whitespace-nowrap px-6 py-4"> </td>
</tr> ); }; const JobsList = ({ jobs }: { jobs: Job[] }) => { if (!jobs?.length) return <div>No Jobs</div> return ( <tbody> {jobs.map((job, idx) => ( <JobsView job={job} key={idx} /> ))} </tbody> ) }
var Urgent = job.isUrgent ? 'Yes' : 'No'; var Status = job.isDone ? 'Done' : 'Open'; return ( <tr className={Urgent === 'Yes' ? 'border-b border-red-200 bg-red-100' : 'text-neutral-800 border-b dark:border-neutral-500'}> <td className="whitespace-nowrap px-6 py-4 font-medium">{job.id}</td> <td className="whitespace-nowrap px-6 py-4">{job.description}</td> <td className="whitespace-nowrap px-6 py-4">{formattedCreatedAt}</td> <td className="whitespace-nowrap px-6 py-4">{job.userId}</td> <td className="whitespace-nowrap px-6 py-4">{Status}</td> <td className={Urgent === 'Yes' ? 'bg-red-500 whitespace-nowrap px-6 py-4"' : 'whitespace-nowrap px-6 py-4"'} >{Urgent}</td> <td className="whitespace-nowrap px-6 py-4"> </td>
</tr> ); }; const JobsList = ({ jobs }: { jobs: Job[] }) => { if (!jobs?.length) return <div>No Jobs</div> return ( <tbody> {jobs.map((job, idx) => ( <JobsView job={job} key={idx} /> ))} </tbody> ) }
Hey @Start2Panic , welcome to JS/TS ecosystem! I started my web dev in PHP long time ago, that was fun :)!
Quick advice: use triple backtick to display your code nicely. Three of them in first line, then code below, and for he end, one more line with three backticks.
You can add, in the first line, the name of the language to help it color it.
Like this (check the image attached below):
As for the issue at hand: so you are going in right direction!
What you want to do is something like
job.user.username
in your JobView
component.
The question is, what does job.user
contain, which fields? By default, in Wasp, User
doesn't contain much stuff, unless you store stuff in it during signup.
Instead, the details like email and username and similar are stored in user.auth.identities
, which has one identity for each Auth method (email&pass, username&pass, google, ...).
So you will likely want to modify your initial Prisam query to be something like this:
Then, you should be able to do job.user.auth.identities[0].email
or something similar.
Check out https://wasp-lang.dev/docs/auth/entities for more details on how User <-> Auth <-> Identities all play together!![No description](https://cdn.answeroverflow.com/1240267908894949386/image.png)
There are two options:
1.
include
relations e.g. include user and auth and then identities.
You can then access the relevant username with task.user.auth.identities[0].providerUserId
2. Or, more preferably, store extra fields directly on the user
using userSignupFields
. Here's an example for address
but you can use username
as well! Add the extra field on the User entity and specify it in the userSignupFields
function: https://wasp-lang.dev/docs/auth/overview#1-defining-extra-fieldsOverview | Wasp
Auth is an essential piece of any serious application. That's why Wasp provides authentication and authorization support out of the box.
Thanks all for the advice.
After some hours of 🤔 I finally found that my query was missing the void part...
Ouf @Start2Panic ! But that is certainly not the only thing, right? That is just the typing, and TypeScript would warn you about that, but the rest is a separate issue right?