react-dnd-html5-backend#getEmptyImage TypeScript Examples
The following examples show how to use
react-dnd-html5-backend#getEmptyImage.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From hive with MIT License | 6 votes |
componentDidMount() {
const { connectDragPreview } = this.props;
if (connectDragPreview) {
connectDragPreview(getEmptyImage(), {
captureDraggingState: true,
});
}
}
Example #2
Source File: QueryBuilderFunctionsExplorerPanel.tsx From legend-studio with Apache License 2.0 | 5 votes |
QueryBuilderFunctionsExplorerListEntry = observer(
(props: {
queryBuilderState: QueryBuilderState;
element: ConcreteFunctionDefinition;
rootPackageName: ROOT_PACKAGE_NAME;
}) => {
const { queryBuilderState, element, rootPackageName } = props;
const node = generateFunctionsExplorerTreeNodeData(
queryBuilderState,
element,
rootPackageName,
);
const functionSignature = generateFunctionSignature(element, true);
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type: QUERY_BUILDER_FUNCTIONS_EXPLORER_TREE_DND_TYPE.FUNCTION,
item: { node: node },
}),
[node],
);
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
return (
<div
className="query-builder__functions-explorer__function"
ref={dragConnector}
>
<div className="query-builder__functions-explorer__function__content">
<div className="query-builder__functions-explorer__function__icon">
<div className="query-builder__functions-explorer__function-icon">
<PURE_FunctionIcon />
</div>
</div>
<div
className="query-builder__functions-explorer__function__label"
title={functionSignature}
>
{functionSignature}
</div>
</div>
<div className="query-builder__functions-explorer__function__actions">
<QueryBuilderFunctionInfoTooltip
element={node.packageableElement as ConcreteFunctionDefinition}
>
<div className="query-builder__functions-explorer__function__action query-builder__functions-explorer__function__node__info">
<InfoCircleIcon />
</div>
</QueryBuilderFunctionInfoTooltip>
</div>
</div>
);
},
)
Example #3
Source File: QueryBuilderParameterPanel.tsx From legend-studio with Apache License 2.0 | 5 votes |
VariableExpressionViewer = observer(
(props: {
queryBuilderState: QueryBuilderState;
variableExpressionState: QueryParameterState;
}) => {
const { queryBuilderState, variableExpressionState } = props;
const queryParameterState = queryBuilderState.queryParametersState;
const variable = variableExpressionState.parameter;
const name = variable.name;
const variableType = variable.genericType?.value.rawType;
const typeName = variableType?.name;
const editVariable = (): void => {
queryParameterState.setSelectedParameter(variableExpressionState);
};
const deleteVariable = (): void =>
queryParameterState.removeParameter(variableExpressionState);
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type: QUERY_BUILDER_PARAMETER_TREE_DND_TYPE.VARIABLE,
item: { variable: variableExpressionState },
}),
[variableExpressionState],
);
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
return (
<div className="query-builder__parameters__parameter" ref={dragConnector}>
<QueryBuilderParameterDragLayer queryBuilderState={queryBuilderState} />
<div className="query-builder__parameters__parameter__content">
<div className="query-builder__parameters__parameter__icon">
<div className="query-builder__parameters__parameter-icon">
<DollarIcon />
</div>
</div>
<div className="query-builder__parameters__parameter__label">
{name}
<div className="query-builder__parameters__parameter__type">
<div className="query-builder__parameters__parameter__type__label">
{typeName}
</div>
</div>
</div>
</div>
<div className="query-builder__parameters__parameter__actions">
<button
className="query-builder__parameters__parameter__action"
tabIndex={-1}
onClick={editVariable}
title="Edit Parameter"
>
<PencilIcon />
</button>
<button
className="query-builder__parameters__parameter__action"
onClick={deleteVariable}
title="Remove"
>
<TimesIcon />
</button>
</div>
</div>
);
},
)
Example #4
Source File: index.tsx From uno-game with MIT License | 5 votes |
DraggableCard: React.FC<CardProps> = (props) => {
const {
card,
index,
style,
className,
onClick,
selected,
isDraggingAnyCard,
onDragEnd,
canBePartOfCurrentCombo,
isMoreThanOneCardBeingDragged,
} = props
const draggableCardRef = useRef(null)
const canCardBeUsed = canBePartOfCurrentCombo || card.canBeUsed
const [{ isDragging }, drag, preview] = useDrag({
item: {
type: CARD_TYPE,
id: card.id,
index,
src: card.src,
name: card.name,
cardType: card.type,
selected,
className,
} as DraggedCardItem,
collect: monitor => ({
isDragging: monitor.isDragging(),
}),
canDrag: canCardBeUsed,
end: onDragEnd,
})
drag(draggableCardRef)
useDidMount(() => {
preview(getEmptyImage(), { captureDraggingState: true })
})
return (
<img
ref={draggableCardRef}
key={card.name}
className={className}
alt={card.name}
src={card.src}
style={{
...style,
opacity: (isDragging || (isDraggingAnyCard && isMoreThanOneCardBeingDragged && selected)) ? 0 : 1,
filter: !canCardBeUsed ? "brightness(0.5)" : "saturate(1.5)",
pointerEvents: canCardBeUsed ? "all" : "none",
...(selected ? {
border: `${Device.isMobile ? "3px" : "5px"} solid #EC0000`,
borderRadius: Device.isMobile ? "8px" : "16px",
} : {}),
}}
onClick={onClick}
/>
)
}
Example #5
Source File: QueryBuilderExplorerPanel.tsx From legend-studio with Apache License 2.0 | 4 votes |
QueryBuilderExplorerTreeNodeContainer = observer(
(
props: TreeNodeContainerProps<
QueryBuilderExplorerTreeNodeData,
{
queryBuilderState: QueryBuilderState;
}
>,
) => {
const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
const { queryBuilderState } = innerProps;
const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] =
useState(false);
const applicationStore = useApplicationStore();
const explorerState = queryBuilderState.explorerState;
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type:
node instanceof QueryBuilderExplorerTreePropertyNodeData
? node.type instanceof Enumeration
? QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY
: node.type instanceof Class
? QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.CLASS_PROPERTY
: QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY
: QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ROOT,
item: (): { node?: QueryBuilderExplorerTreePropertyNodeData } =>
node instanceof QueryBuilderExplorerTreePropertyNodeData
? { node }
: {},
}),
[node],
);
const isExpandable = Boolean(node.childrenIds.length);
const isDerivedProperty =
node instanceof QueryBuilderExplorerTreePropertyNodeData &&
node.property instanceof DerivedProperty;
const isMultiple =
(node instanceof QueryBuilderExplorerTreePropertyNodeData &&
(node.property.multiplicity.upperBound === undefined ||
node.property.multiplicity.upperBound > 1)) ||
(node instanceof QueryBuilderExplorerTreeSubTypeNodeData &&
(node.multiplicity.upperBound === undefined ||
node.multiplicity.upperBound > 1));
const allowPreview =
node.mappingData.mapped &&
node instanceof QueryBuilderExplorerTreePropertyNodeData &&
node.type instanceof PrimitiveType &&
!node.isPartOfDerivedPropertyBranch;
const nodeExpandIcon = isExpandable ? (
node.isOpen ? (
<ChevronDownIcon />
) : (
<ChevronRightIcon />
)
) : (
<div />
);
const selectNode = (): void => onNodeSelect?.(node);
const openNode = (): void => {
if (!node.isOpen) {
onNodeSelect?.(node);
}
};
// context menu
const showContextMenu =
node instanceof QueryBuilderExplorerTreeRootNodeData ||
(node instanceof QueryBuilderExplorerTreePropertyNodeData &&
!(node.type instanceof PrimitiveType));
const onContextMenuOpen = (): void => setIsSelectedFromContextMenu(true);
const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
const previewData = (): void => {
if (node instanceof QueryBuilderExplorerTreePropertyNodeData) {
flowResult(
queryBuilderState.fetchStructureState.projectionState.previewData(
node,
),
).catch(applicationStore.alertUnhandledError);
}
};
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
if (
!node.mappingData.mapped &&
!explorerState.showUnmappedProperties &&
queryBuilderState.querySetupState.isMappingCompatible
) {
return null;
}
return (
<ContextMenu
content={
<QueryBuilderExplorerContextMenu
queryBuilderState={queryBuilderState}
openNode={openNode}
node={node}
/>
}
disabled={
!showContextMenu ||
// NOTE: this might make it hard to modularize
queryBuilderState.fetchStructureState.projectionState.hasParserError
}
menuProps={{ elevation: 7 }}
onOpen={onContextMenuOpen}
onClose={onContextMenuClose}
>
<div
className={clsx(
'tree-view__node__container query-builder-explorer-tree__node__container',
{
'query-builder-explorer-tree__node__container--selected-from-context-menu':
isSelectedFromContextMenu,
'query-builder-explorer-tree__node__container--unmapped':
!node.mappingData.mapped,
},
)}
title={
!node.mappingData.mapped ? 'Property is not mapped' : undefined
}
onClick={selectNode}
ref={
node.mappingData.mapped && !isExpandable ? dragConnector : undefined
}
style={{
paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 1) + 0.5}rem`,
display: 'flex',
}}
>
{node instanceof QueryBuilderExplorerTreeRootNodeData && (
// NOTE: since the root of the tree is the class, not the property, we want to display it differently
<>
<div className="query-builder-explorer-tree__expand-icon">
{nodeExpandIcon}
</div>
<div className="tree-view__node__label query-builder-explorer-tree__root-node__label">
<div className="query-builder-explorer-tree__root-node__label__icon">
<PURE_ClassIcon />
</div>
<div className="query-builder-explorer-tree__root-node__label__text">
{node.label}
</div>
</div>
</>
)}
{(node instanceof QueryBuilderExplorerTreePropertyNodeData ||
node instanceof QueryBuilderExplorerTreeSubTypeNodeData) && (
<>
<div className="tree-view__node__icon query-builder-explorer-tree__node__icon">
<div className="query-builder-explorer-tree__expand-icon">
{nodeExpandIcon}
</div>
<div className="query-builder-explorer-tree__type-icon">
{renderPropertyTypeIcon(node.type)}
</div>
</div>
<div
className={clsx(
'tree-view__node__label query-builder-explorer-tree__node__label query-builder-explorer-tree__node__label--with-action',
{
'query-builder-explorer-tree__node__label--with-preview':
allowPreview,
},
)}
>
{explorerState.humanizePropertyName
? node instanceof QueryBuilderExplorerTreeSubTypeNodeData
? TYPE_CAST_TOKEN + prettyPropertyName(node.label)
: prettyPropertyName(node.label)
: node instanceof QueryBuilderExplorerTreeSubTypeNodeData
? TYPE_CAST_TOKEN + node.label
: node.label}
{isDerivedProperty && (
<div
className="query-builder-explorer-tree__node__label__derived-property"
title="Property is derived and may require user to specify parameter values"
>
(...)
</div>
)}
{isMultiple && (
<div
className="query-builder-explorer-tree__node__label__multiple"
title="Multiple values of this property can cause row explosion"
>
*
</div>
)}
</div>
<div className="query-builder-explorer-tree__node__actions">
{allowPreview && (
<button
className="query-builder-explorer-tree__node__action"
disabled={
explorerState.previewDataState.isGeneratingPreviewData
}
tabIndex={-1}
title="Preview Data"
onClick={previewData}
>
<EyeIcon />
</button>
)}
{node instanceof QueryBuilderExplorerTreePropertyNodeData && (
<QueryBuilderPropertyInfoTooltip
property={node.property}
path={node.id}
isMapped={node.mappingData.mapped}
>
<div className="query-builder-explorer-tree__node__action query-builder-explorer-tree__node__info">
<InfoCircleIcon />
</div>
</QueryBuilderPropertyInfoTooltip>
)}
{node instanceof QueryBuilderExplorerTreeSubTypeNodeData && (
<QueryBuilderSubclassInfoTooltip
subclass={node.subclass}
path={node.id}
isMapped={node.mappingData.mapped}
multiplicity={node.multiplicity}
>
<div className="query-builder-explorer-tree__node__action query-builder-explorer-tree__node__info">
<InfoCircleIcon />
</div>
</QueryBuilderSubclassInfoTooltip>
)}
</div>
</>
)}
</div>
</ContextMenu>
);
},
)
Example #6
Source File: QueryBuilderFilterPanel.tsx From legend-studio with Apache License 2.0 | 4 votes |
QueryBuilderFilterTreeNodeContainer = observer(
(
props: TreeNodeContainerProps<
QueryBuilderFilterTreeNodeData,
{
queryBuilderState: QueryBuilderState;
}
>,
) => {
const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
const { queryBuilderState } = innerProps;
const ref = useRef<HTMLDivElement>(null);
const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] =
useState(false);
const applicationStore = useApplicationStore();
const filterState = queryBuilderState.filterState;
const isExpandable = node instanceof QueryBuilderFilterTreeGroupNodeData;
const selectNode = (): void => onNodeSelect?.(node);
const toggleExpandNode = (): void => node.setIsOpen(!node.isOpen);
const removeNode = (): void => filterState.removeNodeAndPruneBranch(node);
// Drag and Drop
const handleDrop = useCallback(
(item: QueryBuilderFilterDropTarget, type: string): void => {
if (
Object.values<string>(QUERY_BUILDER_FILTER_DND_TYPE).includes(type)
) {
// const dropNode = (item as QueryBuilderFilterConditionDragSource).node;
// TODO: re-arrange
} else {
const dropNode = (item as QueryBuilderExplorerTreeDragSource).node;
let filterConditionState: FilterConditionState;
try {
filterConditionState = new FilterConditionState(
filterState,
buildPropertyExpressionFromExplorerTreeNodeData(
filterState.queryBuilderState.explorerState.nonNullableTreeData,
dropNode,
filterState.queryBuilderState.graphManagerState.graph,
),
);
} catch (error) {
assertErrorThrown(error);
applicationStore.notifyWarning(error.message);
return;
}
if (node instanceof QueryBuilderFilterTreeGroupNodeData) {
filterState.addNodeFromNode(
new QueryBuilderFilterTreeConditionNodeData(
undefined,
filterConditionState,
),
node,
);
} else if (node instanceof QueryBuilderFilterTreeConditionNodeData) {
filterState.newGroupWithConditionFromNode(
new QueryBuilderFilterTreeConditionNodeData(
undefined,
filterConditionState,
),
node,
);
} else if (
node instanceof QueryBuilderFilterTreeBlankConditionNodeData
) {
filterState.replaceBlankNodeWithNode(
new QueryBuilderFilterTreeConditionNodeData(
undefined,
filterConditionState,
),
node,
);
}
}
},
[applicationStore, filterState, node],
);
const [{ isPropertyDragOver }, dropConnector] = useDrop(
() => ({
accept: [
...Object.values(QUERY_BUILDER_FILTER_DND_TYPE),
QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
],
drop: (
item: QueryBuilderFilterConditionDragSource,
monitor: DropTargetMonitor,
): void => {
if (!monitor.didDrop()) {
handleDrop(item, monitor.getItemType() as string);
} // prevent drop event propagation to accomondate for nested DnD
},
// canDrop: (item: QueryBuilderFilterConditionDragSource, monitor: DropTargetMonitor): boolean => {
// // prevent drop inside of children
// // prevent dropping inside my direct ancestor
// return true;
// },
collect: (monitor): { isPropertyDragOver: boolean } => ({
isPropertyDragOver: monitor.isOver({ shallow: true }),
}),
}),
[handleDrop],
);
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type:
node instanceof QueryBuilderFilterTreeGroupNodeData
? QUERY_BUILDER_FILTER_DND_TYPE.GROUP_CONDITION
: node instanceof QueryBuilderFilterTreeConditionNodeData
? QUERY_BUILDER_FILTER_DND_TYPE.CONDITION
: QUERY_BUILDER_FILTER_DND_TYPE.BLANK_CONDITION,
item: (): QueryBuilderFilterConditionDragSource => ({ node }),
end: (): void => filterState.setRearrangingConditions(false),
}),
[node, filterState],
);
dragConnector(dropConnector(ref));
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
// context menu
const onContextMenuOpen = (): void => setIsSelectedFromContextMenu(true);
const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
return (
<ContextMenu
content={
<QueryBuilderFilterConditionContextMenu
queryBuilderState={queryBuilderState}
node={node}
/>
}
menuProps={{ elevation: 7 }}
onOpen={onContextMenuOpen}
onClose={onContextMenuClose}
>
<div
ref={ref}
className={clsx(
'tree-view__node__container query-builder-filter-tree__node__container',
{
'query-builder-filter-tree__node__container--no-hover':
filterState.isRearrangingConditions,
'query-builder-filter-tree__node__container--selected':
node === filterState.selectedNode,
'query-builder-filter-tree__node__container--selected-from-context-menu':
isSelectedFromContextMenu,
},
)}
>
<div
className="query-builder-filter-tree__node__content"
style={{
paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 2) + 1.5}rem`,
display: 'flex',
}}
onClick={selectNode}
>
{isExpandable && (
<div
className="query-builder-filter-tree__expand-icon"
onClick={toggleExpandNode}
>
{node.isOpen ? <ChevronDownIcon /> : <ChevronRightIcon />}
</div>
)}
<div
className={clsx(
'tree-view__node__label query-builder-filter-tree__node__label',
{
'query-builder-filter-tree__node__label--expandable':
isExpandable,
},
)}
>
{node instanceof QueryBuilderFilterTreeGroupNodeData && (
<QueryBuilderFilterGroupConditionEditor
node={node}
isPropertyDragOver={isPropertyDragOver}
/>
)}
{node instanceof QueryBuilderFilterTreeConditionNodeData && (
<QueryBuilderFilterConditionEditor
node={node}
isPropertyDragOver={isPropertyDragOver}
/>
)}
{node instanceof QueryBuilderFilterTreeBlankConditionNodeData && (
<QueryBuilderFilterBlankConditionEditor
node={node}
isPropertyDragOver={isPropertyDragOver}
/>
)}
</div>
</div>
<div className="query-builder-filter-tree__node__actions">
<button
className="query-builder-filter-tree__node__action"
tabIndex={-1}
title="Remove"
onClick={removeNode}
>
<TimesIcon />
</button>
</div>
</div>
</ContextMenu>
);
},
)
Example #7
Source File: QueryBuilderFunctionsExplorerPanel.tsx From legend-studio with Apache License 2.0 | 4 votes |
QueryBuilderFunctionsExplorerTreeNodeContainer = observer(
(
props: TreeNodeContainerProps<
QueryBuilderFunctionsExplorerTreeNodeData,
{
queryBuilderState: QueryBuilderState;
}
>,
) => {
const { node, level, stepPaddingInRem, onNodeSelect } = props;
const isPackage = node.packageableElement instanceof Package;
const name =
node.packageableElement instanceof ConcreteFunctionDefinition
? generateFunctionSignature(node.packageableElement, false)
: node.packageableElement.name;
const isExpandable = Boolean(node.childrenIds.length);
const nodeExpandIcon = isExpandable ? (
node.isOpen ? (
<ChevronDownIcon />
) : (
<ChevronRightIcon />
)
) : (
<div />
);
const iconPackageColor = isDependencyTreeNode(node)
? 'color--dependency'
: '';
const nodeTypeIcon = isPackage ? (
node.isOpen ? (
<FolderOpenIcon className={iconPackageColor} />
) : (
<FolderIcon className={iconPackageColor} />
)
) : (
<PURE_FunctionIcon />
);
const selectNode = (): void => {
onNodeSelect?.(node);
};
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type:
node.packageableElement instanceof ConcreteFunctionDefinition
? QUERY_BUILDER_FUNCTIONS_EXPLORER_TREE_DND_TYPE.FUNCTION
: QUERY_BUILDER_FUNCTIONS_EXPLORER_TREE_DND_TYPE.PACKAGE,
item: (): { node?: QueryBuilderFunctionsExplorerTreeNodeData } =>
node.packageableElement instanceof ConcreteFunctionDefinition
? { node }
: {},
}),
[node],
);
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
return (
<div>
<div
className="tree-view__node__container query-builder__functions-explorer__tree__node__container"
onClick={selectNode}
ref={!isExpandable ? dragConnector : undefined}
style={{
paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 1) + 0.5}rem`,
display: 'flex',
}}
>
{
<>
<div className="tree-view__node__icon query-builder__functions-explorer__tree__node__icon">
<div className="query-builder__functions-explorer__tree__expand-icon">
{nodeExpandIcon}
</div>
<div
className={
'query-builder__functions-explorer__tree__type-icon'
}
>
{nodeTypeIcon}
</div>
</div>
<div
className="tree-view__node__label query-builder__functions-explorer__tree__node__label--with-action"
title={name}
>
{name}
</div>
<div className="query-builder__functions-explorer__tree__node__actions">
{node.packageableElement instanceof
ConcreteFunctionDefinition && (
<QueryBuilderFunctionInfoTooltip
element={node.packageableElement}
>
<div className="query-builder__functions-explorer__tree__node__action query-builder__functions-explorer__tree__node__info">
<InfoCircleIcon />
</div>
</QueryBuilderFunctionInfoTooltip>
)}
</div>
</>
}
</div>
</div>
);
},
)
Example #8
Source File: QueryBuilderPostFilterPanel.tsx From legend-studio with Apache License 2.0 | 4 votes |
QueryBuilderPostFilterTreeNodeContainer = observer(
(
props: TreeNodeContainerProps<
QueryBuilderPostFilterTreeNodeData,
{
queryBuilderState: QueryBuilderState;
}
>,
) => {
const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
const { queryBuilderState } = innerProps;
const ref = useRef<HTMLDivElement>(null);
const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] =
useState(false);
const applicationStore = useApplicationStore();
const postFilterState = queryBuilderState.postFilterState;
const isExpandable =
node instanceof QueryBuilderPostFilterTreeGroupNodeData;
const selectNode = (): void => onNodeSelect?.(node);
const toggleExpandNode = (): void => node.setIsOpen(!node.isOpen);
const removeNode = (): void =>
postFilterState.removeNodeAndPruneBranch(node);
const handleDrop = useCallback(
(item: QueryBuilderPostFilterDropTarget, type: string): void => {
if (type === QUERY_BUILDER_PROJECTION_DND_TYPE.PROJECTION_COLUMN) {
const columnState = (item as QueryBuilderProjectionColumnDragSource)
.columnState;
let conditionState: PostFilterConditionState;
try {
conditionState = new PostFilterConditionState(
postFilterState,
columnState,
undefined,
undefined,
);
conditionState.setValue(
conditionState.operator.getDefaultFilterConditionValue(
conditionState,
),
);
} catch (error) {
assertErrorThrown(error);
applicationStore.notifyWarning(error.message);
return;
}
if (node instanceof QueryBuilderPostFilterTreeGroupNodeData) {
postFilterState.addNodeFromNode(
new QueryBuilderPostFilterTreeConditionNodeData(
undefined,
conditionState,
),
node,
);
} else if (
node instanceof QueryBuilderPostFilterTreeConditionNodeData
) {
postFilterState.newGroupWithConditionFromNode(
new QueryBuilderPostFilterTreeConditionNodeData(
undefined,
conditionState,
),
node,
);
} else if (
node instanceof QueryBuilderPostFilterTreeBlankConditionNodeData
) {
postFilterState.replaceBlankNodeWithNode(
new QueryBuilderPostFilterTreeConditionNodeData(
undefined,
conditionState,
),
node,
);
}
}
},
[applicationStore, postFilterState, node],
);
const [{ isPropertyDragOver }, dropConnector] = useDrop(
() => ({
accept: [
...Object.values(QUERY_BUILDER_POST_FILTER_DND_TYPE),
QUERY_BUILDER_PROJECTION_DND_TYPE.PROJECTION_COLUMN,
],
drop: (
item: QueryBuilderPostFilterConditionDragSource,
monitor: DropTargetMonitor,
): void => {
if (!monitor.didDrop()) {
handleDrop(item, monitor.getItemType() as string);
} // prevent drop event propagation to accomondate for nested DnD
},
collect: (monitor): { isPropertyDragOver: boolean } => ({
isPropertyDragOver: monitor.isOver({ shallow: true }),
}),
}),
[handleDrop],
);
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type:
node instanceof QueryBuilderPostFilterTreeGroupNodeData
? QUERY_BUILDER_POST_FILTER_DND_TYPE.GROUP_CONDITION
: node instanceof QueryBuilderPostFilterTreeConditionNodeData
? QUERY_BUILDER_POST_FILTER_DND_TYPE.CONDITION
: QUERY_BUILDER_POST_FILTER_DND_TYPE.BLANK_CONDITION,
item: (): QueryBuilderPostFilterConditionDragSource => ({ node }),
end: (): void => postFilterState.setRearrangingConditions(false),
}),
[node, postFilterState],
);
dragConnector(dropConnector(ref));
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
// context menu
const onContextMenuOpen = (): void => setIsSelectedFromContextMenu(true);
const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
return (
<ContextMenu
content={
<QueryBuilderPostFilterConditionContextMenu
queryBuilderState={queryBuilderState}
node={node}
/>
}
menuProps={{ elevation: 7 }}
onOpen={onContextMenuOpen}
onClose={onContextMenuClose}
>
<div
ref={ref}
className={clsx(
'tree-view__node__container query-builder-post-filter-tree__node__container',
{
'query-builder-post-filter-tree__node__container--no-hover':
postFilterState.isRearrangingConditions,
'query-builder-post-filter-tree__node__container--selected':
node === postFilterState.selectedNode,
'query-builder-post-filter-tree__node__container--selected-from-context-menu':
isSelectedFromContextMenu,
},
)}
>
<div
className="query-builder-post-filter-tree__node__content"
style={{
paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 2) + 1.5}rem`,
display: 'flex',
}}
onClick={selectNode}
>
{isExpandable && (
<div
className="query-builder-post-filter-tree__expand-icon"
onClick={toggleExpandNode}
>
{node.isOpen ? <ChevronDownIcon /> : <ChevronRightIcon />}
</div>
)}
<div
className={clsx(
'tree-view__node__label query-builder-post-filter-tree__node__label',
{
'query-builder-post-filter-tree__node__label--expandable':
isExpandable,
},
)}
>
{node instanceof QueryBuilderPostFilterTreeGroupNodeData && (
<QueryBuilderPostFilterGroupConditionEditor
node={node}
isPropertyDragOver={isPropertyDragOver}
/>
)}
{node instanceof QueryBuilderPostFilterTreeConditionNodeData && (
<QueryBuilderPostFilterConditionEditor
node={node}
isPropertyDragOver={isPropertyDragOver}
/>
)}
{node instanceof
QueryBuilderPostFilterTreeBlankConditionNodeData && (
<QueryBuilderPostFilterBlankConditionEditor
node={node}
isPropertyDragOver={isPropertyDragOver}
/>
)}
</div>
</div>
<div className="query-builder-post-filter-tree__node__actions">
<button
className="query-builder-post-filter-tree__node__action"
tabIndex={-1}
title="Remove"
onClick={removeNode}
>
<TimesIcon />
</button>
</div>
</div>
</ContextMenu>
);
},
)
Example #9
Source File: QueryBuilderProjectionPanel.tsx From legend-studio with Apache License 2.0 | 4 votes |
QueryBuilderProjectionColumnEditor = observer(
(props: {
projectionColumnState: QueryBuilderProjectionColumnState;
isRearrangingColumns: boolean;
}) => {
const ref = useRef<HTMLDivElement>(null);
const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] =
useState(false);
const onContextMenuOpen = (): void => setIsSelectedFromContextMenu(true);
const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
const { projectionColumnState, isRearrangingColumns } = props;
const queryBuilderState =
projectionColumnState.projectionState.queryBuilderState;
const projectionState =
queryBuilderState.fetchStructureState.projectionState;
const removeColumn = (): void =>
projectionState.removeColumn(projectionColumnState);
// name
const changeColumnName: React.ChangeEventHandler<HTMLInputElement> = (
event,
) => projectionColumnState.setColumnName(event.target.value);
const isDuplicatedColumnName =
projectionColumnState.projectionState.columns.filter(
(column) => column.columnName === projectionColumnState.columnName,
).length > 1;
// aggregation
const aggregateColumnState = projectionState.aggregationState.columns.find(
(column) => column.projectionColumnState === projectionColumnState,
);
const aggreateOperators = projectionState.aggregationState.operators.filter(
(op) => op.isCompatibleWithColumn(projectionColumnState),
);
const changeOperator =
(val: QueryBuilderAggregateOperator | undefined) => (): void =>
projectionState.aggregationState.changeColumnAggregateOperator(
val,
projectionColumnState,
);
// Drag and Drop
const handleHover = useCallback(
(
item: QueryBuilderProjectionColumnDragSource,
monitor: DropTargetMonitor,
): void => {
const dragIndex = projectionState.columns.findIndex(
(e) => e === item.columnState,
);
const hoverIndex = projectionState.columns.findIndex(
(e) => e === projectionColumnState,
);
if (dragIndex === -1 || hoverIndex === -1 || dragIndex === hoverIndex) {
return;
}
// move the item being hovered on when the dragged item position is beyond the its middle point
const hoverBoundingReact = ref.current?.getBoundingClientRect();
const distanceThreshold =
((hoverBoundingReact?.bottom ?? 0) - (hoverBoundingReact?.top ?? 0)) /
2;
const dragDistance =
(monitor.getClientOffset() as XYCoord).y -
(hoverBoundingReact?.top ?? 0);
if (dragIndex < hoverIndex && dragDistance < distanceThreshold) {
return;
}
if (dragIndex > hoverIndex && dragDistance > distanceThreshold) {
return;
}
projectionState.moveColumn(dragIndex, hoverIndex);
},
[projectionColumnState, projectionState],
);
const [, dropConnector] = useDrop(
() => ({
accept: [QUERY_BUILDER_PROJECTION_DND_TYPE.PROJECTION_COLUMN],
hover: (
item: QueryBuilderProjectionColumnDragSource,
monitor: DropTargetMonitor,
): void => handleHover(item, monitor),
}),
[handleHover],
);
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type: QUERY_BUILDER_PROJECTION_DND_TYPE.PROJECTION_COLUMN,
item: (): QueryBuilderProjectionColumnDragSource => {
projectionColumnState.setIsBeingDragged(true);
return { columnState: projectionColumnState };
},
end: (item: QueryBuilderProjectionColumnDragSource | undefined): void =>
item?.columnState.setIsBeingDragged(false),
}),
[projectionColumnState],
);
dragConnector(dropConnector(ref));
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
return (
<div
ref={ref}
className={clsx('query-builder__projection__column', {
'query-builder__projection__column--dragged':
projectionColumnState.isBeingDragged,
'query-builder__projection__column--no-hover': isRearrangingColumns,
})}
>
{projectionColumnState.isBeingDragged && (
<div className="query-builder__projection__column__dnd__placeholder__container">
<div className="query-builder__dnd__placeholder query-builder__projection__column__dnd__placeholder" />
</div>
)}
{!projectionColumnState.isBeingDragged && (
<ContextMenu
content={
<QueryBuilderProjectionColumnContextMenu
projectionColumnState={projectionColumnState}
/>
}
disabled={
!(
projectionColumnState instanceof
QueryBuilderSimpleProjectionColumnState
)
}
className={clsx('query-builder__projection__column__context-menu', {
'query-builder__projection__column--selected-from-context-menu':
isSelectedFromContextMenu,
})}
menuProps={{ elevation: 7 }}
onOpen={onContextMenuOpen}
onClose={onContextMenuClose}
>
<div className="query-builder__projection__column__dnd__indicator">
<div className="query-builder__projection__column__dnd__indicator__handler">
<VerticalDragHandleIcon />
</div>
</div>
<div className="query-builder__projection__column__name">
<InputWithInlineValidation
className="query-builder__projection__column__name__input input-group__input"
spellCheck={false}
value={projectionColumnState.columnName}
onChange={changeColumnName}
validationErrorMessage={
isDuplicatedColumnName ? 'Duplicated column' : undefined
}
/>
</div>
<div className="query-builder__projection__column__value">
{projectionColumnState instanceof
QueryBuilderSimpleProjectionColumnState && (
<QueryBuilderSimpleProjectionColumnEditor
projectionColumnState={projectionColumnState}
/>
)}
{projectionColumnState instanceof
QueryBuilderDerivationProjectionColumnState && (
<QueryBuilderDerivationProjectionColumnEditor
projectionColumnState={projectionColumnState}
/>
)}
</div>
<div className="query-builder__projection__column__aggregate">
<div className="query-builder__projection__column__aggregate__operator">
{aggregateColumnState && (
<div className="query-builder__projection__column__aggregate__operator__label">
{aggregateColumnState.operator.getLabel(
projectionColumnState,
)}
</div>
)}
<DropdownMenu
className="query-builder__projection__column__aggregate__operator__dropdown"
disabled={!aggreateOperators.length}
content={
<MenuContent>
{aggregateColumnState && (
<MenuContentItem
className="query-builder__projection__column__aggregate__operator__dropdown__option"
onClick={changeOperator(undefined)}
>
(none)
</MenuContentItem>
)}
{aggreateOperators.map((op) => (
<MenuContentItem
key={op.uuid}
className="query-builder__projection__column__aggregate__operator__dropdown__option"
onClick={changeOperator(op)}
>
{op.getLabel(projectionColumnState)}
</MenuContentItem>
))}
</MenuContent>
}
menuProps={{
anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
transformOrigin: { vertical: 'top', horizontal: 'left' },
elevation: 7,
}}
>
<button
className={clsx(
'query-builder__projection__column__aggregate__operator__badge',
{
'query-builder__projection__column__aggregate__operator__badge--activated':
Boolean(aggregateColumnState),
},
)}
tabIndex={-1}
title="Choose Aggregate Operator..."
>
<SigmaIcon />
</button>
<button
className="query-builder__projection__column__aggregate__operator__dropdown__trigger"
tabIndex={-1}
title="Choose Aggregate Operator..."
>
<CaretDownIcon />
</button>
</DropdownMenu>
</div>
</div>
<div className="query-builder__projection__column__actions">
<button
className="query-builder__projection__column__action"
tabIndex={-1}
onClick={removeColumn}
title="Remove"
>
<TimesIcon />
</button>
</div>
</ContextMenu>
)}
</div>
);
},
)
Example #10
Source File: GenerationSpecificationEditor.tsx From legend-studio with Apache License 2.0 | 4 votes |
ModelGenerationItem = observer(
(props: {
specState: GenerationSpecificationEditorState;
nodeState: GenerationTreeNodeState;
options: PackageableElementOption<PackageableElement>[];
isRearrangingNodes: boolean;
}) => {
const ref = useRef<HTMLDivElement>(null);
const { nodeState, specState, options, isRearrangingNodes } = props;
const generationTreeNode = nodeState.node;
const editorStore = useEditorStore();
const modelGenerationRef = generationTreeNode.generationElement;
const modelGeneration = modelGenerationRef.value;
const value = { label: modelGeneration.name, value: modelGeneration };
const onChange = (
val: PackageableElementOption<FileGenerationSpecification> | null,
): void => {
if (val !== null) {
packageableElementReference_setValue(modelGenerationRef, val.value);
}
};
const deleteNode = (): void =>
specState.deleteGenerationTreeNode(generationTreeNode);
const visitModelGeneration = (): void =>
editorStore.openElement(modelGeneration);
// generation id
const isUnique =
specState.spec.generationNodes.filter(
(n) => n.id === generationTreeNode.id,
).length < 2;
const isDefault =
generationTreeNode.id ===
generationTreeNode.generationElement.value.path && isUnique;
const changeNodeId: React.ChangeEventHandler<HTMLInputElement> = (event) =>
generationSpecification_setId(generationTreeNode, event.target.value);
// Drag and Drop
const handleHover = useCallback(
(
item: GenerationSpecNodeDropTarget,
monitor: DropTargetMonitor,
): void => {
const dragIndex = specState.generationTreeNodeStates.findIndex(
(e) => e === item.nodeState,
);
const hoverIndex = specState.generationTreeNodeStates.findIndex(
(e) => e === nodeState,
);
if (dragIndex === -1 || hoverIndex === -1 || dragIndex === hoverIndex) {
return;
}
// move the item being hovered on when the dragged item position is beyond the its middle point
const hoverBoundingReact = ref.current?.getBoundingClientRect();
const distanceThreshold =
((hoverBoundingReact?.bottom ?? 0) - (hoverBoundingReact?.top ?? 0)) /
2;
const dragDistance =
(monitor.getClientOffset() as XYCoord).y -
(hoverBoundingReact?.top ?? 0);
if (dragIndex < hoverIndex && dragDistance < distanceThreshold) {
return;
}
if (dragIndex > hoverIndex && dragDistance > distanceThreshold) {
return;
}
specState.moveGenerationNode(dragIndex, hoverIndex);
},
[nodeState, specState],
);
const [, dropConnector] = useDrop(
() => ({
accept: [CORE_DND_TYPE.GENERATION_SPEC_NODE],
hover: (
item: GenerationSpecNodeDragSource,
monitor: DropTargetMonitor,
): void => handleHover(item, monitor),
}),
[handleHover],
);
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type: CORE_DND_TYPE.GENERATION_SPEC_NODE,
item: (): GenerationSpecNodeDragSource => {
nodeState.setIsBeingDragged(true);
return { nodeState };
},
end: (item: GenerationSpecNodeDragSource | undefined): void =>
item?.nodeState.setIsBeingDragged(false),
}),
[nodeState],
);
dragConnector(dropConnector(ref));
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
return (
<div
ref={ref}
className={clsx('generation-spec-model-generation-editor__item', {
'generation-spec-model-generation-editor__item--dragged':
nodeState.isBeingDragged,
'generation-spec-model-generation-editor__item---no-hover':
isRearrangingNodes,
})}
>
{nodeState.isBeingDragged && (
<div className="generation-spec-editor__dnd__placeholder" />
)}
{!nodeState.isBeingDragged && (
<>
<div className="btn--sm generation-spec-model-generation-editor__item__label">
{getElementIcon(editorStore, modelGeneration)}
</div>
<input
className={clsx(
'generation-spec-model-generation-editor__item__id',
{
'generation-spec-model-generation-editor__item__id--has-error':
!isUnique,
},
)}
spellCheck={false}
value={isDefault ? 'DEFAULT' : generationTreeNode.id}
onChange={changeNodeId}
disabled={isDefault}
/>
<CustomSelectorInput
className="generation-spec-model-generation-editor__item__dropdown"
options={options}
onChange={onChange}
value={value}
darkMode={true}
/>
<button
className="btn--dark btn--sm"
onClick={visitModelGeneration}
tabIndex={-1}
title={'See mapping'}
>
<LongArrowRightIcon />
</button>
<button
className="generation-spec-model-generation-editor__item__remove-btn"
onClick={deleteNode}
tabIndex={-1}
title={'Remove'}
>
<TimesIcon />
</button>
</>
)}
</div>
);
},
)