Style face action modal content
This commit is contained in:
parent
6b5cd89db3
commit
e59e0f57d3
|
@ -1,7 +1,15 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Input, Pagination, Table } from 'semantic-ui-react'
|
||||
import styled from 'styled-components'
|
||||
import { TextField } from '../../../primitives/form/Input'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHeader,
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
} from '../../../primitives/Table'
|
||||
import FaceCircleImage from '../FaceCircleImage'
|
||||
import { myFaces_myFaceGroups } from '../__generated__/myFaces'
|
||||
import { singleFaceGroup_faceGroup } from './__generated__/singleFaceGroup'
|
||||
|
@ -13,7 +21,7 @@ const FaceCircleWrapper = styled.div<{ $selected: boolean }>`
|
|||
${({ $selected }) => ($selected ? `#2185c9` : 'rgba(255,255,255,0)')};
|
||||
`
|
||||
|
||||
const FlexCell = styled(Table.Cell)`
|
||||
const FlexCell = styled(TableCell)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`
|
||||
|
@ -21,6 +29,7 @@ const FlexCell = styled(Table.Cell)`
|
|||
export const RowLabel = styled.span<{ $selected: boolean }>`
|
||||
${({ $selected }) => $selected && `font-weight: bold;`}
|
||||
margin-left: 12px;
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
type FaceGroupRowProps = {
|
||||
|
@ -35,7 +44,7 @@ const FaceGroupRow = ({
|
|||
setFaceSelected,
|
||||
}: FaceGroupRowProps) => {
|
||||
return (
|
||||
<Table.Row key={faceGroup.id} onClick={setFaceSelected}>
|
||||
<TableRow key={faceGroup.id} onClick={setFaceSelected}>
|
||||
<FlexCell>
|
||||
<FaceCircleWrapper $selected={faceSelected}>
|
||||
<FaceCircleImage
|
||||
|
@ -44,9 +53,15 @@ const FaceGroupRow = ({
|
|||
selectable={false}
|
||||
/>
|
||||
</FaceCircleWrapper>
|
||||
<RowLabel $selected={faceSelected}>{faceGroup.label}</RowLabel>
|
||||
<span
|
||||
className={`ml-3 ${faceSelected ? 'font-semibold' : ''} ${
|
||||
!faceGroup.label ? 'text-gray-500 italic' : ''
|
||||
}`}
|
||||
>
|
||||
{faceGroup.label ?? 'Unlabeled'}
|
||||
</span>
|
||||
</FlexCell>
|
||||
</Table.Row>
|
||||
</TableRow>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -69,14 +84,14 @@ const SelectFaceGroupTable = ({
|
|||
}: SelectFaceGroupTableProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const PAGE_SIZE = 6
|
||||
// const PAGE_SIZE = 6
|
||||
|
||||
const [page, setPage] = useState(0)
|
||||
// const [page, setPage] = useState(0)
|
||||
const [searchValue, setSearchValue] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
setPage(0)
|
||||
}, [searchValue])
|
||||
// useEffect(() => {
|
||||
// setPage(0)
|
||||
// }, [searchValue])
|
||||
|
||||
const rows = faceGroups
|
||||
.filter(
|
||||
|
@ -93,55 +108,38 @@ const SelectFaceGroupTable = ({
|
|||
/>
|
||||
))
|
||||
|
||||
const pageRows = rows.filter(
|
||||
(_, i) => i >= page * PAGE_SIZE && i < (page + 1) * PAGE_SIZE
|
||||
)
|
||||
// const pageRows = rows.filter(
|
||||
// (_, i) => i >= page * PAGE_SIZE && i < (page + 1) * PAGE_SIZE
|
||||
// )
|
||||
|
||||
return (
|
||||
<Table selectable>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>{title}</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>
|
||||
<Input
|
||||
value={searchValue}
|
||||
onChange={e => setSearchValue(e.target.value)}
|
||||
icon="search"
|
||||
placeholder={t(
|
||||
'people_page.table.select_face_group.search_faces_placeholder',
|
||||
'Search faces...'
|
||||
)}
|
||||
fluid
|
||||
/>
|
||||
</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>{pageRows}</Table.Body>
|
||||
<Table.Footer>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>
|
||||
<Pagination
|
||||
floated="right"
|
||||
firstItem={null}
|
||||
lastItem={null}
|
||||
// nextItem={null}
|
||||
// prevItem={null}
|
||||
activePage={page + 1}
|
||||
totalPages={Math.ceil(rows.length / PAGE_SIZE)}
|
||||
onPageChange={(_, { activePage }) => {
|
||||
if (activePage) {
|
||||
setPage(Math.ceil(activePage as number) - 1)
|
||||
} else {
|
||||
setPage(0)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Footer>
|
||||
</Table>
|
||||
<>
|
||||
<Table className="w-full">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHeaderCell>{title}</TableHeaderCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHeaderCell>
|
||||
<TextField
|
||||
fullWidth
|
||||
value={searchValue}
|
||||
onChange={e => setSearchValue(e.target.value)}
|
||||
placeholder={t(
|
||||
'people_page.tableselect_face_group.search_faces_placeholder',
|
||||
'Search faces...'
|
||||
)}
|
||||
/>
|
||||
</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
</Table>
|
||||
<div className="overflow-auto max-h-[500px] mt-2">
|
||||
<Table className="w-full">
|
||||
<TableBody>{rows}</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Checkbox, Input, Pagination, Table } from 'semantic-ui-react'
|
||||
import styled from 'styled-components'
|
||||
import { ProtectedImage } from '../../../components/photoGallery/ProtectedMedia'
|
||||
import Checkbox from '../../../primitives/form/Checkbox'
|
||||
import { TextField } from '../../../primitives/form/Input'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHeader,
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
} from '../../../primitives/Table'
|
||||
import { myFaces_myFaceGroups_imageFaces } from '../__generated__/myFaces'
|
||||
import { RowLabel } from './SelectFaceGroupTable'
|
||||
import { singleFaceGroup_faceGroup_imageFaces } from './__generated__/singleFaceGroup'
|
||||
|
||||
const SelectImagePreview = styled(ProtectedImage)`
|
||||
|
@ -26,22 +34,21 @@ const ImageFaceRow = ({
|
|||
setFaceSelected,
|
||||
}: ImageFaceRowProps) => {
|
||||
return (
|
||||
<Table.Row key={imageFace.id}>
|
||||
<Table.Cell>
|
||||
<Checkbox checked={faceSelected} onChange={setFaceSelected} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<TableRow key={imageFace.id}>
|
||||
<TableCell>
|
||||
<SelectImagePreview
|
||||
src={imageFace.media.thumbnail?.url}
|
||||
onClick={setFaceSelected}
|
||||
/>
|
||||
</Table.Cell>
|
||||
<Table.Cell width={16}>
|
||||
<RowLabel $selected={faceSelected} onClick={setFaceSelected}>
|
||||
{imageFace.media.title}
|
||||
</RowLabel>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</TableCell>
|
||||
<TableCell className="min-w-64 w-full">
|
||||
<Checkbox
|
||||
label={imageFace.media.title}
|
||||
checked={faceSelected}
|
||||
onChange={setFaceSelected}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -70,14 +77,14 @@ const SelectImageFacesTable = ({
|
|||
}: SelectImageFacesTable) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const PAGE_SIZE = 6
|
||||
// const PAGE_SIZE = 6
|
||||
|
||||
const [page, setPage] = useState(0)
|
||||
// const [page, setPage] = useState(0)
|
||||
const [searchValue, setSearchValue] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
setPage(0)
|
||||
}, [searchValue])
|
||||
// useEffect(() => {
|
||||
// setPage(0)
|
||||
// }, [searchValue])
|
||||
|
||||
const rows = imageFaces
|
||||
.filter(
|
||||
|
@ -102,55 +109,38 @@ const SelectImageFacesTable = ({
|
|||
/>
|
||||
))
|
||||
|
||||
const pageRows = rows.filter(
|
||||
(_, i) => i >= page * PAGE_SIZE && i < (page + 1) * PAGE_SIZE
|
||||
)
|
||||
// const pageRows = rows.filter(
|
||||
// (_, i) => i >= page * PAGE_SIZE && i < (page + 1) * PAGE_SIZE
|
||||
// )
|
||||
|
||||
return (
|
||||
<Table selectable>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell colSpan={3}>{title}</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell colSpan={3}>
|
||||
<Input
|
||||
value={searchValue}
|
||||
onChange={e => setSearchValue(e.target.value)}
|
||||
icon="search"
|
||||
placeholder={t(
|
||||
'people_page.table.select_image_faces.search_images_placeholder',
|
||||
'Search images...'
|
||||
)}
|
||||
fluid
|
||||
/>
|
||||
</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>{pageRows}</Table.Body>
|
||||
<Table.Footer>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell colSpan={3}>
|
||||
<Pagination
|
||||
floated="right"
|
||||
firstItem={null}
|
||||
lastItem={null}
|
||||
// nextItem={null}
|
||||
// prevItem={null}
|
||||
activePage={page + 1}
|
||||
totalPages={Math.ceil(rows.length / PAGE_SIZE)}
|
||||
onPageChange={(_, { activePage }) => {
|
||||
if (activePage) {
|
||||
setPage(Math.ceil(activePage as number) - 1)
|
||||
} else {
|
||||
setPage(0)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Footer>
|
||||
</Table>
|
||||
<>
|
||||
<Table className="w-full">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHeaderCell colSpan={2}>{title}</TableHeaderCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHeaderCell colSpan={2}>
|
||||
<TextField
|
||||
value={searchValue}
|
||||
onChange={e => setSearchValue(e.target.value)}
|
||||
placeholder={t(
|
||||
'people_page.tableselect_image_faces.search_images_placeholder',
|
||||
'Search images...'
|
||||
)}
|
||||
fullWidth
|
||||
/>
|
||||
</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
</Table>
|
||||
<div className="overflow-auto max-h-[500px] mt-2">
|
||||
<Table>
|
||||
<TableBody>{rows}</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { createContext, useContext, useEffect, useState } from 'react'
|
||||
import { FocusScope } from '@react-aria/focus'
|
||||
|
||||
export type UpdateSidebarFn = (content: React.ReactNode) => void
|
||||
export type SidebarPinnedFn = (pin: boolean) => void
|
||||
|
@ -96,11 +95,7 @@ export const Sidebar = () => {
|
|||
pinned ? 'lg:border-l' : 'lg:shadow-separator'
|
||||
} lg:w-[420px] lg:right-0 lg:top-0 lg:z-40`}
|
||||
>
|
||||
{content && (
|
||||
<FocusScope contain={!pinned} restoreFocus={!pinned} autoFocus>
|
||||
{content}
|
||||
</FocusScope>
|
||||
)}
|
||||
{content}
|
||||
<div className="h-24"></div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -46,8 +46,8 @@ const Modal = ({
|
|||
<div className="flex items-center justify-center min-h-screen">
|
||||
<Dialog.Overlay className="fixed inset-0 bg-black opacity-30" />
|
||||
|
||||
<div className="fixed bg-white rounded max-w-[calc(100%-16px)] mx-auto rounded shadow-md border">
|
||||
<div className="p-2">
|
||||
<div className="fixed bg-white max-w-[calc(100%-16px)] mx-auto rounded shadow-md border">
|
||||
<div className="p-4">
|
||||
<Dialog.Title className="text-xl mb-1">{title}</Dialog.Title>
|
||||
<Dialog.Description className="text-sm mb-4">
|
||||
{description}
|
||||
|
|
|
@ -26,14 +26,14 @@ export const TableHeader = styled.thead.attrs({
|
|||
className: 'text-left',
|
||||
})``
|
||||
|
||||
export const TableBody = styled.tbody.attrs({ className: '' })``
|
||||
export const TableBody = styled.tbody.attrs({ className: '' as string })``
|
||||
|
||||
export const TableFooter = styled.tfoot.attrs({ className: '' })``
|
||||
export const TableFooter = styled.tfoot.attrs({ className: '' as string })``
|
||||
|
||||
export const TableRow = styled.tr.attrs({ className: '' })``
|
||||
export const TableRow = styled.tr.attrs({ className: '' as string })``
|
||||
|
||||
export const TableCell = styled.td.attrs({
|
||||
className: 'py-2 px-2 align-top',
|
||||
className: 'py-2 px-2 align-top' as string,
|
||||
})``
|
||||
|
||||
export const TableHeaderCell = styled.th.attrs({
|
||||
|
@ -41,5 +41,5 @@ export const TableHeaderCell = styled.th.attrs({
|
|||
})``
|
||||
|
||||
export const TableScrollWrapper = styled.div.attrs({
|
||||
className: 'block overflow-x-auto whitespace-nowrap',
|
||||
className: 'block overflow-x-auto whitespace-nowrap' as string,
|
||||
})``
|
||||
|
|
Loading…
Reference in New Issue