Skip to content

Commit

Permalink
feat: support iteration fields (#95)
Browse files Browse the repository at this point in the history
Following the issue #94 I
created, here is the start of solution.

I'm not used to Typescript so sorry if I make rookie mistakes. :)

Closes #94

---------

Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
  • Loading branch information
blombard and gr2m committed Oct 30, 2023
1 parent 221c849 commit e581c3d
Show file tree
Hide file tree
Showing 10 changed files with 537 additions and 5 deletions.
5 changes: 2 additions & 3 deletions api/lib/item-fields-nodes-to-fields-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ function projectFieldValueNodeToValue(projectField, node) {
return projectField.optionsById[node.optionId];
case "ProjectV2ItemFieldTextValue":
return node.text;
// TODO: implement iteration fields
// case "ProjectV2ItemFieldIterationValue":
// return null;
case "ProjectV2ItemFieldIterationValue":
return node.title;
}
}
22 changes: 22 additions & 0 deletions api/lib/project-fields-nodes-to-fields-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,28 @@ export function projectFieldsNodesToFieldsMap(state, project, nodes) {
);
}

// If the field is of type "Iteration", then the `configuration` property will be set.
if (node.configuration) {
acc[userFieldNameAlias].optionsById = node.configuration.iterations.concat(node.configuration.completedIterations).reduce(
(acc, option) => {
return {
...acc,
[option.id]: option.title,
};
},
{}
);
acc[userFieldNameAlias].optionsByValue = node.configuration.iterations.concat(node.configuration.completedIterations).reduce(
(acc, option) => {
return {
...acc,
[option.title]: option.id,
};
},
{}
);
}

return acc;
},
optionalFields
Expand Down
4 changes: 3 additions & 1 deletion api/lib/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ const queryProjectNodes = `
... on ProjectV2IterationField {
configuration {
iterations {
id
title
duration
startDate
}
completedIterations {
id
title
duration
startDate
Expand Down Expand Up @@ -186,7 +188,7 @@ export const getProjectItemsPaginatedQuery = `
${queryItemFieldNodes}
}
}
}
}
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,24 @@ export type ProjectFieldNode = {
* `options` is only set on `ProjectV2SingleSelectField`
*/
options?: { id: string; name: string }[];

/**
* `configuration` is only set on `ProjectV2IterationField`
*/
configuration?: {
iterations: {
id: string;
title: string;
duration: number;
startDate: string;
}[];
completedIterations: {
id: string;
title: string;
duration: number;
startDate: string;
}[];
};
};

export type ProjectField =
Expand Down
410 changes: 410 additions & 0 deletions test/recorded/api.items.update-iteration/fixtures.json

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions test/recorded/api.items.update-iteration/prepare.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// @ts-check

/**
* Prepare state in order to record fixtures for test.js. Returns array of arguments that will be passed
* passed as `test(project, ...arguments)`.
*
* @param {import("@octokit/openapi-types").components["schemas"]["repository"]} repository
* @param {import("@octokit/core").Octokit} octokit
* @param {import("../../..").default<{text: string, number: number, date: string, singleSelect: "One" | "Two" | "Three", iteration: "Iteration 1" | "Iteration 2" | "Iteration 3"}>} project
* @returns {Promise<[string]>}
*/
export async function prepare(repository, octokit, project) {
// create a test issue
const { data: issue } = await octokit.request(
"POST /repos/{owner}/{repo}/issues",
{
owner: repository.owner.login,
repo: repository.name,
title: "Issue",
body: "This is a test issue",
}
);

// add issue to project
const item = await project.items.add(issue.node_id, {
text: "text",
number: "1",
date: new Date("2020-02-02").toISOString(),
singleSelect: "One",
iteration: "Iteration 1",
});

return [item.id];
}
20 changes: 20 additions & 0 deletions test/recorded/api.items.update-iteration/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// @ts-check

import GitHubProject from "../../../index.js";

/**
* @param {import("../../../").default} defaultTestProject
* @param {string} [itemId]
*/
export function test(defaultTestProject, itemId = "PVTI_1") {
const project = new GitHubProject({
owner: defaultTestProject.owner,
number: defaultTestProject.number,
octokit: defaultTestProject.octokit,
fields: {
iteration: "Iteration",
},
});

return project.items.update(itemId, { iteration: "Iteration 2" });
}
2 changes: 1 addition & 1 deletion test/recorded/api.items.update-with-emoji-alias/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ export function test(defaultTestingProject, itemId = "PVTI_1") {
"🎯text": "Text",
},
});

return project.items.update(itemId, { "🎯text": "new text" });
}
27 changes: 27 additions & 0 deletions test/snapshots/recorded.test.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -7177,6 +7177,33 @@ Generated by [AVA](https://avajs.dev).
type: 'ISSUE',
}

## api.items.update-iteration

> Snapshot 1
{
content: {
assignees: [],
closed: false,
closedAt: undefined,
createdAt: '2022-02-02T12:00:00Z',
databaseId: 1001,
id: 'I_1',
labels: [],
milestone: null,
number: 1,
repository: 'test-repository',
title: 'Issue',
url: 'https://github.com/github-project-fixtures/test-repository/issues/1',
},
fields: {
iteration: 'Iteration 2',
},
id: 'PVTI_1',
isArchived: false,
type: 'ISSUE',
}

## api.items.update-not-found

> Snapshot 1
Expand Down
Binary file modified test/snapshots/recorded.test.js.snap
Binary file not shown.

0 comments on commit e581c3d

Please sign in to comment.