Skip to content

Commit

Permalink
Merge branch 'main' into merge-main-into-next
Browse files Browse the repository at this point in the history
  • Loading branch information
nsams committed Mar 7, 2024
2 parents b0bed29 + 30d9e0d commit 7034993
Show file tree
Hide file tree
Showing 22 changed files with 323 additions and 89 deletions.
10 changes: 10 additions & 0 deletions .changeset/cuddly-penguins-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@comet/cms-api": minor
---

Support using a service in `@ScopedEntity()` decorator

This can be useful when an entity's scope cannot be derived directly from the passed entity.
For example, a `Page` document's scope is derived by the `PageTreeNode` the document is attached to, but there is no database relation between the two entities.

For page tree document types you can use the provided `PageTreeNodeDocumentEntityScopeService`.
7 changes: 7 additions & 0 deletions .changeset/cyan-mayflies-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@comet/blocks-admin": minor
---

Add `createCompositeBlockSelectField` helper function

To simplify the creation of a select field blocks by hiding the verbose definition of `Form`, `Field` and items.
5 changes: 5 additions & 0 deletions .changeset/pink-forks-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@comet/admin": minor
---

SaveBoundary: Submit multiple Savables sequentially instead of parallel
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
run: pnpm run copy-schema-files

- name: Build
run: pnpm run build:lib
run: pnpm run build:packages

- name: Lint
run: |
Expand Down
89 changes: 73 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,76 @@ sh install.sh

_It is recommended to run `install.sh` every time you switch to the `main` branch._

### Build packages

Before starting individual development processes, build all Comet packages at least once.

```bash
pnpm run build:packages
```

_It is recommended to build all packages every time you switch to the `main` branch._

### Start development processes

