-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: add generate grid form views guide #3338
Open
manuelblum
wants to merge
9
commits into
main
Choose a base branch
from
docs/add-generate-grid-form-guide
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
480fa72
docs: add generate grid form views guide
manuelblum 32de1da
fix: link
manuelblum fcb7df6
fix prettier
manuelblum 10ac816
remove unneccesary documentation
manuelblum e79df00
fix cspell errors
manuelblum 38c0444
docs: link to api generator docs
manuelblum 464ef8d
docs: delete sample code
manuelblum 3a0aa82
docs: remove --prefix examples
manuelblum 0762133
docs: remove potential missleading sentence
manuelblum File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file added
BIN
+32 KB
...rm-views/1-api-entity-with-crud-generator/images/customerDirectoryStructure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+236 KB
...1-api-entity-with-crud-generator/images/customersQueryInPlaygroundWithError.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
156 changes: 156 additions & 0 deletions
156
...s/4-guides/3-generate-grid-form-views/1-api-entity-with-crud-generator/index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
--- | ||
title: API Entity with CRUD Generator | ||
--- | ||
|
||
## Generating an entity with the api-generator | ||
|
||
Since we are building the API first, we will start by generating a new entity. Go into the `api` folder and create a new directory, e.g., `api/src/customer`. Inside this directory, create a new file `customer.entity.ts` with the following content: | ||
|
||
```typescript | ||
import { CrudField, CrudGenerator } from "@comet/cms-api"; | ||
import { BaseEntity, Entity, PrimaryKey, Property } from "@mikro-orm/core"; | ||
import { Field, ID, ObjectType } from "@nestjs/graphql"; | ||
import { v4 } from "uuid"; | ||
|
||
@Entity() | ||
@ObjectType() | ||
@CrudGenerator({ targetDirectory: `${__dirname}/../generated/`, requiredPermission: "customer" }) | ||
export class Customer extends BaseEntity<Customer, "id"> { | ||
@CrudField({ search: true, filter: true, sort: true, input: false }) | ||
@Field(() => ID) | ||
@PrimaryKey({ columnType: "uuid" }) | ||
id: string = v4(); | ||
|
||
@CrudField({ search: true, filter: false, sort: false, input: true }) | ||
@Field() | ||
@Property({ columnType: "text" }) | ||
firstName: string; | ||
|
||
@CrudField({ search: true, filter: false, sort: false, input: true }) | ||
@Field() | ||
@Property({ columnType: "text" }) | ||
lastName: string; | ||
|
||
@CrudField({ search: false, filter: false, sort: false, input: false }) | ||
@Property({ onUpdate: () => new Date() }) | ||
@Field() | ||
updatedAt?: Date = new Date(); | ||
} | ||
``` | ||
|
||
Currently, there is no `api-generator` watch mode - so every time you change the entity following command must be run. Information how to setup API Generator can be found [Setup API Generator](../../../1-getting-started/4-crud-generator/1-api-generator.md) Section. | ||
|
||
```bash | ||
cd api | ||
npm run api-generator | ||
``` | ||
|
||
The **API Generator** will generate multiple files inside the specified `../generated` output directory. It will contain a `customer.resolver.ts` and some dto related files (`customer.filter.ts`, `customer.input.ts`, `customer.sort.ts`, `customer.args.ts`, `paginated-customer.ts`). | ||
|
||
 | ||
