-
Notifications
You must be signed in to change notification settings - Fork 336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(jira-server): Save and allow to reuse recent search queries in the scope phase of poker meeting for JiraServer #6551
Conversation
$providerId: Int | ||
$jiraServerSearchQuery: JiraServerSearchQueryInput | ||
) { | ||
persistIntegrationSearchQuery( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still need to wrap the generic mutation in an individual one on a frontend to request the specific integration response above. An issue with the suggestion to improve: #6567
$teamId: ID! | ||
$service: IntegrationProviderServiceEnum! | ||
$providerId: Int | ||
$jiraServerSearchQuery: JiraServerSearchQueryInput |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is currently no way to accept union as input, so we need to define individual fields for each integration like we do for add integration provider
mutation.
An alternative approach is to use JSON type, but it will require additional validation on the backend.
Later we will be able to use oneof
as soon as it will be released in graphql
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For oneof
you would need to group all input union types into one input object and just add the directive. All it does is adding server side verification. We can already arrange the types in this form and we could also implement the directive now if you feel it's worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oneof
feels cleaner, as we do not need to pass service
, however I think it is ok as is for now
|
||
const mutation = graphql` | ||
mutation RemoveJiraServerSearchQueryMutation($id: ID!, $teamId: ID!) { | ||
removeIntegrationSearchQuery(id: $id, teamId: $teamId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still need to wrap the generic mutation in an individual one on a frontend to request the specific integration response above. An issue with the suggestion to improve: #6567
) { | ||
return {error: {message: `Provider does not exists`}} | ||
} | ||
await upsertIntegrationSearchQueryWithProviderId({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to define two separate SQL queries to correctly handle ON CONFLICT
with nullable providerId
field
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we handle uniqueness and sorting on PostgreSQL side, instead of doing that manually in code
return null | ||
} | ||
|
||
const searchQueries = await getLatestIntegrationSearchQueriesWithProviderId({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two separate SQL queries to be able to request AND providerId IS null
packages/server/postgres/queries/src/getLatestIntegrationSearchQueriesWithProviderIdQuery.sql
Show resolved
Hide resolved
…er-persist-search
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only looked at the DB part yet. I don't see why we need two separate kinds of queries and indexes. Even with allowing null
for "providerId"
that's just another value.
packages/server/postgres/migrations/1652861495447_addIntegrationSearchQuery.ts
Show resolved
Hide resolved
packages/server/postgres/migrations/1652861495447_addIntegrationSearchQuery.ts
Show resolved
Hide resolved
...es/server/postgres/queries/generated/getLatestIntegrationSearchQueriesWithProviderIdQuery.ts
Show resolved
Hide resolved
packages/server/postgres/queries/getLatestIntegrationSearchQueriesWithProviderId.ts
Outdated
Show resolved
Hide resolved
Let's get a reviewer review in first, @nickoferrall could you please take a look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
packages/client/mutations/PersistJiraServerSearchQueryMutation.ts
Outdated
Show resolved
Hide resolved
packages/server/graphql/public/mutations/persistIntegrationSearchQuery.ts
Outdated
Show resolved
Hide resolved
packages/server/graphql/public/mutations/persistIntegrationSearchQuery.ts
Outdated
Show resolved
Hide resolved
packages/server/graphql/public/mutations/persistIntegrationSearchQuery.ts
Outdated
Show resolved
Hide resolved
packages/server/postgres/queries/src/upsertIntegrationSearchQueryWithProviderIdQuery.sql
Show resolved
Hide resolved
packages/server/postgres/queries/src/upsertIntegrationSearchQueryQuery.sql
Show resolved
Hide resolved
@name removeIntegrationSearchQueryQuery | ||
*/ | ||
DELETE FROM "IntegrationSearchQuery" | ||
WHERE "id" = :id AND "userId" = :userId AND "teamId" = :teamId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 Why do we need "userId" and "teamId" here if "id" is already the primary key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Dschoordsch I added this as a validation, to not fetch IntegrationQuery
first and manually check userId
and teamId
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you leave a comment so it's clear for the next one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment
packages/client/components/JiraUniversalScopingSearchHistoryToggle.tsx
Outdated
Show resolved
Hide resolved
return '' | ||
} | ||
|
||
return `jiraServer:${auth.providerId}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-2 The id is not unique, a user can have the same provider for multiple teams, each team has a different auth. Thus you need to use jiraServer:${auth}.id
here.
The main issue here is that we're mixing the providers (which are per team and should be non-null) with the auth (which is per team member and should be nullable). So what we really should do is:
- make
JiraServerIntegration
nullable (also GitLab, AzureDevOps, MSTeams, ...) - move
IntegrationProvider
fields to Team object.
No need to do it in this change, but we should address that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a user can have the same provider for multiple teams
So in future provider will be added to the whole organisation?
Currently, I see that we have teamId
column in the IntegrationProvider
table.
Can we have IntegrationProviderTeam
table with id | providerId | teamId
columns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auth
object does not have id
. Made it like this:
return `jiraServer:${teamId}:${auth.providerId}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the current state, each "IntegrationProvider" has scope "org" or "team". Right now the organization is derived from the team, but we may store it separately at some point #6014
} | ||
|
||
return { | ||
id: searchQuery.id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1 This will not be unique, so we need to prefix it. There is already SearchQueryId.join
but that's Meeting specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Dschoordsch pushed a commit that uses toGlobalId
and fromGlobalId
from graphql-relay
package. I think this way we can avoid creating a new function every time. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue with the proposal #6642
source: RemoveIntegrationSearchQuerySuccessSource | ||
) => RemoveIntegrationSearchQuerySuccessSource | ||
} = { | ||
jiraServerIntegration: (source) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 did you test this resolver is actually necessary? Also you would usually import the generated types here
const RemoveIntegrationSearchQuerySuccess: RemoveIntegrationSearchQuerySuccessResolvers = {
You might need to define the JiraServerIntegration
source properly though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Dschoordsch Does not work for me without this resolver, jiraServerIntegration
returned as `null.
Picking generated type RemoveIntegrationSearchQuerySuccessResolvers
does not work in this case as I need to just forward plain source
here, not actually resolve.
* feat(jira-server): Add pagination of results in sprint poker * Tweak comments
…er-persist-search
…rabol into jira-server-persist-search
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Fixes: #5820
This PR introduces a new PostgreSQL table and new mutaton for storing integrations search queries.
Recent Jira Server search queries are now automatically saved
Also see the next issue with suggeted improvements: #6567
How to test: