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.