|
||
To integrate the new entity into the application, you have to add a new NestJS module. Create a new file `customer.module.ts` in the `api/src/customer` directory with the following content: | ||
|
||
```typescript | ||
import { MikroOrmModule } from "@mikro-orm/nestjs"; | ||
import { Module } from "@nestjs/common"; | ||
|
||
import { Customer } from "./entities/customer.entity"; | ||
import { CustomerResolver } from "./generated/customer.resolver"; | ||
|
||
@Module({ | ||
imports: [MikroOrmModule.forFeature([Customer])], | ||
providers: [CustomerResolver], | ||
}) | ||
export class CustomerModule {} | ||
``` | ||
|
||
This generated module must be added to the `api/src/app.module.ts` and registered. | ||
|
||
```typescript | ||
import { DynamicModule, Module } from "@nestjs/common"; | ||
import { CustomerModule } from "@src/customer/customer.module"; | ||
import { DbModule } from "@src/db/db.module"; | ||
import { ContentScope as BaseContentScope } from "@src/site-configs"; | ||
|
||
import { Config } from "./config/config"; | ||
import { ConfigModule } from "./config/config.module"; | ||
|
||
@Module({}) | ||
export class AppModule { | ||
static forRoot(config: Config): DynamicModule { | ||
return { | ||
module: AppModule, | ||
imports: [ConfigModule.forRoot(config), DbModule, CustomerModule], | ||
}; | ||
} | ||
} | ||
|
||
//... | ||
``` | ||
|
||
As soon the new `CustomerModule` is registered in the app module, the schema will update, and provide the new generated Queries/Mutations, including the Object types and necessary inputs | ||
|
||
```graphql | ||
type Customer { | ||
id: ID! | ||
firstName: String! | ||
lastName: String! | ||
updatedAt: DateTime! | ||
} | ||
|
||
type PaginatedCustomers { | ||
nodes: [Customer!]! | ||
totalCount: Int! | ||
} | ||
|
||
input CustomerFilter { | ||
id: StringFilter | ||
and: [CustomerFilter!] | ||
or: [CustomerFilter!] | ||
} | ||
|
||
input CustomerSort { | ||
field: CustomerSortField! | ||
direction: SortDirection! = ASC | ||
} | ||
|
||
enum CustomerSortField { | ||
id | ||
} | ||
|
||
type Query { | ||
# ... | ||
customer(id: ID!): Customer! | ||
customers( | ||
offset: Int! = 0 | ||
limit: Int! = 25 | ||
search: String | ||
filter: CustomerFilter | ||
sort: [CustomerSort!] | ||
): PaginatedCustomers! | ||
} | ||
|
||
input CustomerInput { | ||
firstName: String! | ||
lastName: String! | ||
} | ||
|
||
input CustomerUpdateInput { | ||
firstName: String | ||
lastName: String | ||
} | ||
|
||
type Mutation { | ||
# ... | ||
createCustomer(input: CustomerInput!): Customer! | ||
updateCustomer(id: ID!, input: CustomerUpdateInput!): Customer! | ||
deleteCustomer(id: ID!): Boolean! | ||
} | ||
``` | ||
|
||
Schema should already be available when you start the GraphQL Playground locally `http:4000/api/graphql`, and you should be able to play around with the queries. | ||
|
||
 | ||
|
||
As soon as you start to execute the first Query, one will see that @mikro-orm will through an error, that the Customer Table does not exists in the Database. |
Binary file added
BIN
+39.4 KB
...ides/3-generate-grid-form-views/2-create-a-migration/images/createMigration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+98.8 KB
...form-views/2-create-a-migration/images/customerQueryInPlaygroundSuccessfull.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+998 KB
...des/3-generate-grid-form-views/2-create-a-migration/images/executeMigration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions
39
docs/docs/4-guides/3-generate-grid-form-views/2-create-a-migration/index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--- | ||
title: Create a migration | ||
--- | ||
|
||
Now it's time to create a simple migration that will create an empty table in the database for the newly created Customer entity. First of all, create a migration with the following command: | ||
|
||
``` | ||
npx mikro-orm migration:create | ||
``` | ||
|
||
 | ||
