Skip to content

Commit

Permalink
It is not possible to override default entity actions
Browse files Browse the repository at this point in the history
  • Loading branch information
fgatti675 committed Dec 14, 2024
1 parent c01f9b3 commit d3166cd
Show file tree
Hide file tree
Showing 33 changed files with 291 additions and 93 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## [3.0.0-beta.12] - 2024-12-

- You can now override custom entity actions. Just provide an action with one of the keys `edit`, `copy` or `delete` in
the `entityActions` prop in the collection view. This will override the default actions for the entity.


## [3.0.0-beta.11] - 2024-12-13

- New Next.js template for FireCMS PRO. You can now create a new project with the PRO template using the CLI.
Expand Down
3 changes: 2 additions & 1 deletion examples/example_pro/src/FirestoreApp/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ export function App() {
if (process.env.NODE_ENV !== "production") {
sourceCollections.push(testCollection);
}

// return sourceCollections;
return mergeCollections(
sourceCollections,
Expand Down Expand Up @@ -325,7 +326,7 @@ export function App() {

const navigationController = useBuildNavigationController({
collections,
collectionPermissions: userManagement.collectionPermissions,
// collectionPermissions: userManagement.collectionPermissions,
views,
adminViews: userManagementAdminViews,
authController,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from "react";
import { CollectionActionsProps, useSnackbarController } from "@firecms/core";
import { CollectionActionsProps, useSideEntityController, useSnackbarController } from "@firecms/core";
import { Button, CloseIcon, IconButton, Select, SelectItem } from "@firecms/ui";

export function SampleCollectionActions({ selectionController }: CollectionActionsProps) {

const sideEntityController = useSideEntityController();
const snackbarController = useSnackbarController();

const onClick = (event: React.MouseEvent) => {
Expand All @@ -13,6 +14,11 @@ export function SampleCollectionActions({ selectionController }: CollectionActio
type: "success",
message: `User defined code here! ${count} products selected`
});
// sideEntityController.open({
// path: "showcase",
// entityId: "delete_me",
// collection: showcaseCollection
// });
};

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
import { buildCollection, buildProperty } from "@firecms/core";
import { AutoAwesomeIcon } from "@firecms/ui";
import React from "react";

export const showcaseCollection = buildCollection({
id: "showcase",
id: "id_showcase",
path: "showcase",
description: "Collection to showcase different field types",
customId: false,
icon: "bento",
name: "Showcase",
entityActions: [
{
name: "Edit",
key: "edit",
onClick: async ({
entity,
collection
}) => {
console.log("Custom action", entity, collection);
}
}
],
subcollections: [{
id: "id_subcollection",
path: "subcollection",
name: "Subcollection",
properties: {
name: {
dataType: "string",
name: "Name"
}
}
}],
properties: {
name: buildProperty({
dataType: "string",
Expand Down
13 changes: 11 additions & 2 deletions packages/cli/templates/template_pro/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ yarn
```

And run the project locally:

```bash
yarn dev
```
Expand Down Expand Up @@ -61,10 +62,18 @@ function isFireCMSUser(){

### Deploying the project

You can deploy the project to Firebase hosting by following [these instructions](https://firecms.co/docs/pro/deployment).
In order to deploy the project, you need to have a valid FireCMS PRO license.
You can develop your project locally without a license, but you will need to purchase one to deploy it. There is a grace
period after the first deployment to allow you to test it in production.

You can create one in the [FireCMS subscriptions](https://app.firecms.co/subscriptions).
When you get your API key, you can set it in the `.env` file.

When creating your license, you need to specify the project IDs that will be using the license. You can find your
project ID in the Firebase console.

You will receive an API key that you need to pass to your FireCMS component. If you are using the starter template, you
can set it in the .env file.




3 changes: 2 additions & 1 deletion packages/datatalk/src/components/TableResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
EntityCollection,
EntityCollectionRowActions,
EntityCollectionTable,
mergeEntityActions,
OnCellValueChange,
PropertiesOrBuilders,
resolveCollection,
Expand Down Expand Up @@ -136,7 +137,7 @@ export function TableResults({
actions.push(copyEntityAction);
actions.push(deleteEntityAction);
if (customEntityActions)
actions.push(...customEntityActions);
return mergeEntityActions(actions, customEntityActions);
return actions;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import {
import { setIn } from "@firecms/formex";
import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
import {
COLLECTION_GROUP_PARENT_ID,
OnCellValueChange,
OnColumnResizeParams,
UniqueFieldValidator,
Expand All @@ -75,8 +76,7 @@ import { useAnalyticsController } from "../../hooks/useAnalyticsController";
import { useSelectionController } from "./useSelectionController";
import { EntityCollectionViewStartActions } from "./EntityCollectionViewStartActions";
import { addRecentId, getRecentIds } from "./utils";

const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
import { mergeEntityActions } from "../../util/entity_actions";

/**
* @group Components
Expand Down Expand Up @@ -458,7 +458,7 @@ export const EntityCollectionView = React.memo(
if (deleteEnabled)
actions.push(deleteEntityAction);
if (customEntityActions)
actions.push(...customEntityActions);
return mergeEntityActions(actions, customEntityActions);
return actions;
};

Expand Down Expand Up @@ -798,7 +798,8 @@ function EntityIdHeaderWidget({
<SearchIcon size={"small"}/>
</IconButton>
}>
<div className={cls("my-2 rounded-lg bg-surface-50 dark:bg-surface-950 text-surface-900 dark:text-white")}>
<div
className={cls("my-2 rounded-lg bg-surface-50 dark:bg-surface-950 text-surface-900 dark:text-white")}>
<form noValidate={true}
onSubmit={(e) => {
e.preventDefault();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { addRecentId } from "../EntityCollectionView/utils";

export const editEntityAction: EntityAction = {
icon: <EditIcon/>,
key: "edit",
name: "Edit",
collapsed: false,
onClick({
Expand Down Expand Up @@ -38,6 +39,7 @@ export const editEntityAction: EntityAction = {
export const copyEntityAction: EntityAction = {
icon: <FileCopyIcon/>,
name: "Copy",
key: "copy",
onClick({
entity,
collection,
Expand All @@ -62,38 +64,11 @@ export const copyEntityAction: EntityAction = {
}
}

export const archiveEntityAction: EntityAction = {
icon: <ArchiveIcon/>,
name: "Archive",
onClick({
entity,
collection,
context: {
dataSource,
}
}): Promise<void> {
// Add your code here
return Promise.resolve(undefined);
}
}

export const openWebsiteAction: EntityAction = {
icon: <OpenInNewIcon/>,
name: "See in website",
onClick({
entity,
collection,
context,
}): Promise<void> {
// open a new tab
window.open(`https://example.com/${entity.id}`, "_blank");
return Promise.resolve(undefined);
}
}

export const deleteEntityAction: EntityAction = {
icon: <DeleteIcon/>,
name: "Delete",
key: "delete",
onClick({
entity,
fullPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EntityCollection, ResolvedEntityCollection, ResolvedProperty } from "..
import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
import { PropertyColumnConfig } from "../EntityCollectionTable/EntityCollectionTableProps";

const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
export const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";

export function useColumnIds<M extends Record<string, any>>(collection: ResolvedEntityCollection<M>, includeSubcollections: boolean): PropertyColumnConfig[] {
return useMemo(() => {
Expand Down
3 changes: 2 additions & 1 deletion packages/firecms_core/src/core/EntityEditView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
getValueInPath,
isHidden,
isReadOnly,
mergeEntityActions,
removeInitialAndTrailingSlashes,
resolveCollection,
resolveDefaultSelectedView,
Expand Down Expand Up @@ -702,7 +703,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
if (deleteEnabled)
actions.push(deleteEntityAction);
if (customEntityActions)
actions.push(...customEntityActions);
return mergeEntityActions(actions, customEntityActions);
return actions;
}, [authController, inputCollection, path]);

Expand Down
2 changes: 1 addition & 1 deletion packages/firecms_core/src/types/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export interface EntityCollection<M extends Record<string, any> = any, USER exte
* `hidden` in the property definition,will be ignored.
* `propertiesOrder` has precedence over `hidden`.
*/
propertiesOrder?: (Extract<keyof M, string> | `subcollection:${string}`)[];
propertiesOrder?: (Extract<keyof M, string> | string | `subcollection:${string}` | "collectionGroupParent")[];

/**
* If enabled, content is loaded in batches. If `false` all entities in the
Expand Down
10 changes: 10 additions & 0 deletions packages/firecms_core/src/types/entity_actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ export type EntityAction<M extends object = any, USER extends User = User> = {
*/
name: string;

/**
* Key of the action. You only need to provide this if you want to
* override the default actions.
* The default actions are:
* - edit
* - delete
* - copy
*/
key?: string;

/**
* Icon of the action
*/
Expand Down
28 changes: 28 additions & 0 deletions packages/firecms_core/src/util/entity_actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { EntityAction } from "../types";

const reservedKeys = ["edit", "copy", "delete"];

export function mergeEntityActions(currentActions: EntityAction[], newActions: EntityAction[]): EntityAction[] {
// given the current actions, replace the ones with the same key
// and append the new ones
const updatedActions: EntityAction[] = [];
currentActions.forEach(action => {
const newAction = newActions.find(a => a.key === action.key);
if (newAction) {
const mergedAction = {
...action,
...newAction
}
updatedActions.push(mergedAction);
} else {
updatedActions.push(action);
}
});
newActions.forEach(action => {
if (!currentActions.find(a => a.key === action.key) && (!action.key || !reservedKeys.includes(action.key))) {
updatedActions.push(action);
}
});
return updatedActions;

}
1 change: 1 addition & 0 deletions packages/firecms_core/src/util/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from "./objects";
export * from "./paths";
export * from "./regexp";
export * from "./navigation_utils";
export * from "./entity_actions";
export * from "./useDebouncedCallback";
export * from "./property_utils";
export * from "./resolutions";
Expand Down
6 changes: 6 additions & 0 deletions website/docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
id: changelog
title: Changelog
---
## [3.0.0-beta.12] - 2024-12-

- You can now override custom entity actions. Just provide an action with one of the keys `edit`, `copy` or `delete` in
the `entityActions` prop in the collection view. This will override the default actions for the entity.


## [3.0.0-beta.11] - 2024-12-13

- New Next.js template for FireCMS PRO. You can now create a new project with the PRO template using the CLI.
Expand Down
19 changes: 11 additions & 8 deletions website/docs/collections/entity_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ modifying data, accessing storage, opening dialogs, etc.
In the `icon` prop, you can pass a React element to show an icon next to the action name.
We recommend using any of the [FireCMS icons](/docs/icons), which are available in the `@firecms/ui` package.


```tsx

export const productsCollection = buildCollection<Product>({
Expand Down Expand Up @@ -53,18 +52,23 @@ export const productsCollection = buildCollection<Product>({
});
```


#### EntityAction

* `name`: Name of the action
* `key`?: Key of the action. You only need to provide this if you want to
override the default actions.
The default actions are:
- edit
- delete
- copy
* `icon`?: React.ReactElement Icon of the action
* `onClick`: (props: EntityActionClickProps) => Promise
Function to be called when the action is clicked
* `collapsed`?: boolean Show this action collapsed in the menu of the collection view. Defaults to true. If false, the action will be shown in the menu
* `onClick`: (props: EntityActionClickProps) => Promise
Function to be called when the action is clicked
* `collapsed`?: boolean Show this action collapsed in the menu of the collection view. Defaults to true. If false, the
action will be shown in the menu
* `includeInForm`?: boolean Show this action in the form, defaults to true
* `disabled`?: boolean Disable this action, defaults to false


#### EntityActionClickProps

* `entity`: Entity being edited
Expand All @@ -77,10 +81,9 @@ Function to be called when the action is clicked
* `onCollectionChange`?: () => void
* `sideEntityController`?: SideEntityController


## Example

Let's build an example where we add an action to archive a product.
Let's build an example where we add an action to archive a product.
When the action is clicked, we will call a Google Cloud Function to that will run some business logic,
in the backend.

Expand Down
Loading

0 comments on commit d3166cd

Please sign in to comment.