diff --git a/catalog/CHANGELOG.md b/catalog/CHANGELOG.md index 25f09cb8347..c2b1c833c35 100644 --- a/catalog/CHANGELOG.md +++ b/catalog/CHANGELOG.md @@ -17,6 +17,7 @@ where verb is one of ## Changes +- [Changed] Add `catalog` fragment to Quilt+ URIs (and to documentation) ([#4213](https://github.com/quiltdata/quilt/pull/4213)) - [Fixed] Athena: fix minor UI bugs ([#4232](https://github.com/quiltdata/quilt/pull/4232)) - [Fixed] Show Athena query editor when no named queries ([#4230](https://github.com/quiltdata/quilt/pull/4230)) - [Fixed] Fix some doc URLs in catalog ([#4205](https://github.com/quiltdata/quilt/pull/4205)) diff --git a/catalog/app/containers/Bucket/CodeSamples/Package.spec.tsx b/catalog/app/containers/Bucket/CodeSamples/Package.spec.tsx new file mode 100644 index 00000000000..f4a3ad49b08 --- /dev/null +++ b/catalog/app/containers/Bucket/CodeSamples/Package.spec.tsx @@ -0,0 +1,33 @@ +import * as React from 'react' +import renderer from 'react-test-renderer' + +import PackageCodeSamples from './Package' + +jest.mock( + './Code', + () => + ({ children }: { children: { label: string; contents: string }[] }) => ( +
+ {children.map(({ label, contents }) => ( +
+
{label}:
{contents}
+
+ ))} +
+ ), +) + +describe('containers/Bucket/CodeSamples/Package', () => { + it('renders catalog property', () => { + const props = { + bucket: 'bucket', + name: 'name', + hash: 'hash', + hashOrTag: 'tag', + path: 'path', + catalog: 'catalog', + } + const tree = renderer.create().toJSON() + expect(tree).toMatchSnapshot() + }) +}) diff --git a/catalog/app/containers/Bucket/CodeSamples/Package.tsx b/catalog/app/containers/Bucket/CodeSamples/Package.tsx index c2763b3d750..fc68e998f73 100644 --- a/catalog/app/containers/Bucket/CodeSamples/Package.tsx +++ b/catalog/app/containers/Bucket/CodeSamples/Package.tsx @@ -54,6 +54,7 @@ interface PackageCodeSamplesProps extends Partial { hash: string hashOrTag: string path: string + catalog: string } export default function PackageCodeSamples({ @@ -62,6 +63,7 @@ export default function PackageCodeSamples({ hash, hashOrTag, path, + catalog, ...props }: PackageCodeSamplesProps) { const hashDisplay = hashOrTag === 'latest' ? '' : R.take(10, hash) @@ -85,10 +87,10 @@ export default function PackageCodeSamples({ { label: 'URI', hl: 'uri', - contents: PackageUri.stringify({ bucket, name, hash, path }), + contents: PackageUri.stringify({ bucket, name, hash, path, catalog }), }, ], - [bucket, name, hashDisplay, hash, path], + [bucket, name, hashDisplay, hash, path, catalog], ) return {code} } diff --git a/catalog/app/containers/Bucket/CodeSamples/__snapshots__/Package.spec.tsx.snap b/catalog/app/containers/Bucket/CodeSamples/__snapshots__/Package.spec.tsx.snap new file mode 100644 index 00000000000..33186f8ac4d --- /dev/null +++ b/catalog/app/containers/Bucket/CodeSamples/__snapshots__/Package.spec.tsx.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`containers/Bucket/CodeSamples/Package renders catalog property 1`] = ` +
+
+
+ Python + : +
+ +
+ import quilt3 as q3 +# Browse [[https://docs.quiltdata.com/quilt-python-sdk-developers/api-reference/package#package.browse]] +p = q3.Package.browse("name", top_hash="hash", registry="s3://bucket") +# make changes to package adding individual files [[https://docs.quiltdata.com/quilt-python-sdk-developers/api-reference/package#package.set]] +p.set("data.csv", "data.csv") +# or whole directories [[https://docs.quiltdata.com/quilt-python-sdk-developers/api-reference/package#package.set_dir]] +p.set_dir("subdir", "subdir") +# and push changes [[https://docs.quiltdata.com/quilt-python-sdk-developers/api-reference/package#package.push]] +p.push("name", registry="s3://bucket", message="Hello World") + +# Download (be mindful of large packages) [[https://docs.quiltdata.com/quilt-python-sdk-developers/api-reference/package#package.install]] +q3.Package.install("name", path="path", top_hash="hash", registry="s3://bucket", dest=".") +
+
+
+
+ CLI + : +
+ +
+ # Download package [[https://docs.quiltdata.com/quilt-python-sdk-developers/api-reference/cli#install]] +quilt3 install "name" --path "path" --top-hash hash --registry s3://bucket --dest . +
+
+
+
+ URI + : +
+ +
+ quilt+s3://bucket#package=name@hash&path=path&catalog=catalog +
+
+
+`; diff --git a/catalog/app/containers/Bucket/PackageTree/PackageTree.tsx b/catalog/app/containers/Bucket/PackageTree/PackageTree.tsx index 5bb2008ef65..31052e6574e 100644 --- a/catalog/app/containers/Bucket/PackageTree/PackageTree.tsx +++ b/catalog/app/containers/Bucket/PackageTree/PackageTree.tsx @@ -468,7 +468,14 @@ function DirDisplay({ Ok: ({ ui: { blocks } }) => ( <> {blocks.code && ( - + )} {blocks.meta && ( ( <> {blocks.code && ( - + )} {blocks.meta && ( <> diff --git a/catalog/app/containers/Bucket/Selection/Dashboard.tsx b/catalog/app/containers/Bucket/Selection/Dashboard.tsx index 2a70719c59b..09e7eb2ed0f 100644 --- a/catalog/app/containers/Bucket/Selection/Dashboard.tsx +++ b/catalog/app/containers/Bucket/Selection/Dashboard.tsx @@ -59,6 +59,7 @@ function FileLink({ className, handle, packageHandle }: FileLinkProps) { const packageUri = PackageUri.stringify({ ...packageHandle, path: handle.key, + catalog: window.location.hostname, }) const children = decodeURIComponent( packageUri.slice(0, packageUri.indexOf('@') + 10) + diff --git a/catalog/app/utils/PackageUri.spec.ts b/catalog/app/utils/PackageUri.spec.ts index 3a017d76939..a89594835d9 100644 --- a/catalog/app/utils/PackageUri.spec.ts +++ b/catalog/app/utils/PackageUri.spec.ts @@ -178,5 +178,18 @@ describe('utils/PackageUri', () => { }), ).toBe('quilt+s3://bucket-name#package=quilt/test@abc1&path=sub%2Fpath') }) + it('should work for bucket, name, hash, path & catalog', () => { + expect( + PackageUri.stringify({ + bucket: 'bucket-name', + name: 'quilt/test', + hash: 'abc1', + path: 'sub/path', + catalog: 'quilt-test', + }), + ).toBe( + 'quilt+s3://bucket-name#package=quilt/test@abc1&path=sub%2Fpath&catalog=quilt-test', + ) + }) }) }) diff --git a/catalog/app/utils/PackageUri.ts b/catalog/app/utils/PackageUri.ts index b1722a910c5..940a17f182e 100644 --- a/catalog/app/utils/PackageUri.ts +++ b/catalog/app/utils/PackageUri.ts @@ -19,6 +19,7 @@ export interface PackageUri { path?: string hash?: string tag?: string + catalog?: string } function parsePackageSpec(spec: string, uri: string) { @@ -95,7 +96,7 @@ export function parse(uri: string): PackageUri { return R.reject(R.isNil, { bucket, name, hash, tag, path }) as unknown as PackageUri } -export function stringify({ bucket, name, hash, tag, path }: PackageUri) { +export function stringify({ bucket, name, hash, tag, path, catalog }: PackageUri) { if (!bucket) throw new Error('PackageUri.stringify: missing "bucket"') if (!name) throw new Error('PackageUri.stringify: missing "name"') if (hash && tag) { @@ -108,5 +109,6 @@ export function stringify({ bucket, name, hash, tag, path }: PackageUri) { pkgSpec += `:${tag}` } const pathPart = path ? `&path=${encodeURIComponent(path)}` : '' - return `quilt+s3://${bucket}#package=${pkgSpec}${pathPart}` + const catalogPart = catalog ? `&catalog=${encodeURIComponent(catalog)}` : '' + return `quilt+s3://${bucket}#package=${pkgSpec}${pathPart}${catalogPart}` } diff --git a/docs/Catalog/URI.md b/docs/Catalog/URI.md index 1f0ff4e36f8..8b31078d5b1 100644 --- a/docs/Catalog/URI.md +++ b/docs/Catalog/URI.md @@ -50,3 +50,6 @@ A Quilt+ URI contains the following components: - `&path=`: An optional fragment after the package, specifying the path to a particular subpackage (i.e., folder or entry) within the package. This is always a relative path, e.g. `CORD19.ipynb` in the example. +- `&catalog=`: An optional fragment specifying the DNS name of the + catalog that generated the URI. This is used to help clients generate the + human-readable URL for that package.