Created
May 5, 2024 12:25
-
-
Save ahmetskilinc/9f568f32839dc16b0c5df94217c9e0c9 to your computer and use it in GitHub Desktop.
Payload Media Grid
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.SortingHeader { | |
display: flex; | |
overflow-x: scroll; | |
gap: 18px; | |
align-items: center; | |
} | |
.MediaGrid { | |
display: grid; | |
gap: 1.5rem; | |
grid-template-columns: repeat(2, minmax(0, 1fr)); | |
@media (min-width: 520px) { | |
grid-template-columns: repeat(3, minmax(0, 1fr)); | |
} | |
@media (min-width: 1024px) { | |
grid-template-columns: repeat(4, minmax(0, 1fr)); | |
} | |
@media (min-width: 1280px) { | |
grid-template-columns: repeat(6, minmax(0, 1fr)); | |
} | |
} | |
.MediaGridCard { | |
outline-style: solid; | |
outline-width: 2px; | |
border-radius: 4px !important; | |
outline-color: rgb(47, 47, 47); | |
text-decoration: none; | |
text-align: left; | |
position: relative; | |
> a > span > span { | |
display: flex !important; | |
flex-direction: column; | |
justify-content: space-between; | |
} | |
} | |
.MediaGridCard:hover { | |
.MediaCardMeta { | |
background-color: rgb(47, 47, 47); | |
} | |
} | |
.MediaGridCardSelect { | |
position: absolute; | |
top: 8px; | |
left: 8px; | |
z-index: 10; | |
} | |
.MediaGridCardMedia { | |
object-fit: contain; | |
aspect-ratio: 1/1; | |
width: 100%; | |
} | |
.MediaCardMeta { | |
padding: 12px; | |
background-color: rgb(34, 34, 34); | |
display: flex; | |
flex-direction: column; | |
flex-grow: 1; | |
flex-shrink: 0; | |
} | |
.MediaGridCardTitle { | |
width: 100%; | |
font-weight: 500; | |
overflow-wrap: anywhere; | |
text-decoration: underline; | |
margin-bottom: 0; | |
} | |
.MediaGridCardAlt { | |
width: 100%; | |
font-weight: 300; | |
overflow-wrap: anywhere; | |
text-decoration: none; | |
margin-bottom: 0; | |
opacity: 0.5; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useWindowInfo } from "@faceless-ui/window-info"; | |
import DeleteMany from "payload/dist/admin/components/elements/DeleteMany"; | |
import EditMany from "payload/dist/admin/components/elements/EditMany"; | |
import { Gutter } from "payload/dist/admin/components/elements/Gutter"; | |
import { ListControls } from "payload/dist/admin/components/elements/ListControls"; | |
import ListSelection from "payload/dist/admin/components/elements/ListSelection"; | |
import SortColumn from "payload/dist/admin/components/elements/SortColumn"; | |
import Paginator from "payload/dist/admin/components/elements/Paginator"; | |
import PerPage from "payload/dist/admin/components/elements/PerPage"; | |
import Pill from "payload/dist/admin/components/elements/Pill"; | |
import PublishMany from "payload/dist/admin/components/elements/PublishMany"; | |
import UnpublishMany from "payload/dist/admin/components/elements/UnpublishMany"; | |
import ViewDescription from "payload/dist/admin/components/elements/ViewDescription"; | |
import { SelectionProvider } from "payload/dist/admin/components/views/collections/List/SelectionProvider"; | |
import SelectRow from "payload/dist/admin/components/views/collections/List/SelectRow"; | |
import SelectAll from "payload/dist/admin/components/views/collections/List/SelectAll"; | |
import { getTranslation } from "payload/dist/utilities/getTranslation"; | |
import { formatDate } from "payload/dist/admin/utilities/formatDate"; | |
import { useConfig } from "payload/dist/admin/components/utilities/Config"; | |
import Meta from "payload/dist/admin/components/utilities/Meta"; | |
import { Button } from "payload/components/elements"; | |
import React, { Fragment } from "react"; | |
import { useTranslation } from "react-i18next"; | |
import type { Props } from "payload/dist/admin/components/views/collections/List/types"; | |
import classes from "./MediaList.module.scss"; | |
const baseClass = "collection-list"; | |
const MediaList = (props: Props) => { | |
const { | |
data, | |
collection: { | |
admin: { description } = {}, | |
labels: { plural: pluralLabel, singular: singularLabel }, | |
}, | |
limit, | |
collection, | |
handlePageChange, | |
handlePerPageChange, | |
handleSearchChange, | |
handleSortChange, | |
handleWhereChange, | |
hasCreatePermission, | |
modifySearchParams, | |
newDocumentURL, | |
resetParams, | |
titleField, | |
customHeader, | |
} = props; | |
const { | |
breakpoints: { s: smallBreak }, | |
} = useWindowInfo(); | |
const { i18n, t } = useTranslation("general"); | |
const { | |
admin: { dateFormat }, | |
routes: { admin: adminRoute }, | |
} = useConfig(); | |
return ( | |
<div className="collection-list"> | |
<Meta title={getTranslation(collection.labels.plural, i18n)} /> | |
<SelectionProvider docs={data.docs} totalDocs={data.totalDocs}> | |
<Gutter className={`${baseClass}__wrap`}> | |
<header className={`${baseClass}__header`}> | |
{customHeader && customHeader} | |
{!customHeader && ( | |
<Fragment> | |
<h1>Media</h1> | |
{hasCreatePermission && ( | |
<Pill | |
aria-label={t("createNewLabel", { label: getTranslation(singularLabel, i18n) })} | |
to={newDocumentURL} | |
> | |
{t("createNew")} | |
</Pill> | |
)} | |
{!smallBreak && <ListSelection label={getTranslation(pluralLabel, i18n)} />} | |
{description && ( | |
<div className={`${baseClass}__sub-header`}> | |
<ViewDescription description={description} /> | |
</div> | |
)} | |
</Fragment> | |
)} | |
</header> | |
<ListControls | |
collection={collection} | |
handleSearchChange={handleSearchChange} | |
handleSortChange={handleSortChange} | |
handleWhereChange={handleWhereChange} | |
modifySearchQuery={modifySearchParams} | |
resetParams={resetParams} | |
titleField={titleField} | |
enableColumns={false} | |
/> | |
<div className={classes.SortingHeader}> | |
<SelectAll /> | |
<SortColumn label="File Name" name="filename" /> | |
<SortColumn label="Alt Tag" name="alt" /> | |
<SortColumn label="Created At" name="createdAt" /> | |
<SortColumn label="Updated At" name="updatedAt" /> | |
</div> | |
<div className={classes.MediaGrid}> | |
{props.data.docs | |
? props.data.docs.map((doc) => ( | |
<Button | |
key={doc.id} | |
className={classes.MediaGridCard} | |
el={"link"} | |
buttonStyle="none" | |
to={`${adminRoute}/collections/media/${doc.id}`} | |
> | |
<div className={classes.MediaGridCardSelect}> | |
<SelectRow id={doc.id} /> | |
</div> | |
{doc.mimeType.includes("image") ? ( | |
doc.mimeType.includes("svg") ? ( | |
<img src={doc.url} className={classes.MediaGridCardMedia} /> | |
) : ( | |
<img src={doc.sizes.optimised.url} className={classes.MediaGridCardMedia} /> | |
) | |
) : ( | |
<video | |
src={doc.url} | |
autoPlay | |
muted | |
loop | |
className={classes.MediaGridCardMedia} | |
/> | |
)} | |
<div className={classes.MediaCardMeta}> | |
<p className={classes.MediaGridCardTitle}>{doc.filename}</p> | |
<p className={classes.MediaGridCardAlt}>{doc.alt || "<No Alt Text>"}</p> | |
{/* <p className={classes.MediaGridCardAlt}> | |
{formatDate(doc.updatedAt, dateFormat, i18n?.language)} | |
</p> */} | |
<p className={classes.MediaGridCardAlt}> | |
{formatDate(doc.createdAt, dateFormat, i18n?.language)} | |
</p> | |
</div> | |
</Button> | |
)) | |
: null} | |
</div> | |
{data.docs && data.docs.length > 0 && ( | |
<div className={`${baseClass}__page-controls`}> | |
<Paginator | |
disableHistoryChange={modifySearchParams === false} | |
hasNextPage={data.hasNextPage} | |
hasPrevPage={data.hasPrevPage} | |
limit={data.limit} | |
nextPage={data.nextPage} | |
numberOfNeighbors={1} | |
onChange={handlePageChange} | |
page={data.page} | |
prevPage={data.prevPage} | |
totalPages={data.totalPages} | |
/> | |
{data?.totalDocs > 0 && ( | |
<Fragment> | |
<div className={`${baseClass}__page-info`}> | |
{data.page * data.limit - (data.limit - 1)}- | |
{data.totalPages > 1 && data.totalPages !== data.page | |
? data.limit * data.page | |
: data.totalDocs}{" "} | |
{t("of")} {data.totalDocs} | |
</div> | |
<PerPage | |
handleChange={handlePerPageChange} | |
limit={limit} | |
limits={collection?.admin?.pagination?.limits} | |
modifySearchParams={modifySearchParams} | |
resetPage={data.totalDocs <= data.pagingCounter} | |
/> | |
{smallBreak && ( | |
<div className={`${baseClass}__list-selection`}> | |
<Fragment> | |
<ListSelection label={getTranslation(collection.labels.plural, i18n)} /> | |
<div className={`${baseClass}__list-selection-actions`}> | |
<EditMany collection={collection} resetParams={resetParams} /> | |
<PublishMany collection={collection} resetParams={resetParams} /> | |
<UnpublishMany collection={collection} resetParams={resetParams} /> | |
<DeleteMany collection={collection} resetParams={resetParams} /> | |
</div> | |
</Fragment> | |
</div> | |
)} | |
</Fragment> | |
)} | |
</div> | |
)} | |
</Gutter> | |
</SelectionProvider> | |
</div> | |
); | |
}; | |
export default MediaList; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment