123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- import {ComponentProps, useEffect} from 'react';
- import {useSortable} from '@dnd-kit/sortable';
- import styled from '@emotion/styled';
- import PanelAlert from 'sentry/components/panels/panelAlert';
- import {Organization} from 'sentry/types';
- import theme from 'sentry/utils/theme';
- import withOrganization from 'sentry/utils/withOrganization';
- import WidgetCard from 'sentry/views/dashboardsV2/widgetCard';
- import {DashboardFilters, Widget} from './types';
- import DnDKitWidgetWrapper from './widgetWrapper';
- const TABLE_ITEM_LIMIT = 20;
- type Props = {
- dragId: string;
- index: string;
- isEditing: boolean;
- onDelete: () => void;
- onDuplicate: () => void;
- onEdit: () => void;
- organization: Organization;
- widget: Widget;
- widgetLimitReached: boolean;
- dashboardFilters?: DashboardFilters;
- isMobile?: boolean;
- isPreview?: boolean;
- windowWidth?: number;
- };
- function SortableWidget(props: Props) {
- const {
- organization,
- widget,
- dragId,
- isEditing,
- widgetLimitReached,
- onDelete,
- onEdit,
- onDuplicate,
- isPreview,
- isMobile,
- windowWidth,
- index,
- dashboardFilters,
- } = props;
- const {
- attributes,
- listeners,
- setNodeRef,
- transform,
- isDragging: currentWidgetDragging,
- isSorting,
- } = useSortable({
- id: dragId,
- transition: null,
- });
- useEffect(() => {
- if (!currentWidgetDragging) {
- return undefined;
- }
- document.body.style.cursor = 'grabbing';
- return function cleanup() {
- document.body.style.cursor = '';
- };
- }, [currentWidgetDragging]);
- let widgetProps: ComponentProps<typeof WidgetCard> = {
- widget,
- isEditing,
- widgetLimitReached,
- onDelete,
- onEdit,
- onDuplicate,
- isSorting,
- hideToolbar: isSorting,
- currentWidgetDragging,
- showContextMenu: true,
- isPreview,
- showWidgetViewerButton: organization.features.includes('widget-viewer-modal'),
- index,
- dashboardFilters,
- renderErrorMessage: errorMessage => {
- return (
- typeof errorMessage === 'string' && (
- <PanelAlert type="error">{errorMessage}</PanelAlert>
- )
- );
- },
- };
- if (organization.features.includes('dashboard-grid-layout')) {
- widgetProps = {
- ...widgetProps,
- isMobile,
- windowWidth,
- // TODO(nar): These aren't necessary for supporting RGL
- isSorting: false,
- currentWidgetDragging: false,
- tableItemLimit: TABLE_ITEM_LIMIT,
- };
- return (
- <GridWidgetWrapper>
- <WidgetCard {...widgetProps} />
- </GridWidgetWrapper>
- );
- }
- const initialStyles: ComponentProps<typeof DnDKitWidgetWrapper>['animate'] = {
- zIndex: 'auto',
- };
- widgetProps = {...widgetProps, draggableProps: {attributes, listeners}};
- return (
- <DnDKitWidgetWrapper
- ref={setNodeRef}
- displayType={widget.displayType}
- layoutId={dragId}
- style={{
- // Origin is set to top right-hand corner where the drag handle is placed.
- // Otherwise, set the origin to be the top left-hand corner when swapping widgets.
- originX: currentWidgetDragging ? 1 : 0,
- originY: 0,
- boxShadow: currentWidgetDragging ? theme.dropShadowHeavy : 'none',
- borderRadius: currentWidgetDragging ? theme.borderRadius : undefined,
- }}
- animate={
- transform
- ? {
- x: transform.x,
- y: transform.y,
- scaleX: transform?.scaleX && transform.scaleX <= 1 ? transform.scaleX : 1,
- scaleY: transform?.scaleY && transform.scaleY <= 1 ? transform.scaleY : 1,
- zIndex: currentWidgetDragging ? theme.zIndex.modal : 'auto',
- }
- : initialStyles
- }
- transformTemplate={(___transform, generatedTransform) => {
- if (isEditing && !!transform) {
- return generatedTransform;
- }
- return 'none';
- }}
- transition={{
- duration: !currentWidgetDragging ? 0.25 : 0,
- easings: {
- type: 'spring',
- },
- }}
- >
- <WidgetCard {...widgetProps} />
- </DnDKitWidgetWrapper>
- );
- }
- export default withOrganization(SortableWidget);
- const GridWidgetWrapper = styled('div')`
- height: 100%;
- `;
|