Skip to content

Commit dd8615f

Browse files
committed
Expose FieldZone.projects relationship in GraphQL API
1 parent 7406ab8 commit dd8615f

File tree

5 files changed

+64
-0
lines changed

5 files changed

+64
-0
lines changed

src/components/field-zone/dto/field-zone.dto.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,25 @@ import {
33
DbUnique,
44
NameField,
55
Resource,
6+
type ResourceRelationsShape,
67
type Secured,
78
SecuredProperty,
89
SecuredString,
910
} from '~/common';
1011
import { e } from '~/core/gel';
1112
import { type LinkTo, RegisterResource } from '~/core/resources';
13+
import { IProject } from '../../project/dto';
1214

1315
@RegisterResource({ db: e.FieldZone })
1416
@ObjectType({
1517
implements: [Resource],
1618
})
1719
export class FieldZone extends Resource {
20+
static readonly Relations = () =>
21+
({
22+
projects: [IProject],
23+
} satisfies ResourceRelationsShape);
24+
1825
@NameField()
1926
@DbUnique()
2027
readonly name: SecuredString;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Parent, ResolveField, Resolver } from '@nestjs/graphql';
2+
import { ListArg } from '~/common';
3+
import { Loader, type LoaderOf } from '~/core';
4+
import { ProjectListInput, SecuredProjectList } from '../project/dto';
5+
import { ProjectLoader } from '../project/project.loader';
6+
import { FieldZone } from './dto';
7+
import { FieldZoneService } from './field-zone.service';
8+
9+
@Resolver(FieldZone)
10+
export class FieldZoneProjectsResolver {
11+
constructor(private readonly fieldZoneService: FieldZoneService) {}
12+
13+
@ResolveField(() => SecuredProjectList, {
14+
description: 'The list of projects in regions within this field zone',
15+
})
16+
async projects(
17+
@Parent() fieldZone: FieldZone,
18+
@ListArg(ProjectListInput) input: ProjectListInput,
19+
@Loader(ProjectLoader) projects: LoaderOf<ProjectLoader>,
20+
): Promise<SecuredProjectList> {
21+
const list = await this.fieldZoneService.listProjects(fieldZone, input);
22+
projects.primeAll(list.items);
23+
return list;
24+
}
25+
}

src/components/field-zone/field-zone.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { forwardRef, Module } from '@nestjs/common';
22
import { splitDb } from '~/core';
33
import { AuthorizationModule } from '../authorization/authorization.module';
4+
import { ProjectModule } from '../project/project.module';
45
import { UserModule } from '../user/user.module';
6+
import { FieldZoneProjectsResolver } from './field-zone-projects.resolver';
57
import { FieldZoneGelRepository } from './field-zone.gel.repository';
68
import { FieldZoneLoader } from './field-zone.loader';
79
import { FieldZoneRepository } from './field-zone.repository';
@@ -12,10 +14,12 @@ import { RestrictZoneDirectorRemovalHandler } from './handlers/restrict-zone-dir
1214
@Module({
1315
imports: [
1416
forwardRef(() => AuthorizationModule),
17+
forwardRef(() => ProjectModule),
1518
forwardRef(() => UserModule),
1619
],
1720
providers: [
1821
FieldZoneResolver,
22+
FieldZoneProjectsResolver,
1923
FieldZoneService,
2024
splitDb(FieldZoneRepository, FieldZoneGelRepository),
2125
FieldZoneLoader,

src/components/field-zone/field-zone.service.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
import { HandleIdLookup } from '~/core';
1111
import { IEventBus } from '~/core/events';
1212
import { Privileges } from '../authorization';
13+
import { type ProjectListInput, type SecuredProjectList } from '../project/dto';
14+
import { ProjectService } from '../project/project.service';
1315
import { UserService } from '../user';
1416
import {
1517
type CreateFieldZone,
@@ -28,6 +30,7 @@ export class FieldZoneService {
2830
private readonly events: IEventBus,
2931
private readonly users: UserService,
3032
private readonly repo: FieldZoneRepository,
33+
private readonly projectService: ProjectService,
3134
) {}
3235

3336
async create(input: CreateFieldZone): Promise<FieldZone> {
@@ -115,4 +118,29 @@ export class FieldZoneService {
115118
items: results.items.map((dto) => this.secure(dto)),
116119
};
117120
}
121+
122+
async listProjects(
123+
fieldZone: FieldZone,
124+
input: ProjectListInput,
125+
): Promise<SecuredProjectList> {
126+
const projectListOutput = await this.projectService.list({
127+
...input,
128+
filter: {
129+
...input.filter,
130+
fieldRegion: {
131+
...(input.filter?.fieldRegion ?? {}),
132+
fieldZone: {
133+
...(input.filter?.fieldRegion?.fieldZone ?? {}),
134+
id: fieldZone.id,
135+
},
136+
},
137+
},
138+
});
139+
140+
return {
141+
...projectListOutput,
142+
canRead: true,
143+
canCreate: false, // Field zone doesn't own project creation
144+
};
145+
}
118146
}

src/components/project/field-zone-project-connection.resolver.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)