|
||
Mikro orm will crate a Migrations file in the `api/migrations` directory. Revise the migrations, and cleanup not necessary sql statements. The migrations to create the Customer table, should then look something like: | ||
|
||
```typescript | ||
import { Migration } from "@mikro-orm/migrations"; | ||
|
||
export class Migration20250203143416 extends Migration { | ||
async up(): Promise<void> { | ||
this.addSql( | ||
'create table "Customer" ("id" uuid not null, "firstName" text not null, "lastName" text not null, "updatedAt" timestamptz(0) not null, constraint "Customer_pkey" primary key ("id"));', | ||
); | ||
} | ||
} | ||
``` | ||
|
||
More infos concerning mikro-orm and the related cli can be found here [mikro-orm - using via cli](https://mikro-orm.io/docs/migrations#using-via-cli). | ||
|
||
To execute the migration and insert the data in the database run the following command: | ||
|
||
```bash | ||
npm run db:migrate | ||
``` | ||
|
||
 | ||
|
||
Now we are ready to execute the Query again in the GraphQL Playground, and one should see that the Query is executed successfully. | ||
|
||
 |
Binary file added
BIN
+473 KB
...orm-views/3-create-fixtures/images/customerQueryInPlaygroundWithFixtureData.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 95 additions & 0 deletions
95
docs/docs/4-guides/3-generate-grid-form-views/3-create-fixtures/index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
--- | ||
title: Create fixtures | ||
--- | ||
|
||
To insert some data into the database, we will use fixtures. Fixtures are a way to insert data into the database. The fixtures are defined in the `db/fixtures/generators` directory in the `api` directory. To generate fixtures, it's often useful to generate a lot of data.[@faker-js/faker](https://github.com/faker-js/faker) is often a good choice for generating a lot of random data. | ||
|
||
## Create Fixtures | ||
|
||
Create a new file in the `fixtures` directory with the following content: | ||
|
||
``` | ||
customer-fixtures.service.ts | ||
``` | ||
|
||
```typescript | ||
import { faker } from "@faker-js/faker"; | ||
import { EntityRepository } from "@mikro-orm/postgresql"; | ||
import { Customer } from "@src/customer/entities/customer.entity"; | ||
import { mapLimit } from "async"; | ||
import { SingleBar } from "cli-progress"; | ||
|
||
interface GenerateCustomerOptions { | ||
repository: EntityRepository<Customer>; | ||
bar: SingleBar; | ||
total: number; | ||
} | ||
|
||
export const generateCustomers = async ({ | ||
repository, | ||
bar, | ||
total, | ||
}: GenerateCustomerOptions): Promise<Customer[]> => { | ||
const generateRandomCustomer = async (): Promise<Customer> => { | ||
const customer = repository.create({ | ||
id: faker.string.uuid(), | ||
firstName: faker.person.firstName(), | ||
lastName: faker.person.lastName(), | ||
}); | ||
|
||
bar.increment(1, { | ||
title: "Customer", | ||
}); | ||
|
||
return customer; | ||
}; | ||
|
||
return mapLimit<number, Customer>(Array(total), 100, async () => generateRandomCustomer()); | ||
}; | ||
``` | ||
|
||
The `generateCustomers` functions is a convenience function, that receives some options, like the repository, a progress bar and the total number of customers to generate. The function then generates the customers and increments the progress bar. | ||
|
||
## Add Fixtures to the FixturesConsole | ||
|
||
Additionally, the created fixtures (`generateCustomer`) must be called and executed. Open `db/fixtures/generators/fixtures.console.ts` an add the fixtures functions calls so the function gets execute when fixtures get created: | ||
|
||
```typescript | ||
export class FixturesConsole { | ||
//.... | ||
async execute(total?: string | number): Promise<void> { | ||
//... | ||
|
||
const multiBar = new MultiBar(this.barOptions, Presets.shades_classic); | ||
|
||
// Add your fixtures here | ||
await Promise.all([ | ||
generateCustomers({ | ||
repository: this.orm.em.getRepository(Customer), | ||
bar: multiBar.create(total, 0), | ||
total, | ||
}), | ||
]); | ||
|
||
multiBar.stop(); | ||
// ... | ||
|
||
await this.orm.em.flush(); | ||
} | ||
} | ||
``` | ||
|
||
## Execute Fixtures | ||
|
||
Everything should be set up now. To execute the fixtures, run the following command: | ||
|
||
```bash | ||
cd api | ||
npm run fixtures | ||
``` | ||
|
||
## Verify Fixtures | ||
|
||
Now we are ready to execute the Query again in the GraphQL Playground, and one should see that the Query is executed successfully and will return the generated Data | ||
|
||
 |
Binary file added
BIN
+89.4 KB
...te-grid-form-views/4-admin-generator-generate-grid/images/adminGeneratorCli.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+134 KB
...ate-grid-form-views/4-admin-generator-generate-grid/images/customerDataGrid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+17.1 KB
...rate-grid-form-views/4-admin-generator-generate-grid/images/customerGridIDE.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions
69
...cs/4-guides/3-generate-grid-form-views/4-admin-generator-generate-grid/index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
--- | ||
title: Admin Generator create DataGrid | ||
--- | ||
|
||
The Admin Generator is a powerful tool to generate a complete CRUD interface for your entities. We will show you how to create a DataGrid with the Admin Generator. | ||
|
||
## Generate DataGrid | ||
|
||
To generate a DataGrid with the Admin Generator, you have to create a `.cometGen.ts` file. Those files are used by the Admin Generator to generate different kinds of interfaces (DataGrids or Forms). Create a new file `CustomerGrid.cometGen.ts` in the `api/src/customer` directory with the following content: | ||
|
||
```typescript | ||
import { future_GridConfig as GridConfig } from "@comet/cms-admin"; | ||
import { GQLCustomer } from "@src/graphql.generated"; | ||
|
||
export const CustomerGrid: GridConfig<GQLCustomer> = { | ||
type: "grid", | ||
gqlType: "Customer", | ||
columns: [ | ||
{ type: "text", name: "id" }, | ||
{ type: "text", name: "firstName" }, | ||
{ type: "text", name: "lastName" }, | ||
], | ||
}; | ||
``` | ||
|
||
The `@comet/cms-admin` has types available for all the different components that can be generated. The `GridConfig` type is used to define the configuration of the DataGrid. The `GQLCustomer` got created in the section before, with the crud generator. The `GQLCustomer` | ||
type is the GraphQL type that will be used to guarantee type safety. The `columns` array defines the columns of the DataGrid. Each column has a `type`, `name` and other properties. | ||
|
||
|
||
## Run Admin Generator | ||
|
||
Unfortunately there is no watch mode available for the Admin Generator. To generate the DataGrid, you have to run the Admin Generator manually. This will delete all already generated files and generate them again. | ||
|
||
Run the following command: | ||
|
||
```bash | ||
cd admin | ||
npm run admin-generator | ||
``` | ||
|
||
The `admin-generator` script is configured in `admin/package.json` and will execute the admin generator binary. | ||
|
||
 | ||
|
||
Two files will be generated in the `admin/src/customers/generated` directory. The `CustomerGrid.tsx` and the `CustomerGrid.generated.ts`. The `CustomerGrid.tsx` is the React component that will render the DataGrid. The `CustomerGrid.generated.ts` has related types and interfaces from the GraphQL Api. | ||
|
||
 | ||
|
||
The component is ready to be used in the application. Simple use the generated component somewhere in your React Application: | ||
|
||
`src/customers/CustomerPage.tsx` | ||
|
||
```typescript | ||
import { StackMainContent } from "@comet/admin"; | ||
import { CustomersGrid } from "@src/customers/generated/CustomerGrid"; | ||
import { FunctionComponent } from "react"; | ||
|
||
export const CustomerPage: FunctionComponent = () => { | ||
return ( | ||
<StackMainContent fullHeight> | ||
<CustomersGrid /> | ||
</StackMainContent> | ||
); | ||
}; | ||
``` | ||
|
||
The generated CustomerGrid will look like this: | ||
|
||
 |
Binary file added
BIN
+109 KB
...te-grid-form-views/5-admin-generator-generate-form/images/adminGeneratorCli.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+19.3 KB
...enerate-grid-form-views/5-admin-generator-generate-form/images/customerForm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good if we'd promote a real service with dependency injection here: https://github.com/vivid-planet/comet/blob/main/demo/api/src/db/fixtures/generators/products-fixture.service.ts#L11