Skip to content

Commit

Permalink
Bug 1807204: Update cursor to show drop status over targets
Browse files Browse the repository at this point in the history
  • Loading branch information
jeff-phillips-18 committed Feb 25, 2020
1 parent ba3408b commit 41c16e9
Show file tree
Hide file tree
Showing 13 changed files with 188 additions and 117 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ComponentType } from 'react';
import * as React from 'react';
import {
GraphElement,
ModelKind,
Expand All @@ -11,7 +11,7 @@ import {
withDndDrop,
withCreateConnector,
withRemoveConnector,
withContextMenu,
withContextMenu as withTopologyContextMenu,
} from '@console/topology';
import Application from './components/nodes/Application';
import ConnectsTo from './components/edges/ConnectsTo';
Expand Down Expand Up @@ -75,6 +75,14 @@ const withNoDrop = () => {
return withDndDrop<any, any, {}, NodeProps>(noDropTargetSpec);
};

const withContextMenu = <E extends GraphElement>(actions: (element: E) => React.ReactElement[]) => {
return withTopologyContextMenu(
actions,
document.getElementById('modal-container'),
'odc-topology-context-menu',
);
};

class ComponentFactory {
private hasServiceBinding: boolean;

Expand All @@ -86,13 +94,17 @@ class ComponentFactory {
this.hasServiceBinding = value;
}

withAddResourceConnector = () => {
return withCreateConnector(createConnectorCallback(this.hasServiceBinding), 'Add Resource');
};

getFactory = (): TopologyComponentFactory => {
return (kind, type): ComponentType<{ element: GraphElement }> | undefined => {
return (kind, type): React.ComponentType<{ element: GraphElement }> | undefined => {
switch (type) {
case TYPE_HELM_RELEASE:
return withSelection(false, true)(withNoDrop()(HelmRelease));
case TYPE_HELM_WORKLOAD:
return withCreateConnector(createConnectorCallback(this.hasServiceBinding))(
return this.withAddResourceConnector()(
withDndDrop<
any,
any,
Expand All @@ -101,37 +113,19 @@ class ComponentFactory {
>(nodeDropTargetSpec)(
withEditReviewAccess('patch')(
withDragNode(nodeDragSourceSpec(type, false))(
withSelection(
false,
true,
)(
withContextMenu(
workloadContextMenu,
document.getElementById('modal-container'),
'odc-topology-context-menu',
)(WorkloadNode),
),
withSelection(false, true)(withContextMenu(workloadContextMenu)(WorkloadNode)),
),
),
),
);
case TYPE_APPLICATION_GROUP:
return withDndDrop(groupWorkloadDropTargetSpec)(
withSelection(
false,
true,
)(
withContextMenu(
groupContextMenu,
document.getElementById('modal-container'),
'odc-topology-context-menu',
)(Application),
),
withSelection(false, true)(withContextMenu(groupContextMenu)(Application)),
);
case TYPE_OPERATOR_BACKED_SERVICE:
return withSelection(false, true)(withNoDrop()(OperatorBackedService));
case TYPE_OPERATOR_WORKLOAD:
return withCreateConnector(createConnectorCallback(this.hasServiceBinding))(
return this.withAddResourceConnector()(
withEditReviewAccess('patch')(
withDndDrop<
any,
Expand All @@ -140,39 +134,21 @@ class ComponentFactory {
NodeProps
>(nodeDropTargetSpec)(
withDragNode(nodeDragSourceSpec(type, false))(
withSelection(
false,
true,
)(
withContextMenu(
workloadContextMenu,
document.getElementById('modal-container'),
'odc-topology-context-menu',
)(WorkloadNode),
),
withSelection(false, true)(withContextMenu(workloadContextMenu)(WorkloadNode)),
),
),
),
);
case TYPE_KNATIVE_SERVICE:
return withCreateConnector(createConnectorCallback(this.hasServiceBinding))(
return this.withAddResourceConnector()(
withDndDrop<
any,
any,
{ droppable?: boolean; hover?: boolean; canDrop?: boolean; dropTarget?: boolean },
NodeProps
>(graphEventSourceDropTargetSpec)(
withEditReviewAccess('update')(
withSelection(
false,
true,
)(
withContextMenu(
nodeContextMenu,
document.getElementById('modal-container'),
'odc-topology-context-menu',
)(KnativeService),
),
withSelection(false, true)(withContextMenu(nodeContextMenu)(KnativeService)),
),
),
);
Expand All @@ -182,35 +158,20 @@ class ComponentFactory {
withSelection(
false,
true,
)(
withContextMenu(
nodeContextMenu,
document.getElementById('modal-container'),
'odc-topology-context-menu',
)(withNoDrop()(EventSource)),
),
)(withContextMenu(nodeContextMenu)(withNoDrop()(EventSource))),
),
);
case TYPE_KNATIVE_REVISION:
return withDragNode(nodeDragSourceSpec(type, false))(
withSelection(
false,
true,
)(
withContextMenu(
nodeContextMenu,
document.getElementById('modal-container'),
'odc-topology-context-menu',
)(withNoDrop()(RevisionNode)),
),
)(withContextMenu(nodeContextMenu)(withNoDrop()(RevisionNode))),
);
case TYPE_REVISION_TRAFFIC:
return TrafficLink;
case TYPE_WORKLOAD:
return withCreateConnector(
createConnectorCallback(this.hasServiceBinding),
'odc-topology-context-menu',
)(
return this.withAddResourceConnector()(
withDndDrop<
any,
any,
Expand All @@ -219,16 +180,7 @@ class ComponentFactory {
>(nodeDropTargetSpec)(
withEditReviewAccess('patch')(
withDragNode(nodeDragSourceSpec(type))(
withSelection(
false,
true,
)(
withContextMenu(
workloadContextMenu,
document.getElementById('modal-container'),
'odc-topology-context-menu',
)(WorkloadNode),
),
withSelection(false, true)(withContextMenu(workloadContextMenu)(WorkloadNode)),
),
),
),
Expand Down Expand Up @@ -256,16 +208,7 @@ class ComponentFactory {
case ModelKind.graph:
return withDndDrop(graphWorkloadDropTargetSpec)(
withPanZoom()(
withSelection(
false,
true,
)(
withContextMenu(
graphContextMenu,
document.getElementById('modal-container'),
'odc-topology-context-menu',
)(GraphComponent),
),
withSelection(false, true)(withContextMenu(graphContextMenu)(GraphComponent)),
),
);
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,20 @@ const graphWorkloadDropTargetSpec: DropTargetSpec<
monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE)
);
},
collect: (monitor) => ({
dragEditInProgress: monitor.isDragging() && editOperations.includes(monitor.getOperation()),
}),
collect: (monitor) => {
const dragEditInProgress =
monitor.isDragging() && editOperations.includes(monitor.getOperation());
const dropHints = monitor.getDropHints() || [];
const dragCreate =
dragEditInProgress &&
monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE &&
dropHints[dropHints.length - 1] === 'create';
return {
dragEditInProgress,
dragCreate,
hasDropTarget: dragEditInProgress && monitor.hasDropTarget(),
};
},
dropHint: 'create',
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
@import '../topology-utils';

.odc-m-drag-active {
cursor: grab !important;
.topology-create-connector {
pointer-events: none;
cursor: no-drop !important;
&.odc-m-valid-drop-target {
cursor: grab !important;
.odc-m-drag-create {
cursor: none;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import * as React from 'react';
import * as classNames from 'classnames';
import { connect } from 'react-redux';
import { RootState } from '@console/internal/redux';
import { GraphComponent as BaseGraphComponent, WithContextMenuProps } from '@console/topology';
import { TopologyFilters, getTopologyFilters } from '../filters/filter-utils';

type GraphComponentProps = React.ComponentProps<typeof BaseGraphComponent> & {
dragEditInProgress?: boolean;
hasDropTarget?: boolean;
dragCreate?: boolean;
filters: TopologyFilters;
} & WithContextMenuProps;

const DRAG_ACTIVE_CLASS = 'odc-m-drag-active';
const FILTER_ACTIVE_CLASS = 'odc-m-filter-active';
const VALID_DROP_CLASS = 'odc-m-valid-drop-target';

const GraphComponent: React.FC<GraphComponentProps> = (props) => {
const { dragEditInProgress, filters } = props;
const { dragEditInProgress, hasDropTarget, dragCreate, filters } = props;
const graphClasses = classNames('odc-graph', { 'odc-m-drag-create': dragCreate });
React.useEffect(() => {
const addClassList = [];
const removeClassList = [];
Expand All @@ -23,15 +28,20 @@ const GraphComponent: React.FC<GraphComponentProps> = (props) => {
dragEditInProgress
? addClassList.push(DRAG_ACTIVE_CLASS)
: removeClassList.push(DRAG_ACTIVE_CLASS);
hasDropTarget ? addClassList.push(VALID_DROP_CLASS) : removeClassList.push(VALID_DROP_CLASS);

if (addClassList.length) {
addClassList.forEach((className) => document.body.classList.add(className));
}
if (removeClassList.length) {
removeClassList.forEach((className) => document.body.classList.remove(className));
}
}, [dragEditInProgress, filters.searchQuery]);
return <BaseGraphComponent {...props} />;
}, [dragEditInProgress, filters.searchQuery, hasDropTarget]);
return (
<g className={graphClasses}>
<BaseGraphComponent {...props} />
</g>
);
};

const GraphComponentState = (state: RootState) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@
cursor: var(--edge__arrow--cursor);
stroke: var(--edge--stroke);
}

&.is-dragging {
cursor: var(--edge--drag-active--cursor);
.topology-connector-arrow {
cursor: var(--edge--drag-active--cursor);
}
}
}

.odc-m-drag-active {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ const KnativeServiceGroup: React.FC<KnativeServiceGroupProps> = ({
}, [editAccess, innerHover, onShowCreateConnector, onHideCreateConnector]);

return (
<Tooltip content="Move sink to service" trigger="manual" isVisible={dropTarget && canDrop}>
<Tooltip
content="Move sink to service"
trigger="manual"
isVisible={dropTarget && canDrop}
tippyProps={{ duration: 0, delay: 0 }}
>
<g
ref={hoverRef}
onClick={onSelect}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ const WorkloadNode: React.FC<WorkloadNodeProps> = ({

return (
<g>
<Tooltip content={tipContent} trigger="manual" isVisible={dropTarget && canDrop}>
<Tooltip
content={tipContent}
trigger="manual"
isVisible={dropTarget && canDrop}
tippyProps={{ duration: 0, delay: 0 }}
>
<BaseNode
outerRadius={radius}
innerRadius={donutStatus && donutStatus.isRollingOut ? radius * 0.45 : radius * 0.55}
Expand Down
3 changes: 3 additions & 0 deletions frontend/packages/topology/src/behavior/dnd-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export interface DndManager {
getDropHints(): string[] | undefined;
canDragSource(sourceId: string | undefined): boolean;
canDropOnTarget(targetId: string | undefined): boolean;
hasDropTarget(): boolean;
isDragging(): boolean;
isDraggingSource(sourceId: string | undefined): boolean;
isOverTarget(
Expand Down Expand Up @@ -172,6 +173,8 @@ export interface DropTargetMonitor extends HandlerManager {
isCancelled(): boolean;
isDragging(): boolean;
isOver(options?: { shallow?: boolean }): boolean;
hasDropTarget(): boolean;
getDropHints(): string[] | undefined;
getItemType(): Identifier | undefined;
getItem(): any;
getDropResult(): any;
Expand Down
6 changes: 6 additions & 0 deletions frontend/packages/topology/src/behavior/useDndDrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ export const useDndDrop = <
isDragging: (): boolean => {
return dndManager.isDragging();
},
hasDropTarget: (): boolean => {
return dndManager.hasDropTarget();
},
getDropHints: (): string[] | undefined => {
return dndManager.getDropHints();
},
isOver(options?: { shallow?: boolean }): boolean {
return dndManager.isOverTarget(idRef.current, options);
},
Expand Down
4 changes: 4 additions & 0 deletions frontend/packages/topology/src/behavior/useDndManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ export class DndManagerImpl implements DndManager {
return this.state.targetIds || [];
}

hasDropTarget(): boolean {
return !!this.getTargetIds().find((id) => this.canDropOnTarget(id));
}

getDropResult(): any {
return this.state.dropResult;
}
Expand Down

0 comments on commit 41c16e9

Please sign in to comment.