From 7ab530b64435ccec030687a5e0eaf50863661da9 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Thu, 17 Oct 2019 14:42:52 +0200 Subject: [PATCH 1/3] Remove ra-tree Closes #3827 --- Makefile | 10 +- docs/Ecosystem.md | 4 +- docs/Labs.md | 17 -- docs/List.md | 64 ----- docs/_layouts/default.html | 5 - examples/simple/package.json | 2 - examples/simple/src/index.js | 2 - examples/simple/src/tags/TagList.js | 137 +++++++--- examples/simple/webpack.config.js | 16 -- packages/ra-tree-core/README.md | 89 ------- packages/ra-tree-core/package.json | 51 ---- packages/ra-tree-core/src/TreeController.js | 95 ------- packages/ra-tree-core/src/actions.js | 21 -- packages/ra-tree-core/src/getTreeFromArray.js | 37 --- .../ra-tree-core/src/getTreeFromArray.spec.js | 55 ---- packages/ra-tree-core/src/index.js | 5 - packages/ra-tree-core/src/reducer.js | 26 -- packages/ra-tree-core/src/selectors.js | 2 - packages/ra-tree-core/tsconfig.json | 9 - packages/ra-tree-language-english/README.md | 29 --- packages/ra-tree-language-english/index.js | 9 - .../ra-tree-language-english/package.json | 22 -- packages/ra-tree-language-french/README.md | 29 --- packages/ra-tree-language-french/index.js | 9 - packages/ra-tree-language-french/package.json | 22 -- packages/ra-tree-ui-materialui/README.md | 242 ------------------ packages/ra-tree-ui-materialui/package.json | 65 ----- .../ra-tree-ui-materialui/src/DragLayer.js | 69 ----- .../ra-tree-ui-materialui/src/DragPreview.js | 52 ---- .../src/IgnoreFormProps.js | 43 ---- .../ra-tree-ui-materialui/src/NodeActions.js | 33 --- .../ra-tree-ui-materialui/src/NodeForm.js | 220 ---------------- .../src/NodeFormActions.js | 11 - .../ra-tree-ui-materialui/src/NodeView.js | 88 ------- .../src/RootDropTarget.js | 91 ------- packages/ra-tree-ui-materialui/src/Tree.js | 221 ---------------- .../ra-tree-ui-materialui/src/TreeNode.js | 196 -------------- .../src/TreeNodeContent.js | 62 ----- .../src/TreeNodeWithChildren.js | 127 --------- .../ra-tree-ui-materialui/src/constants.js | 1 - .../ra-tree-ui-materialui/src/draggable.js | 93 ------- .../ra-tree-ui-materialui/src/droppable.js | 45 ---- packages/ra-tree-ui-materialui/src/index.js | 8 - packages/ra-tree-ui-materialui/tsconfig.json | 9 - tsconfig.json | 14 +- 45 files changed, 107 insertions(+), 2350 deletions(-) delete mode 100644 docs/Labs.md delete mode 100644 packages/ra-tree-core/README.md delete mode 100644 packages/ra-tree-core/package.json delete mode 100644 packages/ra-tree-core/src/TreeController.js delete mode 100644 packages/ra-tree-core/src/actions.js delete mode 100644 packages/ra-tree-core/src/getTreeFromArray.js delete mode 100644 packages/ra-tree-core/src/getTreeFromArray.spec.js delete mode 100644 packages/ra-tree-core/src/index.js delete mode 100644 packages/ra-tree-core/src/reducer.js delete mode 100644 packages/ra-tree-core/src/selectors.js delete mode 100644 packages/ra-tree-core/tsconfig.json delete mode 100644 packages/ra-tree-language-english/README.md delete mode 100644 packages/ra-tree-language-english/index.js delete mode 100644 packages/ra-tree-language-english/package.json delete mode 100644 packages/ra-tree-language-french/README.md delete mode 100644 packages/ra-tree-language-french/index.js delete mode 100644 packages/ra-tree-language-french/package.json delete mode 100644 packages/ra-tree-ui-materialui/README.md delete mode 100644 packages/ra-tree-ui-materialui/package.json delete mode 100644 packages/ra-tree-ui-materialui/src/DragLayer.js delete mode 100644 packages/ra-tree-ui-materialui/src/DragPreview.js delete mode 100644 packages/ra-tree-ui-materialui/src/IgnoreFormProps.js delete mode 100644 packages/ra-tree-ui-materialui/src/NodeActions.js delete mode 100644 packages/ra-tree-ui-materialui/src/NodeForm.js delete mode 100644 packages/ra-tree-ui-materialui/src/NodeFormActions.js delete mode 100644 packages/ra-tree-ui-materialui/src/NodeView.js delete mode 100644 packages/ra-tree-ui-materialui/src/RootDropTarget.js delete mode 100644 packages/ra-tree-ui-materialui/src/Tree.js delete mode 100644 packages/ra-tree-ui-materialui/src/TreeNode.js delete mode 100644 packages/ra-tree-ui-materialui/src/TreeNodeContent.js delete mode 100644 packages/ra-tree-ui-materialui/src/TreeNodeWithChildren.js delete mode 100644 packages/ra-tree-ui-materialui/src/constants.js delete mode 100644 packages/ra-tree-ui-materialui/src/draggable.js delete mode 100644 packages/ra-tree-ui-materialui/src/droppable.js delete mode 100644 packages/ra-tree-ui-materialui/src/index.js delete mode 100644 packages/ra-tree-ui-materialui/tsconfig.json diff --git a/Makefile b/Makefile index c28563dbfcd..5abf24a7eee 100644 --- a/Makefile +++ b/Makefile @@ -74,19 +74,11 @@ build-ra-realtime: @echo "Transpiling ra-realtime files..."; @cd ./packages/ra-realtime && yarn -s build -build-ra-tree-core: - @echo "Transpiling ra-tree-core files..."; - @cd ./packages/ra-tree-core && yarn -s build - -build-ra-tree-ui-materialui: - @echo "Transpiling ra-tree-ui-materialui files..."; - @cd ./packages/ra-tree-ui-materialui && yarn -s build - build-data-generator: @echo "Transpiling data-generator files..."; @cd ./examples/data-generator && yarn -s build -build: build-ra-core build-ra-ui-materialui build-ra-data-fakerest build-ra-data-json-server build-ra-data-simple-rest build-ra-data-graphql build-ra-data-graphcool build-ra-data-graphql-simple build-ra-i18n-polyglot build-ra-input-rich-text build-ra-realtime build-ra-tree-core build-ra-tree-ui-materialui build-data-generator build-react-admin ## compile ES6 files to JS +build: build-ra-core build-ra-ui-materialui build-ra-data-fakerest build-ra-data-json-server build-ra-data-simple-rest build-ra-data-graphql build-ra-data-graphcool build-ra-data-graphql-simple build-ra-i18n-polyglot build-ra-input-rich-text build-ra-realtime build-data-generator build-react-admin ## compile ES6 files to JS doc: ## compile doc as html and launch doc web server @yarn -s doc diff --git a/docs/Ecosystem.md b/docs/Ecosystem.md index 638edca3602..4c839248e9c 100644 --- a/docs/Ecosystem.md +++ b/docs/Ecosystem.md @@ -68,8 +68,8 @@ See the [translation](./Translation.md#available-locales) page. ## Miscellaneous - [marmelab/ra-realtime](https://github.com/marmelab/react-admin/tree/master/packages/ra-realtime): enable realtime updates -- [marmelab/ra-tree-ui-materialui](https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-ui-materialui/): Components to show data represented as a tree. This package is part of our [Labs](/Labs.md) experimentations. This means it misses some features and might not handle all corner cases. Use it at your own risks. Besides, we would really appreciate some feedback! -- [marmelab/ra-tree-core](https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-core/): Components providing the logic but no UI to show data represented as a tree. This package is part of our [Labs](/Labs.md) experimentations. This means it misses some features and might not handle all corner cases. Use it at your own risks. Besides, we would really appreciate some feedback! +- [marmelab/ra-tree-ui-materialui](https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-ui-materialui/): Components to show data represented as a tree. Only compatible with react-admin v2 for now. +- [marmelab/ra-tree-core](https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-core/): Components providing the logic but no UI to show data represented as a tree. Only compatible with react-admin v2 for now. - [ra-customizable-datagrid](https://github.com/fizix-io/ra-customizable-datagrid): plugin that allows to hide / show columns dynamically. - [FusionWorks/react-admin-google-maps](https://github.com/FusionWorks/react-admin-google-maps): Input/view components for displaying location using Google Maps. - [api-platform/admin](https://api-platform.com/docs/admin): create a fully featured admin using React Admin for API supporting the [Hydra Core Vocabulary](http://www.hydra-cg.com/), including but not limited to APIs created using the [API Platform framework](https://api-platform.com) diff --git a/docs/Labs.md b/docs/Labs.md deleted file mode 100644 index f078f572159..00000000000 --- a/docs/Labs.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: default -title: "Labs" ---- - -# Labs - -This section references some projects we're working which are not ready yet for production. They probably miss some features or are not handling all corner cases. Use them at your own risks. Besides, we would really appreciate some feedback! - -## ra-tree - -![ra-tree demo](./img/ra-tree.gif) - -`ra-tree` is a set of components allowing to work with tree data. It is composed of two packages: - -- `ra-tree-core`: The core components which only provides logic and no UI. Read more about it in its [README](https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-core/README.md) -- `ra-tree-ui-materialui`: Some UI components using the previous package and built with material-ui. Read more about it in its [README](https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-ui-materialui/README.md) diff --git a/docs/List.md b/docs/List.md index 33bf2c560c1..63f7bfb122e 100644 --- a/docs/List.md +++ b/docs/List.md @@ -1167,70 +1167,6 @@ When you want to display only one property of a list of records, instead of usin ``` -## The `` component - -When you want to display a hierarchized list of records, instead of using a ``, use the `` component. This component is available in an addon package: [`ra-tree-ui-materialui`](https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-ui-materialui/README.md). - -*Important*: This package is part of our [Labs](/Labs.md) experimentations. This means it misses some features and might not handle all corner cases. Use it at your own risks. Besides, we would really appreciate some feedback! - -It expects that every resource returned from the `List` has a `parent_id` property by default: - -```json -[ - { "id": 1, "name": "Clothing" }, - { "id": 2, "name": "Men", "parent_id": 1 }, - { "id": 3, "name": "Suits", "parent_id": 2 }, - { "id": 6, "name": "Women", "parent_id": 1 }, - { "id": 7, "name": "Dresses", "parent_id": 6 }, - { "id": 10, "name": "Skirts", "parent_id": 6 }, - { "id": 11, "name": "Blouses", "parent_id": 6 } -] -``` - -Here's an example showing how to use it: - -```jsx -// in src/categories.js -import React from 'react'; -import { List, TextField, EditButton, DeleteButton } from 'react-admin'; -import { Tree, NodeView, NodeActions } from 'ra-tree-ui-materialui'; - -const CategoriesActions = props => ( - - - - -); - -export const CategoriesList = (props) => ( - - - }> - - - - -); -``` - -![ra-tree demo](./img/ra-tree.gif) - -**Tip**: The `` component supports drag & drop operations: - -```jsx -export const CategoriesList = (props) => ( - - - }> - - - - -); -``` - -To learn more about this component features, please refers to its [README](https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-ui-materialui/README.md). - ## Using a Custom Iterator A `` can delegate to any iterator component - `` is just one example. An iterator component must accept at least two props: diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index ba59ecb884e..1f59f0b7f72 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -843,11 +843,6 @@ -
  • - - 22. Labs - -
  • diff --git a/examples/simple/package.json b/examples/simple/package.json index 8ac411783fc..cab6beef227 100644 --- a/examples/simple/package.json +++ b/examples/simple/package.json @@ -42,8 +42,6 @@ "ra-input-rich-text": "^3.0.0-alpha.0", "ra-language-english": "^3.0.0-alpha.0", "ra-language-french": "^3.0.0-alpha.0", - "ra-tree-core": "^3.0.0-alpha.0", - "ra-tree-ui-materialui": "^3.0.0-alpha.0", "react": "^16.9.0", "react-admin": "^3.0.0-alpha.0", "react-dom": "^16.9.0" diff --git a/examples/simple/src/index.js b/examples/simple/src/index.js index 664f47381d3..5d4a8230b85 100644 --- a/examples/simple/src/index.js +++ b/examples/simple/src/index.js @@ -3,7 +3,6 @@ import React from 'react'; import { Admin, Resource } from 'react-admin'; // eslint-disable-line import/no-unresolved import { render } from 'react-dom'; import { Route } from 'react-router-dom'; -import { reducer as tree } from 'ra-tree-ui-materialui'; import authProvider from './authProvider'; import comments from './comments'; @@ -23,7 +22,6 @@ render( i18nProvider={i18nProvider} title="Example Admin" layout={Layout} - customReducers={{ tree }} customRoutes={[ ( - {({ node }) => node.record.name} -); +const useStyles = makeStyles({ + card: { + maxWidth: '20em', + marginTop: '1em', + }, +}); +const SmallCard = ({ className, ...props }) => { + const classes = useStyles(); + return ; +}; -const CustomNodeActions = props => ( - - - - - - - -); +const SubTree = ({ level, root, getChildNodes, openChildren, toggleNode }) => { + const childNodes = getChildNodes(root); + const hasChildren = childNodes.length > 0; + const open = openChildren.includes(root.id); + return ( + + hasChildren && toggleNode(root)} + style={{ paddingLeft: level * 16 }} + > + {hasChildren && open && } + {hasChildren && !open && } + {!hasChildren &&
     
    } + + + + + +
    + + + {childNodes.map(node => ( + + ))} + + +
    + ); +}; + +const Tree = ({ ids, data }) => { + const [openChildren, setOpenChildren] = useState([]); + const toggleNode = node => + setOpenChildren(state => { + if (state.includes(node.id)) { + return [ + ...state.splice(0, state.indexOf(node.id)), + ...state.splice(state.indexOf(node.id) + 1, state.length), + ]; + } else { + return [...state, node.id]; + } + }); + const nodes = ids.map(id => data[id]); + const roots = nodes.filter(node => typeof node.parent_id === 'undefined'); + const getChildNodes = root => + nodes.filter(node => node.parent_id === root.id); + return ( + + {roots.map(root => ( + + ))} + + ); +}; const TagList = props => ( - - - }> - - - + + ); diff --git a/examples/simple/webpack.config.js b/examples/simple/webpack.config.js index 074205266c6..8b03c8f194d 100644 --- a/examples/simple/webpack.config.js +++ b/examples/simple/webpack.config.js @@ -93,22 +93,6 @@ module.exports = { 'ra-input-rich-text', 'src' ), - 'ra-tree-core': path.join( - __dirname, - '..', - '..', - 'packages', - 'ra-tree-core', - 'src' - ), - 'ra-tree-ui-materialui': path.join( - __dirname, - '..', - '..', - 'packages', - 'ra-tree-ui-materialui', - 'src' - ), }, }, devServer: { diff --git a/packages/ra-tree-core/README.md b/packages/ra-tree-core/README.md deleted file mode 100644 index 47067ba21bd..00000000000 --- a/packages/ra-tree-core/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# ra-tree-core - -A component to display hierarchized data in [react-admin](https://github.com/marmelab/react-admin). This package is UI agnostic. It provides redux actions, reducers and a component using render prop. - -## Installation - -```sh -npm install --save ra-tree-core -# or -yarn add ra-tree-core -``` - -## Usage - -With a categories ressource having this structure where a category may have a parent category referenced by the `parent_id` field: - -```json -[ - { "id": 1, "name": "Clothing" }, - { "id": 2, "name": "Men", "parent_id": 1 }, - { "id": 3, "name": "Suits", "parent_id": 2 }, - { "id": 4, "name": "Slacks", "parent_id": 3 }, - { "id": 5, "name": "Jackets", "parent_id": 3 }, - { "id": 6, "name": "Women", "parent_id": 1 }, - { "id": 7, "name": "Dresses", "parent_id": 6 }, - { "id": 8, "name": "Evening Gowns", "parent_id": 7 }, - { "id": 9, "name": "Sun Dresses", "parent_id": 7 }, - { "id": 10, "name": "Skirts", "parent_id": 6 }, - { "id": 11, "name": "Blouses", "parent_id": 6 } -] -``` - -```js -// in src/category/list.js -import React from 'react'; -import { - List, - TextField, -} from 'react-admin'; -import { TreeController } from 'ra-tree-core'; -import TreeNode from './TreeNode'; - -export const CategoriesList = (props) => ( - - - {({ tree }) => ( - - {tree.map(node => )} - - )} - - -); -``` - -`react-admin` will fetch the data and the `TreeController` component will build a tree from it. Note that every category which do not have a parent will be considered a root node. The `TreeController` component will call its children function which is responsible for the actual rendering. - -## API - -### - -Meant to be used as the child of the [`List`](https://marmelab.com/react-admin/List.html#the-list-component), [`ReferenceManyField`](https://marmelab.com/react-admin/Fields.html#referencemanyfield) or [ReferenceArrayField](https://marmelab.com/react-admin/Fields.html#referencearrayfield) components. - -The `TreeController` accepts the following props: - -- `getTreeFromArray`: The function used to build the tree from the fetched data. It defaults to one using [performant-array-to-tree](https://github.com/philipstanislaus/performant-array-to-tree) -- `getTreeState`: A function which must return the tree state root from the redux state in case you mounted it on a different key than `tree`. It will be called with a single `state` argument which is the redux state. -- `children`: A function which will be called with a single object argument having the following props - - `tree`: an array of the root nodes. Each node have the following properties: - - `children`: an array of its child nodes - - `depth`: a number indicating its depth in the hierarchy - - `record`: the node's original data - - `getIsNodeExpanded`: a function which takes a node identifier and returns a boolean indicating whether this node is expanded - - `toggleNode`: a function which takes a node identifier and toggles its expanded state - - `expandNode`: a function which takes a node identifier and explicitly expands it - - `closeNode`: a function which takes a node identifier and explicitly closes it - - any additional props received by the `TreeController` component -- `parentSource`: The field used as the parent identifier for each node. Defaults to `parent_id` - -## Roadmap - -- Support nested set hierarchical data -- `TreeSelectInputController` to select a value inside the hierarchical data (with autocomplete showing the matched nodes) -- `TreeInputController` to edit a field containing hierarchical data as json -- `TreeNodeFieldController` to show a node and its hierarchie. It should recursively fetch the parents by default, accepting a custom function to fetch them in one call (`fetchHierarchy`). - -## License - -This library is licensed under the MIT License, and sponsored by [marmelab](http://marmelab.com). diff --git a/packages/ra-tree-core/package.json b/packages/ra-tree-core/package.json deleted file mode 100644 index 364aae52390..00000000000 --- a/packages/ra-tree-core/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "ra-tree-core", - "version": "3.0.0-beta.0", - "description": "A treeview component without ui to use with react-admin", - "main": "lib/index.js", - "module": "esm/index.js", - "sideEffects": false, - "files": [ - "LICENSE", - "*.md", - "lib", - "esm", - "src" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/marmelab/react-admin.git" - }, - "keywords": [ - "reactjs", - "react", - "react-admin", - "admin-on-rest", - "treeview", - "tree" - ], - "author": "Gildas Garcia", - "license": "MIT", - "bugs": { - "url": "https://github.com/marmelab/react-admin/issues" - }, - "homepage": "https://github.com/marmelab/react-admin#readme", - "scripts": { - "build": "yarn run build-cjs && yarn run build-esm", - "build-cjs": "rimraf ./lib && tsc", - "build-esm": "rimraf ./esm && tsc --outDir esm --module es2015", - "watch": "rimraf ./lib && tsc --watch" - }, - "peerDependencies": { - "react": "^16.9.0", - "react-dom": "^16.9.0" - }, - "dependencies": { - "performant-array-to-tree": "^1.1.2", - "prop-types": "^15.6.1" - }, - "devDependencies": { - "cross-env": "^5.2.0", - "rimraf": "^2.6.3" - } -} diff --git a/packages/ra-tree-core/src/TreeController.js b/packages/ra-tree-core/src/TreeController.js deleted file mode 100644 index ef43c4e7c69..00000000000 --- a/packages/ra-tree-core/src/TreeController.js +++ /dev/null @@ -1,95 +0,0 @@ -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import defaultGetTreeFromArray from './getTreeFromArray'; -import { getIsNodeExpanded } from './selectors'; -import { - closeNode as closeNodeAction, - expandNode as expandNodeAction, - toggleNode as toggleNodeAction, -} from './actions'; -import { Component } from 'react'; - -const defaultGetTreeState = state => state.tree; - -export class TreeControllerView extends Component { - static propTypes = { - basePath: PropTypes.string.isRequired, - children: PropTypes.func.isRequired, - closeNode: PropTypes.func.isRequired, - expandNode: PropTypes.func.isRequired, - ids: PropTypes.array.isRequired, - data: PropTypes.object.isRequired, - getTreeFromArray: PropTypes.func, - getTreeState: PropTypes.func, - parentSource: PropTypes.string, - resource: PropTypes.string.isRequired, - toggleNode: PropTypes.func.isRequired, - treeState: PropTypes.object, - }; - - handleGetIsNodeExpanded = nodeId => - getIsNodeExpanded(this.props.treeState, this.props.resource, nodeId); - - handleCloseNode = nodeId => - this.props.closeNode(this.props.resource, nodeId); - - handleExpandNode = nodeId => - this.props.expandNode(this.props.resource, nodeId); - - handleToggleNode = nodeId => - this.props.toggleNode(this.props.resource, nodeId); - - render() { - const { - children, - closeNode, - expandNode, - data: { fetchedAt, ...data }, - getTreeFromArray, - getTreeState, - ids, - parentSource, - resource, - toggleNode, - treeState, - ...props - } = this.props; - const availableData = ids.reduce((acc, id) => [...acc, data[id]], []); - const tree = getTreeFromArray( - Object.values(availableData), - parentSource - ); - - return children({ - getIsNodeExpanded: this.handleGetIsNodeExpanded, - parentSource, - tree, - closeNode: this.handleCloseNode, - expandNode: this.handleExpandNode, - toggleNode: this.handleToggleNode, - resource, - ...props, - }); - } -} - -const mapStateToProps = (state, { getTreeState }) => ({ - treeState: getTreeState(state), -}); - -const TreeController = connect( - mapStateToProps, - { - closeNode: closeNodeAction, - expandNode: expandNodeAction, - toggleNode: toggleNodeAction, - } -)(TreeControllerView); - -TreeController.defaultProps = { - getTreeFromArray: defaultGetTreeFromArray, - getTreeState: defaultGetTreeState, - parentSource: 'parent_id', -}; - -export default TreeController; diff --git a/packages/ra-tree-core/src/actions.js b/packages/ra-tree-core/src/actions.js deleted file mode 100644 index 635fae01162..00000000000 --- a/packages/ra-tree-core/src/actions.js +++ /dev/null @@ -1,21 +0,0 @@ -export const TOGGLE_NODE = 'RA/TREE/TOGGLE_NODE'; -export const EXPAND_NODE = 'RA/TREE/EXPAND_NODE'; -export const CLOSE_NODE = 'RA/TREE/CLOSE_NODE'; - -export const toggleNode = (resource, nodeId) => ({ - type: TOGGLE_NODE, - payload: nodeId, - meta: { resource }, -}); - -export const expandNode = (resource, nodeId) => ({ - type: EXPAND_NODE, - payload: nodeId, - meta: { resource }, -}); - -export const closeNode = (resource, nodeId) => ({ - type: CLOSE_NODE, - payload: nodeId, - meta: { resource }, -}); diff --git a/packages/ra-tree-core/src/getTreeFromArray.js b/packages/ra-tree-core/src/getTreeFromArray.js deleted file mode 100644 index 55dca64ecb6..00000000000 --- a/packages/ra-tree-core/src/getTreeFromArray.js +++ /dev/null @@ -1,37 +0,0 @@ -import { arrayToTree } from 'performant-array-to-tree'; - -/** - * Recursivly create nodes. - */ -const createNode = ({ children, ...node }) => ({ - id: node.data.id, - record: node.data, - children: children ? children.map(child => createNode(child)) : [], -}); - -/** - * Recursivly add a parent property to every nodes so that they can a reference to their parent - */ -const addParent = (node, parent) => ({ - ...node, - children: node.children.map(child => addParent(child, node)), - parent, -}); - -/** - * Build a tree representation of the data returned by the List component - */ -export default (data, parentSource) => { - // arrayToTree requires top level nodes to have their parent id set to null - const sanitizedData = data.map(item => ({ - ...item, - [parentSource]: item[parentSource] || null, - })); - - return arrayToTree(sanitizedData, { - id: 'id', - parentId: parentSource, - }) - .map(node => createNode(node)) - .map(node => addParent(node, null)); -}; diff --git a/packages/ra-tree-core/src/getTreeFromArray.spec.js b/packages/ra-tree-core/src/getTreeFromArray.spec.js deleted file mode 100644 index 2ad7c39d05d..00000000000 --- a/packages/ra-tree-core/src/getTreeFromArray.spec.js +++ /dev/null @@ -1,55 +0,0 @@ -import getTreeFromArray from './getTreeFromArray'; - -const getNode = ({ id, record, children }) => ({ - id, - record, - childCount: children.length, -}); -const getNodeFromData = (record, childCount) => ({ - id: record.id, - record: { ...record, parent_id: record.parent_id || null }, - childCount, -}); - -describe('getTreeFromArray', () => { - it('return a tree from flat data', () => { - const data = [ - { id: 2, name: 'Men', parent_id: 1 }, - { id: 1, name: 'Clothing' }, - { id: 11, name: 'Blouses', parent_id: 6 }, - { id: 8, name: 'Evening Gowns', parent_id: 7 }, - { id: 4, name: 'Slacks', parent_id: 3 }, - { id: 5, name: 'Jackets', parent_id: 3 }, - { id: 3, name: 'Suits', parent_id: 2 }, - { id: 10, name: 'Skirts', parent_id: 6 }, - { id: 6, name: 'Women', parent_id: 1 }, - { id: 7, name: 'Dresses', parent_id: 6 }, - { id: 9, name: 'Sun Dresses', parent_id: 7 }, - ]; - - const tree = getTreeFromArray(data, 'parent_id'); - expect(tree.map(getNode)).toEqual([ - getNodeFromData(data.find(d => d.id === 1), 2), - ]); - expect(tree[0].children.map(getNode)).toEqual([ - getNodeFromData(data.find(d => d.id === 2), 1), - getNodeFromData(data.find(d => d.id === 6), 3), - ]); - expect(tree[0].children[0].children.map(getNode)).toEqual([ - getNodeFromData(data.find(d => d.id === 3), 2), - ]); - expect(tree[0].children[0].children[0].children.map(getNode)).toEqual([ - getNodeFromData(data.find(d => d.id === 4), 0), - getNodeFromData(data.find(d => d.id === 5), 0), - ]); - expect(tree[0].children[1].children.map(getNode)).toEqual([ - getNodeFromData(data.find(d => d.id === 11), 0), - getNodeFromData(data.find(d => d.id === 10), 0), - getNodeFromData(data.find(d => d.id === 7), 2), - ]); - expect(tree[0].children[1].children[2].children.map(getNode)).toEqual([ - getNodeFromData(data.find(d => d.id === 8), 0), - getNodeFromData(data.find(d => d.id === 9), 0), - ]); - }); -}); diff --git a/packages/ra-tree-core/src/index.js b/packages/ra-tree-core/src/index.js deleted file mode 100644 index 17ac39fc58a..00000000000 --- a/packages/ra-tree-core/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import TreeController from './TreeController'; -import reducer from './reducer'; -export { TreeController, reducer }; -export * from './actions'; -export * from './selectors'; diff --git a/packages/ra-tree-core/src/reducer.js b/packages/ra-tree-core/src/reducer.js deleted file mode 100644 index 56ff438b226..00000000000 --- a/packages/ra-tree-core/src/reducer.js +++ /dev/null @@ -1,26 +0,0 @@ -import { CLOSE_NODE, TOGGLE_NODE, EXPAND_NODE } from './actions'; - -const initialState = {}; - -export default (state = initialState, { type, payload: nodeId, meta }) => { - if (![CLOSE_NODE, TOGGLE_NODE, EXPAND_NODE].includes(type)) { - return state; - } - if (!meta.resource) { - console.warn(`The ${type} action does not have a resource meta`); // eslint-disable-line - return state; - } - - return { - ...state, - [meta.resource]: { - ...(state[meta.resource] || {}), - [nodeId]: - type === TOGGLE_NODE - ? state[meta.resource] - ? !state[meta.resource][nodeId] - : true - : type === EXPAND_NODE, - }, - }; -}; diff --git a/packages/ra-tree-core/src/selectors.js b/packages/ra-tree-core/src/selectors.js deleted file mode 100644 index 281c89a77da..00000000000 --- a/packages/ra-tree-core/src/selectors.js +++ /dev/null @@ -1,2 +0,0 @@ -export const getIsNodeExpanded = (state, resource, nodeId) => - (state[resource] && state[resource][nodeId]) || false; diff --git a/packages/ra-tree-core/tsconfig.json b/packages/ra-tree-core/tsconfig.json deleted file mode 100644 index 8be9b276492..00000000000 --- a/packages/ra-tree-core/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "lib", - "rootDir": "src" - }, - "exclude": ["**/*.spec.ts", "**/*.spec.tsx", "**/*.spec.js"], - "include": ["src"] -} diff --git a/packages/ra-tree-language-english/README.md b/packages/ra-tree-language-english/README.md deleted file mode 100644 index a76e95ac47d..00000000000 --- a/packages/ra-tree-language-english/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# English Messages for ra-tree - -English messages for `ra-tree`, an addon providing tree components for [react-admin](https://github.com/marmelab/react-admin), the frontend framework for building admin applications on top of REST/GraphQL services. - -## Installation - -```sh -npm install --save ra-language-english ra-tree-language-english -``` - -## Usage - -```js -import englishMessages from 'ra-language-english'; -import treeEnglishMessages from 'ra-tree-language-english'; -import { mergeTranslations } from 'react-admin'; - -const messages = { - 'en': mergeTranslations(englishMessages, treeEnglishMessages), -}; - - - ... - -``` - -## License - -This translation is licensed under the MIT License, and sponsored by [marmelab](http://marmelab.com). diff --git a/packages/ra-tree-language-english/index.js b/packages/ra-tree-language-english/index.js deleted file mode 100644 index bdf28d1e7c0..00000000000 --- a/packages/ra-tree-language-english/index.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - ra: { - tree: { - drag_preview: - 'Node #%{id} |||| Node #%{id} with %{smart_count} children', - root_target: 'Drop an item here to make it top level', - }, - }, -}; diff --git a/packages/ra-tree-language-english/package.json b/packages/ra-tree-language-english/package.json deleted file mode 100644 index 51bce7d378f..00000000000 --- a/packages/ra-tree-language-english/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "ra-tree-language-english", - "version": "3.0.0-alpha.1", - "description": "English messages for ra-tree, an addon providing tree components for react-admin, the frontend framework for building admin applications on top of REST/GraphQL services", - "main": "index.js", - "repository": { - "type": "git", - "url": "git+https://github.com/marmelab/react-admin.git" - }, - "keywords": [ - "react", - "react-admin", - "ra-tree", - "translation" - ], - "author": "Gildas Garcia", - "license": "MIT", - "bugs": { - "url": "https://github.com/marmelab/react-admin/issues" - }, - "homepage": "https://github.com/marmelab/react-admin#readme" -} diff --git a/packages/ra-tree-language-french/README.md b/packages/ra-tree-language-french/README.md deleted file mode 100644 index 0d40654b693..00000000000 --- a/packages/ra-tree-language-french/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# French Messages for ra-tree - -French messages for `ra-tree`, an addon providing tree components for [react-admin](https://github.com/marmelab/react-admin), the frontend framework for building admin applications on top of REST/GraphQL services. - -## Installation - -```sh -npm install --save ra-language-french ra-tree-language-french -``` - -## Usage - -```js -import frenchMessages from 'ra-language-french'; -import treeFrenchMessages from 'ra-tree-language-french'; -import { mergeTranslations } from 'react-admin'; - -const messages = { - 'fr': mergeTranslations(frenchMessages, treeFrenchMessages), -}; - - - ... - -``` - -## License - -This translation is licensed under the MIT License, and sponsored by [marmelab](http://marmelab.com). diff --git a/packages/ra-tree-language-french/index.js b/packages/ra-tree-language-french/index.js deleted file mode 100644 index bf876588374..00000000000 --- a/packages/ra-tree-language-french/index.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - ra: { - tree: { - drag_preview: - 'Nœud #%{id} |||| Nœud #%{id} contenant %{smart_count} enfants', - root_target: 'Lâcher un nœud ici pour le remonter à la racine', - }, - }, -}; diff --git a/packages/ra-tree-language-french/package.json b/packages/ra-tree-language-french/package.json deleted file mode 100644 index 1057b161cce..00000000000 --- a/packages/ra-tree-language-french/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "ra-tree-language-french", - "version": "3.0.0-alpha.1", - "description": "French messages for ra-tree, an addon providing tree components for react-admin, the frontend framework for building admin applications on top of REST/GraphQL services", - "main": "index.js", - "repository": { - "type": "git", - "url": "git+https://github.com/marmelab/react-admin.git" - }, - "keywords": [ - "react", - "react-admin", - "ra-tree", - "translation" - ], - "author": "Gildas Garcia", - "license": "MIT", - "bugs": { - "url": "https://github.com/marmelab/react-admin/issues" - }, - "homepage": "https://github.com/marmelab/react-admin#readme" -} diff --git a/packages/ra-tree-ui-materialui/README.md b/packages/ra-tree-ui-materialui/README.md deleted file mode 100644 index 3ca00c2776e..00000000000 --- a/packages/ra-tree-ui-materialui/README.md +++ /dev/null @@ -1,242 +0,0 @@ -# ra-tree-ui-materialui - -A Tree component with [material-ui](https://github.com/mui-org/material-ui) to use with [react-admin](https://github.com/marmelab/react-admin). - -![`ra-tree-ui-materialui`](https://github.com/marmelab/react-admin/raw/master/docs/img/ra-tree.gif) - -## Installation - -```sh -npm install --save ra-tree-ui-materialui ra-tree-language-english -# or -yarn add ra-tree-ui-materialui ra-tree-language-english -``` - -## Usage - -With a `categories` ressource having this structure where a category may have a parent category referenced by the `parent_id` field: - -```json -[ - { "id": 1, "name": "Clothing" }, - { "id": 2, "name": "Men", "parent_id": 1 }, - { "id": 3, "name": "Suits", "parent_id": 2 }, - { "id": 4, "name": "Slacks", "parent_id": 3 }, - { "id": 5, "name": "Jackets", "parent_id": 3 }, - { "id": 6, "name": "Women", "parent_id": 1 }, - { "id": 7, "name": "Dresses", "parent_id": 6 }, - { "id": 8, "name": "Evening Gowns", "parent_id": 7 }, - { "id": 9, "name": "Sun Dresses", "parent_id": 7 }, - { "id": 10, "name": "Skirts", "parent_id": 6 }, - { "id": 11, "name": "Blouses", "parent_id": 6 } -] -``` - -First, you need to register the tree reducer and the translations: - -```js -// in App.js -import React from 'react'; -import { Admin, Resource, mergeTranslations } from 'react-admin'; -import { reducer as tree } from 'ra-tree-ui-materialui'; -import englishMessages from 'ra-language-english'; -import treeEnglishMessages from 'ra-tree-language-english'; -import polyglotI18nProvider from 'ra-i18n-polyglot'; - -import dataProvider from './dataProvider'; -import posts from './posts'; -import tags from './tags'; - -const messages = { - 'en': mergeTranslations(englishMessages, treeEnglishMessages), -}; -const i18nProvider = polyglotI18nProvider(locale => messages[locale]); - -const App = () => ( - - - - -) -``` - -You can then use the tree components: - -```js -// in src/category/list.js -import React from 'react'; -import { - List, - TextField, - EditButton, - DeleteButton, -} from 'react-admin'; -import { Tree, NodeView, NodeActions } from 'ra-tree-ui-materialui'; - -const CategoriesActions = props => ( - - - - -); - -export const CategoriesList = (props) => ( - - - }> - - - - -); -``` - -`react-admin` will fetch the data and the `Tree` component will build a tree from it. Note that every category which do not have a parent will be considered a root node. Note that we specified a very high `perPage` prop on the `List` component. Indeed, the `Tree` component needs the entire tree to work so you'll have to make sure your API returns all the required items. - -## Editable - -Requires [react-dnd](https://github.com/react-dnd/react-dnd) to be installed. See [Dependencies](#dependencies). - -```js -import React, { Component } from 'react'; -import { - List, - EditButton, - DeleteButton, - SaveButton, - TextInput, -} from 'react-admin'; -import { IgnoreFormProps, Tree, NodeForm, NodeActions } from 'ra-tree-ui-materialui'; - -const CategoriesActions = props => ( - - - {/* This is important to not get warnings about unknown props with those buttons */} - - - - -) - -const CategoriesList = () => ( - - - }> - {/* Quick name edition */} - - - -); -``` - -## Enabling Drag & Drop - -You can enable drag & drop by adding the following props: - -- `enableDragAndDrop`: Enable drag & drop. This will show drag handles on every nodes -- `allowDropOnRoot`: Setting this prop to `true` will add a root drop zone at the top of the list. Dropping node on it will set their parent to null -- `dragPreviewComponent`: Customize the preview of the currently dragged node by passing your own component. You can leverage the existing `DragPreview` component and adjusts its content. See [DragPreview](#dragpreview) -- `undoableDragDrop`: Enable optimistic updates from drag & drop operations. Defaults to `true` - -```js -// in src/category/list.js -import React from 'react'; -import { - List, - TextField, -} from 'react-admin'; -import { Tree } from 'ra-tree-ui-materialui'; - -export const CategoriesList = (props) => ( - - - - - - - -); -``` - -## API - -### - -The `Tree` component accepts the following props: - -- `enableDragAndDrop`: Enable drag & drop. This will show drag handles on every node -- `allowDropOnRoot`: Setting this prop to `true` will add a root drop zone at the top of the list. Dropping nodes on it will set their parent to null -- `dragPreviewComponent`: Customize the preview of the currently dragged node by passing your own component. You can leverage the existing `DragPreview` component and adjusts its content. See [DragPreview](#dragpreview) -- `getTreeFromArray`: The function used to build the tree from the fetched data. By default, uses a function based on [performant-array-to-tree](https://github.com/philipstanislaus/performant-array-to-tree) -- `getTreeState`: A function which must return the tree state root from the redux state in case you mounted it on a different key than `tree`. It will be called with a single `state` argument which is the redux state. -- `children`: A function which will be called with a single object argument having the following props - - `tree`: an array of the root nodes. Each node have the following properties: - - `children`: an array of its child nodes - - `depth`: a number indicating its depth in the hierarchy - - `record`: the node's original data - - any additional props received by the `TreeController` component -- `parentSource`: The field used as the parent identifier for each node. Defaults to `parent_id` - -### - -The `NodeView` component accepts the following props: - -- `actions`: A component displaying actions for each node - -### - -The `NodeForm` component accepts the following props: - -- `actions`: A component displaying actions for each node -- `submitOnEnter`: Enable or disable the automated form submission on enter -- `undoable`: Enable or disable optimistic updates when editing a node. Defaults to `true` - -### - -By default, the `DragPreview` component will display the node identifier and, if it has children, the number of its children. - -Instead of making a full custom preview component, you can use the `DragPreview` and pass it a child, either a react element or a function. The function will be called with the current `node` and the `translate` function. - -```jsx -import React from 'react'; -import { List, TextField } from 'react-admin'; -import { DragPreview, Tree } from 'ra-tree-ui-materialui'; - -const TagDragPreview = props => ( - - {({ node }) => node.record.name} - -); - -const TagList = props => ( - - - - - - - -); - -export default TagList; -``` - -## Roadmap - -* Support async fetch of nodes -* `TreeSelectInput` to select a value inside the hierarchical data (with autocomplete showing the matched nodes) -* `TreeInput` to edit a field containing hierarchical data as json -* `TreeNodeField` to show a node and its hierarchie. It should recursively fetch the parents by default, allow a custom function to be supplied to fetch them in one call (`fetchHierarchy`) and fallback to a simple `depth` display (`--|--|--[NODE_LABEL]`) if a `depthSource` is supplied. -* Support nested set hierarchical data - -## License - -This library is licensed under the MIT License, and sponsored by [marmelab](http://marmelab.com). diff --git a/packages/ra-tree-ui-materialui/package.json b/packages/ra-tree-ui-materialui/package.json deleted file mode 100644 index 986c6d88651..00000000000 --- a/packages/ra-tree-ui-materialui/package.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "name": "ra-tree-ui-materialui", - "version": "3.0.0-beta.0", - "description": "A treeview component with material-ui to use with react-admin", - "main": "lib/index.js", - "module": "esm/index.js", - "sideEffects": false, - "files": [ - "LICENSE", - "*.md", - "lib", - "esm", - "src" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/marmelab/react-admin.git" - }, - "keywords": [ - "reactjs", - "react", - "react-admin", - "admin-on-rest", - "treeview", - "tree" - ], - "author": "Gildas Garcia", - "license": "MIT", - "bugs": { - "url": "https://github.com/marmelab/react-admin/issues" - }, - "homepage": "https://github.com/marmelab/react-admin#readme", - "scripts": { - "build": "yarn run build-cjs && yarn run build-esm", - "build-cjs": "rimraf ./lib && tsc", - "build-esm": "rimraf ./esm && tsc --outDir esm --module es2015", - "watch": "rimraf ./lib && tsc --watch" - }, - "devDependencies": { - "cross-env": "^5.2.0", - "final-form": "^4.18.4", - "ra-core": "^3.0.0-beta.0", - "ra-tree-core": "^3.0.0-beta.0", - "ra-ui-materialui": "^3.0.0-beta.0", - "react-final-form": "^6.3.0", - "react": "^16.9.0", - "react-dom": "^16.9.0", - "rimraf": "^2.6.3" - }, - "peerDependencies": { - "final-form": "^4.18.4", - "ra-core": "^3.0.0-alpha.0", - "ra-tree-core": "^3.0.0-beta.0", - "ra-ui-materialui": "^3.0.0-beta.0", - "react": "^16.9.0", - "react-dom": "^16.9.0", - "react-final-form": "^6.3.0" - }, - "dependencies": { - "lodash": "^4.17.10", - "prop-types": "^15.6.1", - "react-dnd": "^5.0.0", - "react-dnd-touch-backend": "^0.5.1" - } -} diff --git a/packages/ra-tree-ui-materialui/src/DragLayer.js b/packages/ra-tree-ui-materialui/src/DragLayer.js deleted file mode 100644 index 8f44f265e18..00000000000 --- a/packages/ra-tree-ui-materialui/src/DragLayer.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Custom DragLayer from Alejandro Hernandez - * See https://github.com/react-dnd/react-dnd/issues/592#issuecomment-399287474 - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { DragLayer } from 'react-dnd'; -import { makeStyles } from '@material-ui/core/styles'; -import isEqual from 'lodash/isEqual'; - -const useStyles = makeStyles({ - layer: { - position: 'fixed', - pointerEvents: 'none', - zIndex: 100, - left: 0, - top: 0, - width: '100%', - height: '100%', - }, - item: {}, -}); - -function CustomDragLayer({ - classes: classesOverride, - beingDragged, - dragPreviewComponent: DragPreview, - itemBeingDragged, - offset, -}) { - const classes = useStyles({ classes: classesOverride }); - - if (!beingDragged || !offset) return null; - - return ( -
    -
    - -
    -
    - ); -} - -CustomDragLayer.propTypes = { - beingDragged: PropTypes.bool, - classes: PropTypes.object, - dragPreviewComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]).isRequired, - itemBeingDragged: PropTypes.object, - offset: PropTypes.object, -}; - -export default React.memo( - DragLayer(monitor => ({ - itemBeingDragged: monitor.getItem(), - componentType: monitor.getItemType(), - beingDragged: monitor.isDragging(), - offset: monitor.getSourceClientOffset(), - }))(CustomDragLayer), - (prevProps, nextProps) => isEqual(prevProps.offset, nextProps.offset) -); diff --git a/packages/ra-tree-ui-materialui/src/DragPreview.js b/packages/ra-tree-ui-materialui/src/DragPreview.js deleted file mode 100644 index 085d0aa707a..00000000000 --- a/packages/ra-tree-ui-materialui/src/DragPreview.js +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { makeStyles } from '@material-ui/core/styles'; -import { useTranslate } from 'ra-core'; - -const useStyles = makeStyles(theme => ({ - item: { - alignItems: 'center', - backgroundColor: theme.palette.action.active, - display: 'inline-flex', - height: 72, - minWidth: 72, - paddingTop: theme.spacing(1.5), - paddingBottom: theme.spacing(1.5), - paddingLeft: theme.spacing(6), - paddingRight: theme.spacing(4), - }, -})); - -function DragPreview({ - children, - className, - classes: classesOverride, - node, - style, -}) { - const classes = useStyles({ classes: classesOverride }); - const translate = useTranslate(); - return ( -
    - {children - ? typeof children === 'function' - ? children({ node, translate }) - : children - : translate('ra.tree.drag_preview', { - id: node.id, - smart_count: node.children.length, - })} -
    - ); -} - -DragPreview.propTypes = { - children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), - className: PropTypes.string, - classes: PropTypes.object, - node: PropTypes.object, - style: PropTypes.object, - translate: PropTypes.func.isRequired, -}; - -export default React.memo(DragPreview, () => true); diff --git a/packages/ra-tree-ui-materialui/src/IgnoreFormProps.js b/packages/ra-tree-ui-materialui/src/IgnoreFormProps.js deleted file mode 100644 index 71f96c9e348..00000000000 --- a/packages/ra-tree-ui-materialui/src/IgnoreFormProps.js +++ /dev/null @@ -1,43 +0,0 @@ -import React, { Children, Fragment, cloneElement } from 'react'; -import PropTypes from 'prop-types'; - -const sanitizeRestProps = ({ - handleSubmit, - handleSubmitWithRedirect, - invalid, - pristine, - saving, - submitOnEnter, - ...rest -}) => rest; - -/** - * This component ensure form related props are not passed to its children. This is required - * in `NodeActions` is used inside a NodeForm and buttons not related to form (such as EditButton - * or DeleteButton) are used. - * - * @example - * const CustomNodeActions = props => ( - * - * - * - * - * - * - * - * - * ); - */ -const IgnoreFormProps = ({ children, ...props }) => ( - - {Children.map(children, child => - cloneElement(child, sanitizeRestProps(props)) - )} - -); - -IgnoreFormProps.propTypes = { - children: PropTypes.node.isRequired, -}; - -export default IgnoreFormProps; diff --git a/packages/ra-tree-ui-materialui/src/NodeActions.js b/packages/ra-tree-ui-materialui/src/NodeActions.js deleted file mode 100644 index a0eed173970..00000000000 --- a/packages/ra-tree-ui-materialui/src/NodeActions.js +++ /dev/null @@ -1,33 +0,0 @@ -import React, { cloneElement, Children } from 'react'; -import PropTypes from 'prop-types'; -import { makeStyles } from '@material-ui/core/styles'; - -const useStyles = makeStyles(theme => ({ - root: { - alignItems: 'center', - marginLeft: 'auto', - marginRight: theme.spacing(4), - }, -})); - -function NodeActions({ children, classes: classesOverride, ...props }) { - const classes = useStyles({ classes: classesOverride }); - - return ( - - {Children.map(children, action => - action ? cloneElement(action, props) : null - )} - - ); -} - -NodeActions.propTypes = { - classes: PropTypes.object.isRequired, - basePath: PropTypes.string.isRequired, - children: PropTypes.node, - record: PropTypes.object.isRequired, - resource: PropTypes.string.isRequired, -}; - -export default NodeActions; diff --git a/packages/ra-tree-ui-materialui/src/NodeForm.js b/packages/ra-tree-ui-materialui/src/NodeForm.js deleted file mode 100644 index 13f3e6afd7f..00000000000 --- a/packages/ra-tree-ui-materialui/src/NodeForm.js +++ /dev/null @@ -1,220 +0,0 @@ -import React, { cloneElement, Children, useCallback } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { makeStyles } from '@material-ui/core/styles'; -import { Form } from 'react-final-form'; -import { - crudUpdate as crudUpdateAction, - startUndoable as startUndoableAction, -} from 'ra-core'; - -import NodeFormActions from './NodeFormActions'; - -const useStyles = makeStyles({ - root: { - alignItems: 'center', - display: 'flex', - flexGrow: 1, - }, -}); - -const sanitizeRestProps = ({ - anyTouched, - array, - asyncBlurFields, - asyncValidate, - asyncValidating, - autofill, - blur, - cancelDropOnChildren, - change, - clearAsyncError, - clearFields, - clearSubmit, - clearSubmitErrors, - crudUpdate, - destroy, - dirty, - dispatch, - dispatchCrudUpdate, - form, - getTreeState, - handleSubmit, - initialize, - initialized, - initialValues, - invalid, - isDragging, - onSelect, - onToggleItem, - onUnselectItems, - parentSource, - pristine, - pure, - redirect, - reset, - resetSection, - save, - startUndoable, - submit, - submitFailed, - submitSucceeded, - submitting, - touch, - translate, - triggerSubmit, - undoable, - undoableDragDrop, - untouch, - valid, - validate, - ...props -}) => props; - -function NodeForm({ - actions, - basePath, - children, - classes: classesOverride, - handleSubmit: handleSubmitProp, - invalid, - node, - pristine, - resource, - saving, - submitOnEnter = true, - ...props -}) { - const classes = useStyles({ classes: classesOverride }); - - const handleClick = useCallback(event => { - event.persist(); - // This ensure clicking on an input or button does not collapse/expand a node - // When clicking on the form (empty spaces around inputs) however, it should - // propagate to the parent - if (event.target.tagName.toLowerCase() !== 'form') { - event.stopPropagation(); - } - }, []); - - const { cancelDropOnChildren } = props; - const handleDrop = useCallback( - event => { - event.persist(); - if (cancelDropOnChildren) { - event.preventDefault(); - } - }, - [cancelDropOnChildren] - ); - - const { - dispatchCrudUpdate, - node: { record }, - startUndoable, - undoable = true, - } = props; - const handleSubmit = useCallback(() => { - return handleSubmitProp(values => - undoable - ? startUndoable( - crudUpdateAction( - resource, - record.id, - { ...record, ...values }, - record, - basePath, - false - ) - ) - : dispatchCrudUpdate( - resource, - record.id, - { ...record, ...values }, - record, - basePath, - false - ) - ); - }, [ - basePath, - handleSubmitProp, - resource, - dispatchCrudUpdate, - record, - startUndoable, - undoable, - ]); - - return ( -
    ( - - {Children.map(children, field => - field - ? cloneElement(field, { - basePath: field.props.basePath || basePath, - onDrop: handleDrop, - record: node.record, - resource, - }) - : null - )} - {actions && - cloneElement(actions, { - basePath, - record: node.record, - resource, - handleSubmit: handleSubmit, - handleSubmitWithRedirect: handleSubmit, - invalid, - pristine, - saving, - submitOnEnter, - })} -
    - )} - /> - ); -} - -NodeForm.propTypes = { - actions: PropTypes.node, - basePath: PropTypes.string.isRequired, - cancelDropOnChildren: PropTypes.bool, - children: PropTypes.node, - classes: PropTypes.object, - dispatchCrudUpdate: PropTypes.func.isRequired, - handleSubmit: PropTypes.func.isRequired, - invalid: PropTypes.bool, - node: PropTypes.object.isRequired, - pristine: PropTypes.bool, - resource: PropTypes.string.isRequired, - saving: PropTypes.bool, - startUndoable: PropTypes.func.isRequired, - submitOnEnter: PropTypes.bool, - undoable: PropTypes.bool, -}; - -NodeForm.defaultProps = { - actions: , -}; - -const mapStateToProps = (state, { node }) => ({ - initialValues: node.record, - record: node.record, -}); - -export default connect( - mapStateToProps, - { - dispatchCrudUpdate: crudUpdateAction, - startUndoable: startUndoableAction, - } -)(NodeForm); diff --git a/packages/ra-tree-ui-materialui/src/NodeFormActions.js b/packages/ra-tree-ui-materialui/src/NodeFormActions.js deleted file mode 100644 index 6f84cf31f32..00000000000 --- a/packages/ra-tree-ui-materialui/src/NodeFormActions.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { SaveButton } from 'ra-ui-materialui'; -import NodeActions from './NodeActions'; - -const NodeFormActions = props => ( - - - -); - -export default NodeFormActions; diff --git a/packages/ra-tree-ui-materialui/src/NodeView.js b/packages/ra-tree-ui-materialui/src/NodeView.js deleted file mode 100644 index cf189972fc7..00000000000 --- a/packages/ra-tree-ui-materialui/src/NodeView.js +++ /dev/null @@ -1,88 +0,0 @@ -import React, { cloneElement, Children } from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { makeStyles } from '@material-ui/core/styles'; - -const CONTAINER_CLASS = 'treenode-content'; - -const useStyles = makeStyles({ - root: { - alignItems: 'center', - display: 'flex', - flexGrow: 1, - }, -}); - -const sanitizeRestProps = ({ - cancelDropOnChildren, - crudUpdate, - dispatchCrudUpdate, - getTreeState, - isDragging, - onSelect, - onToggleItem, - onUnselectItems, - parentSource, - startUndoable, - translate, - undoable, - undoableDragDrop, - ...rest -}) => rest; - -function NodeView({ - actions, - basePath, - children, - classes: classesOverride, - node, - resource, - ...props -}) { - const classes = useStyles({ classes: classesOverride }); - - const handleClick = event => { - event.persist(); - // This ensure clicking on a button does not collapse/expand a node - // When clicking on the form (empty spaces around buttons) however, it should - // propagate to the parent - if (!event.target.matches(`.${CONTAINER_CLASS}`)) { - event.stopPropagation(); - } - }; - - return ( -
    - {Children.map(children, field => - field - ? cloneElement(field, { - basePath: field.props.basePath || basePath, - record: node.record, - resource, - }) - : null - )} - {actions && - cloneElement(actions, { - basePath, - record: node.record, - resource, - })} -
    - ); -} - -NodeView.propTypes = { - actions: PropTypes.node, - basePath: PropTypes.string.isRequired, - children: PropTypes.node, - classes: PropTypes.object, - node: PropTypes.object.isRequired, - resource: PropTypes.string.isRequired, -}; - -export default NodeView; diff --git a/packages/ra-tree-ui-materialui/src/RootDropTarget.js b/packages/ra-tree-ui-materialui/src/RootDropTarget.js deleted file mode 100644 index 1ea90416ce8..00000000000 --- a/packages/ra-tree-ui-materialui/src/RootDropTarget.js +++ /dev/null @@ -1,91 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { DropTarget } from 'react-dnd'; -import { makeStyles } from '@material-ui/core/styles'; -import Typography from '@material-ui/core/Typography'; -import ListItem from '@material-ui/core/ListItem'; -import IconGetApp from '@material-ui/icons/GetApp'; -import { useTranslate } from 'ra-core'; - -import { DROP_TARGET_TYPE } from './constants'; - -const useStyles = makeStyles(theme => ({ - root: { - paddingLeft: theme.spacing(6), - }, - text: { - paddingLeft: theme.spacing(2), - paddingTop: theme.spacing(1), - paddingBottom: theme.spacing(1), - }, - hover: { - backgroundColor: theme.palette.action.active, - }, -})); - -function RootDropTarget({ - canDrop, - classes: classesOverride, - connectDropTarget, - isOverCurrent, -}) { - const classes = useStyles({ classes: classesOverride }); - const translate = useTranslate(); - - return ( - - - {connectDropTarget( -
    - - {translate('ra.tree.root_target')} - -
    - )} -
    - ); -} - -RootDropTarget.propTypes = { - canDrop: PropTypes.bool, - classes: PropTypes.object, - connectDropTarget: PropTypes.func.isRequired, - isOverCurrent: PropTypes.bool, -}; - -const dropTargetSpecs = { - drop(props, monitor) { - if (monitor.isOver({ shallow: true })) { - return { id: null, record: { id: null } }; - } - - return undefined; - }, - canDrop(props, monitor) { - const item = monitor.getItem(); - return !!item.parent; - }, -}; - -const dropTargetConnect = (connect, monitor) => ({ - connectDropTarget: connect.dropTarget(), - isOver: monitor.isOver(), - isOverCurrent: monitor.isOver({ shallow: true }), - canDrop: monitor.canDrop(), - item: monitor.getItem(), -}); - -export default React.memo( - DropTarget(DROP_TARGET_TYPE, dropTargetSpecs, dropTargetConnect)( - RootDropTarget - ), - (prevProps, nextProps) => - prevProps.canDrop === nextProps.canDrop && - prevProps.isOverCurrent === nextProps.isOverCurrent -); diff --git a/packages/ra-tree-ui-materialui/src/Tree.js b/packages/ra-tree-ui-materialui/src/Tree.js deleted file mode 100644 index 25a080b837d..00000000000 --- a/packages/ra-tree-ui-materialui/src/Tree.js +++ /dev/null @@ -1,221 +0,0 @@ -import React, { Children, useEffect, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { makeStyles } from '@material-ui/core/styles'; -import List from '@material-ui/core/List'; -import { TreeController } from 'ra-tree-core'; -import { DragDropContext } from 'react-dnd'; -import TouchBackend from 'react-dnd-touch-backend'; - -import draggable from './draggable'; -import droppable from './droppable'; -import DragLayer from './DragLayer'; -import DefaultDragPreview from './DragPreview'; -import DefaultTreeNode from './TreeNode'; -import DefaultTreeNodeContent from './TreeNodeContent'; -import DefaultTreeNodeWithChildren from './TreeNodeWithChildren'; -import RootDropTarget from './RootDropTarget'; - -const useStyles = makeStyles({ - root: { - display: 'flex', - flexDirection: 'column', - }, -}); - -const sanitizeRestProps = ({ - currentSort, - defaultTitle, - displayedFilters, - filterValues, - getTreeState, - hasBulkActions, - hasCreate, - hideFilter, - loading, - loaded, - loadedOnce, - perPage, - selectedIds, - setFilters, - setPage, - setPerPage, - setSelectedIds, - setSort, - showFilter, - ...rest -}) => rest; - -const warnAboutChildren = () => - console.warn( - // eslint-disable-line - `You passed multiple children to the Tree component. You must either pass it a NodeView or a NodeForm component as its only child: - - - - - - - - // Or - - - - - - - -If you need actions on each node, use the actions prop on either the NodeView or NodeForm component: - - const MyNodeActions = props => ( - - - - - - ); - - - }> - - - - - // Or - - const MyNodeActions = props => ( - - - - - - - - - ); - - - }> - - - -` - ); - -function Tree({ - allowDropOnRoot, - children, - classes: classesOverride, - dragPreviewComponent, - enableDragAndDrop, - parentSource, - treeNodeComponent, - treeNodeWithChildrenComponent, - treeNodeContentComponent, - ...props -}) { - const classes = useStyles({ classes: classesOverride }); - useEffect(() => { - const childrenCount = Children.count(children); - - if (childrenCount > 1 && process.env.NODE_ENV !== 'production') { - warnAboutChildren(); - } - }, [children]); - - const Container = enableDragAndDrop - ? DragDropContext( - TouchBackend({ - enableKeyboardEvents: true, - enableMouseEvents: true, - enableTouchEvents: true, - }) - )('div') - : Fragment; - - const TreeNode = enableDragAndDrop - ? droppable(treeNodeComponent) - : treeNodeComponent; - - const TreeNodeContent = enableDragAndDrop - ? draggable(treeNodeContentComponent) - : treeNodeContentComponent; - - return ( - - {({ getTreeState, tree, ...controllerProps }) => ( - - {enableDragAndDrop ? ( - - ) : null} - - {enableDragAndDrop && allowDropOnRoot ? ( - - ) : null} - {tree.map(node => ( - - {children} - - ))} - - - )} - - ); -} - -Tree.propTypes = { - allowDropOnRoot: PropTypes.bool, - basePath: PropTypes.string.isRequired, - children: PropTypes.node, - classes: PropTypes.object, - enableDragAndDrop: PropTypes.bool, - getTreeFromArray: PropTypes.func, - parentSource: PropTypes.string, - resource: PropTypes.string.isRequired, - dragPreviewComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]), - treeNodeComponent: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), - treeNodeContentComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]), - treeNodeWithChildrenComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]), -}; - -Tree.defaultProps = { - classes: {}, - parentSource: 'parent_id', - dragPreviewComponent: DefaultDragPreview, - treeNodeComponent: DefaultTreeNode, - treeNodeContentComponent: DefaultTreeNodeContent, - treeNodeWithChildrenComponent: DefaultTreeNodeWithChildren, -}; - -export default Tree; diff --git a/packages/ra-tree-ui-materialui/src/TreeNode.js b/packages/ra-tree-ui-materialui/src/TreeNode.js deleted file mode 100644 index 9f8648cdfba..00000000000 --- a/packages/ra-tree-ui-materialui/src/TreeNode.js +++ /dev/null @@ -1,196 +0,0 @@ -import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import ListItem from '@material-ui/core/ListItem'; -import { makeStyles } from '@material-ui/core/styles'; - -const useStyles = makeStyles(theme => ({ - expandIcon: { - margin: 0, - left: -theme.spacing(6), - right: 'auto' /* fix for material-ui 3 */, - }, - root: { - alignItems: 'baseline', - display: 'flex', - padding: 0, - flexGrow: 1, - }, - node: { - alignItems: 'baseline', - display: 'flex', - padding: 0, - flexGrow: 1, - paddingLeft: theme.spacing(6), - }, - leaf: { - display: 'flex', - flexGrow: 1, - margin: 0, - padding: 0, - paddingLeft: theme.spacing(6), - paddingRight: theme.spacing(4), - position: 'relative', - }, - - panel: { - background: 'transparent', - display: 'block', - flexGrow: 1, - margin: 0, - }, - panelDetails: { - display: 'flex', - flexDirection: 'column', - padding: 0, - }, - panelSummary: { - display: 'flex', - justifyContent: 'space-between', - margin: 0, - padding: 0, - }, - panelSummaryExpanded: { - margin: 0, - }, - panelSummaryContent: { - alignItems: 'center', - margin: 0, - - // JSS notation to reference another class (here panelSummaryExpanded) - '&$panelSummaryExpanded': { - margin: 0, - }, - }, - handle: { - cursor: 'drag', - alignItems: 'center', - display: 'flex', - marginRight: theme.spacing(2), - }, - draggingOver: { - background: theme.palette.action.hover, - }, -})); - -function TreeNode({ - basePath, - canDrop, - children, - classes: classesOverride, - closeNode, - connectDropTarget, - expandNode, - getIsNodeExpanded, - isOver, - isOverCurrent, - itemType, - node, - resource, - treeNodeComponent, - treeNodeWithChildrenComponent: TreeNodeWithChildren, - treeNodeContentComponent: TreeNodeContent, - toggleNode, - ...props -}) { - const classes = useStyles({ classes: classesOverride }); - const handleDrop = event => { - if (isOver && canDrop) { - event.persist(); - event.preventDefault(); - } - }; - - return connectDropTarget( -
    - 0, - [classes.leaf]: node.children.length === 0, - [classes.draggingOver]: isOverCurrent, - }), - }} - dense - disableGutters - > - {node.children.length > 0 ? ( - - {children} - - ) : ( - - - {children} - - - )} - -
    - ); -} - -TreeNode.propTypes = { - basePath: PropTypes.string.isRequired, - canDrop: PropTypes.bool, - children: PropTypes.node, - classes: PropTypes.object, - closeNode: PropTypes.func, - connectDropTarget: PropTypes.func, - expandNode: PropTypes.func, - getIsNodeExpanded: PropTypes.func, - isOver: PropTypes.bool, - isOverCurrent: PropTypes.bool, - itemType: PropTypes.string, - node: PropTypes.object.isRequired, - resource: PropTypes.string.isRequired, - toggleNode: PropTypes.func, - treeNodeComponent: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), - treeNodeContentComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]).isRequired, - treeNodeWithChildrenComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]), -}; - -TreeNode.defaultProps = { - connectDropTarget: target => target, -}; -export default TreeNode; diff --git a/packages/ra-tree-ui-materialui/src/TreeNodeContent.js b/packages/ra-tree-ui-materialui/src/TreeNodeContent.js deleted file mode 100644 index 20598e4e33e..00000000000 --- a/packages/ra-tree-ui-materialui/src/TreeNodeContent.js +++ /dev/null @@ -1,62 +0,0 @@ -import React, { cloneElement, Children, Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import IconDragHandle from '@material-ui/icons/DragHandle'; - -class TreeNodeContent extends Component { - static propTypes = { - basePath: PropTypes.string.isRequired, - cancelDropOnChildren: PropTypes.bool, - connectDragPreview: PropTypes.func, - connectDragSource: PropTypes.func, - containerElement: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - PropTypes.string, - ]), - children: PropTypes.node, - classes: PropTypes.object.isRequired, - expandNode: PropTypes.func, - isLeaf: PropTypes.bool, - node: PropTypes.object.isRequired, - resource: PropTypes.string.isRequired, - submit: PropTypes.func, - }; - - static defaultProps = { - containerElement: 'div', - }; - - render() { - const { - children, - classes, - connectDragPreview, - connectDragSource, - containerElement: Container, - expandNode, - submit, - isLeaf, - node, - ...props - } = this.props; - return ( - - {cloneElement(Children.only(children), { node, ...props })} - {connectDragPreview && - connectDragPreview(, { - // IE fallback: specify that we'd rather screenshot the node - // when it already knows it's being dragged so we can hide it with CSS. - captureDraggingState: true, - })} - {connectDragSource && - connectDragSource( -
    - -
    - )} -
    - ); - } -} - -export default TreeNodeContent; diff --git a/packages/ra-tree-ui-materialui/src/TreeNodeWithChildren.js b/packages/ra-tree-ui-materialui/src/TreeNodeWithChildren.js deleted file mode 100644 index ae6df3b2c8c..00000000000 --- a/packages/ra-tree-ui-materialui/src/TreeNodeWithChildren.js +++ /dev/null @@ -1,127 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import List from '@material-ui/core/List'; -import ExpansionPanel from '@material-ui/core/ExpansionPanel'; -import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails'; -import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary'; -import KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDown'; - -export class TreeNodeWithChildren extends Component { - static propTypes = { - basePath: PropTypes.string.isRequired, - cancelDropOnChildren: PropTypes.bool, - children: PropTypes.node, - classes: PropTypes.object, - closeNode: PropTypes.func, - expandNode: PropTypes.func, - getIsNodeExpanded: PropTypes.func, - isExpanded: PropTypes.bool, - node: PropTypes.object.isRequired, - resource: PropTypes.string.isRequired, - toggleNode: PropTypes.func, - treeNodeComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]), - treeNodeContentComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]).isRequired, - treeNodeWithChildrenComponent: PropTypes.oneOfType([ - PropTypes.element, - PropTypes.func, - ]), - }; - - handleChange = () => { - const { toggleNode, node } = this.props; - - toggleNode(node.id); - }; - - render() { - const { - basePath, - cancelDropOnChildren, - children, - classes, - closeNode, - expandNode, - getIsNodeExpanded, - isExpanded, - node, - resource, - toggleNode, - treeNodeComponent: TreeNode, - treeNodeWithChildrenComponent, - treeNodeContentComponent: TreeNodeContent, - ...props - } = this.props; - - return ( - - } - > - - {children} - - - - - {node.children.map(child => ( - - {children} - - ))} - - - - ); - } -} - -export default TreeNodeWithChildren; diff --git a/packages/ra-tree-ui-materialui/src/constants.js b/packages/ra-tree-ui-materialui/src/constants.js deleted file mode 100644 index d2b6ba44159..00000000000 --- a/packages/ra-tree-ui-materialui/src/constants.js +++ /dev/null @@ -1 +0,0 @@ -export const DROP_TARGET_TYPE = 'RA/TREE/NODE'; diff --git a/packages/ra-tree-ui-materialui/src/draggable.js b/packages/ra-tree-ui-materialui/src/draggable.js deleted file mode 100644 index 03cf6ba3cb8..00000000000 --- a/packages/ra-tree-ui-materialui/src/draggable.js +++ /dev/null @@ -1,93 +0,0 @@ -import compose from 'recompose/compose'; -import { connect } from 'react-redux'; -import { DragSource } from 'react-dnd'; -import { - crudUpdate as crudUpdateAction, - startUndoable as startUndoableAction, -} from 'ra-core'; -import { expandNode as expandNodeAction } from 'ra-tree-core'; - -import { DROP_TARGET_TYPE } from './constants'; - -const dragSourceSpecs = { - beginDrag(props) { - return props.node; - }, - endDrag( - { - basePath, - dispatchCrudUpdate, - expandNode, - node, - parentSource, - resource, - startUndoable, - undoableDragDrop = true, - }, - monitor - ) { - if (!monitor.didDrop()) { - return; - } - - const droppedOnNode = monitor.getDropResult(); - if ( - typeof droppedOnNode.id === 'undefined' || - droppedOnNode.id === node.record[parentSource] - ) { - return; - } - - // Ensure the node on which the dragged node has been dropped is expanded along with its parents - // to avoid the dropped node to disappear - let nodeToExpand = droppedOnNode; - expandNode(resource, nodeToExpand.id); - - if (nodeToExpand.parent) { - do { - nodeToExpand = nodeToExpand.parent; - expandNode(resource, nodeToExpand.id); - } while (nodeToExpand.parent); - } - - if (undoableDragDrop) { - return startUndoable( - crudUpdateAction( - resource, - node.record.id, - { ...node.record, [parentSource]: droppedOnNode.id }, - node.record, - basePath, - false - ) - ); - } - - return dispatchCrudUpdate( - resource, - node.record.id, - { ...node.record, [parentSource]: droppedOnNode.id }, - node.record, - basePath, - false - ); - }, -}; - -const dragSourceConnect = (connect, monitor) => ({ - connectDragPreview: connect.dragPreview(), - connectDragSource: connect.dragSource(), - isDragging: monitor.isDragging(), -}); - -export default compose( - connect( - undefined, - { - dispatchCrudUpdate: crudUpdateAction, - expandNode: expandNodeAction, - startUndoable: startUndoableAction, - } - ), - DragSource(DROP_TARGET_TYPE, dragSourceSpecs, dragSourceConnect) -); diff --git a/packages/ra-tree-ui-materialui/src/droppable.js b/packages/ra-tree-ui-materialui/src/droppable.js deleted file mode 100644 index 7080aeb8354..00000000000 --- a/packages/ra-tree-ui-materialui/src/droppable.js +++ /dev/null @@ -1,45 +0,0 @@ -import { DropTarget } from 'react-dnd'; - -import { DROP_TARGET_TYPE } from './constants'; - -const isDraggingAParent = (props, monitor) => { - const draggedNode = monitor.getItem(); - - if (!draggedNode) { - return false; - } - let node = props.node; - - while (node) { - // If the dragged node is a parent of the current node, it can't be dropped - if (draggedNode.id === node.id) { - return true; - } - node = node.parent; - } - - return false; -}; - -const dropTargetSpecs = { - drop(props, monitor) { - if (monitor.isOver({ shallow: true })) { - return props.node; - } - - return undefined; - }, - canDrop(props, monitor) { - return !isDraggingAParent(props, monitor); - }, -}; - -const dropTargetConnect = (connect, monitor) => ({ - connectDropTarget: connect.dropTarget(), - isOver: monitor.isOver(), - isOverCurrent: monitor.isOver({ shallow: true }), - canDrop: monitor.canDrop(), - itemType: monitor.getItemType(), -}); - -export default DropTarget(DROP_TARGET_TYPE, dropTargetSpecs, dropTargetConnect); diff --git a/packages/ra-tree-ui-materialui/src/index.js b/packages/ra-tree-ui-materialui/src/index.js deleted file mode 100644 index d383931c08d..00000000000 --- a/packages/ra-tree-ui-materialui/src/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import DragPreview from './DragPreview'; -import IgnoreFormProps from './IgnoreFormProps'; -import NodeActions from './NodeActions'; -import NodeView from './NodeView'; -import NodeForm from './NodeForm'; -import Tree from './Tree'; -export { DragPreview, IgnoreFormProps, NodeActions, NodeView, NodeForm, Tree }; -export * from 'ra-tree-core'; diff --git a/packages/ra-tree-ui-materialui/tsconfig.json b/packages/ra-tree-ui-materialui/tsconfig.json deleted file mode 100644 index 8be9b276492..00000000000 --- a/packages/ra-tree-ui-materialui/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "lib", - "rootDir": "src" - }, - "exclude": ["**/*.spec.ts", "**/*.spec.tsx", "**/*.spec.js"], - "include": ["src"] -} diff --git a/tsconfig.json b/tsconfig.json index 7b6a1529e0a..9b11d9ca012 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,15 @@ { "compilerOptions": { /* Basic Options */ - "target": - "ES5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, - "module": - "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, + "target": "ES5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, "lib": [ "es2017", "dom" ] /* Specify library files to be included in the compilation. */, "allowJs": true /* Allow javascript files to be compiled. */, // "checkJs": true, /* Report errors in .js files. */ - "jsx": - "react" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, + "jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, // "declaration": true /* Generates corresponding '.d.ts' file. */, // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "sourceMap": true /* Generates corresponding '.map' file. */, @@ -42,8 +39,7 @@ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ /* Module Resolution Options */ - "moduleResolution": - "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ @@ -74,8 +70,6 @@ // { "path": "./packages/ra-data-simple-rest" }, // { "path": "./packages/ra-input-rich-text" }, // { "path": "./packages/ra-realtime" }, - // { "path": "./packages/ra-tree-core" }, - // { "path": "./packages/ra-tree-ui-materialui" }, // { "path": "./packages/ra-ui-materialui" }, // { "path": "./packages/react-admin" } // ] From 411482c70b4f5d562627c30273c33a0dfb1d3807 Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Thu, 17 Oct 2019 15:19:36 +0200 Subject: [PATCH 2/3] Add upgrade guide --- UPGRADE.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 724de4c87bb..c36d01ba908 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1281,4 +1281,10 @@ export default ({ sagaMiddleware.run(saga); return store; }; -``` \ No newline at end of file +``` + +## No More Tree Packages in Core + +The `ra-tree` and `ra-tree-ui-material-ui` packages were removed in v3. The v2 version performed poorly, and we don't want to delay v3 to reimplement the Tree packages. + +If you were using these packages just for displaying a tree, you'll have to reimplement a basic tree widget, taking the Tags list from the Simple example as an inspiration. If you were using these packages for creating and updating a tree, we recommend that you wait until the core team or another community member publishes a Tree packahe compatible with v3. From 08af1edbe65966ce92827ee25b0b069056a66c88 Mon Sep 17 00:00:00 2001 From: Francois Zaninotto Date: Thu, 17 Oct 2019 15:52:13 +0200 Subject: [PATCH 3/3] Update UPGRADE.md Co-Authored-By: Gildas Garcia --- UPGRADE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index c36d01ba908..64753b699c6 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1287,4 +1287,4 @@ export default ({ The `ra-tree` and `ra-tree-ui-material-ui` packages were removed in v3. The v2 version performed poorly, and we don't want to delay v3 to reimplement the Tree packages. -If you were using these packages just for displaying a tree, you'll have to reimplement a basic tree widget, taking the Tags list from the Simple example as an inspiration. If you were using these packages for creating and updating a tree, we recommend that you wait until the core team or another community member publishes a Tree packahe compatible with v3. +If you were using these packages just for displaying a tree, you'll have to reimplement a basic tree widget, taking the Tags list from the Simple example as an inspiration. If you were using these packages for creating and updating a tree, we recommend that you wait until the core team or another community member publishes a Tree package compatible with v3.