[dev-process-manager](https://github.com/vivid-planet/dev-process-manager) is used for local development.
We recommend only running the development process you will need.
Typically, you will need a subset of the available development processes.

Start Comet Admin packages
Here are a few examples:

```bash
pnpm run dev:admin
```
1. You want to add a new component to `@comet/admin`

Start CMS packages
Start the development process for `@comet/admin`:

```bash
pnpm run dev:cms
```
```bash
npx dev-pm start @comet-admin
```

It is also possbile to start specific microservices
Create a development story in Storybook:

```bash
pnpm run dev:cms:api # (api|admin|site)
```
```bash
pnpm run storybook
```

2. You want to add a CMS feature to the API

Start the development process for `@comet/cms-api`:

```bash
npx dev-pm start @cms-api
```

Start Demo API:

```bash
npx dev-pm start @demo-api
```

The Demo API will be available at [http://localhost:4000/](http://localhost:4000/)

3. You want to add a CMS feature to the Admin

Start the development process for `@comet/cms-admin`:

```bash
npx dev-pm start @cms-admin
```

Start Demo API and Admin:

```bash
npx dev-pm start @demo-api @demo-admin
```

The Demo Admin will be available at [http://localhost:8000/](http://localhost:8000/)

See [dev-pm.config.js](/dev-pm.config.js) for a list of all available processes and process groups.

#### Start Demo

```bash
pnpm run dev:demo
npx dev-pm start @demo
```

Demo will be available at
Expand All @@ -68,10 +112,10 @@ Demo will be available at
- API: [http://localhost:4000/](http://localhost:4000/)
- Site: [http://localhost:3000/](http://localhost:3000/)

It is also possbile to start specific microservices
It is also possible to start specific microservices

```bash
pnpm run dev:demo:api # (api|admin|site)
npx dev-pm start @demo-api # (@demo-api|@demo-admin|@demo-site)
```

#### Start Storybook
Expand All @@ -90,12 +134,25 @@ pnpm run docs

The docs will be available at [http://localhost:3000/](http://localhost:3000/)

### Stop Processes
### Stop processes

```bash
npx dev-pm shutdown
```

### Dev scripts

We provide `dev:*` scripts for the most common use cases.
For example, to start the Demo, you can also run:

```bash
pnpm run dev:demo
```

However, we recommend directly using dev-process-manager for greater control over which development processes to start.

See [package.json](/package.json) for a list of all available dev scripts.

## Develop in a project

### additional Requirements
Expand Down
30 changes: 12 additions & 18 deletions demo/admin/src/common/blocks/HeadlineBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SelectField, TextField } from "@comet/admin";
import { TextField } from "@comet/admin";
import { BlockCategory, BlocksFinalForm, createCompositeBlock, createCompositeSetting } from "@comet/blocks-admin";
import { createCompositeBlockSelectField } from "@comet/blocks-admin/lib/blocks/helpers/createCompositeBlockSelectField";
import { createRichTextBlock } from "@comet/cms-admin";
import { MenuItem } from "@mui/material";
import { HeadlineBlockData } from "@src/blocks.generated";
import { LinkBlock } from "@src/common/blocks/LinkBlock";
import * as React from "react";
Expand Down Expand Up @@ -39,23 +39,17 @@ export const HeadlineBlock = createCompositeBlock(
title: "Headline",
},
level: {
block: createCompositeSetting<HeadlineBlockData["level"]>({
block: createCompositeBlockSelectField<HeadlineBlockData["level"]>({
defaultValue: "header-one",
AdminComponent: ({ state, updateState }) => (
<BlocksFinalForm<Pick<HeadlineBlockData, "level">>
onSubmit={({ level }) => updateState(level)}
initialValues={{ level: state }}
>
<SelectField name="level" label="Level" fullWidth>
<MenuItem value="header-one">Header One</MenuItem>
<MenuItem value="header-two">Header Two</MenuItem>
<MenuItem value="header-three">Header Three</MenuItem>
<MenuItem value="header-four">Header Four</MenuItem>
<MenuItem value="header-five">Header Five</MenuItem>
<MenuItem value="header-six">Header Six</MenuItem>
</SelectField>
</BlocksFinalForm>
),
fieldProps: { label: "Level", fullWidth: true },
options: [
{ value: "header-one", label: "Header One" },
{ value: "header-two", label: "Header Two" },
{ value: "header-three", label: "Header Three" },
{ value: "header-four", label: "Header Four" },
{ value: "header-five", label: "Header Five" },
{ value: "header-six", label: "Header Six" },
],
}),
},
},
Expand Down
1 change: 1 addition & 0 deletions demo/api/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,7 @@ type Query {
builds(limit: Float): [Build!]!
autoBuildStatus: AutoBuildStatus!
link(linkId: ID!): Link
page(id: ID!): Page!
pageTreeNode(id: ID!): PageTreeNode
pageTreeNodeByPath(path: String!, scope: PageTreeNodeScopeInput!): PageTreeNode
pageTreeNodeList(scope: PageTreeNodeScopeInput!, category: String): [PageTreeNode!]!
Expand Down
3 changes: 2 additions & 1 deletion demo/api/src/links/entities/link.entity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BlockDataInterface } from "@comet/blocks-api";
import { DocumentInterface, RootBlockDataScalar, RootBlockType } from "@comet/cms-api";
import { DocumentInterface, PageTreeNodeDocumentEntityScopeService, RootBlockDataScalar, RootBlockType, ScopedEntity } from "@comet/cms-api";
import { BaseEntity, Entity, OptionalProps, PrimaryKey, Property } from "@mikro-orm/core";
import { Field, ID, ObjectType } from "@nestjs/graphql";
import { LinkBlock } from "@src/common/blocks/linkBlock/link.block";
Expand All @@ -9,6 +9,7 @@ import { v4 as uuid } from "uuid";
@ObjectType({
implements: () => [DocumentInterface],
})
@ScopedEntity(PageTreeNodeDocumentEntityScopeService)
export class Link extends BaseEntity<Link, "id"> implements DocumentInterface {
[OptionalProps]?: "createdAt" | "updatedAt";

Expand Down
3 changes: 2 additions & 1 deletion demo/api/src/links/links.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AffectedEntity, PageTreeNodeVisibility, PageTreeService, validateNotModified } from "@comet/cms-api";
import { AffectedEntity, PageTreeNodeVisibility, PageTreeService, RequiredPermission, validateNotModified } from "@comet/cms-api";
import { InjectRepository } from "@mikro-orm/nestjs";
import { EntityRepository } from "@mikro-orm/postgresql";
import { UnauthorizedException } from "@nestjs/common";
Expand All @@ -8,6 +8,7 @@ import { LinkInput } from "./dto/link.input";
import { Link } from "./entities/link.entity";

@Resolver(() => Link)
@RequiredPermission("pageTree")
export class LinksResolver {
constructor(@InjectRepository(Link) readonly repository: EntityRepository<Link>, private readonly pageTreeService: PageTreeService) {}

Expand Down
3 changes: 2 additions & 1 deletion demo/api/src/pages/entities/page.entity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BlockDataInterface, RootBlock, RootBlockEntity } from "@comet/blocks-api";
import { DocumentInterface, RootBlockDataScalar, RootBlockType } from "@comet/cms-api";
import { DocumentInterface, PageTreeNodeDocumentEntityScopeService, RootBlockDataScalar, RootBlockType, ScopedEntity } from "@comet/cms-api";
import { BaseEntity, Entity, OptionalProps, PrimaryKey, Property } from "@mikro-orm/core";
import { Field, ID, ObjectType } from "@nestjs/graphql";
import { v4 as uuid } from "uuid";
Expand All @@ -12,6 +12,7 @@ import { SeoBlock } from "../blocks/seo.block";
implements: () => [DocumentInterface],
})
@RootBlockEntity()
@ScopedEntity(PageTreeNodeDocumentEntityScopeService)
export class Page extends BaseEntity<Page, "id"> implements DocumentInterface {
[OptionalProps]?: "createdAt" | "updatedAt";

Expand Down
8 changes: 7 additions & 1 deletion demo/api/src/pages/pages.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { InjectRepository } from "@mikro-orm/nestjs";
import { EntityRepository } from "@mikro-orm/postgresql";
import { UnauthorizedException } from "@nestjs/common";
import { Args, ID, Mutation, Parent, ResolveField, Resolver } from "@nestjs/graphql";
import { Args, ID, Mutation, Parent, Query, ResolveField, Resolver } from "@nestjs/graphql";
import { PageTreeNode } from "@src/page-tree/entities/page-tree-node.entity";

import { PageInput } from "./dto/page.input";
Expand All @@ -20,6 +20,12 @@ import { Page } from "./entities/page.entity";
export class PagesResolver {
constructor(@InjectRepository(Page) private readonly repository: EntityRepository<Page>, private readonly pageTreeService: PageTreeService) {}

@Query(() => Page)
@AffectedEntity(Page)
async page(@Args("id", { type: () => ID }) id: string): Promise<Page> {
return this.repository.findOneOrFail({ id });
}

@ResolveField(() => PageTreeNode, { nullable: true })
async pageTreeNode(@Parent() page: Page): Promise<PageTreeNodeInterface | null> {
return this.pageTreeService.createReadApi().getFirstNodeByAttachedPageId(page.id);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentInterface } from "@comet/cms-api";
import { DocumentInterface, PageTreeNodeDocumentEntityScopeService, ScopedEntity } from "@comet/cms-api";
import { BaseEntity, Entity, OptionalProps, PrimaryKey, Property } from "@mikro-orm/core";
import { Field, ID, ObjectType } from "@nestjs/graphql";
import { v4 as uuid } from "uuid";
Expand All @@ -7,6 +7,7 @@ import { v4 as uuid } from "uuid";
@ObjectType({
implements: () => [DocumentInterface],
})
@ScopedEntity(PageTreeNodeDocumentEntityScopeService)
export class PredefinedPage extends BaseEntity<PredefinedPage, "id"> implements DocumentInterface {
[OptionalProps]?: "createdAt" | "updatedAt";

Expand Down
2 changes: 2 additions & 0 deletions demo/api/src/predefined-page/predefined-page.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
PageTreeService,
RequestContext,
RequestContextInterface,
RequiredPermission,
validateNotModified,
} from "@comet/cms-api";
import { InjectRepository } from "@mikro-orm/nestjs";
Expand All @@ -19,6 +20,7 @@ import { PredefinedPage } from "./entities/predefined-page.entity";
import { PredefinedPageService } from "./predefined-page.service";

@Resolver(() => PredefinedPage)
@RequiredPermission("pageTree")
export class PredefinedPageResolver {
constructor(
@InjectRepository(PredefinedPage) private readonly repository: EntityRepository<PredefinedPage>,
Expand Down
35 changes: 12 additions & 23 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,20 @@
},
"license": "BSD-2-Clause",
"scripts": {
"build": "pnpm recursive run build",
"build:admin": "pnpm recursive --filter '@comet/admin*' run build",
"build:admin:skippable": "test -f packages/admin/admin/lib/index.d.ts && echo 'Skipping Admin build' || $npm_execpath build:admin",
"build:cms": "pnpm recursive --filter '@comet/cms*' --filter '@comet/blocks*' run build",
"build:cms:admin": "pnpm recursive --filter '@comet/cms-admin' --filter '@comet/blocks-admin' run build",
"build:cms:admin:skippable": "test -f packages/admin/cms-admin/lib/index.d.ts && echo 'Skipping CMS Admin build' || $npm_execpath build:cms:admin",
"build:cms:api": "pnpm recursive --filter '@comet/cms-api' --filter '@comet/blocks-api' run build",
"build:cms:api:skippable": "test -f packages/api/cms-api/lib/index.d.ts && echo 'Skipping CMS API build' || $npm_execpath build:cms:api",
"build:cms:site": "pnpm recursive --filter '@comet/cms-site' run build",
"build:cms:site:skippable": "test -f packages/site/cms-site/lib/index.d.ts && echo 'Skipping CMS Site build' || $npm_execpath build:cms:site",
"build:cms:skippable": "test -f packages/admin/cms-admin/lib/index.d.ts && echo 'Skipping CMS build' || $npm_execpath build:cms",
"build:storybook": "pnpm recursive --filter '@comet/admin*' --filter '@comet/eslint-plugin' run build && pnpm --filter comet-storybook run build-storybook",
"build:lib": "pnpm recursive --filter '@comet/*' run build",
"build:packages": "pnpm recursive --filter '@comet/*' run build",
"build:docs": "pnpm recursive --filter '@comet/eslint-plugin' --filter '@comet/admin*' --filter 'comet-docs' run build",
"clean": "pnpm recursive run clean",
"copy-schema-files": "node copy-schema-files.js",
"dev:admin": "pnpm recursive --filter '@comet/admin*' run clean && dotenv -c -- dev-pm start @comet-admin",
"dev:cms": "pnpm recursive --filter '@comet/cms*' run clean && $npm_execpath build:admin:skippable && dotenv -c -- dev-pm start @cms",
"dev:cms:admin": "pnpm recursive --filter '@comet/cms-admin' --filter '@comet/blocks-admin' run clean && $npm_execpath build:admin:skippable && dotenv -c -- dev-pm start @cms-admin",
"dev:cms:api": "pnpm recursive --filter '@comet/cms-api' --filter '@comet/blocks-api' run clean && dotenv -c -- dev-pm start @cms-api",
"dev:cms:site": "pnpm recursive --filter '@comet/cms-site' run clean && dotenv -c -- dev-pm start @cms-site",
"dev:demo": "$npm_execpath build:admin:skippable && $npm_execpath build:cms:skippable && dotenv -c -- dev-pm start @demo",
"dev:demo:admin": "$npm_execpath build:admin:skippable && $npm_execpath build:cms:admin:skippable && dotenv -c -- dev-pm start @demo-admin",
"dev:demo:api": "$npm_execpath build:cms:api:skippable && dotenv -c -- dev-pm start @demo-api",
"dev:demo:site": "$npm_execpath build:cms:site:skippable && dotenv -c -- dev-pm start @demo-site",
"dev:admin": "dev-pm start @comet-admin",
"dev:cms": "dev-pm start @cms",
"dev:cms:admin": "dev-pm start @cms-admin",
"dev:cms:api": "dev-pm start @cms-api",
"dev:cms:site": "dev-pm start @cms-site",
"dev:demo": "dev-pm start @demo",
"dev:demo:admin": "dev-pm start @demo-admin",
"dev:demo:api": "dev-pm start @demo-api",
"dev:demo:site": "dev-pm start @demo-site",
"postinstall": "husky install",
"intl:extract": "formatjs extract './packages/admin/**/*.ts*' --out-file 'lang/en.json' --ignore './**.d.ts' --ignore './**.d.ts.map' --format simple --throws",
"lint": "pnpm recursive run lint",
Expand All @@ -41,10 +30,10 @@
"docs": "pnpm --filter ./docs run start",
"test": "pnpm recursive run test",
"version": "$npm_execpath changeset version && pnpm install --lockfile-only",
"publish": "pnpm run build:lib && $npm_execpath changeset publish"
"publish": "pnpm run build:packages && $npm_execpath changeset publish"
},
"devDependencies": {
"@comet/dev-process-manager": "^2.3.2",
"@comet/dev-process-manager": "^2.5.1",
"@comet/eslint-plugin": "workspace:*",
"@formatjs/cli": "^4.8.3",
"@types/node": "^18.0.0",
Expand Down
14 changes: 7 additions & 7 deletions packages/admin/admin/src/saveBoundary/SaveBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ export function SaveBoundary({ onAfterSave, ...props }: SaveBoundaryProps) {
setHasErrors(false);
setSaving(true);
try {
const saveSuccess = !(
await Promise.all(
Object.values(saveStates.current).map((state) => {
return state.doSave();
}),
)
).some((saveSuccess) => !saveSuccess);
let saveSuccess = true;
for (const state of Object.values(saveStates.current)) {
const result = await state.doSave();
if (!result) {
saveSuccess = false;
}
}
if (!saveSuccess) {
setHasErrors(true);
} else {
Expand Down
Loading

0 comments on commit 7034993

Please sign in to comment.