From df22d445ede3758d30ae4f17a0c9fa23873bfdf1 Mon Sep 17 00:00:00 2001 From: Maksim Chervonnyi Date: Mon, 16 Sep 2024 19:02:14 +0200 Subject: [PATCH] redesign form cards using accordion --- .github/workflows/deploy-catalog.yaml | 1 + .../app/containers/Admin/Buckets/Buckets.tsx | 299 ++++++++++-------- .../Admin/Buckets/LongQueryConfig.tsx | 6 +- 3 files changed, 169 insertions(+), 137 deletions(-) diff --git a/.github/workflows/deploy-catalog.yaml b/.github/workflows/deploy-catalog.yaml index 250f30ed2f8..639f70eb154 100644 --- a/.github/workflows/deploy-catalog.yaml +++ b/.github/workflows/deploy-catalog.yaml @@ -5,6 +5,7 @@ on: branches: - master - admin-bucket-page-long-query-config + - admin-bucket-page-long-query-config-redesign paths: - '.github/workflows/deploy-catalog.yaml' - 'catalog/**' diff --git a/catalog/app/containers/Admin/Buckets/Buckets.tsx b/catalog/app/containers/Admin/Buckets/Buckets.tsx index 4805a9a92b3..ccf39fad4ef 100644 --- a/catalog/app/containers/Admin/Buckets/Buckets.tsx +++ b/catalog/app/containers/Admin/Buckets/Buckets.tsx @@ -11,6 +11,7 @@ import useResizeObserver from 'use-resize-observer' import * as M from '@material-ui/core' import * as Lab from '@material-ui/lab' +import bucketIcon from 'components/BucketIcon/bucket.svg' import * as Buttons from 'components/Buttons' import * as Dialog from 'components/Dialog' import JsonDisplay from 'components/JsonDisplay' @@ -73,62 +74,97 @@ interface CardAvatarProps { } function CardAvatar({ className, src }: CardAvatarProps) { - if (src.startsWith('http')) return + if (src.startsWith('http') || src.startsWith('data')) { + return ( + + ) + } return {src} } const useCardStyles = M.makeStyles((t) => ({ - avatar: { - display: 'block', + icon: { + marginRight: t.spacing(2), }, header: { paddingBottom: t.spacing(1), }, content: { paddingTop: 0, - '& > * + *': { + '& > *': { marginTop: t.spacing(1), }, }, + form: { + padding: t.spacing(0, 5), + flexGrow: 1, + }, + summaryInner: { + flexGrow: 1, + '&:empty': { + display: 'none', + }, + }, + summary: { + alignItems: 'flex-start', + cursor: 'default', + }, })) interface CardProps { + actions?: React.ReactNode children?: React.ReactNode className?: string disabled?: boolean + editing: boolean + form: React.ReactNode icon?: string | null - onEdit?: () => void - subTitle?: string - title: React.ReactNode + onEdit: (ex: boolean) => void + title: string } function Card({ + actions, children, className, disabled, + editing, + form, icon, onEdit, - subTitle, title, }: CardProps) { const classes = useCardStyles() return ( - - - edit - - ) - } - avatar={icon && } - className={classes.header} - subheader={subTitle} - title={title} - /> - {children && {children}} - + onEdit(ex)} + disabled={disabled} + > + {editing ? 'close' : 'edit'}} + > + {icon && } +
+ {title} + {!editing && !!children && ( +
event.stopPropagation()}> + {children} +
+ )} +
+
+ +
{form}
+
+ {actions && {actions}} +
) } @@ -572,20 +608,11 @@ function Hint({ children }: HintProps) { ) } -const useInlineActionsStyles = M.makeStyles((t) => ({ - actions: { - display: 'flex', - justifyContent: 'flex-end', - padding: t.spacing(2, 0, 0), - '& > * + *': { - // Spacing between direct children - marginLeft: t.spacing(2), - }, - }, +const useInlineActionsStyles = M.makeStyles({ error: { flexGrow: 1, }, -})) +}) interface InlineActionsProps { form: FF.FormApi @@ -600,7 +627,7 @@ function InlineActions({ form, onCancel }: InlineActionsProps) { onCancel() }, [form, onCancel]) return ( -
+ <> {state.submitFailed && ( Save -
+ ) } @@ -680,21 +707,12 @@ function InlineForm({ className, children, title }: InlineFormProps) { interface PrimaryFormProps { bucket?: BucketConfig className?: string - children?: React.ReactNode } -function PrimaryForm({ bucket, children, className }: PrimaryFormProps) { +function PrimaryForm({ bucket, className }: PrimaryFormProps) { return ( - - {bucket ? ( - - ) : ( +
+ {!bucket && ( - {children} - +
) } @@ -763,22 +780,18 @@ interface PrimaryCardProps { function PrimaryCard({ className, bucket, form }: PrimaryCardProps) { const [editing, setEditing] = React.useState(false) - if (editing) { - return ( - - setEditing(false)} /> - - ) - } return ( } + actions={ setEditing(false)} />} className={className} disabled={form.getState().submitting} - icon={bucket.iconUrl || undefined} - onEdit={() => setEditing(true)} - subTitle={`s3://${bucket.name}`} - title={bucket.title} + icon={bucket.iconUrl || bucketIcon} + onEdit={setEditing} + title={editing ? `s3://${bucket.name}` : bucket.title} + editing={editing} > + {`s3://${bucket.name}`} {bucket.description && ( {bucket.description} )} @@ -787,13 +800,12 @@ function PrimaryCard({ className, bucket, form }: PrimaryCardProps) { } interface MetadataFormProps { - children?: React.ReactNode - className: string + className?: string } -function MetadataForm({ children, className }: MetadataFormProps) { +function MetadataForm({ className }: MetadataFormProps) { return ( - +
- {children} - +
) } @@ -860,6 +870,16 @@ const useMetadataCardStyles = M.makeStyles((t) => ({ marginLeft: t.spacing(0.5), }, }, + content: { + flexDirection: 'column', + }, + form: { + flexGrow: 1, + }, + actions: { + padding: 0, + display: 'block', + }, })) interface MetadataCardProps { @@ -871,20 +891,16 @@ interface MetadataCardProps { function MetadataCard({ bucket, className, form }: MetadataCardProps) { const classes = useMetadataCardStyles() const [editing, setEditing] = React.useState(false) - if (editing) { - return ( - - setEditing(false)} /> - - ) - } return ( setEditing(true)} + onEdit={setEditing} title="Metadata" + form={} + actions={ setEditing(false)} />} > {bucket.description && ( {bucket.description} @@ -928,22 +944,20 @@ function MetadataCard({ bucket, className, form }: MetadataCardProps) { interface IndexingAndNotificationsFormProps { bucket?: BucketConfig - children?: React.ReactNode - className: string + className?: string reindex?: () => void settings: Model.GQLTypes.ContentIndexingSettings } function IndexingAndNotificationsForm({ bucket, - children, className, reindex, settings, }: IndexingAndNotificationsFormProps) { const classes = useIndexingAndNotificationsFormStyles() return ( - +
{!!reindex && ( @@ -1108,8 +1122,7 @@ function IndexingAndNotificationsForm({ /> )} - {children} - +
) } @@ -1142,25 +1155,22 @@ function IndexingAndNotificationsCard({ const data = GQL.useQueryS(CONTENT_INDEXING_SETTINGS_QUERY) const settings = data.config.contentIndexingSettings - if (editing) { - return ( - - setEditing(false)} /> - - ) - } - const { enableDeepIndexing, snsNotificationArn } = bucketToFormValues(bucket) return ( + } + actions={ setEditing(false)} />} + editing={editing} className={className} disabled={form.getState().submitting} - onEdit={() => setEditing(true)} + onEdit={setEditing} icon="find_in_page" title="Indexing and notifications" > @@ -1226,16 +1236,14 @@ function IndexingAndNotificationsCard({ } interface PreviewFormProps { - children?: React.ReactNode - className: string + className?: string } -function PreviewForm({ children, className }: PreviewFormProps) { +function PreviewForm({ className }: PreviewFormProps) { return ( - +
- {children} - +
) } @@ -1247,20 +1255,18 @@ interface PreviewCardProps { function PreviewCard({ bucket, className, form }: PreviewCardProps) { const [editing, setEditing] = React.useState(false) - if (editing) { - return ( - - setEditing(false)} /> - - ) - } return ( } + actions={ setEditing(false)} />} + editing={editing} className={className} disabled={form.getState().submitting} - onEdit={() => setEditing(true)} + onEdit={setEditing} icon="code" - title={`Permissive HTML rendering is ${bucket.browsable ? 'enabled' : 'disabled'}`} + title={`Permissive HTML rendering${ + editing ? '' : ` is ${bucket.browsable ? 'enabled' : 'disabled'}` + }`} /> ) } @@ -1287,22 +1293,19 @@ function LongQueryConfigCard({ tabulatorTables, }: LongQueryConfigCardProps) { const [editing, setEditing] = React.useState(false) - if (editing) { - return ( - + return ( + setEditing(false)} tabulatorTables={tabulatorTables} /> - - ) - } - return ( - setEditing(true)} + onEdit={setEditing} icon="query_builder" title={ tabulatorTables.length @@ -1320,6 +1323,17 @@ function LongQueryConfigCard({ const useStyles = M.makeStyles((t) => ({ card: { + marginTop: t.spacing(1), + '&:first-child': { + marginTop: 0, + }, + }, + formTitle: { + ...t.typography.h6, + marginBottom: t.spacing(2), + }, + form: { + padding: t.spacing(2), '& + &': { marginTop: t.spacing(2), }, @@ -1463,19 +1477,30 @@ function Add({ back, settings, submit }: AddProps) { Add a bucket
-
- - - - + + + + + + Metadata + + + + + Indexing and notifications + + + + + + + + + Longitudal query configs will be available after creating the bucket + + - - Longitudal query configs will be available after creating the bucket -
{submitFailed && ( @@ -1658,7 +1683,13 @@ interface BucketFieldSkeletonProps { } function BucketFieldSkeleton({ className, width }: BucketFieldSkeletonProps) { - return } /> + return ( + + + + + + ) } interface CardsPlaceholderProps { diff --git a/catalog/app/containers/Admin/Buckets/LongQueryConfig.tsx b/catalog/app/containers/Admin/Buckets/LongQueryConfig.tsx index bee2b783d41..bf62e394830 100644 --- a/catalog/app/containers/Admin/Buckets/LongQueryConfig.tsx +++ b/catalog/app/containers/Admin/Buckets/LongQueryConfig.tsx @@ -319,7 +319,7 @@ const useConfigsStyles = M.makeStyles((t) => ({ marginBottom: t.spacing(3), }, actions: { - marginTop: t.spacing(2), + margin: t.spacing(2, -5, 0), display: 'flex', justifyContent: 'flex-end', padding: t.spacing(2, 0, 0), @@ -342,7 +342,7 @@ export default function Configs({ bucket, tabulatorTables, onClose }: ConfigsPro loadMode('yaml') const [toAdd, setToAdd] = React.useState(tabulatorTables.length === 0) return ( -
+ <> {tabulatorTables.map((tabulatorTable) => (
- + ) }