import * as React from 'react'; import { ElementTypeIri } from '../../data/model'; import { DiagramView } from '../../diagram/view'; import { highlightSubstring } from '../listElementView'; import { TreeNode } from './treeModel'; const EXPAND_ICON = require('../../../../images/tree/expand-toggle.svg'); const COLLAPSE_ICON = require('../../../../images/tree/collapse-toggle.svg'); const DEFAULT_LEAF_ICON = require('../../../../images/tree/leaf-default.svg'); const DEFAULT_PARENT_ICON = require('../../../../images/tree/leaf-folder.svg'); interface CommonProps { view: DiagramView; searchText?: string; selectedNode?: TreeNode; onSelect: (node: TreeNode) => void; creatableClasses: ReadonlyMap; onClickCreate: (node: TreeNode) => void; onDragCreate: (node: TreeNode) => void; } export interface LeafProps extends CommonProps { node: TreeNode; } interface State { expanded?: boolean; } const LEAF_CLASS = 'ontodia-class-leaf'; export class Leaf extends React.Component { constructor(props: LeafProps) { super(props); this.state = { expanded: Boolean(this.props.searchText), }; } componentWillReceiveProps(nextProps: LeafProps) { if (this.props.searchText !== nextProps.searchText) { this.setState({ expanded: Boolean(nextProps.searchText), }); } } render() { const {node, ...otherProps} = this.props; const {view, selectedNode, searchText, creatableClasses} = otherProps; const {expanded} = this.state; let toggleIcon: string | undefined; if (node.derived.length > 0) { toggleIcon = expanded ? COLLAPSE_ICON : EXPAND_ICON; } let {icon} = view.getTypeStyle([node.model.id]); if (!icon) { icon = node.derived.length === 0 ? DEFAULT_LEAF_ICON : DEFAULT_PARENT_ICON; } let bodyClass = `${LEAF_CLASS}__body`; if (selectedNode && selectedNode.model === node.model) { bodyClass += ` ${LEAF_CLASS}__body--selected`; } const label = highlightSubstring( node.label, searchText, {className: `${LEAF_CLASS}__highlighted-term`} ); return (
{toggleIcon ? : null}
{label} {node.model.count ? ( {node.model.count} ) : null}
{creatableClasses.get(node.model.id) ? (
) : null}
{expanded && node.derived.length > 0 ? ( ) : null}
); } private onClick = (e: React.MouseEvent<{}>) => { e.preventDefault(); const {node, onSelect} = this.props; onSelect(node); } private toggle = () => { this.setState((state): State => ({expanded: !state.expanded})); } private onClickCreate = () => { this.props.onClickCreate(this.props.node); } private onDragCreate = (e: React.DragEvent) => { // sets the drag data to support drag-n-drop in Firefox // see https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations for more details // IE supports only 'text' and 'URL' formats, see https://msdn.microsoft.com/en-us/ie/ms536744(v=vs.94) e.dataTransfer.setData('text', ''); this.props.onDragCreate(this.props.node); } } export interface ForestProps extends CommonProps { className?: string; nodes: ReadonlyArray; } export class Forest extends React.Component { render() { const {nodes, className, ...otherProps} = this.props; return (
{nodes.map(node => ( ))}
); } }