Skip to content

Commit 09d5fd6

Browse files
fiskusnl0greptile-apps[bot]Copilot
authored
BSQIK/Search: UI: 1) table view; 2) show objects within packages; 3) search for packages tab (#4413)
Co-authored-by: Alexei Mochalov <[email protected]> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: nl_0 <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 4c60cce commit 09d5fd6

File tree

106 files changed

+7223
-4128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+7223
-4128
lines changed

catalog/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ where verb is one of
1818

1919
## Changes
2020

21+
- [Added] Search: Table view for package search results (including matching entries) ([#4413](https://github.com/quiltdata/quilt/pull/4413))
22+
- [Changed] Packages tab: Use search view to navigate packages ([#4413](https://github.com/quiltdata/quilt/pull/4413))
2123
- [Fixed] Freeform search: pass 'size' set to 0 to backend, properly handle 'from' ([#4432](https://github.com/quiltdata/quilt/pull/4432))
2224
- [Changed] Increase font size in tooltips and make them uniform ([#4425](https://github.com/quiltdata/quilt/pull/4425))
2325
- [Added] Detect directories and redirect to trailing-slash URLs (e.g., `catalog-host/dir``catalog-host/dir/`). ([#4398](https://github.com/quiltdata/quilt/pull/4398))

catalog/app/components/Assistant/Model/GlobalContext/__snapshots__/navigation.spec.ts.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,20 @@ exports[`components/Assistant/Model/GlobalTools/navigation NavigateSchema produc
310310
"title": "OLDEST",
311311
"type": "string",
312312
},
313+
{
314+
"enum": [
315+
"LEX_ASC",
316+
],
317+
"title": "LEX_ASC",
318+
"type": "string",
319+
},
320+
{
321+
"enum": [
322+
"LEX_DESC",
323+
],
324+
"title": "LEX_DESC",
325+
"type": "string",
326+
},
313327
],
314328
"description": "Order of search results",
315329
"title": "Search result order",

catalog/app/components/BucketIcon/BucketIcon.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ interface BucketIconProps
2222
custom?: string
2323
stub?: string
2424
}
25-
src: string
25+
src?: string
2626
}
2727

2828
export default function BucketIcon({

catalog/app/components/FileEditor/FileEditor.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ function EditorSuspended({
7171
err: $TSFixMe, // PreviewError
7272
) => (
7373
<div>
74-
{/* @ts-expect-error */}
7574
<PreviewDisplay data={AsyncResult.Err(err)} />
7675
</div>
7776
),

catalog/app/components/Filters/Container.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ const useStyles = M.makeStyles((t) => ({
1818
alignItems: 'center',
1919
display: 'flex',
2020
justifyContent: 'space-between',
21-
margin: t.spacing(0, 0, 1.5),
21+
margin: t.spacing(0, 0, 0.5),
22+
},
23+
closable: {
24+
marginBottom: t.spacing(1.5),
2225
},
2326
title: {
2427
...t.typography.body2,
@@ -66,7 +69,7 @@ export default function Container({
6669
const classes = useStyles()
6770
return (
6871
<div className={cx(classes.root, className)}>
69-
<div className={classes.header}>
72+
<div className={cx(classes.header, onDeactivate && classes.closable)}>
7073
<div className={classes.title}>{title}</div>
7174
{onDeactivate && (
7275
<M.IconButton size="small" className={classes.close} onClick={onDeactivate}>

catalog/app/components/Filters/List.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ interface ListProps {
6262
onChange: (v: string[]) => void
6363
placeholder?: string
6464
searchThreshold?: number
65-
value: string[]
65+
value: readonly string[]
6666
}
6767

6868
export default function List({

catalog/app/components/JsonEditor/PreviewValue.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,32 @@ function PreviewObject({ value }: PreviewObjectProps) {
8080

8181
interface PreviewValueProps {
8282
value: JsonValue
83+
fallback?: React.ReactNode
84+
strQuot?: string
8385
}
8486

85-
export default function PreviewValue({ value }: PreviewValueProps) {
86-
if (value === EMPTY_VALUE || value === undefined) return ''
87+
export default function PreviewValue({
88+
value,
89+
fallback = '',
90+
strQuot = '"',
91+
}: PreviewValueProps) {
92+
if (value === EMPTY_VALUE || value === undefined) return fallback
8793

8894
if (Array.isArray(value)) return <PreviewArray value={value} />
8995

9096
if (R.is(Object, value)) return <PreviewObject value={value} />
9197

9298
if (value === null) return 'null'
9399

94-
if (R.is(String, value)) return <span>&quot;{value}&quot;</span>
100+
if (R.is(String, value)) {
101+
return (
102+
<span>
103+
{strQuot}
104+
{value}
105+
{strQuot}
106+
</span>
107+
)
108+
}
95109

96110
return value.toString()
97111
}

catalog/app/components/JsonEditor/State.ts

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,6 @@ const getSchemaItem = ({
5454

5555
const noKeys: string[] = []
5656

57-
function getSchemaItemKeys(schemaItem: JsonSchema): string[] {
58-
if (!schemaItem || !schemaItem.properties) return noKeys
59-
const keys = Object.keys(schemaItem.properties)
60-
61-
if (!schemaItem.required) return keys
62-
63-
const sortOrder = schemaItem.required.reduce(
64-
(memo: { [x: string]: number }, key: string, index: number) => ({
65-
[key]: index,
66-
...memo,
67-
}),
68-
{} as { [x: string]: number },
69-
)
70-
const getSortIndex = (key: string) =>
71-
R.ifElse(R.has(key), R.prop(key), R.always(Infinity))(sortOrder)
72-
return R.sortBy(getSortIndex, keys)
73-
}
74-
7557
type SortOrder = React.MutableRefObject<{
7658
counter: number
7759
dict: Record<JSONPointer.Pointer, number>
@@ -104,7 +86,7 @@ export function iterateSchema(
10486
if (!schema.properties) return memo
10587

10688
const requiredKeys = schema.required
107-
getSchemaItemKeys(schema).forEach((key) => {
89+
JSONSchema.getSchemaItemKeysOr(schema, noKeys).forEach((key) => {
10890
// eslint-disable-next-line no-param-reassign
10991
sortOrder.current.counter += 1
11092

@@ -291,7 +273,9 @@ function getSchemaItemKeysByPath(
291273
objPath: JSONPointer.Path,
292274
): ObjectKey[] {
293275
const item = getJsonDictItemRecursively(jsonDict, objPath)
294-
return item && item.valueSchema ? getSchemaItemKeys(item.valueSchema) : noKeys
276+
return item && item.valueSchema
277+
? JSONSchema.getSchemaItemKeysOr(item.valueSchema, noKeys)
278+
: noKeys
295279
}
296280

297281
function getSchemaAndObjKeys(
@@ -310,7 +294,7 @@ export function mergeSchemaAndObjRootKeys(
310294
schema: JsonSchema,
311295
obj: JsonRecord,
312296
): ObjectKey[] {
313-
const schemaKeys = getSchemaItemKeys(schema)
297+
const schemaKeys = JSONSchema.getSchemaItemKeysOr(schema, noKeys)
314298
const objKeys = getObjValueKeys(obj)
315299
return R.uniq([...schemaKeys, ...objKeys])
316300
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import * as React from 'react'
2+
import renderer from 'react-test-renderer'
3+
4+
import { createBoundary } from 'utils/ErrorBoundary'
5+
6+
import { FullWidthProvider, Container, useSetFullWidth } from './Container'
7+
8+
const ErrorBoundary = createBoundary(() => (error: Error) => (
9+
<span>Error: {error.message}</span>
10+
))
11+
12+
const EmptyContainer = () => (
13+
<ErrorBoundary>
14+
<Container>{''}</Container>
15+
</ErrorBoundary>
16+
)
17+
18+
describe('components/Layout/Container', () => {
19+
it('requires Provider', () => {
20+
jest.spyOn(console, 'error').mockImplementationOnce(jest.fn())
21+
const tree = renderer.create(<EmptyContainer />)
22+
expect(tree).toMatchSnapshot()
23+
})
24+
25+
it('has restricted width by default', () => {
26+
const tree = renderer.create(
27+
<FullWidthProvider>
28+
<EmptyContainer />
29+
</FullWidthProvider>,
30+
)
31+
expect(tree.root.findByProps({ maxWidth: 'lg' })).toBeTruthy()
32+
expect(() => tree.root.findByProps({ maxWidth: false })).toThrow()
33+
expect(tree).toMatchSnapshot()
34+
})
35+
36+
it('has full width once set', () => {
37+
const SetFullWidth = () => {
38+
useSetFullWidth()
39+
return <>long content</>
40+
}
41+
const tree = renderer.create(
42+
<FullWidthProvider>
43+
<Container>
44+
<SetFullWidth />
45+
</Container>
46+
</FullWidthProvider>,
47+
)
48+
renderer.act(() => {})
49+
expect(() => tree.root.findByProps({ maxWidth: 'lg' })).toThrow()
50+
expect(tree.root.findByProps({ maxWidth: false })).toBeTruthy()
51+
expect(tree).toMatchSnapshot()
52+
})
53+
54+
it('still has full width when other remove full width', () => {
55+
// TODO: Show some warning or throw error:
56+
// Some component is designed for narrow layout,
57+
// but is rendered in `fullWidth`,
58+
// because there are rendered other components designed for `fullWidth`.
59+
60+
const SetFullWidth = () => {
61+
useSetFullWidth()
62+
return <>long content</>
63+
}
64+
const UnmountSetFullWidth = () => {
65+
const [x, setX] = React.useState(true)
66+
React.useEffect(() => {
67+
setX(false)
68+
}, [])
69+
return x ? <SetFullWidth /> : <>short content</>
70+
}
71+
const tree = renderer.create(
72+
<FullWidthProvider>
73+
<Container>
74+
<UnmountSetFullWidth />
75+
<SetFullWidth />
76+
<UnmountSetFullWidth />
77+
<SetFullWidth />
78+
<UnmountSetFullWidth />
79+
</Container>
80+
</FullWidthProvider>,
81+
)
82+
renderer.act(() => {})
83+
expect(() => tree.root.findByProps({ maxWidth: 'lg' })).toThrow()
84+
expect(tree.root.findByProps({ maxWidth: false })).toBeTruthy()
85+
expect(tree).toMatchSnapshot()
86+
})
87+
})
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import cx from 'classnames'
2+
import invariant from 'invariant'
3+
import * as React from 'react'
4+
import * as M from '@material-ui/core'
5+
6+
const Ctx = React.createContext<{
7+
state: boolean
8+
adjustCounter: (inc: number) => void
9+
} | null>(null)
10+
11+
interface FullWidthProviderProps {
12+
children: React.ReactNode
13+
}
14+
15+
export function FullWidthProvider({ children }: FullWidthProviderProps) {
16+
const [state, setState] = React.useState(false)
17+
const counterRef = React.useRef(0)
18+
const adjustCounter = React.useCallback((inc: number) => {
19+
counterRef.current += inc
20+
setState(counterRef.current > 0)
21+
}, [])
22+
return <Ctx.Provider value={{ state, adjustCounter }}>{children}</Ctx.Provider>
23+
}
24+
25+
export function useSetFullWidth() {
26+
const ctx = React.useContext(Ctx)
27+
invariant(ctx, 'Context must be used within a Provider')
28+
const { adjustCounter } = ctx
29+
React.useEffect(() => {
30+
adjustCounter(1)
31+
return () => {
32+
adjustCounter(-1)
33+
}
34+
}, [adjustCounter])
35+
}
36+
37+
export function useGetFullWidth() {
38+
const ctx = React.useContext(Ctx)
39+
invariant(ctx, 'Context must be used within a Provider')
40+
return ctx.state
41+
}
42+
43+
const useStyles = M.makeStyles((t) => ({
44+
fullWidth: {
45+
animation: t.transitions.create('$expand'),
46+
},
47+
contained: {
48+
animation: t.transitions.create('$collapse'),
49+
},
50+
'@keyframes expand': {
51+
'0%': {
52+
transform: 'scaleX(0.94)',
53+
},
54+
'100%': {
55+
transform: 'scaleX(1)',
56+
},
57+
},
58+
'@keyframes collapse': {
59+
'0%': {
60+
opacity: 0.3,
61+
},
62+
'100%': {
63+
opacity: 1,
64+
},
65+
},
66+
}))
67+
68+
export function Container({ children, className }: M.ContainerProps) {
69+
const classes = useStyles()
70+
71+
const fullWidth = useGetFullWidth()
72+
73+
return (
74+
<M.Container
75+
className={cx(fullWidth ? classes.fullWidth : classes.contained, className)}
76+
maxWidth={!fullWidth && 'lg'}
77+
>
78+
{children}
79+
</M.Container>
80+
)
81+
}
82+
83+
export default Container

0 commit comments

Comments
 (0)