Skip to content

Commit

Permalink
Selective metadata packages list (#2941)
Browse files Browse the repository at this point in the history
  • Loading branch information
fiskus committed Jul 21, 2022
1 parent c26dfc4 commit 45c12dc
Show file tree
Hide file tree
Showing 8 changed files with 448 additions and 61 deletions.
192 changes: 149 additions & 43 deletions catalog/app/containers/Bucket/PackageList/PackageList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as dateFns from 'date-fns'
import * as jsonpath from 'jsonpath'
import * as R from 'ramda'
import * as React from 'react'
import * as RRDom from 'react-router-dom'
Expand All @@ -18,6 +19,7 @@ import * as Format from 'utils/format'
import parseSearch from 'utils/parseSearch'
import mkStorage from 'utils/storage'
import { readableQuantity } from 'utils/string'
import { JsonRecord } from 'utils/types'
import useDebouncedInput from 'utils/useDebouncedInput'
import usePrevious from 'utils/usePrevious'
import useQuery from 'utils/useQuery'
Expand Down Expand Up @@ -136,10 +138,123 @@ function Counts({ counts, total }: CountsProps) {
)
}

const usePackageStyles = M.makeStyles((t) => ({
root: {
const useRevisionAttributesStyles = M.makeStyles((t) => ({
revisionsNumber: {
...t.typography.subtitle2,
color: t.palette.text.secondary,
position: 'relative',
},
updated: {
...t.typography.body2,
color: t.palette.text.secondary,
position: 'relative',
marginLeft: t.spacing(2),
},
}))

interface RevisionAttributesProps {
className: string
revisions: {
total: number
}
modified: Date
}

function RevisionAttributes({ className, modified, revisions }: RevisionAttributesProps) {
const classes = useRevisionAttributesStyles()
const t = M.useTheme()
const xs = M.useMediaQuery(t.breakpoints.down('xs'))
return (
<div className={className}>
<span className={classes.revisionsNumber}>
{revisions.total}{' '}
{xs ? (
'Rev.'
) : (
<Format.Plural value={revisions.total} one="Revision" other="Revisions" />
)}
</span>
<span
className={classes.updated}
title={modified ? modified.toString() : undefined}
>
{xs ? 'Upd. ' : 'Updated '}
{modified ? <Format.Relative value={modified} /> : '[unknown: see console]'}
</span>
</div>
)
}

const useRevisionMetaStyles = M.makeStyles((t) => ({
root: {
borderTop: `1px solid ${t.palette.divider}`,
padding: t.spacing(2),
...t.typography.body2,
color: t.palette.text.secondary,
},
section: {
'& + &': {
marginTop: t.spacing(1),
},
},
tag: {
'& + &': {
marginLeft: t.spacing(1),
},
},
}))

interface RevisionMetaProps {
sections: (string | string[])[]
}

function RevisionMeta({ sections }: RevisionMetaProps) {
const classes = useRevisionMetaStyles()

return (
<div className={classes.root}>
{sections.map((section, i) => (
<div className={classes.section} key={`${i}+${section}`}>
{Array.isArray(section)
? section.map((label, j) => (
<M.Chip
className={classes.tag}
label={label}
key={`${j}+${label}`}
size="small"
variant="outlined"
/>
))
: section}
</div>
))}
</div>
)
}

function usePackageMeta(
name: string,
revision: { message: string | null; userMeta: JsonRecord | null } | null,
): (string | string[])[] {
// TODO: move visible meta calculation to the graphql
const preferences = BucketPreferences.use()
return React.useMemo(() => {
const { message, userMeta } =
preferences?.ui.packages[name] || preferences?.ui.packages['*'] || {}
const output = []
if (message && revision?.message) output.push(revision.message)
if (userMeta && revision?.userMeta)
userMeta.forEach((jPath) => {
const section = jsonpath.value(revision.userMeta, jPath)
if (typeof section === 'string') output.push(section)
if (Array.isArray(section)) output.push(section.filter(R.is(String)))
})
return output
}, [name, preferences, revision])
}

const usePackageStyles = M.makeStyles((t) => ({
root: {
[t.breakpoints.down('xs')]: {
borderRadius: 0,
},
Expand All @@ -148,15 +263,17 @@ const usePackageStyles = M.makeStyles((t) => ({
marginTop: t.spacing(1),
},
},
base: {
padding: t.spacing(2),
position: 'relative',
},
handleContainer: {
WebkitBoxOrient: 'vertical',
WebkitLineClamp: 2,
display: '-webkit-box',
overflow: 'hidden',
overflowWrap: 'break-word',
paddingLeft: t.spacing(2),
paddingRight: t.spacing(21),
paddingTop: t.spacing(2),
textOverflow: 'ellipsis',
},
handle: {
Expand All @@ -178,57 +295,46 @@ const usePackageStyles = M.makeStyles((t) => ({
background: t.palette.action.hover,
},
},
revisions: {
...t.typography.subtitle2,
color: t.palette.text.secondary,
position: 'relative',
},
updated: {
...t.typography.body2,
color: t.palette.text.secondary,
position: 'relative',
attributes: {
marginTop: t.spacing(1),
},
}))

type PackageProps = NonNullable<
ResultOf<typeof PACKAGE_LIST_QUERY>['packages']
>['page'][number]

function Package({ name, modified, revisions, bucket, accessCounts }: PackageProps) {
function Package({
name,
modified,
revisions,
bucket,
accessCounts,
revision,
}: PackageProps) {
const { urls } = NamedRoutes.use()
const classes = usePackageStyles()
const t = M.useTheme()
const xs = M.useMediaQuery(t.breakpoints.down('xs'))
const meta = usePackageMeta(name, revision)
return (
<M.Paper className={classes.root}>
<div className={classes.handleContainer}>
<RRDom.Link
className={classes.handle}
to={urls.bucketPackageDetail(bucket, name)}
>
<span className={classes.handleClickArea} />
<span className={classes.handleText}>{name}</span>
</RRDom.Link>
<div className={classes.base}>
<div className={classes.handleContainer}>
<RRDom.Link
className={classes.handle}
to={urls.bucketPackageDetail(bucket, name)}
>
<span className={classes.handleClickArea} />
<span className={classes.handleText}>{name}</span>
</RRDom.Link>
</div>
<RevisionAttributes
className={classes.attributes}
modified={modified}
revisions={revisions}
/>
{!!accessCounts && <Counts {...accessCounts} />}
</div>
<M.Box pl={2} pb={2} pt={1}>
<span className={classes.revisions}>
{revisions.total}{' '}
{xs ? (
'Rev.'
) : (
<Format.Plural value={revisions.total} one="Revision" other="Revisions" />
)}
</span>
<M.Box mr={2} component="span" />
<span
className={classes.updated}
title={modified ? modified.toString() : undefined}
>
{xs ? 'Upd. ' : 'Updated '}
{modified ? <Format.Relative value={modified} /> : '[unknown: see console]'}
</span>
</M.Box>
{!!accessCounts && <Counts {...accessCounts} />}
{!!meta && !!meta.length && <RevisionMeta sections={meta} />}
</M.Paper>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ export type containers_Bucket_PackageList_gql_PackageListQuery = {
>
}
>
readonly revision: Types.Maybe<
{ readonly __typename: 'PackageRevision' } & Pick<
Types.PackageRevision,
'message' | 'userMeta'
>
>
}
>
}
Expand Down Expand Up @@ -179,6 +185,17 @@ export const containers_Bucket_PackageList_gql_PackageListDocument = {
],
},
},
{
kind: 'Field',
name: { kind: 'Name', value: 'revision' },
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'message' } },
{ kind: 'Field', name: { kind: 'Name', value: 'userMeta' } },
],
},
},
],
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ query (
value
}
}
revision {
message
userMeta
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const expectedDefaults = {
packages: true,
queries: true,
},
packages: {},
sourceBuckets: {
list: [],
},
Expand Down
37 changes: 36 additions & 1 deletion catalog/app/utils/BucketPreferences/BucketPreferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ type BlocksPreferences = Record<'analytics' | 'browser' | 'code' | 'meta', boole

export type NavPreferences = Record<'files' | 'packages' | 'queries', boolean>

interface PackagePreferencesInput {
message?: true
user_meta?: ReadonlyArray<string>
}
interface PackagePreferences {
message?: true
userMeta?: ReadonlyArray<string>
}
type PackagesListPreferencesInput = Record<string, PackagePreferencesInput>
type PackagesListPreferences = Record<string, PackagePreferences>

type DefaultSourceBucketInput = string
type SourceBucketsInput = Record<string, null>

Expand All @@ -25,6 +36,7 @@ interface UiPreferencesInput {
blocks?: Partial<BlocksPreferences>
defaultSourceBucket?: DefaultSourceBucketInput
nav?: Partial<NavPreferences>
packages?: PackagesListPreferencesInput
sourceBuckets?: SourceBucketsInput
}

Expand All @@ -41,6 +53,7 @@ interface UiPreferences {
actions: ActionPreferences
blocks: BlocksPreferences
nav: NavPreferences
packages: PackagesListPreferences
sourceBuckets: SourceBuckets
}

Expand Down Expand Up @@ -68,6 +81,11 @@ const defaultPreferences: BucketPreferences = {
packages: true,
queries: true,
},
packages: {
'*': {
message: true,
},
},
sourceBuckets: {
getDefault: () => '',
list: [],
Expand All @@ -86,6 +104,19 @@ function validate(data: unknown): asserts data is BucketPreferencesInput {
if (errors.length) throw new bucketErrors.BucketPreferencesInvalid({ errors })
}

function parsePackages(packages?: PackagesListPreferencesInput): PackagesListPreferences {
return Object.entries(packages || {}).reduce(
(memo, [name, { message, user_meta }]) => ({
...memo,
[name]: {
message,
userMeta: user_meta,
},
}),
defaultPreferences.ui.packages,
)
}

function parseSourceBuckets(
sentry: SentryInstance,
sourceBuckets?: SourceBucketsInput,
Expand All @@ -110,10 +141,14 @@ function parseSourceBuckets(
}
}

export function extendDefaults(data: BucketPreferencesInput, sentry: SentryInstance) {
export function extendDefaults(
data: BucketPreferencesInput,
sentry: SentryInstance,
): BucketPreferences {
return {
ui: {
...R.mergeDeepRight(defaultPreferences.ui, data?.ui || {}),
packages: parsePackages(data?.ui?.packages),
sourceBuckets: parseSourceBuckets(
sentry,
data?.ui?.sourceBuckets,
Expand Down
Loading

0 comments on commit 45c12dc

Please sign in to comment.