Sidebar: people section + album path
This commit is contained in:
parent
ca9bb092f9
commit
06fd166483
|
@ -60,6 +60,8 @@ models:
|
||||||
fields:
|
fields:
|
||||||
faceGroup:
|
faceGroup:
|
||||||
resolver: true
|
resolver: true
|
||||||
|
media:
|
||||||
|
resolver: true
|
||||||
FaceRectangle:
|
FaceRectangle:
|
||||||
model: github.com/photoview/photoview/api/graphql/models.FaceRectangle
|
model: github.com/photoview/photoview/api/graphql/models.FaceRectangle
|
||||||
SiteInfo:
|
SiteInfo:
|
||||||
|
|
|
@ -288,6 +288,8 @@ type FaceGroupResolver interface {
|
||||||
ImageFaceCount(ctx context.Context, obj *models.FaceGroup) (int, error)
|
ImageFaceCount(ctx context.Context, obj *models.FaceGroup) (int, error)
|
||||||
}
|
}
|
||||||
type ImageFaceResolver interface {
|
type ImageFaceResolver interface {
|
||||||
|
Media(ctx context.Context, obj *models.ImageFace) (*models.Media, error)
|
||||||
|
|
||||||
FaceGroup(ctx context.Context, obj *models.ImageFace) (*models.FaceGroup, error)
|
FaceGroup(ctx context.Context, obj *models.ImageFace) (*models.FaceGroup, error)
|
||||||
}
|
}
|
||||||
type MediaResolver interface {
|
type MediaResolver interface {
|
||||||
|
@ -2054,6 +2056,7 @@ type MediaEXIF {
|
||||||
flash: Int
|
flash: Int
|
||||||
"An index describing the mode for adjusting the exposure of the image"
|
"An index describing the mode for adjusting the exposure of the image"
|
||||||
exposureProgram: Int
|
exposureProgram: Int
|
||||||
|
"GPS coordinates of where the image was taken"
|
||||||
coordinates: Coordinates
|
coordinates: Coordinates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3892,14 +3895,14 @@ func (ec *executionContext) _ImageFace_media(ctx context.Context, field graphql.
|
||||||
Object: "ImageFace",
|
Object: "ImageFace",
|
||||||
Field: field,
|
Field: field,
|
||||||
Args: nil,
|
Args: nil,
|
||||||
IsMethod: false,
|
IsMethod: true,
|
||||||
IsResolver: false,
|
IsResolver: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
ctx = rctx // use context from middleware stack in children
|
ctx = rctx // use context from middleware stack in children
|
||||||
return obj.Media, nil
|
return ec.resolvers.ImageFace().Media(rctx, obj)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
|
@ -3911,9 +3914,9 @@ func (ec *executionContext) _ImageFace_media(ctx context.Context, field graphql.
|
||||||
}
|
}
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
res := resTmp.(models.Media)
|
res := resTmp.(*models.Media)
|
||||||
fc.Result = res
|
fc.Result = res
|
||||||
return ec.marshalNMedia2githubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐMedia(ctx, field.Selections, res)
|
return ec.marshalNMedia2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐMedia(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _ImageFace_rectangle(ctx context.Context, field graphql.CollectedField, obj *models.ImageFace) (ret graphql.Marshaler) {
|
func (ec *executionContext) _ImageFace_rectangle(ctx context.Context, field graphql.CollectedField, obj *models.ImageFace) (ret graphql.Marshaler) {
|
||||||
|
@ -10692,10 +10695,19 @@ func (ec *executionContext) _ImageFace(ctx context.Context, sel ast.SelectionSet
|
||||||
atomic.AddUint32(&invalids, 1)
|
atomic.AddUint32(&invalids, 1)
|
||||||
}
|
}
|
||||||
case "media":
|
case "media":
|
||||||
out.Values[i] = ec._ImageFace_media(ctx, field, obj)
|
field := field
|
||||||
if out.Values[i] == graphql.Null {
|
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
res = ec._ImageFace_media(ctx, field, obj)
|
||||||
|
if res == graphql.Null {
|
||||||
atomic.AddUint32(&invalids, 1)
|
atomic.AddUint32(&invalids, 1)
|
||||||
}
|
}
|
||||||
|
return res
|
||||||
|
})
|
||||||
case "rectangle":
|
case "rectangle":
|
||||||
out.Values[i] = ec._ImageFace_rectangle(ctx, field, obj)
|
out.Values[i] = ec._ImageFace_rectangle(ctx, field, obj)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
|
|
|
@ -31,6 +31,19 @@ type ImageFace struct {
|
||||||
Rectangle FaceRectangle `gorm:"not null"`
|
Rectangle FaceRectangle `gorm:"not null"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *ImageFace) FillMedia(db *gorm.DB) error {
|
||||||
|
if f.Media.ID != 0 {
|
||||||
|
// media already exists
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Model(&f).Association("Media").Find(&f.Media); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type FaceDescriptor face.Descriptor
|
type FaceDescriptor face.Descriptor
|
||||||
|
|
||||||
// GormDataType datatype used in database
|
// GormDataType datatype used in database
|
||||||
|
|
|
@ -46,6 +46,14 @@ func (r imageFaceResolver) FaceGroup(ctx context.Context, obj *models.ImageFace)
|
||||||
return &faceGroup, nil
|
return &faceGroup, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r imageFaceResolver) Media(ctx context.Context, obj *models.ImageFace) (*models.Media, error) {
|
||||||
|
if err := obj.FillMedia(r.Database); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &obj.Media, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r faceGroupResolver) ImageFaces(ctx context.Context, obj *models.FaceGroup, paginate *models.Pagination) ([]*models.ImageFace, error) {
|
func (r faceGroupResolver) ImageFaces(ctx context.Context, obj *models.FaceGroup, paginate *models.Pagination) ([]*models.ImageFace, error) {
|
||||||
user := auth.UserFromContext(ctx)
|
user := auth.UserFromContext(ctx)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
"react-test-renderer": "^17.0.2",
|
"react-test-renderer": "^17.0.2",
|
||||||
"styled-components": "^5.3.0",
|
"styled-components": "^5.3.0",
|
||||||
"subscriptions-transport-ws": "^0.9.19",
|
"subscriptions-transport-ws": "^0.9.19",
|
||||||
|
"tailwind-override": "^0.2.3",
|
||||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4",
|
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4",
|
||||||
"typescript": "^4.3.5",
|
"typescript": "^4.3.5",
|
||||||
"url-join": "^4.0.1"
|
"url-join": "^4.0.1"
|
||||||
|
@ -24041,6 +24042,11 @@
|
||||||
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
|
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tailwind-override": {
|
||||||
|
"version": "0.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwind-override/-/tailwind-override-0.2.3.tgz",
|
||||||
|
"integrity": "sha512-psWRqXL3TiI2h/YtzRq7dwKO6N7CrsEs4v99rNHgqEclfx4IioM0cHZ9O6pzerV3E6bZi6DhCbeq0z67Xs5PIQ=="
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"name": "@tailwindcss/postcss7-compat",
|
"name": "@tailwindcss/postcss7-compat",
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
|
@ -46037,6 +46043,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tailwind-override": {
|
||||||
|
"version": "0.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwind-override/-/tailwind-override-0.2.3.tgz",
|
||||||
|
"integrity": "sha512-psWRqXL3TiI2h/YtzRq7dwKO6N7CrsEs4v99rNHgqEclfx4IioM0cHZ9O6pzerV3E6bZi6DhCbeq0z67Xs5PIQ=="
|
||||||
|
},
|
||||||
"tailwindcss": {
|
"tailwindcss": {
|
||||||
"version": "npm:@tailwindcss/postcss7-compat@2.2.4",
|
"version": "npm:@tailwindcss/postcss7-compat@2.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.4.tgz",
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
"react-test-renderer": "^17.0.2",
|
"react-test-renderer": "^17.0.2",
|
||||||
"styled-components": "^5.3.0",
|
"styled-components": "^5.3.0",
|
||||||
"subscriptions-transport-ws": "^0.9.19",
|
"subscriptions-transport-ws": "^0.9.19",
|
||||||
|
"tailwind-override": "^0.2.3",
|
||||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4",
|
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4",
|
||||||
"typescript": "^4.3.5",
|
"typescript": "^4.3.5",
|
||||||
"url-join": "^4.0.1"
|
"url-join": "^4.0.1"
|
||||||
|
@ -71,12 +72,12 @@
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
"@testing-library/react": "^12.0.0",
|
"@testing-library/react": "^12.0.0",
|
||||||
"@testing-library/user-event": "^13.1.9",
|
"@testing-library/user-event": "^13.1.9",
|
||||||
|
"apollo": "2.33.4",
|
||||||
|
"apollo-language-server": "1.26.3",
|
||||||
"husky": "^6.0.0",
|
"husky": "^6.0.0",
|
||||||
"i18next-parser": "^4.2.0",
|
"i18next-parser": "^4.2.0",
|
||||||
"lint-staged": "^11.0.1",
|
"lint-staged": "^11.0.1",
|
||||||
"tsc-files": "^1.1.2",
|
"tsc-files": "^1.1.2"
|
||||||
"apollo": "2.33.4",
|
|
||||||
"apollo-language-server": "1.26.3"
|
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
|
|
|
@ -10,8 +10,10 @@ import useDelay from '../../hooks/useDelay'
|
||||||
|
|
||||||
import { ReactComponent as GearIcon } from './icons/gear.svg'
|
import { ReactComponent as GearIcon } from './icons/gear.svg'
|
||||||
|
|
||||||
const BreadcrumbList = styled.ol`
|
export const BreadcrumbList = styled.ol<{ hideLastArrow?: boolean }>`
|
||||||
& li::after {
|
&
|
||||||
|
${({ hideLastArrow }) =>
|
||||||
|
hideLastArrow ? 'li:not(:last-child)::after' : 'li::after'} {
|
||||||
content: '';
|
content: '';
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='5px' height='6px' viewBox='0 0 5 6'%3E%3Cpolyline fill='none' stroke='%23979797' points='0.74 0.167710644 3.57228936 3 0.74 5.83228936' /%3E%3C/svg%3E");
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='5px' height='6px' viewBox='0 0 5 6'%3E%3Cpolyline fill='none' stroke='%23979797' points='0.74 0.167710644 3.57228936 3 0.74 5.83228936' /%3E%3C/svg%3E");
|
||||||
width: 5px;
|
width: 5px;
|
||||||
|
|
|
@ -23,12 +23,13 @@ import MediaSidebarMap from './MediaSidebarMap'
|
||||||
import {
|
import {
|
||||||
sidebarMediaQuery,
|
sidebarMediaQuery,
|
||||||
sidebarMediaQueryVariables,
|
sidebarMediaQueryVariables,
|
||||||
sidebarMediaQuery_media_album,
|
sidebarMediaQuery_media_album_path,
|
||||||
sidebarMediaQuery_media_exif,
|
sidebarMediaQuery_media_exif,
|
||||||
sidebarMediaQuery_media_faces,
|
sidebarMediaQuery_media_faces,
|
||||||
sidebarMediaQuery_media_thumbnail,
|
sidebarMediaQuery_media_thumbnail,
|
||||||
sidebarMediaQuery_media_videoMetadata,
|
sidebarMediaQuery_media_videoMetadata,
|
||||||
} from './__generated__/sidebarMediaQuery'
|
} from './__generated__/sidebarMediaQuery'
|
||||||
|
import { BreadcrumbList } from '../../album/AlbumTitle'
|
||||||
|
|
||||||
const SIDEBAR_MEDIA_QUERY = gql`
|
const SIDEBAR_MEDIA_QUERY = gql`
|
||||||
query sidebarMediaQuery($id: ID!) {
|
query sidebarMediaQuery($id: ID!) {
|
||||||
|
@ -82,6 +83,10 @@ const SIDEBAR_MEDIA_QUERY = gql`
|
||||||
album {
|
album {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
path {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
}
|
||||||
}
|
}
|
||||||
faces {
|
faces {
|
||||||
id
|
id
|
||||||
|
@ -95,6 +100,15 @@ const SIDEBAR_MEDIA_QUERY = gql`
|
||||||
id
|
id
|
||||||
label
|
label
|
||||||
}
|
}
|
||||||
|
media {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
thumbnail {
|
||||||
|
url
|
||||||
|
width
|
||||||
|
height
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,20 +176,26 @@ const SidebarContent = ({ media, hidePreview }: SidebarContentProps) => {
|
||||||
sidebarMap = <MediaSidebarMap coordinates={mediaCoordinates} />
|
sidebarMap = <MediaSidebarMap coordinates={mediaCoordinates} />
|
||||||
}
|
}
|
||||||
|
|
||||||
let albumLink = null
|
let albumPath = null
|
||||||
const mediaAlbum = media.album
|
const mediaAlbum = media.album
|
||||||
if (!isNil(mediaAlbum)) {
|
if (!isNil(mediaAlbum)) {
|
||||||
albumLink = (
|
const pathElms = [...(mediaAlbum.path ?? []), mediaAlbum].map(album => (
|
||||||
<div className="mx-4 my-4">
|
<li key={album.id} className="inline-block hover:underline">
|
||||||
<h2 className="uppercase text-xs text-gray-900 font-semibold">
|
|
||||||
{t('sidebar.media.album', 'Album')}
|
|
||||||
</h2>
|
|
||||||
<Link
|
<Link
|
||||||
className="text-blue-900 hover:underline"
|
className="text-blue-900 hover:underline"
|
||||||
to={`/album/${mediaAlbum.id}`}
|
to={`/album/${album.id}`}
|
||||||
>
|
>
|
||||||
{mediaAlbum.title}
|
{album.title}
|
||||||
</Link>
|
</Link>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
|
||||||
|
albumPath = (
|
||||||
|
<div className="mx-4 my-4">
|
||||||
|
<h2 className="uppercase text-xs text-gray-900 font-semibold">
|
||||||
|
{t('sidebar.media.album_path', 'Album path')}
|
||||||
|
</h2>
|
||||||
|
<BreadcrumbList hideLastArrow={true}>{pathElms}</BreadcrumbList>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -198,7 +218,7 @@ const SidebarContent = ({ media, hidePreview }: SidebarContentProps) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ExifDetails media={media} />
|
<ExifDetails media={media} />
|
||||||
{albumLink}
|
{albumPath}
|
||||||
<MediaSidebarPeople media={media} />
|
<MediaSidebarPeople media={media} />
|
||||||
{sidebarMap}
|
{sidebarMap}
|
||||||
<SidebarMediaDownload media={media} />
|
<SidebarMediaDownload media={media} />
|
||||||
|
@ -232,7 +252,12 @@ export interface MediaSidebarMedia {
|
||||||
exif?: sidebarMediaQuery_media_exif | null
|
exif?: sidebarMediaQuery_media_exif | null
|
||||||
faces?: sidebarMediaQuery_media_faces[]
|
faces?: sidebarMediaQuery_media_faces[]
|
||||||
downloads?: sidebarDownloadQuery_media_downloads[]
|
downloads?: sidebarDownloadQuery_media_downloads[]
|
||||||
album?: sidebarMediaQuery_media_album
|
album?: {
|
||||||
|
__typename: 'Album'
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
path?: sidebarMediaQuery_media_album_path[]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaSidebarType = {
|
type MediaSidebarType = {
|
||||||
|
|
|
@ -1,15 +1,39 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import FaceCircleImage from '../../../Pages/PeoplePage/FaceCircleImage'
|
||||||
|
import { Button } from '../../../primitives/form/Input'
|
||||||
import { SidebarSection, SidebarSectionTitle } from '../SidebarComponents'
|
import { SidebarSection, SidebarSectionTitle } from '../SidebarComponents'
|
||||||
import { MediaSidebarMedia } from './MediaSidebar'
|
import { MediaSidebarMedia } from './MediaSidebar'
|
||||||
import { sidebarMediaQuery_media_faces } from './__generated__/sidebarMediaQuery'
|
import { sidebarMediaQuery_media_faces } from './__generated__/sidebarMediaQuery'
|
||||||
|
|
||||||
|
import { ReactComponent as PeopleDotsIcon } from './icons/peopleDotsIcon.svg'
|
||||||
|
|
||||||
type MediaSidebarFaceProps = {
|
type MediaSidebarFaceProps = {
|
||||||
face: sidebarMediaQuery_media_faces
|
face: sidebarMediaQuery_media_faces
|
||||||
}
|
}
|
||||||
|
|
||||||
const MediaSidebarPerson = ({ face }: MediaSidebarFaceProps) => {
|
const MediaSidebarPerson = ({ face }: MediaSidebarFaceProps) => {
|
||||||
return <div>{face.faceGroup.label ?? 'unlabeled'}</div>
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li className="inline-block">
|
||||||
|
<Link to={`/people/${face.faceGroup.id}`}>
|
||||||
|
<FaceCircleImage imageFace={face} selectable={true} size="100px" />
|
||||||
|
</Link>
|
||||||
|
<div
|
||||||
|
className={`text-center ${
|
||||||
|
face.faceGroup.label ? 'text-black' : 'text-gray-600'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{face.faceGroup.label ??
|
||||||
|
t('people_page.face_group.unlabeled', 'Unlabeled')}
|
||||||
|
<Button className="px-2 py-1.5 align-middle ml-1">
|
||||||
|
<PeopleDotsIcon className="text-gray-500" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaSidebarFacesProps = {
|
type MediaSidebarFacesProps = {
|
||||||
|
@ -18,16 +42,21 @@ type MediaSidebarFacesProps = {
|
||||||
|
|
||||||
const MediaSidebarPeople = ({ media }: MediaSidebarFacesProps) => {
|
const MediaSidebarPeople = ({ media }: MediaSidebarFacesProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const faceElms = (media.faces ?? []).map(face => (
|
const faceElms = (media.faces ?? []).map(face => (
|
||||||
<MediaSidebarPerson key={face.id} face={face} />
|
<MediaSidebarPerson key={face.id} face={face} />
|
||||||
))
|
))
|
||||||
|
|
||||||
|
if (faceElms.length == 0) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarSection>
|
<SidebarSection>
|
||||||
<SidebarSectionTitle>
|
<SidebarSectionTitle>
|
||||||
{t('sidebar.people.title', 'People')}
|
{t('sidebar.people.title', 'People')}
|
||||||
</SidebarSectionTitle>
|
</SidebarSectionTitle>
|
||||||
<div>{faceElms}</div>
|
<div className="overflow-x-auto">
|
||||||
|
<ul className="flex gap-4 mx-4">{faceElms}</ul>
|
||||||
|
</div>
|
||||||
</SidebarSection>
|
</SidebarSection>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,10 +128,17 @@ export interface sidebarMediaQuery_media_exif {
|
||||||
coordinates: sidebarMediaQuery_media_exif_coordinates | null
|
coordinates: sidebarMediaQuery_media_exif_coordinates | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface sidebarMediaQuery_media_album_path {
|
||||||
|
__typename: 'Album'
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface sidebarMediaQuery_media_album {
|
export interface sidebarMediaQuery_media_album {
|
||||||
__typename: 'Album'
|
__typename: 'Album'
|
||||||
id: string
|
id: string
|
||||||
title: string
|
title: string
|
||||||
|
path: sidebarMediaQuery_media_album_path[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface sidebarMediaQuery_media_faces_rectangle {
|
export interface sidebarMediaQuery_media_faces_rectangle {
|
||||||
|
@ -148,11 +155,38 @@ export interface sidebarMediaQuery_media_faces_faceGroup {
|
||||||
label: string | null
|
label: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface sidebarMediaQuery_media_faces_media_thumbnail {
|
||||||
|
__typename: 'MediaURL'
|
||||||
|
/**
|
||||||
|
* URL for previewing the image
|
||||||
|
*/
|
||||||
|
url: string
|
||||||
|
/**
|
||||||
|
* Width of the image in pixels
|
||||||
|
*/
|
||||||
|
width: number
|
||||||
|
/**
|
||||||
|
* Height of the image in pixels
|
||||||
|
*/
|
||||||
|
height: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface sidebarMediaQuery_media_faces_media {
|
||||||
|
__typename: 'Media'
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
/**
|
||||||
|
* URL to display the media in a smaller resolution
|
||||||
|
*/
|
||||||
|
thumbnail: sidebarMediaQuery_media_faces_media_thumbnail | null
|
||||||
|
}
|
||||||
|
|
||||||
export interface sidebarMediaQuery_media_faces {
|
export interface sidebarMediaQuery_media_faces {
|
||||||
__typename: 'ImageFace'
|
__typename: 'ImageFace'
|
||||||
id: string
|
id: string
|
||||||
rectangle: sidebarMediaQuery_media_faces_rectangle
|
rectangle: sidebarMediaQuery_media_faces_rectangle
|
||||||
faceGroup: sidebarMediaQuery_media_faces_faceGroup
|
faceGroup: sidebarMediaQuery_media_faces_faceGroup
|
||||||
|
media: sidebarMediaQuery_media_faces_media
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface sidebarMediaQuery_media {
|
export interface sidebarMediaQuery_media {
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="12px" height="3px" viewBox="0 0 8 2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<path d="M1,0 C1.55228475,0 2,0.44771525 2,1 C2,1.55228475 1.55228475,2 1,2 C0.44771525,2 0,1.55228475 0,1 C0,0.44771525 0.44771525,0 1,0 Z M4,0 C4.55228475,0 5,0.44771525 5,1 C5,1.55228475 4.55228475,2 4,2 C3.44771525,2 3,1.55228475 3,1 C3,0.44771525 3.44771525,0 4,0 Z M7,0 C7.55228475,0 8,0.44771525 8,1 C8,1.55228475 7.55228475,2 7,2 C6.44771525,2 6,1.55228475 6,1 C6,0.44771525 6.44771525,0 7,0 Z" fill="currentColor"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 583 B |
|
@ -1,3 +1,5 @@
|
||||||
|
import classNames, { Argument as ClassNamesArg } from 'classnames'
|
||||||
|
import { overrideTailwindClasses } from 'tailwind-override'
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
export interface DebouncedFn<F extends (...args: any[]) => any> {
|
export interface DebouncedFn<F extends (...args: any[]) => any> {
|
||||||
|
@ -41,3 +43,7 @@ export function isNil(value: any): value is undefined | null {
|
||||||
export function exhaustiveCheck(value: never) {
|
export function exhaustiveCheck(value: never) {
|
||||||
throw new Error(`Exhaustive check failed with value: ${value}`)
|
throw new Error(`Exhaustive check failed with value: ${value}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function tailwindClassNames(...args: ClassNamesArg[]) {
|
||||||
|
return overrideTailwindClasses(classNames(args))
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import classNames, { Argument as ClassNamesArg } from 'classnames'
|
||||||
import { ReactComponent as ActionArrowIcon } from './icons/textboxActionArrow.svg'
|
import { ReactComponent as ActionArrowIcon } from './icons/textboxActionArrow.svg'
|
||||||
import { ReactComponent as LoadingSpinnerIcon } from './icons/textboxLoadingSpinner.svg'
|
import { ReactComponent as LoadingSpinnerIcon } from './icons/textboxLoadingSpinner.svg'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
import { tailwindClassNames } from '../../helpers/utils'
|
||||||
|
|
||||||
type TextFieldProps = {
|
type TextFieldProps = {
|
||||||
label?: string
|
label?: string
|
||||||
|
@ -164,7 +165,10 @@ export const Submit = ({
|
||||||
...props
|
...props
|
||||||
}: SubmitProps & React.ButtonHTMLAttributes<HTMLInputElement>) => (
|
}: SubmitProps & React.ButtonHTMLAttributes<HTMLInputElement>) => (
|
||||||
<input
|
<input
|
||||||
className={classNames(buttonStyles({ variant, background }), className)}
|
className={tailwindClassNames(
|
||||||
|
buttonStyles({ variant, background }),
|
||||||
|
className
|
||||||
|
)}
|
||||||
type="submit"
|
type="submit"
|
||||||
value={children}
|
value={children}
|
||||||
{...props}
|
{...props}
|
||||||
|
@ -179,7 +183,10 @@ export const Button = ({
|
||||||
...props
|
...props
|
||||||
}: ButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>) => (
|
}: ButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>) => (
|
||||||
<button
|
<button
|
||||||
className={classNames(buttonStyles({ variant, background }), className)}
|
className={tailwindClassNames(
|
||||||
|
buttonStyles({ variant, background }),
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
Loading…
Reference in New Issue