Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COM-357: Add support for additional content in DAM grid rows #1697

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .changeset/heavy-rules-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"@comet/cms-admin": minor
---

Support additional content in DAM Data Grid rows

**Example**

```tsx
<DamConfigProvider
value={{
renderAdditionalRowContent: (row) => <Chip size="small" icon={<UnsplashIcon />} label="Unsplash" />,
}}
>
...
</DamConfigProvider>
```
9 changes: 8 additions & 1 deletion demo/admin/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { Route, Switch } from "react-router-dom";

import MasterHeader from "./common/MasterHeader";
import MasterMenu, { masterMenuData, pageTreeDocumentTypes } from "./common/MasterMenu";
import { renderUnsplashChip } from "./dam/renderUnsplashChip";
import { getMessages } from "./lang";

const GlobalStyle = () => (
Expand Down Expand Up @@ -65,7 +66,13 @@ class App extends React.Component {
resolveSiteConfigForScope: (configs, scope: ContentScope) => configs[scope.domain],
}}
>
<DamConfigProvider value={{ scopeParts: ["domain"], additionalToolbarItems: <ImportFromUnsplash /> }}>
<DamConfigProvider
value={{
scopeParts: ["domain"],
additionalToolbarItems: <ImportFromUnsplash />,
renderAdditionalRowContent: renderUnsplashChip,
}}
>
<IntlProvider locale="en" messages={getMessages()}>
<LocaleProvider resolveLocaleForScope={(scope: ContentScope) => scope.domain}>
<MuiThemeProvider theme={theme}>
Expand Down
14 changes: 14 additions & 0 deletions demo/admin/src/dam/renderUnsplashChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { DamRow } from "@comet/cms-admin";
import { Chip } from "@mui/material";
import React from "react";
import { FormattedMessage } from "react-intl";

import UnsplashIcon from "./UnsplashIcon";

function renderUnsplashChip(row: DamRow) {
return row.__typename === "DamFile" && row.importSourceType === "unsplash" ? (
<Chip size="small" icon={<UnsplashIcon />} label={<FormattedMessage id="dam.unsplashImport.chip.label" defaultMessage="Unsplash" />} />
) : null;
}

export { renderUnsplashChip };
27 changes: 19 additions & 8 deletions packages/admin/cms-admin/src/dam/DataGrid/FolderDataGrid.gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const damFileTableFragment = gql`
...DamFileThumbnail
}
updatedAt
importSourceId
importSourceType
}
${damFileThumbnailFragment}
`;
Expand Down Expand Up @@ -60,6 +62,20 @@ export const damFolderQuery = gql`
${damFolderTableFragment}
`;

export const damRowFragment = gql`
fragment DamRow on DamItem {
... on DamFile {
...DamFileTable
}
... on DamFolder {
...DamFolderTable
}
}

${damFileTableFragment}
${damFolderTableFragment}
`;

export const damItemsListQuery = gql`
query DamItemsList(
$folderId: ID
Expand All @@ -82,18 +98,13 @@ export const damItemsListQuery = gql`
scope: $scope
) {
nodes {
... on DamFile {
...DamFileTable
}
... on DamFolder {
...DamFolderTable
}
...DamRow
}
totalCount
}
}
${damFileTableFragment}
${damFolderTableFragment}

