UBERF-7944: Support for not_planed close for issues (#6396)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2024-08-27 14:10:50 +07:00 committed by GitHub
parent e231f89e0b
commit d7820206c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 81 additions and 31 deletions

View File

@ -3,24 +3,17 @@
// //
--> -->
<script lang="ts"> <script lang="ts">
import { Ref, WithLookup, groupByArray } from '@hcengineering/core' import { Ref, WithLookup } from '@hcengineering/core'
import { import { GithubPullRequestReviewState, GithubReview } from '@hcengineering/github'
GithubPullRequestReviewState,
GithubReview,
GithubReviewComment,
GithubReviewThread
} from '@hcengineering/github'
import { ActivityMessageHeader, ActivityMessageTemplate } from '@hcengineering/activity-resources' import { ActivityMessageHeader, ActivityMessageTemplate } from '@hcengineering/activity-resources'
import { Person, PersonAccount } from '@hcengineering/contact' import { Person, PersonAccount } from '@hcengineering/contact'
import { personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources' import { personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
import { IntlString } from '@hcengineering/platform' import { IntlString } from '@hcengineering/platform'
import { MessageViewer, createQuery } from '@hcengineering/presentation' import { MessageViewer } from '@hcengineering/presentation'
import { Component, PaletteColorIndexes, getPlatformColor, themeStore } from '@hcengineering/ui'
import diffview from '@hcengineering/diffview'
import github from '../../plugin'
import ReviewCommentPresenter from './ReviewCommentPresenter.svelte'
import { isEmptyMarkup } from '@hcengineering/text' import { isEmptyMarkup } from '@hcengineering/text'
import { PaletteColorIndexes, getPlatformColor, themeStore } from '@hcengineering/ui'
import github from '../../plugin'
export let value: WithLookup<GithubReview> export let value: WithLookup<GithubReview>
export let showNotify: boolean = false export let showNotify: boolean = false

View File

@ -68,7 +68,11 @@
) )
} }
async function changeResolution (): Promise<void> { async function changeResolution (): Promise<void> {
await getClient().update(value, { isResolved: !value.isResolved, resolvedBy: null }) if (value.isResolved) {
await getClient().update(value, { isResolved: false, resolvedBy: null })
} else {
await getClient().update(value, { isResolved: true, resolvedBy: getCurrentAccount()._id })
}
} }
const toRefPersonAccount = (account: Ref<Account>): Ref<PersonAccount> => account as Ref<PersonAccount> const toRefPersonAccount = (account: Ref<Account>): Ref<PersonAccount> => account as Ref<PersonAccount>

View File

@ -1057,14 +1057,15 @@ export abstract class IssueSyncManagerBase {
} }
break break
case task.statusCategory.Won: case task.statusCategory.Won:
if (issueExternal.state !== 'CLOSED') { if (issueExternal.state !== 'CLOSED' || issueExternal.stateReason !== 'COMPLETED') {
issueUpdate.state = 'CLOSED' issueUpdate.state = 'CLOSED'
issueUpdate.stateReason = 'COMPLETED'
} }
break break
case task.statusCategory.Lost: case task.statusCategory.Lost:
if (issueExternal.state !== 'CLOSED') { if (issueExternal.state !== 'CLOSED' || issueExternal.stateReason !== 'NOT_PLANNED') {
issueUpdate.state = 'CLOSED' issueUpdate.state = 'CLOSED'
// issueUpdate.stateReason = 'not_planed'// Not supported change to github issueUpdate.stateReason = 'not_planed' // Not supported change to github
} }
break break
} }

View File

@ -21,9 +21,6 @@ import core, {
generateId, generateId,
makeCollaborativeDoc makeCollaborativeDoc
} from '@hcengineering/core' } from '@hcengineering/core'
import task, { TaskType, calcRank } from '@hcengineering/task'
import tracker, { Issue, IssuePriority } from '@hcengineering/tracker'
import { Issue as GithubIssue, IssuesEvent, ProjectsV2ItemEvent } from '@octokit/webhooks-types'
import github, { import github, {
DocSyncInfo, DocSyncInfo,
GithubIntegrationRepository, GithubIntegrationRepository,
@ -32,6 +29,9 @@ import github, {
IntegrationRepositoryData, IntegrationRepositoryData,
GithubIssue as TGithubIssue GithubIssue as TGithubIssue
} from '@hcengineering/github' } from '@hcengineering/github'
import task, { TaskType, calcRank } from '@hcengineering/task'
import tracker, { Issue, IssuePriority } from '@hcengineering/tracker'
import { Issue as GithubIssue, IssuesEvent, ProjectsV2ItemEvent } from '@octokit/webhooks-types'
import { Octokit } from 'octokit' import { Octokit } from 'octokit'
import config from '../config' import config from '../config'
import { import {
@ -667,7 +667,7 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan
okit: Octokit, okit: Octokit,
account: Ref<Account> account: Ref<Account>
): Promise<boolean> { ): Promise<boolean> {
const { state, body, ...issueUpdate } = await this.collectIssueUpdate( const { state, stateReason, body, ...issueUpdate } = await this.collectIssueUpdate(
info, info,
existing, existing,
platformUpdate, platformUpdate,
@ -683,6 +683,41 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan
const hasFieldStateChanges = Object.keys(issueUpdate).length > 0 || state !== undefined const hasFieldStateChanges = Object.keys(issueUpdate).length > 0 || state !== undefined
// We should allow modification from user. // We should allow modification from user.
const closeIssue = async (): Promise<void> => {
await okit?.graphql(
`
mutation closeIssue($issue: ID!) {
closeIssue(input: {
issueId: $issue,
stateReason: ${stateReason === 'not_planed' ? 'NOT_PLANNED' : 'COMPLETED'}
}) {
issue {
id
updatedAt
}
}
}`,
{ issue: issueExternal.id }
)
}
const reopenIssue = async (): Promise<void> => {
await okit?.graphql(
`
mutation reopenIssue($issue: ID!) {
reopenIssue(input: {
issueId: $issue
}) {
issue {
id
updatedAt
}
}
}`,
{ issue: issueExternal.id }
)
}
if (hasFieldStateChanges || body !== undefined) { if (hasFieldStateChanges || body !== undefined) {
if (body !== undefined && !isLocked) { if (body !== undefined && !isLocked) {
await this.ctx.withLog( await this.ctx.withLog(
@ -696,12 +731,15 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan
workspace: this.provider.getWorkspaceId().name workspace: this.provider.getWorkspaceId().name
}) })
if (isGHWriteAllowed()) { if (isGHWriteAllowed()) {
if (state === 'OPEN') {
// We need to call re-open issue
await reopenIssue()
}
await okit?.graphql( await okit?.graphql(
` `
mutation updateIssue($issue: ID!, $body: String! ) { mutation updateIssue($issue: ID!, $body: String! ) {
updateIssue(input: { updateIssue(input: {
id: $issue, id: $issue,
${state !== undefined ? `state: ${state as string}` : ''}
${gqlp(issueUpdate)}, ${gqlp(issueUpdate)},
body: $body body: $body
}) { }) {
@ -713,6 +751,9 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan
}`, }`,
{ issue: issueExternal.id, body } { issue: issueExternal.id, body }
) )
if (state === 'CLOSED') {
await closeIssue()
}
} }
}, },
{ url: issueExternal.url, id: existing._id } { url: issueExternal.url, id: existing._id }
@ -725,12 +766,17 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan
async () => { async () => {
this.ctx.info('update fields', { ...issueUpdate, workspace: this.provider.getWorkspaceId().name }) this.ctx.info('update fields', { ...issueUpdate, workspace: this.provider.getWorkspaceId().name })
if (isGHWriteAllowed()) { if (isGHWriteAllowed()) {
await okit?.graphql( const hasOtherChanges = Object.keys(issueUpdate).length > 0
` if (state === 'OPEN') {
// We need to call re-open issue
await reopenIssue()
}
if (hasOtherChanges) {
await okit?.graphql(
`
mutation updateIssue($issue: ID!) { mutation updateIssue($issue: ID!) {
updateIssue(input: { updateIssue(input: {
id: $issue, id: $issue,
${state !== undefined ? `state: ${state as string}` : ''}
${gqlp(issueUpdate)} ${gqlp(issueUpdate)}
}) { }) {
issue { issue {
@ -739,8 +785,12 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan
} }
} }
}`, }`,
{ issue: issueExternal.id } { issue: issueExternal.id }
) )
}
if (state === 'CLOSED') {
await closeIssue()
}
} }
}, },
{ url: issueExternal.url } { url: issueExternal.url }

View File

@ -992,7 +992,7 @@ export class PullRequestSyncManager extends IssueSyncManagerBase implements DocS
okit: Octokit, okit: Octokit,
account: Ref<Account> account: Ref<Account>
): Promise<boolean> { ): Promise<boolean> {
let { state, body, ...issueUpdate } = await this.collectIssueUpdate( let { state, stateReason, body, ...issueUpdate } = await this.collectIssueUpdate(
info, info,
existing, existing,
platformUpdate, platformUpdate,

View File

@ -204,7 +204,9 @@ export class ReviewThreadSyncManager implements DocSyncManager {
case 'resolved': case 'resolved':
case 'unresolved': { case 'unresolved': {
const isResolved = event.action === 'resolved' const isResolved = event.action === 'resolved'
const reviewData = await this.client.findOne(github.class.DocSyncInfo, { url: event.thread.node_id }) const reviewData = await this.client.findOne(github.class.DocSyncInfo, {
url: event.thread.node_id.toLocaleLowerCase()
})
if (reviewData !== undefined) { if (reviewData !== undefined) {
const reviewObj: GithubReviewThread | undefined = await this.client.findOne<GithubReviewThread>( const reviewObj: GithubReviewThread | undefined = await this.client.findOne<GithubReviewThread>(
@ -225,12 +227,12 @@ export class ReviewThreadSyncManager implements DocSyncManager {
}, },
lastModified lastModified
) )
await this.client.update( await this.client.diffUpdate(
reviewObj, reviewObj,
{ {
isResolved isResolved,
resolvedBy: account
}, },
false,
lastModified, lastModified,
account account
) )