Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions src/consumer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ const updateIssue = async (issueId, fields) => {
if (response.status !== 204) throw new Error(await response.text());
};

const createDescription = (description) => ({
...description,
type: "doc",
content: description.content.filter(
(content) => content.type !== "mediaSingle"
),
});

const cloneIssue = async (issue, fields) => {
const bodyData = {
fields: {
Expand All @@ -48,6 +56,9 @@ const cloneIssue = async (issue, fields) => {
"labels",
]),
...fields,
description: issue.fields.description
? createDescription(issue.fields.description)
: null,
},
update: {},
};
Expand Down Expand Up @@ -96,6 +107,29 @@ const changeStatusDoneIssue = async (issueIdOrKey) => {
if (response.status !== 204) throw new Error(await response.text());
};

const linkCloneIssueToParent = async (issueKey, parentKey) => {
const bodyData = {
type: { id: "10006" }, // This is id for split from
inwardIssue: { key: parentKey },
outwardIssue: { key: issueKey },
};

const response = await api.asApp().requestJira(route`/rest/api/3/issueLink`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(bodyData),
});

console.log(
`linkCloneIssueToParent Response: ${response.status} ${response.statusText}`
);

if (response.status !== 201) throw new Error(await response.text());
};

const handleSplit = async (issueIdOrKey: string) => {
const issue = await getIssue(issueIdOrKey);

Expand All @@ -108,16 +142,22 @@ const handleSplit = async (issueIdOrKey: string) => {
Number(issue.fields[CONFIGS.STORY_POINT_FIELD_NAME] ?? 0) - nextStoryPoint;

if (newStoryPoint > 0) {
const sprints = issue.fields[CONFIGS.SPRINT_FIELD_NAME];
const activeSprint = sprints?.find(
(sprint) => sprint.state === "active"
)?.id;

const cloned = await cloneIssue(issue, {
...(!issue.fields.issuetype.subtask && {
[CONFIGS.SPRINT_FIELD_NAME]:
issue.fields[CONFIGS.SPRINT_FIELD_NAME]?.[0]?.id,
// Note this is a subtask and subtasks cannot be associated to a sprint. It's associated to the same sprint as its parent.
[CONFIGS.SPRINT_FIELD_NAME]: activeSprint,
}),
[CONFIGS.STORY_POINT_FIELD_NAME]: newStoryPoint,
summary: `${issue.fields.summary} - SPLIT`,
});

await changeStatusDoneIssue(cloned.id);
await linkCloneIssueToParent(cloned.key, issueIdOrKey);
}

await updateIssue(issue.id, {
Expand Down
17 changes: 1 addition & 16 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,11 @@ const getBoardSprints = async (boardId) => {

const App = () => {
const [issues, setIssues] = useState();
const [nextSprintId, setNextSprintId] = useState();;
const [isConfirm, setConfirm] = useState(false);
const [isCompleted, setCompleted] = useState(false);
const [sprints] = useState(async () => await getBoardSprints(CONFIGS.CASHY_BOARD_ID));

const activeSprint = sprints?.find(sprint => sprint.state === 'active')
const activeSprintNumber = Number(activeSprint?.name?.match(/\d+/)?.[0])
const suggestNextSprintId = activeSprintNumber && sprints?.find(sprint => sprint.state === 'future' && Number(sprint.name?.match(/\d+/)?.[0]) === activeSprintNumber + 1)?.id

const handleSubmit = async (v) => {
setNextSprintId(v.nextSprint)
const data = await searchIssues(v.targetSprint)
setIssues(data
.filter(issue =>
Expand Down Expand Up @@ -81,7 +75,7 @@ const App = () => {
}

const actionsButtons = [
<Button text="Split tasks" onClick={handleConfirmSplit} disabled={!nextSprintId} />
<Button text="Split tasks" onClick={handleConfirmSplit} />
]

return (
Expand All @@ -94,15 +88,6 @@ const App = () => {
<Option defaultSelected={sprint.state === 'active'} label={sprint.name} value={sprint.id} key={sprint.id} />
))}
</Select>

<Select label="Next sprint" name="nextSprint" isRequired>
{sprints
?.filter(sprint => sprint.state !== 'active')
?.map(sprint => (
<Option defaultSelected={sprint.id === suggestNextSprintId} label={sprint.name} value={sprint.id} key={sprint.id} />
))}
</Select>

</Form>


Expand Down