${damRowFragment}
`;

export const moveDamFilesMutation = gql`
Expand Down
3 changes: 3 additions & 0 deletions packages/admin/cms-admin/src/dam/DataGrid/FolderDataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
GQLDamItemListPositionQueryVariables,
GQLDamItemsListQuery,
GQLDamItemsListQueryVariables,
GQLDamRowFragment,
} from "./FolderDataGrid.gql.generated";
import * as sc from "./FolderDataGrid.sc";
import { FolderHead } from "./FolderHead";
Expand All @@ -60,6 +61,8 @@ export {

export type DamItemSelectionMap = Map<string, "file" | "folder">;

export type DamRow = GQLDamRowFragment;

interface FolderDataGridProps extends DamConfig {
id?: string;
breadcrumbs?: BreadcrumbItem[];
Expand Down
29 changes: 18 additions & 11 deletions packages/admin/cms-admin/src/dam/DataGrid/label/DamItemLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Typography } from "@mui/material";
import { styled } from "@mui/material/styles";
import { Box } from "@mui/system";
import * as React from "react";

import { MarkedMatches, TextMatch } from "../../../common/MarkedMatches";
import { useDamConfig } from "../../config/useDamConfig";
import { isFile } from "../../helpers/isFile";
import { GQLDamFileTableFragment, GQLDamFolderTableFragment } from "../FolderDataGrid";
import { DamRow, GQLDamFileTableFragment, GQLDamFolderTableFragment } from "../FolderDataGrid";
import { ArchivedTag } from "../tags/ArchivedTag";
import { LicenseValidityTags } from "../tags/LicenseValidityTags";
import { DamThumbnail } from "../thumbnail/DamThumbnail";
Expand All @@ -29,7 +31,7 @@ const Path = styled(Typography)`
`;

interface DamItemLabelProps {
asset: GQLDamFolderTableFragment | GQLDamFileTableFragment;
asset: DamRow;
johnnyomair marked this conversation as resolved.
Show resolved Hide resolved
showPath?: boolean;
matches?: TextMatch[];
showLicenseWarnings?: boolean;
Expand All @@ -55,22 +57,27 @@ const getFolderPath = (folder: GQLDamFolderTableFragment) => {
};

const DamItemLabel = ({ asset, showPath = false, matches, showLicenseWarnings = false }: DamItemLabelProps): React.ReactElement => {
const { renderAdditionalRowContent } = useDamConfig();

return (
<LabelWrapper>
<DamThumbnail asset={asset} />
<NameWrapper>
<Typography>{matches ? <MarkedMatches text={asset.name} matches={matches} /> : asset.name}</Typography>
{showPath && <Path variant="body2">{isFile(asset) ? getFilePath(asset) : getFolderPath(asset)}</Path>}
</NameWrapper>
{isFile(asset) && asset.archived && <ArchivedTag />}
{isFile(asset) && showLicenseWarnings && (
<LicenseValidityTags
expirationDate={asset.license?.expirationDate ? new Date(asset.license.expirationDate) : undefined}
isNotValidYet={asset.license?.isNotValidYet}
expiresWithinThirtyDays={asset.license?.expiresWithinThirtyDays}
hasExpired={asset.license?.hasExpired}
/>
)}
<Box sx={{ display: "flex", alignItems: "center", gap: 2, paddingX: 2 }}>
{isFile(asset) && asset.archived && <ArchivedTag />}
{isFile(asset) && showLicenseWarnings && (
<LicenseValidityTags
expirationDate={asset.license?.expirationDate ? new Date(asset.license.expirationDate) : undefined}
isNotValidYet={asset.license?.isNotValidYet}
expiresWithinThirtyDays={asset.license?.expiresWithinThirtyDays}
hasExpired={asset.license?.hasExpired}
/>
)}
{renderAdditionalRowContent?.(asset)}
</Box>
</LabelWrapper>
);
};
Expand Down
1 change: 0 additions & 1 deletion packages/admin/cms-admin/src/dam/DataGrid/tags/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const Tag = styled("div")<{ type?: "warning" | "error" | "info" | "neutra
align-items: center;
height: 20px;
border-radius: 4px;
margin-left: 10px;
padding: 4px 5px;
box-sizing: border-box;
font-size: 12px;
Expand Down
3 changes: 3 additions & 0 deletions packages/admin/cms-admin/src/dam/config/DamConfigContext.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import * as React from "react";

import { DamRow } from "../DataGrid/FolderDataGrid";

export interface DamConfig {
additionalMimeTypes?: string[];
scopeParts?: string[];
enableLicenseFeature?: boolean;
requireLicense?: boolean;
additionalToolbarItems?: React.ReactNode;
renderAdditionalRowContent?: (row: DamRow) => React.ReactNode;
Comment on lines 10 to +11
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to add the render prefix because this is a render prop. However, it's kinda odd that additionalToolbarItems isn't a render prop. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, they could both use the same technique

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we prefer? We currently have three different techniques in our code base:

yes, they could both use the same technique

I can't really use ReactNode here for both cases because I need to pass row

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the difference between the first two?

}

export const DamConfigContext = React.createContext<DamConfig | undefined>(undefined);
1 change: 1 addition & 0 deletions packages/admin/cms-admin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export { useDamConfig } from "./dam/config/useDamConfig";
export { useCurrentDamFolder } from "./dam/CurrentDamFolderProvider";
export { DamPage } from "./dam/DamPage";
export { useDamFileUpload } from "./dam/DataGrid/fileUpload/useDamFileUpload";
export type { DamRow } from "./dam/DataGrid/FolderDataGrid";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imho that name is too generic (for a public export)

DamRowFragment? DamRowData?

Copy link
Collaborator Author

@johnnyomair johnnyomair Feb 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe DamGridItem or DamGridRow?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's data structure (that contains just the data) vs. component (that renders it)

usually our exports are components, so I could think DamGridRow is also a component

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could simply re-export the generated GraphQL type without a renaming, what do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why you add it to the public api is, because it gets passed in renderAdditionalRowContent render prop.

final-form names the arguments passed to a render function eg FieldRenderProps, maybe you could use AdditionalRowContentRenderProps accordingly?

export { DashboardHeader, DashboardHeaderProps } from "./dashboard/DashboardHeader";
export { DashboardWidgetRoot, DashboardWidgetRootProps } from "./dashboard/widgets/DashboardWidgetRoot";
export { LatestBuildsDashboardWidget } from "./dashboard/widgets/LatestBuildsDashboardWidget";
Expand Down
Loading