Skip to content

Commit 3739399

Browse files
committed
Hydrate labels for engagements
1 parent ee4db27 commit 3739399

File tree

7 files changed

+87
-7
lines changed

7 files changed

+87
-7
lines changed

dbschema/common.gel

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ module default {
1818
)
1919
)
2020
);
21-
21+
22+
function array_join_maybe(array: array<str>, delimiter: str) -> optional str using (
23+
with joined := array_join(array, delimiter)
24+
select if joined = "" then <str>{} else joined
25+
);
26+
2227
scalar type nanoid extending str;
2328

2429
scalar type RichText extending json;

dbschema/migrations/00018-m1jf7p4.edgeql

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/engagement/dto/engagement.dto.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ class Engagement extends Interfaces {
8181
@Field(() => IProject)
8282
declare readonly parent: BaseNode;
8383

84+
readonly label: Readonly<{
85+
project: string;
86+
language: string | null;
87+
intern: string | null;
88+
}>;
89+
8490
@Field(() => SecuredEngagementStatus, {
8591
middleware: [parentIdMiddleware],
8692
})

src/components/engagement/engagement.gel.repository.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,51 @@ const languageHydrate = e.shape(e.LanguageEngagement, (le) => ({
6363
...baseHydrate(le),
6464
__typename: le.__type__.name,
6565
...languageExtraHydrate,
66+
label: e.select({
67+
project: le.project.name,
68+
language: le.language.name,
69+
intern: e.cast(e.str, e.set()),
70+
}),
6671
}));
6772

6873
const internshipHydrate = e.shape(e.InternshipEngagement, (ie) => ({
6974
...baseHydrate(ie),
7075
__typename: ie.__type__.name,
7176
...internshipExtraHydrate,
77+
label: e.select({
78+
project: ie.project.name,
79+
language: e.cast(e.str, e.set()),
80+
intern: e.array_join_maybe(
81+
e.array([ie.intern.displayFirstName, ie.intern.displayLastName]),
82+
' ',
83+
),
84+
}),
7285
}));
7386

74-
const hydrate = e.shape(e.Engagement, (engagement) => ({
75-
...baseHydrate(engagement),
76-
...e.is(e.LanguageEngagement, languageExtraHydrate),
77-
...e.is(e.InternshipEngagement, internshipExtraHydrate),
78-
}));
87+
const hydrate = e.shape(e.Engagement, (engagement) => {
88+
const langEng = e.select(e.LanguageEngagement, () => ({
89+
filter_single: { id: engagement.id },
90+
}));
91+
const internEng = e.select(e.InternshipEngagement, () => ({
92+
filter_single: { id: engagement.id },
93+
}));
94+
return {
95+
...baseHydrate(engagement),
96+
...e.is(e.LanguageEngagement, languageExtraHydrate),
97+
...e.is(e.InternshipEngagement, internshipExtraHydrate),
98+
label: e.select({
99+
project: engagement.project.name,
100+
language: langEng.language.name,
101+
intern: e.array_join_maybe(
102+
e.array([
103+
internEng.intern.displayFirstName,
104+
internEng.intern.displayLastName,
105+
]),
106+
' ',
107+
),
108+
}),
109+
};
110+
});
79111

80112
export const ConcreteRepos = {
81113
LanguageEngagement: class LanguageEngagementRepository extends RepoFor(

src/components/engagement/engagement.repository.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {
4949
requestingUser,
5050
SortCol,
5151
sortWith,
52+
textJoinMaybe,
5253
whereNotDeletedInChangeset,
5354
} from '~/core/database/query';
5455
import { Privileges } from '../authorization';
@@ -168,6 +169,7 @@ export class EngagementRepository extends CommonRepository {
168169
relation('out', '', 'mouEnd', ACTIVE),
169170
node('mouEnd'),
170171
])
172+
.apply(matchNames)
171173
.match([
172174
[
173175
node('project'),
@@ -193,6 +195,11 @@ export class EngagementRepository extends CommonRepository {
193195
step: 'step.value',
194196
},
195197
language: 'language { .id }',
198+
label: {
199+
project: 'projectName.value',
200+
language: 'languageName.value',
201+
intern: textJoinMaybe(['dfn.value', 'dln.value']),
202+
},
196203
pnp: { id: 'props.pnp' },
197204
growthPlan: { id: 'props.growthPlan' },
198205
ceremony: 'ceremony { .id }',

src/components/engagement/handlers/validate-eng-date-overrides-on-project-change.handler.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export class ValidateEngDateOverridesOnProjectChangeHandlerSetLastStatusDate
3434
>((eng) => {
3535
const common = {
3636
id: eng.id,
37+
label: (eng.label.language ?? eng.label.intern)!,
3738
} as const;
3839
const { startDateOverride: start, endDateOverride: end } = eng;
3940
return [
@@ -73,6 +74,7 @@ class EngagementDateOverrideConflictException extends RangeException {
7374
readonly engagements: NonEmptyArray<
7475
Readonly<{
7576
id: ID<'Engagement'>;
77+
label: string;
7678
point: 'start' | 'end';
7779
date: CalendarDate;
7880
}>
@@ -85,7 +87,7 @@ class EngagementDateOverrideConflictException extends RangeException {
8587
...engagements.map((eng) => {
8688
const pointStr = eng.point === 'start' ? 'Start' : 'End';
8789
const dateStr = eng.date.toISO();
88-
return ` - ${pointStr} date of ${eng.id} is ${dateStr}`;
90+
return ` - ${pointStr} date of ${eng.label} is ${dateStr}`;
8991
}),
9092
].join('\n');
9193
super({ message });

src/core/database/query/cypher-functions.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,26 @@ export const apoc = {
8989
setLabels: (node: ExpressionInput, labels: readonly string[]) =>
9090
procedure('apoc.create.setLabels', ['node'])({ node: exp(node), labels }),
9191
},
92+
text: {
93+
/**
94+
* @see https://neo4j.com/docs/apoc/current/overview/apoc.text/apoc.text.join/
95+
*/
96+
join: (list: ExpressionInput, delimiter: string) =>
97+
fn('apoc.text.join')(list, delimiter),
98+
},
99+
};
100+
101+
export const cleanTextList = (list: ExpressionInput) =>
102+
exp(`[x IN ${exp(list)} WHERE x IS NOT NULL AND trim(x) <> '' | trim(x)]`);
103+
104+
export const textJoinMaybe = (items: ExpressionInput, delimiter = ' ') => {
105+
const cleaned = cleanTextList(items);
106+
return exp(
107+
`CASE WHEN size(${cleaned}) = 0 THEN null ELSE ${apoc.text.join(
108+
`${cleaned}`,
109+
`"${delimiter}"`,
110+
)} END`,
111+
);
92112
};
93113

94114
/**

0 commit comments

Comments
 (0)