Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit fb922dd

Browse files
authored
Make repos sortable by size (#44360)
* Back end: Made repos sortable by size * Added order selector to UI, then reverted it. * Added index on `repo_size_bytes` * Added an integration test case and an end-to-end test case for "sort by size"
1 parent a6e293b commit fb922dd

File tree

18 files changed

+231
-89
lines changed

18 files changed

+231
-89
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ All notable changes to Sourcegraph are documented in this file.
3030
- OIDC success/fail login attempts are now a part of the audit log. [#44467](https://github.com/sourcegraph/sourcegraph/pull/44467)
3131
- A new experimental GraphQL query, `permissionsSyncJobs`, that lists the states of recently completed permissions sync jobs and the state of each provider. The TTL of entries retrained can be configured with `authz.syncJobsRecordsTTL`. [#44387](https://github.com/sourcegraph/sourcegraph/pull/44387), [#44258](https://github.com/sourcegraph/sourcegraph/pull/44258)
3232
- The search input has a new search history button and allows cycling through recent searches via up/down arrow keys. [#44544](https://github.com/sourcegraph/sourcegraph/pull/44544)
33+
- Repositories can now be ordered by size on the repo admin page. [#44360](https://github.com/sourcegraph/sourcegraph/pull/44360)
3334

3435
### Changed
3536

client/web/src/components/FilteredConnection/FilterControl.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ export interface FilteredConnectionFilterValue {
1414
}
1515

1616
/**
17-
* A filter to display next to the filter input field.
17+
* A filter to display next to the search input field.
1818
*/
1919
export interface FilteredConnectionFilter {
2020
/** The UI label for the filter. */
2121
label: string
2222

23+
/** "radio" or "select" */
2324
type: string
2425

2526
/**

client/web/src/components/FilteredConnection/FilteredConnection.tsx

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react'
22

33
import * as H from 'history'
4-
import { uniq, isEqual } from 'lodash'
4+
import { isEqual, uniq } from 'lodash'
55
import { combineLatest, merge, Observable, of, Subject, Subscription } from 'rxjs'
66
import {
77
catchError,
@@ -10,24 +10,24 @@ import {
1010
distinctUntilChanged,
1111
filter,
1212
map,
13+
scan,
14+
share,
1315
skip,
1416
startWith,
1517
switchMap,
1618
takeUntil,
1719
tap,
18-
scan,
19-
share,
2020
} from 'rxjs/operators'
2121

2222
import { asError, ErrorLike, isErrorLike, logger } from '@sourcegraph/common'
2323

24-
import { ConnectionNodes, ConnectionNodesState, ConnectionNodesDisplayProps, ConnectionProps } from './ConnectionNodes'
24+
import { ConnectionNodes, ConnectionNodesDisplayProps, ConnectionNodesState, ConnectionProps } from './ConnectionNodes'
2525
import { Connection, ConnectionQueryArguments } from './ConnectionType'
2626
import { QUERY_KEY } from './constants'
2727
import { FilteredConnectionFilter, FilteredConnectionFilterValue } from './FilterControl'
28-
import { ConnectionError, ConnectionLoading, ConnectionForm, ConnectionContainer } from './ui'
28+
import { ConnectionContainer, ConnectionError, ConnectionForm, ConnectionLoading } from './ui'
2929
import type { ConnectionFormProps } from './ui/ConnectionForm'
30-
import { getFilterFromURL, getUrlQuery, parseQueryInt, hasID } from './utils'
30+
import { getFilterFromURL, getUrlQuery, hasID, parseQueryInt } from './utils'
3131

3232
/**
3333
* Fields that belong in FilteredConnectionProps and that don't depend on the type parameters. These are the fields
@@ -110,8 +110,9 @@ interface FilteredConnectionProps<C extends Connection<N>, N, NP = {}, HP = {}>
110110
* The arguments for the Props.queryConnection function.
111111
*/
112112
export interface FilteredConnectionQueryArguments extends ConnectionQueryArguments {}
113+
113114
interface FilteredConnectionState<C extends Connection<N>, N> extends ConnectionNodesState {
114-
activeValues: Map<string, FilteredConnectionFilterValue>
115+
activeFilterValues: Map<string, FilteredConnectionFilterValue>
115116

116117
/** The fetched connection data or an error (if an error occurred). */
117118
connectionOrError?: C | ErrorLike
@@ -150,7 +151,7 @@ export class FilteredConnection<
150151
}
151152

152153
private queryInputChanges = new Subject<string>()
153-
private activeValuesChanges = new Subject<Map<string, FilteredConnectionFilterValue>>()
154+
private activeFilterValuesChanges = new Subject<Map<string, FilteredConnectionFilterValue>>()
154155
private showMoreClicks = new Subject<void>()
155156
private componentUpdates = new Subject<FilteredConnectionProps<C, N, NP, HP>>()
156157
private subscriptions = new Subscription()
@@ -177,7 +178,7 @@ export class FilteredConnection<
177178
this.state = {
178179
loading: true,
179180
query: (!this.props.hideSearch && this.props.useURLQuery && searchParameters.get(QUERY_KEY)) || '',
180-
activeValues:
181+
activeFilterValues:
181182
(this.props.useURLQuery && getFilterFromURL(searchParameters, this.props.filters)) ||
182183
new Map<string, FilteredConnectionFilterValue>(),
183184
first: (this.props.useURLQuery && parseQueryInt(searchParameters, 'first')) || this.props.defaultFirst!,
@@ -186,7 +187,7 @@ export class FilteredConnection<
186187
}
187188

188189
public componentDidMount(): void {
189-
const activeValuesChanges = this.activeValuesChanges.pipe(startWith(this.state.activeValues))
190+
const activeFilterValuesChanges = this.activeFilterValuesChanges.pipe(startWith(this.state.activeFilterValues))
190191

191192
const queryChanges = (this.props.querySubject
192193
? merge(this.queryInputChanges, this.props.querySubject)
@@ -205,19 +206,19 @@ export class FilteredConnection<
205206
const refreshRequests = new Subject<{ forceRefresh: boolean }>()
206207

207208
this.subscriptions.add(
208-
activeValuesChanges
209+
activeFilterValuesChanges
209210
.pipe(
210211
tap(values => {
211-
if (this.props.filters === undefined || this.props.onValueSelect === undefined) {
212+
if (this.props.filters === undefined || this.props.onFilterSelect === undefined) {
212213
return
213214
}
214215
for (const filter of this.props.filters) {
215-
if (this.props.onValueSelect) {
216+
if (this.props.onFilterSelect) {
216217
const value = values.get(filter.id)
217218
if (value === undefined) {
218219
continue
219220
}
220-
this.props.onValueSelect(filter, value)
221+
this.props.onFilterSelect(filter, value)
221222
}
222223
}
223224
})
@@ -228,44 +229,48 @@ export class FilteredConnection<
228229
this.subscriptions.add(
229230
// Use this.activeFilterChanges not activeFilterChanges so that it doesn't trigger on the initial mount
230231
// (it doesn't need to).
231-
this.activeValuesChanges.subscribe(values => {
232-
this.setState({ activeValues: new Map(values) })
232+
this.activeFilterValuesChanges.subscribe(values => {
233+
this.setState({ activeFilterValues: new Map(values) })
233234
})
234235
)
235236

236237
this.subscriptions.add(
237238
combineLatest([
238239
queryChanges,
239-
activeValuesChanges,
240+
activeFilterValuesChanges,
240241
refreshRequests.pipe(
241242
startWith<{ forceRefresh: boolean }>({ forceRefresh: false })
242243
),
243244
])
244245
.pipe(
245-
// Track whether the query or the active filter changed
246+
// Track whether the query or the active order or filter changed
246247
scan<
247248
[string, Map<string, FilteredConnectionFilterValue> | undefined, { forceRefresh: boolean }],
248249
{
249250
query: string
250-
values: Map<string, FilteredConnectionFilterValue> | undefined
251+
filterValues: Map<string, FilteredConnectionFilterValue> | undefined
251252
shouldRefresh: boolean
252253
queryCount: number
253254
}
254255
>(
255-
({ query, values, queryCount }, [currentQuery, currentValues, { forceRefresh }]) => ({
256+
(
257+
{ query, filterValues, queryCount },
258+
[currentQuery, currentFilterValues, { forceRefresh }]
259+
) => ({
256260
query: currentQuery,
257-
values: currentValues,
258-
shouldRefresh: forceRefresh || query !== currentQuery || values !== currentValues,
261+
filterValues: currentFilterValues,
262+
shouldRefresh:
263+
forceRefresh || query !== currentQuery || filterValues !== currentFilterValues,
259264
queryCount: queryCount + 1,
260265
}),
261266
{
262267
query: this.state.query,
263-
values: this.state.activeValues,
268+
filterValues: this.state.activeFilterValues,
264269
shouldRefresh: false,
265270
queryCount: 0,
266271
}
267272
),
268-
switchMap(({ query, values, shouldRefresh, queryCount }) => {
273+
switchMap(({ query, filterValues, shouldRefresh, queryCount }) => {
269274
const result = this.props
270275
.queryConnection({
271276
// If this is our first query and we were supplied a value for `visible`,
@@ -274,7 +279,7 @@ export class FilteredConnection<
274279
first: (queryCount === 1 && this.state.visible) || this.state.first,
275280
after: shouldRefresh ? undefined : this.state.after,
276281
query,
277-
...(values ? this.buildArgs(values) : {}),
282+
...(filterValues ? this.buildArgs(filterValues) : {}),
278283
})
279284
.pipe(
280285
catchError(error => [asError(error)]),
@@ -362,7 +367,7 @@ export class FilteredConnection<
362367
this.props.onUpdate(
363368
connectionOrError,
364369
this.state.query,
365-
this.buildArgs(this.state.activeValues)
370+
this.buildArgs(this.state.activeFilterValues)
366371
)
367372
}
368373
this.setState({ connectionOrError, ...rest })
@@ -447,7 +452,7 @@ export class FilteredConnection<
447452
)
448453
.subscribe(newFilterValues => {
449454
if (this.props.useURLQuery) {
450-
this.activeValuesChanges.next(newFilterValues)
455+
this.activeFilterValuesChanges.next(newFilterValues)
451456
}
452457
})
453458
)
@@ -458,12 +463,12 @@ export class FilteredConnection<
458463
private urlQuery({
459464
first,
460465
query,
461-
values,
466+
filterValues,
462467
visibleResultCount,
463468
}: {
464469
first?: number
465470
query?: string
466-
values?: Map<string, FilteredConnectionFilterValue>
471+
filterValues?: Map<string, FilteredConnectionFilterValue>
467472
visibleResultCount?: number
468473
}): string {
469474
if (!first) {
@@ -472,8 +477,8 @@ export class FilteredConnection<
472477
if (!query) {
473478
query = this.state.query
474479
}
475-
if (!values) {
476-
values = this.state.activeValues
480+
if (!filterValues) {
481+
filterValues = this.state.activeFilterValues
477482
}
478483

479484
return getUrlQuery({
@@ -483,7 +488,7 @@ export class FilteredConnection<
483488
// Always set through `defaultProps`
484489
default: this.props.defaultFirst!,
485490
},
486-
values,
491+
filterValues,
487492
visibleResultCount,
488493
search: this.props.location.search,
489494
filters: this.props.filters,
@@ -526,8 +531,8 @@ export class FilteredConnection<
526531
onInputChange={this.onChange}
527532
autoFocus={this.props.autoFocus}
528533
filters={this.props.filters}
529-
onValueSelect={this.onDidSelectValue}
530-
values={this.state.activeValues}
534+
onFilterSelect={this.onDidSelectFilterValue}
535+
filterValues={this.state.activeFilterValues}
531536
compact={this.props.compact}
532537
formClassName={this.props.formClassName}
533538
/>
@@ -590,23 +595,23 @@ export class FilteredConnection<
590595
this.queryInputChanges.next(event.currentTarget.value)
591596
}
592597

593-
private onDidSelectValue = (filter: FilteredConnectionFilter, value: FilteredConnectionFilterValue): void => {
598+
private onDidSelectFilterValue = (filter: FilteredConnectionFilter, value: FilteredConnectionFilterValue): void => {
594599
if (this.props.filters === undefined) {
595600
return
596601
}
597-
const values = new Map(this.state.activeValues)
602+
const values = new Map(this.state.activeFilterValues)
598603
values.set(filter.id, value)
599-
this.activeValuesChanges.next(values)
604+
this.activeFilterValuesChanges.next(values)
600605
}
601606

602607
private onClickShowMore = (): void => {
603608
this.showMoreClicks.next()
604609
}
605610

606-
private buildArgs = (values: Map<string, FilteredConnectionFilterValue>): FilteredConnectionArgs => {
611+
private buildArgs = (filterValues: Map<string, FilteredConnectionFilterValue>): FilteredConnectionArgs => {
607612
let args: FilteredConnectionArgs = {}
608-
for (const key of values.keys()) {
609-
const value = values.get(key)
613+
for (const key of filterValues.keys()) {
614+
const value = filterValues.get(key)
610615
if (value === undefined) {
611616
continue
612617
}

client/web/src/components/FilteredConnection/ui/ConnectionForm.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ export interface ConnectionFormProps {
4242
*/
4343
filters?: FilteredConnectionFilter[]
4444

45-
onValueSelect?: (filter: FilteredConnectionFilter, value: FilteredConnectionFilterValue) => void
45+
onFilterSelect?: (filter: FilteredConnectionFilter, value: FilteredConnectionFilterValue) => void
4646

4747
/** An element rendered as a sibling of the filters. */
4848
additionalFilterElement?: React.ReactElement
4949

50-
values?: Map<string, FilteredConnectionFilterValue>
50+
filterValues?: Map<string, FilteredConnectionFilterValue>
5151

5252
compact?: boolean
5353
}
@@ -68,9 +68,9 @@ export const ConnectionForm = React.forwardRef<HTMLInputElement, ConnectionFormP
6868
onInputChange,
6969
autoFocus,
7070
filters,
71-
onValueSelect,
71+
onFilterSelect,
72+
filterValues,
7273
additionalFilterElement,
73-
values,
7474
compact,
7575
},
7676
reference
@@ -89,8 +89,8 @@ export const ConnectionForm = React.forwardRef<HTMLInputElement, ConnectionFormP
8989
className={classNames(styles.form, !compact && styles.noncompact, formClassName)}
9090
onSubmit={handleSubmit}
9191
>
92-
{filters && onValueSelect && values && (
93-
<FilterControl filters={filters} onValueSelect={onValueSelect} values={values}>
92+
{filters && onFilterSelect && filterValues && (
93+
<FilterControl filters={filters} onValueSelect={onFilterSelect} values={filterValues}>
9494
{additionalFilterElement}
9595
</FilterControl>
9696
)}

client/web/src/components/FilteredConnection/utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export interface GetUrlQueryParameters {
7070
default: number
7171
}
7272
query?: string
73-
values?: Map<string, FilteredConnectionFilterValue>
73+
filterValues?: Map<string, FilteredConnectionFilterValue>
7474
filters?: FilteredConnectionFilter[]
7575
visibleResultCount?: number
7676
search: Location['search']
@@ -82,7 +82,7 @@ export interface GetUrlQueryParameters {
8282
export const getUrlQuery = ({
8383
first,
8484
query,
85-
values,
85+
filterValues,
8686
visibleResultCount,
8787
filters,
8888
search,
@@ -97,9 +97,9 @@ export const getUrlQuery = ({
9797
searchParameters.set('first', String(first.actual))
9898
}
9999

100-
if (values && filters) {
100+
if (filterValues && filters) {
101101
for (const filter of filters) {
102-
const value = values.get(filter.id)
102+
const value = filterValues.get(filter.id)
103103
if (value === undefined) {
104104
continue
105105
}

0 commit comments

Comments
 (0)