mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 00:45:53 +08:00
feat: add the ability to drag columns (#3100)
* feat: add the ability to drag columns * feat: add the ability to drag columns in the logs explorer * feat: update drag logic * fix: resolve comments * feat: resolve comment regarding error handling --------- Co-authored-by: Vishal Sharma <makeavish786@gmail.com> Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
parent
07833b9859
commit
8f1451e154
@ -69,6 +69,7 @@
|
||||
"papaparse": "5.4.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-drag-listview": "2.0.0",
|
||||
"react-force-graph": "^1.41.0",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-i18next": "^11.16.1",
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* eslint-disable react/jsx-props-no-spreading */
|
||||
|
||||
import { Table } from 'antd';
|
||||
import type { TableProps } from 'antd/es/table';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { dragColumnParams } from 'hooks/useDragColumns/configs';
|
||||
import {
|
||||
SyntheticEvent,
|
||||
useCallback,
|
||||
@ -8,12 +10,18 @@ import {
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import ReactDragListView from 'react-drag-listview';
|
||||
import { ResizeCallbackData } from 'react-resizable';
|
||||
|
||||
import ResizableHeader from './ResizableHeader';
|
||||
import { DragSpanStyle } from './styles';
|
||||
import { ResizeTableProps } from './types';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function ResizeTable({ columns, ...restprops }: TableProps<any>): JSX.Element {
|
||||
function ResizeTable({
|
||||
columns,
|
||||
onDragColumn,
|
||||
...restProps
|
||||
}: ResizeTableProps): JSX.Element {
|
||||
const [columnsData, setColumns] = useState<ColumnsType>([]);
|
||||
|
||||
const handleResize = useCallback(
|
||||
@ -31,16 +39,32 @@ function ResizeTable({ columns, ...restprops }: TableProps<any>): JSX.Element {
|
||||
[columnsData],
|
||||
);
|
||||
|
||||
const mergeColumns = useMemo(
|
||||
const mergedColumns = useMemo(
|
||||
() =>
|
||||
columnsData.map((col, index) => ({
|
||||
...col,
|
||||
...(onDragColumn && {
|
||||
title: (
|
||||
<DragSpanStyle className="dragHandler">
|
||||
{col?.title?.toString() || ''}
|
||||
</DragSpanStyle>
|
||||
),
|
||||
}),
|
||||
onHeaderCell: (column: ColumnsType<unknown>[number]): unknown => ({
|
||||
width: column.width,
|
||||
onResize: handleResize(index),
|
||||
}),
|
||||
})),
|
||||
[columnsData, handleResize],
|
||||
})) as ColumnsType<any>,
|
||||
[columnsData, onDragColumn, handleResize],
|
||||
);
|
||||
|
||||
const tableParams = useMemo(
|
||||
() => ({
|
||||
...restProps,
|
||||
components: { header: { cell: ResizableHeader } },
|
||||
columns: mergedColumns,
|
||||
}),
|
||||
[mergedColumns, restProps],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@ -49,15 +73,17 @@ function ResizeTable({ columns, ...restprops }: TableProps<any>): JSX.Element {
|
||||
}
|
||||
}, [columns]);
|
||||
|
||||
return (
|
||||
<Table
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...restprops}
|
||||
components={{ header: { cell: ResizableHeader } }}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
columns={mergeColumns as ColumnsType<any>}
|
||||
/>
|
||||
return onDragColumn ? (
|
||||
<ReactDragListView.DragColumn {...dragColumnParams} onDragEnd={onDragColumn}>
|
||||
<Table {...tableParams} />
|
||||
</ReactDragListView.DragColumn>
|
||||
) : (
|
||||
<Table {...tableParams} />
|
||||
);
|
||||
}
|
||||
|
||||
ResizeTable.defaultProps = {
|
||||
onDragColumn: undefined,
|
||||
};
|
||||
|
||||
export default ResizeTable;
|
||||
|
@ -2,10 +2,16 @@ import styled from 'styled-components';
|
||||
|
||||
export const SpanStyle = styled.span`
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
right: -0.313rem;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
width: 10px;
|
||||
width: 0.625rem;
|
||||
height: 100%;
|
||||
cursor: col-resize;
|
||||
`;
|
||||
|
||||
export const DragSpanStyle = styled.span`
|
||||
display: flex;
|
||||
margin: -1rem;
|
||||
padding: 1rem;
|
||||
`;
|
||||
|
6
frontend/src/components/ResizeTable/types.ts
Normal file
6
frontend/src/components/ResizeTable/types.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { TableProps } from 'antd';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export interface ResizeTableProps extends TableProps<any> {
|
||||
onDragColumn?: (fromIndex: number, toIndex: number) => void;
|
||||
}
|
@ -8,4 +8,6 @@ export enum LOCALSTORAGE {
|
||||
LOGS_LINES_PER_ROW = 'LOGS_LINES_PER_ROW',
|
||||
LOGS_LIST_OPTIONS = 'LOGS_LIST_OPTIONS',
|
||||
TRACES_LIST_OPTIONS = 'TRACES_LIST_OPTIONS',
|
||||
TRACES_LIST_COLUMNS = 'TRACES_LIST_COLUMNS',
|
||||
LOGS_LIST_COLUMNS = 'LOGS_LIST_COLUMNS',
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
import { dragColumnParams } from 'hooks/useDragColumns/configs';
|
||||
import ReactDragListView from 'react-drag-listview';
|
||||
import { TableComponents } from 'react-virtuoso';
|
||||
|
||||
import { TableStyled } from './styles';
|
||||
|
||||
interface LogsCustomTableProps {
|
||||
handleDragEnd: (fromIndex: number, toIndex: number) => void;
|
||||
}
|
||||
|
||||
export const LogsCustomTable = ({
|
||||
handleDragEnd,
|
||||
}: LogsCustomTableProps): TableComponents['Table'] =>
|
||||
function CustomTable({ style, children }): JSX.Element {
|
||||
return (
|
||||
<ReactDragListView.DragColumn
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...dragColumnParams}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<TableStyled style={style}>{children}</TableStyled>
|
||||
</ReactDragListView.DragColumn>
|
||||
);
|
||||
};
|
@ -1,22 +1,26 @@
|
||||
import { ColumnTypeRender } from 'components/Logs/TableView/types';
|
||||
import { useTableView } from 'components/Logs/TableView/useTableView';
|
||||
import { cloneElement, ReactElement, ReactNode, useCallback } from 'react';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import useDragColumns from 'hooks/useDragColumns';
|
||||
import { getDraggedColumns } from 'hooks/useDragColumns/utils';
|
||||
import {
|
||||
cloneElement,
|
||||
ReactElement,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { TableComponents, TableVirtuoso } from 'react-virtuoso';
|
||||
|
||||
import { infinityDefaultStyles } from './config';
|
||||
import { LogsCustomTable } from './LogsCustomTable';
|
||||
import {
|
||||
TableCellStyled,
|
||||
TableHeaderCellStyled,
|
||||
TableRowStyled,
|
||||
TableStyled,
|
||||
} from './styles';
|
||||
import { InfinityTableProps } from './types';
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
const CustomTable: TableComponents['Table'] = ({ style, children }) => (
|
||||
<TableStyled style={style}>{children}</TableStyled>
|
||||
);
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
const CustomTableRow: TableComponents['TableRow'] = ({
|
||||
children,
|
||||
@ -31,11 +35,25 @@ function InfinityTable({
|
||||
}: InfinityTableProps): JSX.Element | null {
|
||||
const { onEndReached } = infitiyTableProps;
|
||||
const { dataSource, columns } = useTableView(tableViewProps);
|
||||
const { draggedColumns, onDragColumns } = useDragColumns<
|
||||
Record<string, unknown>
|
||||
>(LOCALSTORAGE.LOGS_LIST_COLUMNS);
|
||||
|
||||
const tableColumns = useMemo(
|
||||
() => getDraggedColumns<Record<string, unknown>>(columns, draggedColumns),
|
||||
[columns, draggedColumns],
|
||||
);
|
||||
|
||||
const handleDragEnd = useCallback(
|
||||
(fromIndex: number, toIndex: number) =>
|
||||
onDragColumns(tableColumns, fromIndex, toIndex),
|
||||
[tableColumns, onDragColumns],
|
||||
);
|
||||
|
||||
const itemContent = useCallback(
|
||||
(index: number, log: Record<string, unknown>): JSX.Element => (
|
||||
<>
|
||||
{columns.map((column) => {
|
||||
{tableColumns.map((column) => {
|
||||
if (!column.render) return <td>Empty</td>;
|
||||
|
||||
const element: ColumnTypeRender<Record<string, unknown>> = column.render(
|
||||
@ -60,20 +78,29 @@ function InfinityTable({
|
||||
})}
|
||||
</>
|
||||
),
|
||||
[columns],
|
||||
[tableColumns],
|
||||
);
|
||||
|
||||
const tableHeader = useCallback(
|
||||
() => (
|
||||
<tr>
|
||||
{columns.map((column) => (
|
||||
<TableHeaderCellStyled key={column.key}>
|
||||
{column.title as string}
|
||||
</TableHeaderCellStyled>
|
||||
))}
|
||||
{tableColumns.map((column) => {
|
||||
const isDragColumn = column.key !== 'expand';
|
||||
|
||||
return (
|
||||
<TableHeaderCellStyled
|
||||
isDragColumn={isDragColumn}
|
||||
key={column.key}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...(isDragColumn && { className: 'dragHandler' })}
|
||||
>
|
||||
{column.title as string}
|
||||
</TableHeaderCellStyled>
|
||||
);
|
||||
})}
|
||||
</tr>
|
||||
),
|
||||
[columns],
|
||||
[tableColumns],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -81,7 +108,8 @@ function InfinityTable({
|
||||
style={infinityDefaultStyles}
|
||||
data={dataSource}
|
||||
components={{
|
||||
Table: CustomTable,
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
Table: LogsCustomTable({ handleDragEnd }),
|
||||
// TODO: fix it in the future
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { themeColors } from 'constants/theme';
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface TableHeaderCellStyledProps {
|
||||
isDragColumn: boolean;
|
||||
}
|
||||
|
||||
export const TableStyled = styled.table`
|
||||
width: 100%;
|
||||
border-top: 1px solid rgba(253, 253, 253, 0.12);
|
||||
@ -26,10 +30,12 @@ export const TableRowStyled = styled.tr`
|
||||
}
|
||||
`;
|
||||
|
||||
export const TableHeaderCellStyled = styled.th`
|
||||
export const TableHeaderCellStyled = styled.th<TableHeaderCellStyledProps>`
|
||||
padding: 0.5rem;
|
||||
border-inline-end: 1px solid rgba(253, 253, 253, 0.12);
|
||||
background-color: #1d1d1d;
|
||||
${({ isDragColumn }): string => (isDragColumn ? 'cursor: col-resize;' : '')}
|
||||
|
||||
&:first-child {
|
||||
border-start-start-radius: 2px;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ interface UseOptionsMenuProps {
|
||||
interface UseOptionsMenu {
|
||||
options: OptionsQuery;
|
||||
config: OptionsMenuConfig;
|
||||
handleOptionsChange: (newQueryData: OptionsQuery) => void;
|
||||
}
|
||||
|
||||
const useOptionsMenu = ({
|
||||
@ -306,6 +307,7 @@ const useOptionsMenu = ({
|
||||
return {
|
||||
options: optionsQueryData,
|
||||
config: optionsMenuConfig,
|
||||
handleOptionsChange: handleRedirectWithOptionsData,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,8 @@ import { useOptionsMenu } from 'container/OptionsMenu';
|
||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { Pagination, URL_PAGINATION } from 'hooks/queryPagination';
|
||||
import useDragColumns from 'hooks/useDragColumns';
|
||||
import { getDraggedColumns } from 'hooks/useDragColumns/utils';
|
||||
import useUrlQueryData from 'hooks/useUrlQueryData';
|
||||
import history from 'lib/history';
|
||||
import { RowData } from 'lib/query/createTableColumnsFromQuery';
|
||||
@ -37,6 +39,10 @@ function ListView(): JSX.Element {
|
||||
},
|
||||
});
|
||||
|
||||
const { draggedColumns, onDragColumns } = useDragColumns<RowData>(
|
||||
LOCALSTORAGE.TRACES_LIST_COLUMNS,
|
||||
);
|
||||
|
||||
const { queryData: paginationQueryData } = useUrlQueryData<Pagination>(
|
||||
URL_PAGINATION,
|
||||
);
|
||||
@ -82,9 +88,10 @@ function ListView(): JSX.Element {
|
||||
queryTableDataResult,
|
||||
]);
|
||||
|
||||
const columns = useMemo(() => getListColumns(options?.selectColumns || []), [
|
||||
options?.selectColumns,
|
||||
]);
|
||||
const columns = useMemo(() => {
|
||||
const updatedColumns = getListColumns(options?.selectColumns || []);
|
||||
return getDraggedColumns(updatedColumns, draggedColumns);
|
||||
}, [options?.selectColumns, draggedColumns]);
|
||||
|
||||
const transformedQueryTableData = useMemo(
|
||||
() => transformDataWithDate(queryTableData) || [],
|
||||
@ -106,6 +113,12 @@ function ListView(): JSX.Element {
|
||||
[],
|
||||
);
|
||||
|
||||
const handleDragColumn = useCallback(
|
||||
(fromIndex: number, toIndex: number) =>
|
||||
onDragColumns(columns, fromIndex, toIndex),
|
||||
[columns, onDragColumns],
|
||||
);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<TraceExplorerControls
|
||||
@ -127,6 +140,7 @@ function ListView(): JSX.Element {
|
||||
dataSource={transformedQueryTableData}
|
||||
columns={columns}
|
||||
onRow={handleRow}
|
||||
onDragColumn={handleDragColumn}
|
||||
/>
|
||||
)}
|
||||
</Container>
|
||||
|
7
frontend/src/hooks/useDragColumns/configs.ts
Normal file
7
frontend/src/hooks/useDragColumns/configs.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export const COLUMNS = 'columns';
|
||||
|
||||
export const dragColumnParams = {
|
||||
ignoreSelector: '.react-resizable-handle',
|
||||
nodeSelector: 'th',
|
||||
handleSelector: '.dragHandler',
|
||||
};
|
75
frontend/src/hooks/useDragColumns/index.ts
Normal file
75
frontend/src/hooks/useDragColumns/index.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
import getFromLocalstorage from 'api/browser/localstorage/get';
|
||||
import setToLocalstorage from 'api/browser/localstorage/set';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import useUrlQueryData from 'hooks/useUrlQueryData';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
|
||||
import { COLUMNS } from './configs';
|
||||
import { UseDragColumns } from './types';
|
||||
|
||||
const useDragColumns = <T>(storageKey: LOCALSTORAGE): UseDragColumns<T> => {
|
||||
const {
|
||||
query: draggedColumnsQuery,
|
||||
queryData: draggedColumns,
|
||||
redirectWithQuery: redirectWithDraggedColumns,
|
||||
} = useUrlQueryData<ColumnsType<T>>(COLUMNS, []);
|
||||
|
||||
const localStorageDraggedColumns = useMemo(
|
||||
() => getFromLocalstorage(storageKey),
|
||||
[storageKey],
|
||||
);
|
||||
|
||||
const handleRedirectWithDraggedColumns = useCallback(
|
||||
(columns: ColumnsType<T>) => {
|
||||
redirectWithDraggedColumns(columns);
|
||||
|
||||
setToLocalstorage(storageKey, JSON.stringify(columns));
|
||||
},
|
||||
[storageKey, redirectWithDraggedColumns],
|
||||
);
|
||||
|
||||
const onDragColumns = useCallback(
|
||||
(columns: ColumnsType<T>, fromIndex: number, toIndex: number): void => {
|
||||
const columnsData = [...columns];
|
||||
const item = columnsData.splice(fromIndex, 1)[0];
|
||||
columnsData.splice(toIndex, 0, item);
|
||||
|
||||
handleRedirectWithDraggedColumns(columnsData);
|
||||
},
|
||||
[handleRedirectWithDraggedColumns],
|
||||
);
|
||||
|
||||
const redirectWithNewDraggedColumns = useCallback(
|
||||
async (localStorageColumns: string) => {
|
||||
let nextDraggedColumns: ColumnsType<T> = [];
|
||||
|
||||
try {
|
||||
const parsedDraggedColumns = await JSON.parse(localStorageColumns);
|
||||
nextDraggedColumns = parsedDraggedColumns;
|
||||
} catch (e) {
|
||||
console.log('error while parsing json');
|
||||
} finally {
|
||||
redirectWithDraggedColumns(nextDraggedColumns);
|
||||
}
|
||||
},
|
||||
[redirectWithDraggedColumns],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (draggedColumnsQuery || !localStorageDraggedColumns) return;
|
||||
|
||||
redirectWithNewDraggedColumns(localStorageDraggedColumns);
|
||||
}, [
|
||||
draggedColumnsQuery,
|
||||
localStorageDraggedColumns,
|
||||
redirectWithNewDraggedColumns,
|
||||
]);
|
||||
|
||||
return {
|
||||
draggedColumns,
|
||||
onDragColumns,
|
||||
};
|
||||
};
|
||||
|
||||
export default useDragColumns;
|
10
frontend/src/hooks/useDragColumns/types.ts
Normal file
10
frontend/src/hooks/useDragColumns/types.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
|
||||
export type UseDragColumns<T> = {
|
||||
draggedColumns: ColumnsType<T>;
|
||||
onDragColumns: (
|
||||
columns: ColumnsType<T>,
|
||||
fromIndex: number,
|
||||
toIndex: number,
|
||||
) => void;
|
||||
};
|
37
frontend/src/hooks/useDragColumns/utils.ts
Normal file
37
frontend/src/hooks/useDragColumns/utils.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
|
||||
const filterColumns = <T>(
|
||||
initialColumns: ColumnsType<T>,
|
||||
findColumns: ColumnsType<T>,
|
||||
isColumnExist = true,
|
||||
): ColumnsType<T> =>
|
||||
initialColumns.filter(({ title: columnTitle }) => {
|
||||
const column = findColumns.find(({ title }) => title === columnTitle);
|
||||
|
||||
return isColumnExist ? !!column : !column;
|
||||
});
|
||||
|
||||
export const getDraggedColumns = <T>(
|
||||
currentColumns: ColumnsType<T>,
|
||||
draggedColumns: ColumnsType<T>,
|
||||
): ColumnsType<T> => {
|
||||
if (draggedColumns.length) {
|
||||
const actualDruggedColumns = filterColumns<T>(draggedColumns, currentColumns);
|
||||
const newColumns = filterColumns<T>(
|
||||
currentColumns,
|
||||
actualDruggedColumns,
|
||||
false,
|
||||
);
|
||||
|
||||
return [...actualDruggedColumns, ...newColumns].reduce((acc, { title }) => {
|
||||
const column = currentColumns.find(
|
||||
({ title: columnTitle }) => title === columnTitle,
|
||||
);
|
||||
|
||||
if (column) return [...acc, column];
|
||||
return acc;
|
||||
}, [] as ColumnsType<T>);
|
||||
}
|
||||
|
||||
return currentColumns;
|
||||
};
|
@ -3719,6 +3719,14 @@ babel-preset-react-app@^10.0.0:
|
||||
babel-plugin-macros "^3.1.0"
|
||||
babel-plugin-transform-react-remove-prop-types "^0.4.24"
|
||||
|
||||
babel-runtime@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
||||
integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==
|
||||
dependencies:
|
||||
core-js "^2.4.0"
|
||||
regenerator-runtime "^0.11.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
|
||||
@ -4474,6 +4482,11 @@ core-js-compat@^3.25.1:
|
||||
dependencies:
|
||||
browserslist "^4.21.5"
|
||||
|
||||
core-js@^2.4.0:
|
||||
version "2.6.12"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz"
|
||||
@ -9999,7 +10012,7 @@ prompts@^2.0.1, prompts@^2.4.1:
|
||||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.5"
|
||||
|
||||
prop-types@15, prop-types@15.x, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
|
||||
prop-types@15, prop-types@15.x, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
|
||||
version "15.8.1"
|
||||
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
@ -10513,6 +10526,14 @@ react-dom@18.2.0:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react-drag-listview@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-drag-listview/-/react-drag-listview-2.0.0.tgz#b8e7ec5f980ecbbf3abb85f50db0b03cd764edbf"
|
||||
integrity sha512-7Apx/1Xt4qu+JHHP0rH6aLgZgS7c2MX8ocHVGCi03KfeIWEu0t14MhT3boQKM33l5eJrE/IWfExFTvoYq22fsg==
|
||||
dependencies:
|
||||
babel-runtime "^6.26.0"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
react-draggable@^4.0.0, react-draggable@^4.0.3:
|
||||
version "4.4.5"
|
||||
resolved "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz"
|
||||
@ -10808,6 +10829,11 @@ regenerator-runtime@0.13.9:
|
||||
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz"
|
||||
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
|
||||
|
||||
regenerator-runtime@^0.11.0:
|
||||
version "0.11.1"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
|
||||
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
|
||||
|
||||
regenerator-runtime@^0.13.11:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"
|
||||
|
Loading…
x
Reference in New Issue
Block a user