From e965e529c6f140fa866d1af689051fbdf19174a7 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Wed, 14 Oct 2020 19:09:03 +0300 Subject: [PATCH] Web: Components: added props newItems and onClickBadge() for render Badge witch counter new Items --- .../src/components/tree-menu/README.md | 64 ++-- .../src/components/tree-menu/index.js | 339 +++++++++++------- .../tree-menu/sub-components/tree-node.js | 157 +++++--- .../components/tree-menu/tree-menu.stories.js | 154 +++++--- .../components/tree-menu/tree-menu.test.js | 88 ++--- 5 files changed, 478 insertions(+), 324 deletions(-) diff --git a/web/ASC.Web.Components/src/components/tree-menu/README.md b/web/ASC.Web.Components/src/components/tree-menu/README.md index 2337c98eef..e275fe89f7 100644 --- a/web/ASC.Web.Components/src/components/tree-menu/README.md +++ b/web/ASC.Web.Components/src/components/tree-menu/README.md @@ -14,37 +14,37 @@ import { TreeMenu } from "asc-web-components"; ### Properties TreeMenu -| Props | Type | Required | Values | Default | Description | -| --------------------- | :----------------: | :------: | :----: | :-----: | ------------------------------------------------------------------------------------------------------- | -| `autoExpandParent` | `bool` | - | - | `false` | Whether auto expand parent treeNodes | -| `checkable` | `bool` | - | - | `false` | Whether support checked | -| `className` | `string` | - | - | - | Accepts class | -| `defaultExpandAll` | `bool` | - | - | `false` | Expand all treeNodes | -| `defaultExpandParent` | `bool` | - | - | `true` | Auto expand parent treeNodes when init | -| `disabled` | `bool` | - | - | `false` | Whether disabled the tree | -| `draggable` | `bool` | - | - | `false` | Whether can drag treeNode | -| `id` | `string` | - | - | - | Accepts id | -| `multiple` | `bool` | - | - | `false` | Whether multiple select | -| `onDragEnd` | `func` | - | - | - | it execs when fire the tree's dragend event | -| `onDragEnter` | `func` | - | - | - | it execs when fire the tree's dragenter event | -| `onDragLeave` | `func` | - | - | - | it execs when fire the tree's dragleave event | -| `onDragOver` | `func` | - | - | - | it execs when fire the tree's dragover event | -| `onDragStart` | `func` | - | - | - | it execs when fire the tree's dragstart event | -| `onDrop` | `func` | - | - | - | it execs when fire the tree's drop event | -| `onExpand` | `func` | - | - | - | fire on treeNode expand or not | -| `onLoad` | `func` | - | - | - | Trigger when a node is loaded. If you set the loadedKeys, you must handle onLoad to avoid infinity loop | -| `onMouseEnter` | `func` | - | - | - | call when mouse enter a treeNode | -| `onMouseLeave` | `func` | - | - | - | call when mouse leave a treeNode | -| `onRightClick` | `func` | - | - | - | select current treeNode and show customized contextmenu | -| `onSelect` | `func` | - | - | - | click the treeNode to fire | -| `showIcon` | `bool` | - | - | `true` | Whether show icon | -| `showLine` | `bool` | - | - | `false` | Whether show line | -| `style` | `obj`, `array` | - | - | - | Accepts css style | -| `loadData` | `func` | - | - | - | load data asynchronously and the return value should be a promise | -| `isFullFillSelection` | `bool` | - | - | `true` | to select the selection style of the active node | -| `gapBetweenNodes` | `string` | - | - | `15` | for setting the spacing between nodes | -|`gapBetweenNodesTablet`| `string` | - | - | - | to set spacing between nodes on tablets and phones (if necessary) | -| `isEmptyRootNode` | `bool` | - | - | `false` | swipe the root node to the left if there are no nested elements | +| Props | Type | Required | Values | Default | Description | +| ----------------------- | :------------: | :------: | :----: | :-----: | ------------------------------------------------------------------------------------------------------- | +| `autoExpandParent` | `bool` | - | - | `false` | Whether auto expand parent treeNodes | +| `checkable` | `bool` | - | - | `false` | Whether support checked | +| `className` | `string` | - | - | - | Accepts class | +| `defaultExpandAll` | `bool` | - | - | `false` | Expand all treeNodes | +| `defaultExpandParent` | `bool` | - | - | `true` | Auto expand parent treeNodes when init | +| `disabled` | `bool` | - | - | `false` | Whether disabled the tree | +| `draggable` | `bool` | - | - | `false` | Whether can drag treeNode | +| `id` | `string` | - | - | - | Accepts id | +| `multiple` | `bool` | - | - | `false` | Whether multiple select | +| `onDragEnd` | `func` | - | - | - | it execs when fire the tree's dragend event | +| `onDragEnter` | `func` | - | - | - | it execs when fire the tree's dragenter event | +| `onDragLeave` | `func` | - | - | - | it execs when fire the tree's dragleave event | +| `onDragOver` | `func` | - | - | - | it execs when fire the tree's dragover event | +| `onDragStart` | `func` | - | - | - | it execs when fire the tree's dragstart event | +| `onDrop` | `func` | - | - | - | it execs when fire the tree's drop event | +| `onExpand` | `func` | - | - | - | fire on treeNode expand or not | +| `onLoad` | `func` | - | - | - | Trigger when a node is loaded. If you set the loadedKeys, you must handle onLoad to avoid infinity loop | +| `onMouseEnter` | `func` | - | - | - | call when mouse enter a treeNode | +| `onMouseLeave` | `func` | - | - | - | call when mouse leave a treeNode | +| `onRightClick` | `func` | - | - | - | select current treeNode and show customized contextmenu | +| `onSelect` | `func` | - | - | - | click the treeNode to fire | +| `showIcon` | `bool` | - | - | `true` | Whether show icon | +| `showLine` | `bool` | - | - | `false` | Whether show line | +| `style` | `obj`, `array` | - | - | - | Accepts css style | +| `loadData` | `func` | - | - | - | load data asynchronously and the return value should be a promise | +| `isFullFillSelection` | `bool` | - | - | `true` | to select the selection style of the active node | +| `gapBetweenNodes` | `string` | - | - | `15` | for setting the spacing between nodes | +| `gapBetweenNodesTablet` | `string` | - | - | - | to set spacing between nodes on tablets and phones (if necessary) | +| `isEmptyRootNode` | `bool` | - | - | `false` | swipe the root node to the left if there are no nested elements | ### Properties TreeNode @@ -59,3 +59,5 @@ import { TreeMenu } from "asc-web-components"; | `key` | `bool` | - | - | - | it's used with tree props's (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys. you'd better to set it, and it must be unique in the tree's all treeNodes | | `style` | `object` | - | - | - | set style to treeNode | | `title` | `string`,`element` | - | - | - | tree/subTree's title | +| `newItems` | `number` | - | - | - | If value > 0 then a badge with the number of new elements will be displayed | +| `onBadgeClick` | `func` | - | - | - | call when click on badge | diff --git a/web/ASC.Web.Components/src/components/tree-menu/index.js b/web/ASC.Web.Components/src/components/tree-menu/index.js index 3582f475d7..9ee9766357 100644 --- a/web/ASC.Web.Components/src/components/tree-menu/index.js +++ b/web/ASC.Web.Components/src/components/tree-menu/index.js @@ -1,8 +1,10 @@ /* eslint-disable react/prop-types */ -import React from 'react'; -import styled, { css } from 'styled-components'; -import PropTypes from 'prop-types'; -import Tree from 'rc-tree'; +import React from "react"; +import styled, { css } from "styled-components"; +import PropTypes from "prop-types"; +import Tree from "rc-tree"; + +import Badge from "../badge"; const StyledTreeMenu = styled(Tree)` margin: 0; @@ -18,32 +20,33 @@ const StyledTreeMenu = styled(Tree)` margin-left: 4px; } - ${props => props.isEmptyRootNode && - css` - & > li > span.rc-tree-switcher-noop { - display: none; - } - ` - } + ${props => + props.isEmptyRootNode && + css` + & > li > span.rc-tree-switcher-noop { + display: none; + } + `} .rc-tree-node-content-wrapper { - margin-bottom: ${props => +props.gapBetweenNodes - 15 + 'px;'}; + position: static !important; + margin-bottom: ${props => +props.gapBetweenNodes - 15 + "px;"}; @media(max-width: 1024px) { - margin-bottom: ${props => props.gapBetweenNodesTablet - ? +props.gapBetweenNodesTablet - 15 + 'px;' - : +props.gapBetweenNodes - 15 + 'px;' - }; + margin-bottom: ${props => + props.gapBetweenNodesTablet + ? +props.gapBetweenNodesTablet - 15 + "px;" + : +props.gapBetweenNodes - 15 + "px;"}; } }; - ${props => !props.isFullFillSelection && - css` - & .rc-tree-node-selected { - width: min-content !important; - padding-right: 5px; - max-width: 100%; - } - ` - } - + ${props => + !props.isFullFillSelection && + css` + span.rc-tree-node-selected { + width: min-content !important; + padding-right: 5px; + max-width: 85%; + } + `} + & .rc-tree-node-selected .rc-tree-title { ${props => !props.isFullFillSelection && "width: 85%;"} } @@ -69,9 +72,9 @@ const StyledTreeMenu = styled(Tree)` .rc-tree-child-tree-open { display: block; ${props => props.disableSwitch && "margin: 0 0 25px 0;"} - margin-left: ${props => props.disableSwitch ? "27px" : "8px"}; + margin-left: ${props => (props.disableSwitch ? "27px" : "8px")}; li:first-child{ - margin-top: ${props => props.disableSwitch ? "10px" : "6px"}; + margin-top: ${props => (props.disableSwitch ? "10px" : "6px")}; margin-left: 0; } @@ -102,129 +105,201 @@ const StyledTreeMenu = styled(Tree)` margin-right: 2px; vertical-align: top; } - ${props => props.switcherIcon != null ? - css` - li span.rc-tree-switcher{ - background: none; + ${props => + props.switcherIcon != null + ? css` + li span.rc-tree-switcher { + background: none; } - ` - : '' - } - ${props => props.disableSwitch ? - css` - li span.rc-tree-switcher{ - height: 0; - margin: 0; - width: 0; + ` + : ""} + ${props => + props.disableSwitch + ? css` + li span.rc-tree-switcher { + height: 0; + margin: 0; + width: 0; } - ` - : `` - } + ` + : ``} `; const TreeMenu = React.forwardRef((props, ref) => { - //console.log("TreeMenu render"); - const { defaultExpandAll, defaultExpandParent, showIcon, showLine, multiple, disabled, draggable, checkable, children, switcherIcon, icon, - onDragStart, onDrop, onSelect, onDragEnter, onDragEnd, onDragLeave, onDragOver, onCheck, onExpand, onLoad, onMouseEnter, onMouseLeave, onRightClick, - defaultSelectedKeys, expandedKeys, defaultExpandedKeys, defaultCheckedKeys, selectedKeys, className, id, style, loadData, disableSwitch, - isFullFillSelection, gapBetweenNodes, gapBetweenNodesTablet, isEmptyRootNode } = props; + //console.log("TreeMenu render"); + const { + defaultExpandAll, + defaultExpandParent, + showIcon, + showLine, + multiple, + disabled, + draggable, + checkable, + children, + switcherIcon, + icon, + onDragStart, + onDrop, + onSelect, + onDragEnter, + onDragEnd, + onDragLeave, + onDragOver, + onCheck, + onExpand, + onLoad, + onMouseEnter, + onMouseLeave, + onRightClick, + defaultSelectedKeys, + expandedKeys, + defaultExpandedKeys, + defaultCheckedKeys, + selectedKeys, + className, + id, + style, + loadData, + disableSwitch, + isFullFillSelection, + gapBetweenNodes, + gapBetweenNodesTablet, + isEmptyRootNode + } = props; - const expandedKeysProp = expandedKeys ? { expandedKeys: expandedKeys } : {}; + const expandedKeysProp = expandedKeys ? { expandedKeys: expandedKeys } : {}; - const onTreeNodeSelect = (data, e) => { - const result = e.selected ? data : [e.node.props.eventKey]; - onSelect(result, e); - } - return ( - { + const result = e.selected ? data : [e.node.props.eventKey]; + onSelect(result, e); + }; - selectedKeys={selectedKeys} - defaultSelectedKeys={defaultSelectedKeys} - defaultExpandedKeys={defaultExpandedKeys} - defaultCheckedKeys={defaultCheckedKeys} + const renderChildren = children => { + const items = []; - onDragStart={onDragStart} - onDrop={onDrop} - onDragEnd={onDragEnd} - onDragLeave={onDragLeave} - onDragOver={onDragOver} + React.Children.forEach(children, (child, i) => { + if ( + child.props.newItems > 0 && + typeof child.props.newItems === "number" + ) { + const el = React.cloneElement(child, { + key: child.props.id, + icon: ( + <> + {child.props.icon} + + + ) + }); + items.push(el); + } else { + items.push(child); + } + }); + return items; + }; - switcherIcon={switcherIcon} - onSelect={onTreeNodeSelect} - onDragEnter={onDragEnter} + const modifiedChildren = renderChildren(children); - onCheck={onCheck} - onExpand={onExpand} - - onLoad={onLoad} - onMouseEnter={onMouseEnter} - onMouseLeave={onMouseLeave} - onRightClick={onRightClick} - - disableSwitch={disableSwitch} - isFullFillSelection={isFullFillSelection} - gapBetweenNodes={gapBetweenNodes} - gapBetweenNodesTablet={gapBetweenNodesTablet} - isEmptyRootNode={isEmptyRootNode} - > - {children} - - ); -}) + return ( + <> + + {modifiedChildren} + + + ); +}); TreeMenu.propTypes = { - checkable: PropTypes.bool, - draggable: PropTypes.bool, - disabled: PropTypes.bool, - multiple: PropTypes.bool, - showIcon: PropTypes.bool, - showLine: PropTypes.bool, - defaultExpandAll: PropTypes.bool, - defaultExpandParent: PropTypes.bool, + checkable: PropTypes.bool, + draggable: PropTypes.bool, + disabled: PropTypes.bool, + multiple: PropTypes.bool, + showIcon: PropTypes.bool, + showLine: PropTypes.bool, + defaultExpandAll: PropTypes.bool, + defaultExpandParent: PropTypes.bool, - icon: PropTypes.func, - onDragStart: PropTypes.func, - onDrop: PropTypes.func, - loadData: PropTypes.func, + icon: PropTypes.func, + onDragStart: PropTypes.func, + onDrop: PropTypes.func, + loadData: PropTypes.func, - children: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.node), - PropTypes.node - ]), - className: PropTypes.string, - id: PropTypes.string, - style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]), + className: PropTypes.string, + id: PropTypes.string, + style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), - disableSwitch: PropTypes.bool, + disableSwitch: PropTypes.bool, - isFullFillSelection: PropTypes.bool, - gapBetweenNodes: PropTypes.string, - gapBetweenNodesTablet: PropTypes.string, - isEmptyRootNode: PropTypes.bool -} + isFullFillSelection: PropTypes.bool, + gapBetweenNodes: PropTypes.string, + gapBetweenNodesTablet: PropTypes.string, + isEmptyRootNode: PropTypes.bool +}; TreeMenu.defaultProps = { - disableSwitch: false, - isFullFillSelection: true, - gapBetweenNodes: '15', - isEmptyRootNode: false -} + disableSwitch: false, + isFullFillSelection: true, + gapBetweenNodes: "15", + isEmptyRootNode: false +}; TreeMenu.displayName = "TreeMenu"; -export default TreeMenu \ No newline at end of file +export default TreeMenu; diff --git a/web/ASC.Web.Components/src/components/tree-menu/sub-components/tree-node.js b/web/ASC.Web.Components/src/components/tree-menu/sub-components/tree-node.js index 4fb3308c5b..9d7393faa0 100644 --- a/web/ASC.Web.Components/src/components/tree-menu/sub-components/tree-node.js +++ b/web/ASC.Web.Components/src/components/tree-menu/sub-components/tree-node.js @@ -1,37 +1,89 @@ -import React from 'react'; -import styled, { css } from 'styled-components'; -import { Icons } from '../../icons'; -import { getCssFromSvg } from '../../icons/get-css-from-svg'; -import {TreeNode} from 'rc-tree'; -import ReactDOMServer from 'react-dom/server'; +import React from "react"; +import styled, { css } from "styled-components"; +import { Icons } from "../../icons"; +import { getCssFromSvg } from "../../icons/get-css-from-svg"; +import { TreeNode } from "rc-tree"; +import ReactDOMServer from "react-dom/server"; var checkboxIcon, - checkboxСheckedIcon, - сheckboxDisabledIcon, - сheckboxHoverIcon, - сheckboxIndeterminateIcon, - checkboxCheckedDisabledIcon, - checkboxCheckedHoverIcon, - checkboxIndeterminateDisabledIcon, - checkboxIndeterminateHoverIcon, - // eslint-disable-next-line no-unused-vars - treeIcon; + checkboxСheckedIcon, + сheckboxDisabledIcon, + сheckboxHoverIcon, + сheckboxIndeterminateIcon, + checkboxCheckedDisabledIcon, + checkboxCheckedHoverIcon, + checkboxIndeterminateDisabledIcon, + checkboxIndeterminateHoverIcon, + // eslint-disable-next-line no-unused-vars + treeIcon; -(function(){ - checkboxIcon = getCssFromSvg(ReactDOMServer.renderToString()); - сheckboxDisabledIcon = getCssFromSvg(ReactDOMServer.renderToString()); - сheckboxHoverIcon = getCssFromSvg(ReactDOMServer.renderToString()); +(function() { + checkboxIcon = getCssFromSvg( + ReactDOMServer.renderToString() + ); + сheckboxDisabledIcon = getCssFromSvg( + ReactDOMServer.renderToString( + + ) + ); + сheckboxHoverIcon = getCssFromSvg( + ReactDOMServer.renderToString( + + ) + ); - checkboxСheckedIcon= getCssFromSvg(ReactDOMServer.renderToString()); - checkboxCheckedDisabledIcon= getCssFromSvg(ReactDOMServer.renderToString()); - checkboxCheckedHoverIcon = getCssFromSvg(ReactDOMServer.renderToString()); + checkboxСheckedIcon = getCssFromSvg( + ReactDOMServer.renderToString() + ); + checkboxCheckedDisabledIcon = getCssFromSvg( + ReactDOMServer.renderToString( + + ) + ); + checkboxCheckedHoverIcon = getCssFromSvg( + ReactDOMServer.renderToString( + + ) + ); - сheckboxIndeterminateIcon = getCssFromSvg(ReactDOMServer.renderToString()); - checkboxIndeterminateDisabledIcon = getCssFromSvg(ReactDOMServer.renderToString()); - checkboxIndeterminateHoverIcon = getCssFromSvg(ReactDOMServer.renderToString()); + сheckboxIndeterminateIcon = getCssFromSvg( + ReactDOMServer.renderToString() + ); + checkboxIndeterminateDisabledIcon = getCssFromSvg( + ReactDOMServer.renderToString( + + ) + ); + checkboxIndeterminateHoverIcon = getCssFromSvg( + ReactDOMServer.renderToString( + + ) + ); - treeIcon = getCssFromSvg(ReactDOMServer.renderToString()); -}()); + treeIcon = getCssFromSvg( + ReactDOMServer.renderToString() + ); +})(); const TreeNodeMenu = styled(TreeNode)` @@ -82,10 +134,10 @@ const TreeNodeMenu = styled(TreeNode)` padding: 0; } .rc-tree-node-content-wrapper { - width: ${props => props.disableSwitch ? "90%" : "108%"}; + width: ${props => (props.disableSwitch ? "90%" : "108%")}; display: inline-block; position: relative; - /*min-width: ${props => props.disableSwitch ? "160px" : "190px"};*/ + /*min-width: ${props => (props.disableSwitch ? "160px" : "190px")};*/ overflow: hidden; cursor: pointer; @@ -94,10 +146,10 @@ const TreeNodeMenu = styled(TreeNode)` vertical-align: top; left: 0; - background: ${props => props.dragging ? "#F8F7BF" : "none"}; + background: ${props => (props.dragging ? "#F8F7BF" : "none")}; :hover { - background: ${props => props.dragging ? "#EFEFB2" : "none"}; + background: ${props => (props.dragging ? "#EFEFB2" : "none")}; } } span.rc-tree-switcher, @@ -117,7 +169,7 @@ const TreeNodeMenu = styled(TreeNode)` background-attachment: scroll; } span.rc-tree-iconEle { - display: ${props => props.icon ? 'inline-block' : 'none'}; + display: ${props => (props.icon ? "inline-block" : "none")}; } span.rc-tree-switcher { @@ -214,33 +266,50 @@ const TreeNodeMenu = styled(TreeNode)` } span.rc-tree-title{ display: inline-block; - width: ${props => !props.disableSwitch - ? props.icon ? 'calc(100% - 44px)' : 'calc(100% - 20px)' - : '100%'}; + width: ${props => + !props.disableSwitch + ? props.icon + ? "calc(100% - 44px)" + : "calc(100% - 20px)" + : "100%"}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: #333; - padding-left: ${props => (props.icon || props.disableSwitch) ? '0' : '20px'}; + padding-left: ${props => + props.icon || props.disableSwitch ? "0" : "20px"}; } span.rc-tree-title:first-child{ max-width: 100%; } + .newItem { + position: absolute; + right: 0px; + top: 2px; + } .rc-tree-node-selected { background: #DFE2E3; mix-blend-mode: normal; border-radius: 3px; z-index: 0; - ${props => props.disableSwitch && - css` - min-width: 0; - width: auto; - ` - } + ${props => + props.disableSwitch && + css` + min-width: 0; + width: auto; + `} :hover { background: #DFE2E3; } + overflow: visible; + + } + .newItem { + position: absolute; + right: -30px; + top: 2px; + } `; -export default TreeNodeMenu; \ No newline at end of file +export default TreeNodeMenu; diff --git a/web/ASC.Web.Components/src/components/tree-menu/tree-menu.stories.js b/web/ASC.Web.Components/src/components/tree-menu/tree-menu.stories.js index 8f0fd73edd..ca681f61ae 100644 --- a/web/ASC.Web.Components/src/components/tree-menu/tree-menu.stories.js +++ b/web/ASC.Web.Components/src/components/tree-menu/tree-menu.stories.js @@ -1,24 +1,27 @@ -import React, { useState } from 'react'; -import { storiesOf } from '@storybook/react'; -import { withKnobs, boolean, text, select, number } from '@storybook/addon-knobs/react'; -import withReadme from 'storybook-readme/with-readme'; -import Readme from './README.md'; -import TreeMenu from '.'; -import TreeNode from './sub-components/tree-node'; -import { Icons } from '../icons'; -import { action } from '@storybook/addon-actions'; - +import React, { useState } from "react"; +import { storiesOf } from "@storybook/react"; +import { + withKnobs, + boolean, + text, + select, + number +} from "@storybook/addon-knobs/react"; +import withReadme from "storybook-readme/with-readme"; +import Readme from "./README.md"; +import TreeMenu from "."; +import TreeNode from "./sub-components/tree-node"; +import { Icons } from "../icons"; +import { action } from "@storybook/addon-actions"; const iconNames = Object.keys(Icons); const treeData = [ { - key: '0-0', children: - [ - { key: '0-0-0' }, - { key: '0-0-1' } - ], - }, + key: "0-0", + children: [{ key: "0-0-0" }, { key: "0-0-1" }], + newItems: 1 + } ]; const TreeMenuStory = props => { @@ -28,22 +31,32 @@ const TreeMenuStory = props => { const [gData, setGData] = useState(data); const [autoExpandParent, setAutoExpandParent] = useState(true); - const [expandedKeys, setExpandedKeys] = useState(['0-0-key', '0-0-0-key', '0-0-0-0-key']); + const [expandedKeys, setExpandedKeys] = useState([ + "0-0-key", + "0-0-0-key", + "0-0-0-0-key" + ]); - const onDragStart = (info) => { + const onDragStart = info => { info.event.persist(); }; - const onDragEnter = (info) => { + const onDragEnter = info => { setExpandedKeys(info.expandedKeys); }; - const onDrop = (info) => { + const onBadgeClick = e => { + const id = e.currentTarget.dataset.id; + console.log("Clocked on badge: ", id); + }; + + const onDrop = info => { info.event.persist(); const dropKey = info.node.props.eventKey; const dragKey = info.dragNode.props.eventKey; - const dropPos = info.node.props.pos.split('-'); - const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]); + const dropPos = info.node.props.pos.split("-"); + const dropPosition = + info.dropPosition - Number(dropPos[dropPos.length - 1]); const loop = (treeData, key, callback) => { treeData.forEach((item, index, arr) => { @@ -66,7 +79,7 @@ const TreeMenuStory = props => { }); if (!info.dropToGap) { - loop(treeData, dropKey, (item) => { + loop(treeData, dropKey, item => { item.children = item.children || []; item.children.push(dragObj); }); @@ -75,7 +88,7 @@ const TreeMenuStory = props => { info.node.props.expanded && dropPosition === 1 ) { - loop(treeData, dropKey, (item) => { + loop(treeData, dropKey, item => { item.children = item.children || []; item.children.unshift(dragObj); }); @@ -94,65 +107,90 @@ const TreeMenuStory = props => { } setGData(treeData); }; - const onExpand = (expandedKeys) => { + const onExpand = expandedKeys => { setExpandedKeys(expandedKeys); setAutoExpandParent(false); - } + }; const getTreeNodes = tree => { - return tree.map((item) => { + return tree.map(item => { if (item.children && item.children.length) { - return {getTreeNodes(item.children)}; + return ( + + {getTreeNodes(item.children)} + + ); } - return ; + return ( + + ); }); }; - - - const switcherIcon = (obj) => { + const switcherIcon = obj => { if (obj.isLeaf) { return null; } if (obj.expanded) { - return + return ( + + ); } else { - return + return ( + + ); } }; return (
onDragStart(info)} - onDrop={(info) => onDrop(info)} + onDragStart={info => onDragStart(info)} + onDrop={info => onDrop(info)} onDragEnter={onDragEnter} - switcherIcon={switcherIcon} - onSelect={action("select")} onLoad={action("load")} - onCheck={action("check")} - onRightClick={action("rightClick")} > {getTreeNodes(gData)} @@ -161,9 +199,7 @@ const TreeMenuStory = props => { ); }; -storiesOf('Components|Tree', module) +storiesOf("Components|Tree", module) .addDecorator(withKnobs) .addDecorator(withReadme(Readme)) - .add('base', () => ); - - + .add("base", () => ); diff --git a/web/ASC.Web.Components/src/components/tree-menu/tree-menu.test.js b/web/ASC.Web.Components/src/components/tree-menu/tree-menu.test.js index a52903d2e5..01264b27a6 100644 --- a/web/ASC.Web.Components/src/components/tree-menu/tree-menu.test.js +++ b/web/ASC.Web.Components/src/components/tree-menu/tree-menu.test.js @@ -1,10 +1,10 @@ -import React from 'react'; -import { mount } from 'enzyme'; -import TreeMenu from '.'; -import TreeNode from './sub-components/tree-node'; +import React from "react"; +import { mount } from "enzyme"; +import TreeMenu from "."; +import TreeNode from "./sub-components/tree-node"; -describe('', () => { - it('renders without error', () => { +describe("", () => { + it("renders without error", () => { const wrapper = mount( ', () => { showLine={false} > - + ); @@ -26,7 +23,7 @@ describe('', () => { expect(wrapper).toExist(); }); - it('accepts id', () => { + it("accepts id", () => { const wrapper = mount( ', () => { showLine={false} > - + ); - expect(wrapper.prop('id')).toEqual('testId'); + expect(wrapper.prop("id")).toEqual("testId"); }); - it('accepts className', () => { + it("accepts className", () => { const wrapper = mount( ', () => { showLine={false} > - + ); - expect(wrapper.prop('className')).toEqual('test'); + expect(wrapper.prop("className")).toEqual("test"); }); - it('accepts style', () => { + it("accepts style", () => { const wrapper = mount( ', () => { showLine={false} > - + ); - expect(wrapper.getDOMNode().style).toHaveProperty('color', 'red'); + expect(wrapper.getDOMNode().style).toHaveProperty("color", "red"); }); - it('accepts isFullFillSelection', () => { + it("accepts isFullFillSelection", () => { const wrapper = mount( - + - + ); - expect(wrapper.prop('isFullFillSelection')).toEqual(false); + expect(wrapper.prop("isFullFillSelection")).toEqual(false); }); - it('accepts gapBetweenNodes and gapBetweenNodesTablet', () => { + it("accepts gapBetweenNodes and gapBetweenNodesTablet", () => { const wrapper = mount( - + - + ); - expect(wrapper.prop('gapBetweenNodes')).toEqual('22'); - expect(wrapper.prop('gapBetweenNodesTablet')).toEqual('24'); + expect(wrapper.prop("gapBetweenNodes")).toEqual("22"); + expect(wrapper.prop("gapBetweenNodesTablet")).toEqual("24"); }); - it('accepts isEmptyRootNode', () => { + it("accepts isEmptyRootNode", () => { const wrapper = mount( - + - + ); - expect(wrapper.prop('isEmptyRootNode')).toEqual(true); + expect(wrapper.prop("isEmptyRootNode")).toEqual(true); }); });