Skip to content

Commit

Permalink
instrument s3 object route; cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
nl0 committed Aug 14, 2024
1 parent acf1da4 commit 5885d1b
Show file tree
Hide file tree
Showing 11 changed files with 380 additions and 321 deletions.
Original file line number Diff line number Diff line change
@@ -1,42 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`components/Assistant/Model/GlobalTools/navigation NavigableRouteSchema should decode input 1`] = `
{
"name": "search",
"params": {
"buckets": [],
"order": "NEWEST",
"params": {
"filter": [],
"resultType": "p",
"userMetaFilters": [
{
"path": "/author",
"predicate": {
"type": "KeywordEnum",
"value": {
"terms": [
"Aneesh",
"Maksim",
],
},
},
},
],
},
"searchString": "",
},
}
`;

exports[`components/Assistant/Model/GlobalTools/navigation NavigableRouteSchema should decode input 2`] = `
{
"hash": "",
"pathname": "/search",
"search": "o=NEWEST&meta.e%2Fauthor=%22Aneesh%22%2C%22Maksim%22",
}
`;

exports[`components/Assistant/Model/GlobalTools/navigation NavigateSchema produced JSON Schema should match the snapshot 1`] = `
{
"$defs": {
Expand Down Expand Up @@ -667,21 +630,64 @@ exports[`components/Assistant/Model/GlobalTools/navigation NavigateSchema produc
},
{
"additionalProperties": false,
"description": "Bucket root page",
"description": "Bucket overview page",
"properties": {
"name": {
"const": "bucket",
"const": "bucket.overview",
},
"params": {
"$id": "/schemas/{}",
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"bucket": {
"type": "string",
},
{
"type": "array",
},
"required": [
"bucket",
],
"type": "object",
},
},
"required": [
"name",
"params",
],
"type": "object",
},
{
"additionalProperties": false,
"description": "S3 Object (aka File) Detail page",
"properties": {
"name": {
"const": "bucket.object",
},
"params": {
"additionalProperties": false,
"properties": {
"bucket": {
"type": "string",
},
"mode": {
"description": "Contents preview mode",
"title": "Viewing Mode",
"type": "string",
},
"path": {
"description": "a string",
"title": "string & Brand<"S3Path">",
"type": "string",
},
"version": {
"description": "S3 Object Version ID (omit for latest version)",
"title": "Version ID",
"type": "string",
},
},
"required": [
"bucket",
"path",
],
"type": "object",
},
},
"required": [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as Eff from 'effect'
import { JSONSchema, Schema } from '@effect/schema'

import * as nav from './navigation'
Expand All @@ -16,38 +17,67 @@ describe('components/Assistant/Model/GlobalTools/navigation', () => {
})
})
})
describe('NavigableRouteSchema', () => {
it('should decode input', async () => {
const routeInput = {
name: 'search',
params: {
searchString: '',
buckets: [],
order: 'NEWEST',
describe('routes', () => {
const TEST_CASES = [
{
route: {
name: 'search',
params: {
resultType: 'p',
filter: [],
userMetaFilters: [
{
path: '/author',
predicate: {
type: 'KeywordEnum',
value: {
terms: ['Aneesh', 'Maksim'],
searchString: '',
buckets: [],
order: 'NEWEST',
params: {
resultType: 'p',
filter: [],
userMetaFilters: [
{
path: '/author',
predicate: {
type: 'KeywordEnum',
value: {
terms: ['Aneesh', 'Maksim'],
},
},
},
},
],
],
},
},
},
}
const routeDecoded = Schema.decodeUnknownSync(nav.NavigableRouteSchema)(routeInput)
expect(routeDecoded).toMatchSnapshot()
loc: {
pathname: '/search',
search: 'o=NEWEST&meta.e%2Fauthor=%22Aneesh%22%2C%22Maksim%22',
hash: '',
},
},
{
route: {
name: 'bucket.overview',
params: {
bucket: 'test-bucket',
},
},
loc: {
pathname: '/b/test-bucket',
search: '',
hash: '',
},
},
]

const route = nav.routes[routeDecoded.name]
// @ts-expect-error
const loc = await Schema.encodePromise(route.paramsSchema)(routeDecoded.params)
expect(loc).toMatchSnapshot()
})
const encode = Eff.flow(
Schema.decodeUnknown(nav.NavigableRouteSchema),
Eff.Effect.andThen(nav.locationFromRoute),
Eff.Effect.runPromise,
)

for (let i in TEST_CASES) {
const tc = TEST_CASES[i]
describe(`${i + 1}: ${tc.route.name}`, () => {
it('should encode', async () => {
const loc = await encode(tc.route)
expect(loc).toEqual(tc.loc)
})
})
}
})
})
23 changes: 13 additions & 10 deletions catalog/app/components/Assistant/Model/GlobalContext/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as React from 'react'
import * as RR from 'react-router-dom'
import { Schema as S } from '@effect/schema'

import bucketRoutes from 'containers/Bucket/Routes'
import search from 'containers/Search/Route'
import * as ROUTES from 'constants/routes'
import * as Log from 'utils/Logging'
Expand All @@ -21,6 +22,7 @@ const routeList = [
Nav.makeRoute({
name: 'home',
path: ROUTES.home.path,
exact: true,
description: 'Home page',
// searchParams: S.Struct({
// // XXX: passing this param doesn't actually work bc of how it's implemented in
Expand Down Expand Up @@ -92,12 +94,7 @@ const routeList = [
// <UriResolver />
// </Route>
//
Nav.makeRoute({
name: 'bucket',
path: ROUTES.bucketRoot.path,
description: 'Bucket root page',
// XXX: this should hold the bucket name and subroute info (e.g. package vs file view)
}),
...bucketRoutes,
] as const

type KnownRoute = (typeof routeList)[number]
Expand All @@ -114,6 +111,10 @@ export const NavigableRouteSchema = S.Union(

type NavigableRoute = typeof NavigableRouteSchema.Type

export const locationFromRoute = (route: NavigableRoute) =>
// @ts-expect-error
S.encode(routes[route.name].paramsSchema)(route.params)

type History = ReturnType<typeof RR.useHistory>

const WAIT_TIMEOUT = Eff.Duration.seconds(30)
Expand All @@ -128,9 +129,7 @@ const navigate = (
enter: [`to: ${route.name}`, Log.br, 'params:', route.params],
})(
Eff.pipe(
route.params,
// @ts-expect-error
S.encode(routes[route.name].paramsSchema),
locationFromRoute(route),
Eff.Effect.tap((loc) => Eff.Effect.log(`Navigating to location:`, Log.br, loc)),
Eff.Effect.andThen((loc) => Eff.Effect.sync(() => history.push(loc))),
Eff.Effect.andThen(() =>
Expand Down Expand Up @@ -166,7 +165,11 @@ interface Match {
const matchLocation = (loc: typeof Nav.Location.Type): Match | null =>
Eff.pipe(
Eff.Array.findFirst(routeList, (route) =>
RR.matchPath(loc.pathname, { path: route.path, exact: true })
RR.matchPath(loc.pathname, {
path: route.path,
exact: route.exact,
strict: route.strict,
})
? Eff.Option.some(route)
: Eff.Option.none(),
),
Expand Down
24 changes: 20 additions & 4 deletions catalog/app/containers/Bucket/File.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as React from 'react'
import { Link, useHistory, useLocation, useParams } from 'react-router-dom'
import * as M from '@material-ui/core'

import * as Assistant from 'components/Assistant'
import * as BreadCrumbs from 'components/BreadCrumbs'
import * as Buttons from 'components/Buttons'
import * as FileEditor from 'components/FileEditor'
Expand All @@ -30,15 +31,26 @@ import { up, decode, handleToHttpsUri } from 'utils/s3paths'
import { readableBytes, readableQuantity } from 'utils/string'

import FileCodeSamples from './CodeSamples/File'
import * as AssistantContext from './FileAssistantContext'
import FileProperties from './FileProperties'
import * as FileView from './FileView'
import QuratorButton from './Qurator/Button'
import QuratorContext from './Qurator/Context'
import Section from './Section'
import renderPreview from './renderPreview'
import * as requests from './requests'
import { useViewModes, viewModeToSelectOption } from './viewModes'

function SummarizeButton() {
const assist = Assistant.use()
const msg = 'Summarize this document'
return (
<M.IconButton color="primary" onClick={() => assist(msg)} edge="end">
<M.Tooltip title="Summarize and chat with AI">
<M.Icon>assistant</M.Icon>
</M.Tooltip>
</M.IconButton>
)
}

const useVersionInfoStyles = M.makeStyles(({ typography }) => ({
version: {
...linkStyle,
Expand Down Expand Up @@ -84,6 +96,8 @@ function VersionInfo({ bucket, path, version }) {

const data = useData(requests.objectVersions, { s3, bucket, path })

AssistantContext.useVersionsContext(data)

return (
<>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
Expand Down Expand Up @@ -344,6 +358,8 @@ export default function File() {
resetKey,
})

AssistantContext.useCurrentVersionContext(version, objExistsData, versionExistsData)

const objExists = objExistsData.case({
_: () => false,
Ok: requests.ObjectExistence.case({
Expand Down Expand Up @@ -483,7 +499,8 @@ export default function File() {
{cfg.qurator &&
BucketPreferences.Result.match(
{
Ok: ({ ui: { blocks } }) => (blocks.qurator ? <QuratorButton /> : null),
// XXX: only show this when the object exists?
Ok: ({ ui: { blocks } }) => (blocks.qurator ? <SummarizeButton /> : null),
_: () => null,
},
prefs,
Expand Down Expand Up @@ -514,7 +531,6 @@ export default function File() {
{!!cfg.analyticsBucket && !!blocks.analytics && (
<Analytics {...{ bucket, path }} />
)}
{cfg.qurator && <QuratorContext handle={handle} />}
{blocks.meta && (
<>
<FileView.ObjectMeta handle={handle} />
Expand Down
Loading

0 comments on commit 5885d1b

Please sign in to comment.