Skip to content
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: Implement be search and lazy loading for GitHub resources #3987

Merged
Merged
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
14 changes: 12 additions & 2 deletions frontend/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,18 @@ export default {
projectPermissions: (perm: string) =>
`To use this feature you need the <i>${perm}</i> permission for this project.<br/>Please contact a member of this project who has administrator privileges.`,
resourceTypes: {
GITHUB_ISSUE: { id: 1, label: 'GitHub Issue', type: 'GITHUB' },
GITHUB_PR: { id: 2, label: 'GitHub PR', type: 'GITHUB' },
GITHUB_ISSUE: {
id: 1,
label: 'Issue',
resourceType: 'issues',
type: 'GITHUB',
},
GITHUB_PR: {
id: 2,
label: 'Pull Request',
resourceType: 'pulls',
type: 'GITHUB',
},
},
roles: {
'ADMIN': 'Organisation Administrator',
Expand Down
50 changes: 17 additions & 33 deletions frontend/common/services/useGithub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,6 @@ export const githubService = service
.enhanceEndpoints({ addTagTypes: ['Github'] })
.injectEndpoints({
endpoints: (builder) => ({
getGithubIssues: builder.query<
Res['githubIssues'],
Req['getGithubIssues']
>({
providesTags: [{ id: 'LIST', type: 'Github' }],
query: (query: Req['getGithubIssues']) => ({
url: `organisations/${query.organisation_id}/github/issues/?repo_name=${query.repo_name}&repo_owner=${query.repo_owner}`,
}),
}),
getGithubPulls: builder.query<Res['githubPulls'], Req['getGithubPulls']>({
providesTags: [{ id: 'LIST', type: 'Github' }],
query: (query: Req['getGithubPulls']) => ({
url: `organisations/${query.organisation_id}/github/pulls/?repo_name=${query.repo_name}&repo_owner=${query.repo_owner}`,
}),
}),
getGithubRepos: builder.query<Res['githubRepos'], Req['getGithubRepos']>({
providesTags: [{ id: 'LIST', type: 'Github' }],
query: (query: Req['getGithubRepos']) => ({
Expand All @@ -32,30 +17,30 @@ export const githubService = service
})}`,
}),
}),
getGithubResources: builder.query<
Res['githubResources'],
Req['getGithubResources']
>({
providesTags: [{ id: 'LIST', type: 'Github' }],
query: (query: Req['getGithubResources']) => ({
url:
`organisations/${query.organisation_id}/github/${query.github_resource}/` +
`?repo_name=${query.repo_name}&repo_owner=${query.repo_owner}&page_size=${query.page_size}&page=${query.page}&search_text=${query.q}`,
}),
}),
// END OF ENDPOINTS
}),
})

export async function getGithubIssues(
store: any,
data: Req['getGithubIssues'],
options?: Parameters<
typeof githubService.endpoints.getGithubIssues.initiate
>[1],
) {
return store.dispatch(
githubService.endpoints.getGithubIssues.initiate(data, options),
)
}
export async function getGithubPulls(
export async function getGithubResources(
store: any,
data: Req['getGithubPulls'],
data: Req['getGithubResources'],
options?: Parameters<
typeof githubService.endpoints.getGithubPulls.initiate
typeof githubService.endpoints.getGithubResources.initiate
>[1],
) {
return store.dispatch(
githubService.endpoints.getGithubPulls.initiate(data, options),
githubService.endpoints.getGithubResources.initiate(data, options),
)
}
export async function getGithubRepos(
Expand All @@ -72,14 +57,13 @@ export async function getGithubRepos(
// END OF FUNCTION_EXPORTS

export const {
useGetGithubIssuesQuery,
useGetGithubPullsQuery,
useGetGithubReposQuery,
useGetGithubResourcesQuery,
// END OF EXPORTS
} = githubService

/* Usage examples:
const { data, isLoading } = useGetGithubIssuesQuery({ id: 2 }, {}) //get hook
const { data, isLoading } = useGetGithubResourcesQuery({ id: 2 }, {}) //get hook
const [createGithub, { isLoading, data, isSuccess }] = useCreateGithubMutation() //create hook
githubService.endpoints.getGithub.select({id: 2})(store.getState()) //access data from any function
*/
10 changes: 3 additions & 7 deletions frontend/common/types/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,16 +412,12 @@ export type Req = {
repository_owner: string
}
}
getGithubIssues: {
getGithubResources: PagedRequest<{
organisation_id: string
repo_name: string
repo_owner: string
}
getGithubPulls: {
organisation_id: string
repo_name: string
repo_owner: string
}
github_resource: string
}>
getGithubRepos: { installation_id: string; organisation_id: string }
getServersideEnvironmentKeys: { environmentId: string }
deleteServersideEnvironmentKeys: { environmentId: string; id: string }
Expand Down
144 changes: 8 additions & 136 deletions frontend/common/types/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export type PagedResponse<T> = {
previous?: string
results: T[]
}
export interface GitHubPagedResponse<T> extends PagedResponse<T> {
incomplete_results: boolean
}
export type FlagsmithValue = string | number | boolean | null

export type FeatureVersionState = {
Expand Down Expand Up @@ -112,7 +115,7 @@ export type ExternalResource = {
url: string
type: string
project?: number
metadata: null | { status: string }
metadata?: { state?: string; title?: string }
feature: number
}

Expand Down Expand Up @@ -157,155 +160,25 @@ export type LaunchDarklyProjectImport = {
project: number
}

export type Issue = {
url: string
repository_url: string
labels_url: string
comments_url: string
events_url: string
export type GithubResources = {
html_url: string
id: number
number: number
title: string
state: string
created_at: string
updated_at: string
closed_at: null | string
body: string
timeline_url: string
}

export type PullRequest = {
url: string
id: number
html_url: string
issue_url: string
number: number
state: string
locked: boolean
title: string
body: string | null
created_at: string
updated_at: string
closed_at: string | null
merged_at: string | null
draft: boolean
comments_url: string
statuses_url: string
}

export type GithubPaginatedRepos<T> = {
total_count: number
repository_selection: string
repositories: T[]
results: T[]
}

export type Repository = {
id: number
node_id: string
name: string
full_name: string
private: boolean
owner: {
login: string
id: number
node_id: string
avatar_url: string
gravatar_id: string
url: string
html_url: string
followers_url: string
following_url: string
gists_url: string
starred_url: string
subscriptions_url: string
organizations_url: string
repos_url: string
events_url: string
received_events_url: string
type: string
site_admin: boolean
}
html_url: string
description: string | null
fork: boolean
url: string
forks_url: string
keys_url: string
collaborators_url: string
teams_url: string
hooks_url: string
issue_events_url: string
events_url: string
assignees_url: string
branches_url: string
tags_url: string
blobs_url: string
git_tags_url: string
git_refs_url: string
trees_url: string
statuses_url: string
languages_url: string
stargazers_url: string
contributors_url: string
subscribers_url: string
subscription_url: string
commits_url: string
git_commits_url: string
comments_url: string
issue_comment_url: string
contents_url: string
compare_url: string
merges_url: string
archive_url: string
downloads_url: string
issues_url: string
pulls_url: string
milestones_url: string
notifications_url: string
labels_url: string
releases_url: string
deployments_url: string
created_at: string
updated_at: string
pushed_at: string
git_url: string
ssh_url: string
clone_url: string
svn_url: string
homepage: string | null
size: number
stargazers_count: number
watchers_count: number
language: string
has_issues: boolean
has_projects: boolean
has_downloads: boolean
has_wiki: boolean
has_pages: boolean
has_discussions: boolean
forks_count: number
mirror_url: string | null
archived: boolean
disabled: boolean
open_issues_count: number
license: string | null
allow_forking: boolean
is_template: boolean
web_commit_signoff_required: boolean
topics: string[]
visibility: string
forks: number
open_issues: number
watchers: number
default_branch: string
permissions: {
admin: boolean
maintain: boolean
push: boolean
triage: boolean
pull: boolean
}
owner: { login: string }
}

export type GithubRepository = {
Expand Down Expand Up @@ -770,8 +643,7 @@ export type Res = {
externalResource: PagedResponse<ExternalResource>
githubIntegrations: PagedResponse<githubIntegration>
githubRepository: PagedResponse<GithubRepository>
githubIssues: Issue[]
githubPulls: PullRequest[]
githubResources: GitHubPagedResponse<GithubResources>
githubRepos: GithubPaginatedRepos<Repository>
segmentPriorities: {}
featureSegment: FeatureState['feature_segment']
Expand Down
7 changes: 7 additions & 0 deletions frontend/common/useInfiniteScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const useInfiniteScroll = <
) => {
const [localPage, setLocalPage] = useState(1)
const [combinedData, setCombinedData] = useState<RES | null>(null)
const [loadingCombinedData, setLoadingCombinedData] = useState(false)
const [q, setQ] = useState('')

const queryResponse = useGetDataListQuery({
Expand All @@ -39,12 +40,16 @@ const useInfiniteScroll = <
} as RES
})
}
setLoadingCombinedData(false)
}
}, //eslint-disable-next-line
[queryResponse?.data]
)

const searchItems = useThrottle((search: string) => {
if (q !== search) {
setLoadingCombinedData(true)
}
setQ(search)
setLocalPage(1)
}, throttle)
Expand All @@ -61,8 +66,10 @@ const useInfiniteScroll = <

return {
data: combinedData,
isFetching: queryResponse.isFetching,
isLoading: queryResponse.isLoading,
loadMore,
loadingCombinedData: loadingCombinedData && queryResponse.isFetching,
refresh,
response: queryResponse,
searchItems,
Expand Down
Loading