Skip to content

Commit 22999e4

Browse files
committed
Include question ID in JSON exports of health check retros, fix group being ignored on import
1 parent 0ef1e70 commit 22999e4

8 files changed

Lines changed: 54 additions & 25 deletions

File tree

backend/src/export/RetroJsonExport.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
CurveCubicBezier,
1212
Colour,
1313
} from '../shared/api-entities';
14+
import { getQuestionID, makeUserAnswerID } from '../shared/health';
1415

1516
type MaybeAsyncIterable<T> = Iterable<T> | AsyncIterable<T>;
1617

@@ -34,6 +35,7 @@ export interface RetroItemJsonExport {
3435
created: string;
3536
category: string;
3637
group?: string | undefined;
38+
for?: string | undefined;
3739
message: string;
3840
votes: number;
3941
completed?: string | undefined;
@@ -141,14 +143,17 @@ function importRetroItemAttachment(
141143
}
142144
}
143145

144-
function exportRetroItem(item: RetroItem): RetroItemJsonExport {
146+
function exportRetroItem(item: RetroItem, format: string): RetroItemJsonExport {
145147
const result: RetroItemJsonExport = {
146148
created: exportTimestamp(item.created),
147149
category: item.category,
148150
group: item.group,
149151
message: item.message,
150152
votes: item.votes,
151153
};
154+
if (format === 'health') {
155+
result.for = getQuestionID(item);
156+
}
152157
if (item.doneTime > 0) {
153158
result.completed = exportTimestamp(item.doneTime);
154159
}
@@ -158,9 +163,12 @@ function exportRetroItem(item: RetroItem): RetroItemJsonExport {
158163
return result;
159164
}
160165

161-
function importRetroItem(item: RetroItemJsonExport): RetroItem {
166+
function importRetroItem(item: RetroItemJsonExport, format: string): RetroItem {
162167
return {
163-
id: randomUUID(),
168+
id:
169+
format === 'health' && item.for
170+
? makeUserAnswerID(item.for, randomUUID())
171+
: randomUUID(),
164172
created: importTimestamp(item.created),
165173
category: item.category,
166174
group: item.group,
@@ -193,21 +201,21 @@ function importRetroHistoryItem(
193201
};
194202
}
195203

196-
function exportRetroData(archive: RetroData): RetroDataJsonExport {
204+
function exportRetroData(retro: RetroData): RetroDataJsonExport {
197205
return {
198-
format: archive.format,
199-
options: archive.options,
200-
items: archive.items.map(exportRetroItem),
201-
history: archive.history.map(exportRetroHistoryItem),
206+
format: retro.format,
207+
options: retro.options,
208+
items: retro.items.map((item) => exportRetroItem(item, retro.format)),
209+
history: retro.history.map(exportRetroHistoryItem),
202210
};
203211
}
204212

205-
export function importRetroDataJson(archive: RetroDataJsonExport): RetroData {
213+
export function importRetroDataJson(retro: RetroDataJsonExport): RetroData {
206214
return {
207-
format: archive.format,
208-
options: archive.options,
209-
items: archive.items.map(importRetroItem),
210-
history: archive.history?.map(importRetroHistoryItem) ?? [],
215+
format: retro.format,
216+
options: retro.options,
217+
items: retro.items.map((item) => importRetroItem(item, retro.format)),
218+
history: retro.history?.map(importRetroHistoryItem) ?? [],
211219
};
212220
}
213221

backend/src/helpers/exportedJsonParsers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export const extractExportedColour = json.exactObject({
2929
export const extractExportedRetroItem = json.object<RetroItemJsonExport>({
3030
created: jsonIsoDate,
3131
category: json.string,
32+
group: json.optional(json.string),
33+
for: json.optional(json.string),
3234
message: json.string,
3335
votes: json.number,
3436
completed: json.optional(jsonIsoDate),

backend/src/routers/openapi.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,12 @@ export const openapi = Buffer.from(
15361536
"The type of the item. The meaning of this will vary depending on the type of retro, but 'action' is a common category denoting Action Items.",
15371537
example: 'happy',
15381538
},
1539+
for: {
1540+
type: 'string',
1541+
description:
1542+
'For health check retros, this is the question ID associated with this answer.',
1543+
example: 'learning',
1544+
},
15391545
message: {
15401546
type: 'string',
15411547
description: 'The user-provided content of the item.',

backend/src/shared/health.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ interface AnswersSummary {
1818
counts: Counts;
1919
}
2020

21+
export const getQuestionID = (item: RetroItem) => item.id.split(':')[0]!;
22+
23+
export const makeUserAnswerID = (questionID: string, userID: string) =>
24+
`${questionID}:${userID}`;
25+
2126
export function summariseHealthVotes(
2227
retroItems: RetroItem[],
2328
): HealthSummary | null {
@@ -28,7 +33,7 @@ export function summariseHealthVotes(
2833
if (item.category === 'action') {
2934
continue;
3035
}
31-
const questionID = item.id.split(':')[0]!;
36+
const questionID = getQuestionID(item);
3237
let answer = answers.get(questionID);
3338
if (!answer) {
3439
answer = { id: questionID, counts: { ...ZERO_COUNTS } };

frontend/src/actions/healthRetro.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import type { Retro, RetroItem } from '../shared/api-entities';
2-
import type { AnswerID, HealthSummary } from '../shared/health';
2+
import {
3+
makeUserAnswerID,
4+
type AnswerID,
5+
type HealthSummary,
6+
} from '../shared/health';
37
import type { Spec } from '../api/reducer';
48
import { setRetroState } from './retro';
59

@@ -24,9 +28,6 @@ export const addHistoricSummary = (summary: HealthSummary): Spec<Retro>[] => [
2428
{ history: ['push', summary] },
2529
];
2630

27-
export const makeUserAnswerID = (questionID: string, userID: string) =>
28-
`${questionID}:${userID}`;
29-
3031
export const answerQuestion = (
3132
group: string | undefined,
3233
questionID: string,

frontend/src/components/guidance/Preview.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
Retro,
77
RetroItem,
88
} from '../../shared/api-entities';
9-
import type { AnswerID } from '../../shared/health';
9+
import { makeUserAnswerID, type AnswerID } from '../../shared/health';
1010
import { classNames } from '../../helpers/classNames';
1111
import { useWindowSize, type Size } from '../../hooks/env/useWindowSize';
1212
import type { Spec } from '../../api/reducer';
@@ -130,7 +130,10 @@ export const answerHealth = (
130130
delay: (animate ? 1700 : 0) + delayAnswer,
131131
spec: {
132132
localState: {
133-
[`health-message:${questionID}:${userID}`]: ['=', '...' + message],
133+
[`health-message:${makeUserAnswerID(questionID, userID)}`]: [
134+
'=',
135+
'...' + message,
136+
],
134137
},
135138
},
136139
},
@@ -140,7 +143,7 @@ export const answerHealth = (
140143
items: [
141144
'push',
142145
{
143-
id: `${questionID}:${userID}`,
146+
id: makeUserAnswerID(questionID, userID),
144147
category: answerID,
145148
message,
146149
created: 0,
@@ -170,7 +173,7 @@ export const addHealthAnswers = (
170173
'push',
171174
...Object.entries(allAnswers).flatMap(([userID, answers]) =>
172175
answers.map(([questionID, answerID, message = '']) => ({
173-
id: `${questionID}:${userID}`,
176+
id: makeUserAnswerID(questionID, userID),
174177
category: answerID,
175178
message,
176179
created: 0,

frontend/src/components/retro-formats/health/questions/Questions.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { useLayoutEffect, type FunctionComponent } from 'react';
22
import { Link } from 'wouter';
33
import type { RetroItem } from '../../../../shared/api-entities';
4-
import type { AnswerID } from '../../../../shared/health';
4+
import { makeUserAnswerID, type AnswerID } from '../../../../shared/health';
55
import { startViewTransition } from '../../../../helpers/viewTransition';
66
import { classNames } from '../../../../helpers/classNames';
77
import { useStateMap } from '../../../../hooks/useStateMap';
88
import {
99
getQuestionProgress,
10-
makeUserAnswerID,
1110
type HealthQuestion,
1211
} from '../../../../actions/healthRetro';
1312
import { Examples } from '../common/Examples';

frontend/src/shared/health.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ interface AnswersSummary {
1818
counts: Counts;
1919
}
2020

21+
export const getQuestionID = (item: RetroItem) => item.id.split(':')[0]!;
22+
23+
export const makeUserAnswerID = (questionID: string, userID: string) =>
24+
`${questionID}:${userID}`;
25+
2126
export function summariseHealthVotes(
2227
retroItems: RetroItem[],
2328
): HealthSummary | null {
@@ -28,7 +33,7 @@ export function summariseHealthVotes(
2833
if (item.category === 'action') {
2934
continue;
3035
}
31-
const questionID = item.id.split(':')[0]!;
36+
const questionID = getQuestionID(item);
3237
let answer = answers.get(questionID);
3338
if (!answer) {
3439
answer = { id: questionID, counts: { ...ZERO_COUNTS } };

0 commit comments

Comments
 (0)