react-dnd-html5-backend#HTML5Backend TypeScript Examples
The following examples show how to use
react-dnd-html5-backend#HTML5Backend.
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: DragAndDropTreeProvider.tsx From frontend-sample-showcase with MIT License | 6 votes |
DragAndDropTreeProvider: React.FC = () => {
// See documentation on DndProvider backends: https://react-dnd.github.io/react-dnd/docs/overview
return (
<DndProvider backend={HTML5Backend}>
<DragAndDropTreeComponent />
</DndProvider>
);
}
Example #2
Source File: index.tsx From anew-server with MIT License | 6 votes |
render() {
const { order } = this.state;
const { children } = this.props;
const tabs: any[] = [];
React.Children.forEach(children, (c) => {
tabs.push(c);
});
const orderTabs = tabs.slice().sort((a, b) => {
const orderA = order.indexOf(a.key);
const orderB = order.indexOf(b.key);
if (orderA !== -1 && orderB !== -1) {
return orderA - orderB;
}
if (orderA !== -1) {
return -1;
}
if (orderB !== -1) {
return 1;
}
const ia = tabs.indexOf(a);
const ib = tabs.indexOf(b);
return ia - ib;
});
return (
<DndProvider backend={HTML5Backend}>
<Tabs renderTabBar={this.renderTabBar} {...this.props}>
{orderTabs}
</Tabs>
</DndProvider>
);
}
Example #3
Source File: material-ui-dnd-grid.tsx From ui-schema with MIT License | 6 votes |
HTML5toTouch: MultiBackendOptions = {
backends: [
{
id: 'html5',
backend: HTML5Backend,
transition: PointerTransition,
},
{
id: 'touch',
backend: TouchBackend,
options: {enableMouseEvents: true},
preview: true,
transition: TouchTransition,
},
],
}
Example #4
Source File: DragSortEditTable.tsx From datart with Apache License 2.0 | 6 votes |
DragSortEditTable: React.FC<DragEditTableProps> = ({
components,
...restProps
}) => {
const DragEditComponents = {
body: {
row: DraggableAndEditableBodyRow,
cell: EditableCell,
},
};
const onMoveRow = useCallback((a, b) => {
// const dragRow = rows[dragIndex];
// rows.splice(dragIndex, 1);
// rows.splice(hoverIndex, 0, dragRow);
// setRows([...rows]);
}, []);
return (
<DndProvider backend={HTML5Backend}>
<Table
rowClassName={() => 'editable-row'}
components={DragEditComponents}
{...restProps}
/>
</DndProvider>
);
}
Example #5
Source File: index.tsx From calendar-hack with MIT License | 6 votes |
CustomHTML5toTouch: Backends = {
backends: [
{
backend: HTML5Backend as any,
transition: MouseTransition,
// by default, will dispatch a duplicate `mousedown` event when this backend is activated
//preview: true,
},
{
backend: TouchBackend as any,
// Note that you can call your backends with options
options: {
enableMouseEvents: true,
skipDispatchOnTransition: true // will not dispatch a duplicate `touchstart` event when this backend is activated
},
preview: true,
transition: TouchTransition,
}
]
}
Example #6
Source File: index.tsx From gio-design with Apache License 2.0 | 6 votes |
public render() {
const { collection, getId, template, container } = this.props;
const { collections, SortableItemClass } = this.state;
const SortableItem = SortableItemClass;
const children = collections.map((props: ItemWithId, i: number) => {
const originalPosition = collection.indexOf(props);
const key = getId ? getId(props, i) : props.value;
const canDrag = props.canDrag === false ? props.canDrag : true;
return (
<SortableItem
sortData={props}
canDrag={canDrag}
index={i}
key={key}
position={originalPosition}
onHover={this._handleHover}
onDrop={this._handleDrop}
onCancel={this._handleCancel}
template={template}
/>
);
});
return (
<DndProvider backend={HTML5Backend as any}>
{React.createElement(
container,
_.omit(this.props, ['collection', 'container', 'onSorted', 'template']),
children
)}
</DndProvider>
);
}
Example #7
Source File: Programs.tsx From gear-js with GNU General Public License v3.0 | 6 votes |
Programs: VFC = () => {
const isUploadedProgramsPage = useMatch(routes.uploadedPrograms);
const isAllProgramsPage = useMatch(routes.allPrograms);
const isAllMessagesPage = useMatch(routes.messages);
let currentPage = SWITCH_PAGE_TYPES.UPLOAD_PROGRAM;
if (isUploadedProgramsPage) {
currentPage = SWITCH_PAGE_TYPES.UPLOADED_PROGRAMS;
} else if (isAllProgramsPage) {
currentPage = SWITCH_PAGE_TYPES.ALL_PROGRAMS;
} else if (isAllMessagesPage) {
currentPage = SWITCH_PAGE_TYPES.ALL_MESSAGES;
}
return (
<div className="main-content-wrapper">
<ProgramSwitch pageType={currentPage} />
{currentPage === SWITCH_PAGE_TYPES.UPLOAD_PROGRAM && (
<>
<DndProvider backend={HTML5Backend}>
<Upload />
</DndProvider>
<BlockList />
</>
)}
{currentPage === SWITCH_PAGE_TYPES.UPLOADED_PROGRAMS && <Recent />}
{currentPage === SWITCH_PAGE_TYPES.ALL_PROGRAMS && <All />}
{currentPage === SWITCH_PAGE_TYPES.ALL_MESSAGES && <Messages />}
</div>
);
}
Example #8
Source File: Viewer.tsx From legend-studio with Apache License 2.0 | 6 votes |
Viewer: React.FC = () => (
<EditorStoreProvider>
<ViewerStoreProvider>
<DndProvider backend={HTML5Backend}>
<ViewerInner />
</DndProvider>
</ViewerStoreProvider>
</EditorStoreProvider>
)
Example #9
Source File: editor-component.tsx From utopia with MIT License | 6 votes |
export function EditorComponent(props: EditorProps) {
const indexedDBFailed = useEditorState(
(store) => store.editor.indexedDBFailed,
'EditorComponent indexedDBFailed',
)
return indexedDBFailed ? (
<FatalIndexedDBErrorComponent />
) : (
<DndProvider backend={HTML5Backend}>
<EditorComponentInner {...props} />
</DndProvider>
)
}
Example #10
Source File: $todoListId.tsx From remix-hexagonal-architecture with MIT License | 6 votes |
export default function TodoListPage() {
const todoListPage = useTodoListPage();
return (
<DndProvider backend={HTML5Backend}>
<TodoList todoListPage={todoListPage} />
</DndProvider>
);
}
Example #11
Source File: page-container.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
RenderMainContent = React.memo(
({
noWrapper,
customMain,
route,
layout,
}: {
noWrapper: boolean;
customMain: Function | JSX.Element | null;
route: RouteConfig;
layout: {
[k: string]: any;
};
}) => {
return (
<ErrorBoundary>
<DndProvider backend={HTML5Backend}>
{noWrapper ? (
<>
{typeof customMain === 'function' ? customMain() : customMain}
{renderRoutes(route.routes)}
</>
) : (
<Card className={layout && layout.fullHeight ? 'h-full overflow-auto' : ''}>
{typeof customMain === 'function' ? customMain() : customMain}
{renderRoutes(route.routes)}
</Card>
)}
</DndProvider>
</ErrorBoundary>
);
},
)
Example #12
Source File: index.tsx From datart with Apache License 2.0 | 5 votes |
DraggableList = props => {
return (
<DndProvider backend={HTML5Backend}>
<DraggableContainer {...props} />
</DndProvider>
);
}
Example #13
Source File: QueryEditor.tsx From legend-studio with Apache License 2.0 | 5 votes |
QueryEditor: React.FC = () => (
<DndProvider backend={HTML5Backend}>
<QueryEditorInner />
</DndProvider>
)
Example #14
Source File: EditorElementFactory.tsx From next-core with GNU General Public License v3.0 | 5 votes |
export function EditorElementFactory(
EditorComponent: EditorComponentType,
options?: EditorElementOptions
): EditorBrickElementConstructor {
class NewEditorElement extends UpdatingElement {
static get selfLayout(): EditorSelfLayout {
return options?.selfLayout;
}
@property({ type: Number })
nodeUid: number;
@property({ attribute: false })
editorProps: StoryDoc["editorProps"];
connectedCallback(): void {
// Don't override user's style settings.
// istanbul ignore else
if (!this.style.display) {
this.style.display = "block";
}
if (options?.brickStyle) {
for (const [key, value] of Object.entries(options.brickStyle)) {
(this.style as unknown as Record<string, string>)[key] = value;
}
}
this._render();
}
disconnectedCallback(): void {
ReactDOM.unmountComponentAtNode(this);
}
protected _render(): void {
// istanbul ignore else
if (this.isConnected && this.nodeUid) {
ReactDOM.render(
<BrickWrapper>
<BuilderProvider>
<DndProvider backend={HTML5Backend}>
<EditorComponent
nodeUid={this.nodeUid}
editorProps={this.editorProps}
/>
</DndProvider>
</BuilderProvider>
</BrickWrapper>,
this
);
}
}
}
return NewEditorElement;
}
Example #15
Source File: Editor.tsx From legend-studio with Apache License 2.0 | 5 votes |
Editor: React.FC = () => (
<EditorStoreProvider>
<DndProvider backend={HTML5Backend}>
<EditorInner />
</DndProvider>
</EditorStoreProvider>
)
Example #16
Source File: App.tsx From querybook with Apache License 2.0 | 5 votes |
App = () => (
<DndProvider backend={HTML5Backend}>
<Provider store={reduxStore}>
<AppRouter />
</Provider>
</DndProvider>
)
Example #17
Source File: Drag.tsx From gio-design with Apache License 2.0 | 5 votes |
Drag: React.FC<DragListProps> & {
Item: React.FC<DragItemProps>;
} = (props) => {
const { onChange, className, style, options: propsOptions, disabled, ...rest } = props;
const [options, setOptions] = useState(propsOptions);
useEffect(() => {
setOptions(propsOptions);
}, [propsOptions]);
const prefixCls = `${usePrefixCls(PREFIX)}`;
const onMoved = (dragIndex: number, hoverIndex: number) => {
const dragCard = options[dragIndex];
const updateOptions = update(options, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragCard],
],
});
setOptions(updateOptions);
onChange?.(updateOptions);
};
return (
<DndProvider backend={HTML5Backend}>
<List className={classNames(`${prefixCls}--drag`, className)} style={style}>
{options?.map((option: OptionProps, index: number) => (
<DragItem
{...option}
{...rest}
index={index}
onMoved={onMoved}
disabled={option?.disabled ?? disabled}
key={option?.value}
/>
))}
</List>
</DndProvider>
);
}
Example #18
Source File: index.tsx From next-basics with GNU General Public License v3.0 | 5 votes |
protected _render(): void {
// istanbul ignore else
if (this.isConnected) {
ReactDOM.render(
<BrickWrapper>
<BuilderProvider>
<DndProvider backend={HTML5Backend}>
<BuilderContainer
ref={this._managerRef}
appId={this.appId}
dataSource={this.dataSource}
brickList={this.brickList}
editorList={this.editorList}
providerList={this.providerList}
routeList={this.routeList}
templateList={this.templateList}
snippetList={this.snippetList}
templateSources={this.templateSources}
storyList={this.storyList}
processing={this.processing}
highlightTokens={this.highlightTokens}
containerForContextModal={this.containerForContextModal}
migrateClipboard={this.migrateClipboard}
clipboardData={this.clipboardData}
showDataView={this.showDataView}
initialFullscreen={this.fullscreen}
initialToolboxTab={this.toolboxTab}
initialHiddenWrapper={this.hiddenWrapper}
initialEventStreamNodeId={this.eventStreamNodeId}
initialClipboardType={this.clipboardType}
initialClipboardSource={this.clipboardSource}
initialClipboardNodeType={this.clipboardNodeType}
initialCanvasIndex={this.canvasIndex}
initialStoryboardQuery={this.storyboardQuery}
onNodeAdd={this._handleNodeAdd}
onSnippetApply={this._handleSnippetApply}
onNodeReorder={this._handleNodeReorder}
onNodeMove={this._handleNodeMove}
onNodeClick={this._handleNodeClick}
onAskForDeletingNode={this._handleAskForDeletingNode}
onToggleFullscreen={this._handleToggleFullscreen}
onSwitchToolboxTab={this._handleSwitchToolboxTab}
onSwitchHiddenWrapper={this._handleSwitchHiddenWrapper}
onSelectEventStreamNode={this._handleSelectEventsViewNode}
onClipboardChange={this._handleClipboardChange}
onNodeCopy={this._handleNodeCopy}
onNodeCut={this._handleNodeCut}
onNodeCopyPaste={this._handleNodeCopyPaste}
onNodeCutPaste={this._handleNodeCutPaste}
onClipboardClear={this._handleClipboardClear}
onContextUpdate={this._handleContextUpdate}
onRouteSelect={this._handleRouteSelect}
onTemplateSelect={this._handleTemplateSelect}
onSnippetSelect={this._handleSnippetSelect}
onCurrentRouteClick={this._handleCurrentRouteClick}
onCurrentTemplateClick={this._handleCurrentTemplateClick}
onCurrentSnippetClick={this._handleCurrentSnippetClick}
onBuildAndPush={this._handleBuildAndPush}
onPreview={this._handlePreview}
onAskForAppendingBrick={this._handleAskForAppendingBrick}
onAskForAppendingRoute={this._handleAskForAppendingRoute}
onEventNodeClick={this._handleEventNodeClick}
onConvertToTemplate={this._handleConvertToTemplate}
onWorkbenchClose={this._handleWorkbenchClose}
onSwitchCanvasIndex={this._handleSwitchCanvasIndex}
onStoryboardQueryUpdate={this._handleStoryboardQueryUpdate}
onClickHighlightToken={this._handleHighlightTokenClick}
/>
</DndProvider>
</BuilderProvider>
</BrickWrapper>,
this
);
}
}
Example #19
Source File: LayerList.tsx From datart with Apache License 2.0 | 4 votes |
LayerList: React.FC<{}> = memo(() => {
const dispatch = useDispatch();
const allWidgetsInfo = useSelector(selectAllWidgetInfoMap);
const sortLayoutWidgets = useSelector(selectSortAllWidgets);
const { boardId } = useContext(BoardContext);
const [cards, setCards] = useState<NameCard[]>([]);
useEffect(() => {
const card = sortLayoutWidgets.map(
ele =>
({
index: ele.config.index,
id: ele.id,
widgetType: ele.config.type,
name: ele.config.name,
editing: allWidgetsInfo[ele.id]?.editing || false,
selected: allWidgetsInfo[ele.id]?.selected || false,
} as NameCard),
);
setCards(card);
}, [allWidgetsInfo, sortLayoutWidgets]);
const moveCard = useCallback(
(
dragIndex: number,
hoverIndex: number,
dragZIndex: number,
hoverZIndex: number,
) => {
const newCards = JSON.parse(JSON.stringify(cards));
[newCards[dragIndex], newCards[hoverIndex]] = [
newCards[hoverIndex],
newCards[dragIndex],
];
newCards[dragIndex].index = dragZIndex;
newCards[hoverIndex].index = hoverZIndex;
setCards(newCards);
},
[cards],
);
const moveEnd = useCallback(() => {
const newWidgets: updateWidgetConf[] = [];
cards.forEach(ele => {
sortLayoutWidgets.forEach(widget => {
if (widget.id === ele.id && widget.config.index !== ele.index) {
const newConfig = produce(widget.config, draft => {
draft.index = ele.index;
});
newWidgets.push({ id: widget.id, config: newConfig });
}
});
});
if (newWidgets.length) {
dispatch(editBoardStackActions.updateWidgetsConfig(newWidgets));
}
}, [cards, dispatch, sortLayoutWidgets]);
const clearSelectedWidgets = () => {
dispatch(editWidgetInfoActions.clearSelectedWidgets());
};
const nameList = cards
.sort((a, b) => b.index - a.index)
.map((ele, index) => (
<WidgetWrapProvider
id={ele.id}
key={ele.id}
boardEditing={true}
boardId={boardId}
>
<NameItem
widgetType={ele.widgetType}
key={ele.id}
index={index}
zIndex={ele.index!}
card={ele}
moveCard={moveCard}
moveEnd={moveEnd}
></NameItem>
</WidgetWrapProvider>
));
return (
<DndProvider backend={HTML5Backend}>
<Wrapper onClick={clearSelectedWidgets}>
<h3 className="title">组件</h3>
<div className="nameList">{nameList}</div>
<div className="bottom"></div>
</Wrapper>
</DndProvider>
);
})
Example #20
Source File: BrickTable.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
export function BrickTable(props: BrickTableProps): React.ReactElement {
if (props.error) {
throw props.error;
}
const {
configProps,
columns,
rowKey,
expandIconAsCell,
expandIconColumnIndex,
childrenColumnName,
deleteEnabled,
scroll,
optimizedColumns,
onDelete, // 用于 brick form 中,will be deprecated
ellipsisInfo,
showHeader,
} = props;
const initData = useMemo(() => {
return (
props.dataSource &&
(rowKey
? props.dataSource
: props.dataSource.map((item, index) =>
isNil(item.key) ? { ...item, key: index } : item
))
);
}, [props.dataSource, rowKey]);
const [data, setData] = useState(initData);
const rowKeyExpandIconMapRef = useRef<Map<unknown, React.ReactNode>>(
new Map()
);
const columnTitleBrickDataMapRef = useRef<
Map<CustomColumn, { title: unknown }>
>(new Map());
const useBrickItemBrickDataMapRef = useRef<
Map<UseBrickConf, ItemBrickDataMap>
>(new Map());
const itemExpandedRowBrickDataMapRef = useRef<Map<unknown, unknown>>(
new Map()
);
useEffect(() => {
itemExpandedRowBrickDataMapRef.current.clear();
setData(initData);
}, [initData]);
const expandIconColumnIndexOffset = configProps?.rowSelection ? -1 : 0;
const customColumns = useMemo(() => {
if (columns) {
columnTitleBrickDataMapRef.current.clear();
useBrickItemBrickDataMapRef.current.clear();
const customColumns = columns.map((column, index) => {
const {
useBrick,
component,
valueSuffix,
cellStatus,
titleUseBrick,
headerBrick,
colSpanKey,
rowSpanKey,
...columnConf
} = column;
if (headerBrick?.useBrick || titleUseBrick) {
if (titleUseBrick) {
// eslint-disable-next-line no-console
console.warn(
"`titleUseBrick` of `<presentational-bricks.brick-table>` is deprecated, use `headerBrick` instead."
);
}
const useBrick = headerBrick?.useBrick || titleUseBrick;
let data = columnTitleBrickDataMapRef.current.get(column);
if (!data) {
data = {
title: columnConf.title,
};
columnTitleBrickDataMapRef.current.set(column, data);
}
columnConf.title = getCustomHeader(useBrick, data);
}
if (useBrick || component) {
let itemBrickDataMap: ItemBrickDataMap;
if (useBrick) {
itemBrickDataMap =
useBrickItemBrickDataMapRef.current.get(useBrick);
if (!itemBrickDataMap) {
itemBrickDataMap = new Map();
useBrickItemBrickDataMapRef.current.set(
useBrick,
itemBrickDataMap
);
}
}
columnConf.render = getCustomComp(
useBrick,
component,
itemBrickDataMap
);
if (optimizedColumns?.includes(column.dataIndex)) {
// [only update when record changed](https://ant.design/components/table-cn/#%E4%B8%BA%E4%BB%80%E4%B9%88-%E6%9B%B4%E6%96%B0-state-%E4%BC%9A%E5%AF%BC%E8%87%B4%E5%85%A8%E8%A1%A8%E6%B8%B2%E6%9F%93%EF%BC%9F)
columnConf.shouldCellUpdate = (record, prevRecord) => {
return !isEqual(record, prevRecord);
};
}
} else if (valueSuffix) {
columnConf.render = (value) => value + valueSuffix;
}
if (
!expandIconAsCell &&
index === expandIconColumnIndex + expandIconColumnIndexOffset
) {
const innerRender = columnConf.render;
columnConf.render = function ExpandIcon(value, record, index) {
return (
<>
{!record[childrenColumnName] &&
rowKeyExpandIconMapRef.current.get(
rowKey ? record[rowKey] : record
)}
{innerRender ? innerRender(value, record, index) : value}
</>
);
};
}
if (cellStatus || colSpanKey || rowSpanKey) {
const innerRender = columnConf.render;
columnConf.render = (value, item, index) => {
return {
children: innerRender ? innerRender(value, item, index) : value,
props: {
colSpan: item[colSpanKey],
rowSpan: item[rowSpanKey],
style: cellStatus && getCellStyle(cellStatus, item, value),
},
};
};
}
if (typeof columnConf.dataIndex === "string") {
columnConf.dataIndex = toPath(columnConf.dataIndex);
}
if (columnConf.verticalAlign === "top") {
columnConf.className
? (columnConf.className += " alignTop")
: (columnConf.className = "alignTop");
}
if (columnConf.verticalAlign === "bottom") {
columnConf.className
? (columnConf.className += " alignBottom")
: (columnConf.className = "alignBottom");
}
if (ellipsisInfo) {
columnConf.className = styles.ellipsisInfoCell;
}
return columnConf;
});
if (deleteEnabled) {
const render = (value: any, item: any, index: number) => {
return (
<Icon
onClick={() => onDelete?.(index)}
component={() => <FontAwesomeIcon icon="trash-alt" />}
style={{ color: "#167be0" }}
/>
);
};
customColumns.push({
title: "操作",
render,
});
}
return customColumns;
}
}, [
columns,
childrenColumnName,
expandIconAsCell,
expandIconColumnIndex,
expandIconColumnIndexOffset,
rowKey,
deleteEnabled,
onDelete,
ellipsisInfo,
]);
const expandedRowRender = (record: Record<string, any>, index: number) => {
let data = itemExpandedRowBrickDataMapRef.current.get(record);
if (!data) {
data = {
rowData: record,
rowIndex: index,
};
itemExpandedRowBrickDataMapRef.current.set(record, data);
}
return (
<BrickAsComponent
useBrick={props.expandedRowBrick.useBrick}
data={data}
/>
);
};
const components = {
body: {
row: DraggableBodyRow,
},
};
const moveRow = (dragIndex: number, hoverIndex: number) => {
const dragRow = data[dragIndex];
const newData = update(data, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragRow],
],
});
setData(newData);
props.onDrag && props.onDrag(newData);
};
const onExpand = (expanded: boolean, record: Record<string, any>) => {
props.onExpand && props.onExpand(expanded, record);
};
const onExpandedRowsChange = (expandedRows: React.Key[]) => {
props.onExpandedRowsChange && props.onExpandedRowsChange(expandedRows);
};
const getCustomExpandIcon = (iconProps: any) => {
const { record, expandable, expanded, onExpand } = iconProps;
let icon = props.expandIcon?.collapsedIcon || downMenuIcon;
let iconNode: React.ReactNode;
if (expandable) {
if (!expanded) {
icon = props.expandIcon?.expandedIcon || rightMenuIcon;
}
iconNode = (
<span
className={styles.expandIconSpan}
data-testid="expand-icon"
onClick={(e) => {
onExpand(record, e);
}}
>
<GeneralIcon icon={icon} />
</span>
);
} else {
iconNode = (
<span className={styles.expandIconSpan} data-testid="expand-icon">
<span style={{ visibility: "hidden" }}>
<GeneralIcon icon={icon} />
</span>
</span>
);
}
if (iconNode) {
if (!expandIconAsCell) {
rowKeyExpandIconMapRef.current.set(
rowKey ? record[rowKey] : record,
iconNode
);
}
return iconNode;
} else {
return <></>;
}
};
const pickExpandProps = pickBy(
{
expandIconColumnIndex,
expandIconAsCell,
expandRowByClick: props.expandRowByClick,
expandedRowKeys: props.expandedRowKeys,
defaultExpandAllRows: props.defaultExpandAllRows,
},
(item) => !isNil(item)
);
let table = (
<Table
className={classNames(styles.brickTable, {
[styles.expandIconCellHidden]: !expandIconAsCell,
[styles.customDropTable]: props.tableDraggable,
[styles.tableThTransparent]: props.thTransparent,
[styles.zebraPatternTable]: data?.length >= 2 && props.zebraPattern,
})}
dataSource={data}
{...(props.tableDraggable
? {
components,
onRow: (record, index) => ({
index,
moveRow: moveRow,
}),
}
: {})}
columns={customColumns}
onChange={props.onChange}
{...(props.expandedRowBrick
? {
expandedRowRender,
}
: {})}
{...pickExpandProps}
onExpand={onExpand}
onExpandedRowsChange={onExpandedRowsChange}
rowKey={rowKey}
childrenColumnName={childrenColumnName}
rowClassName={(record, index) =>
props.zebraPattern && index % 2 ? styles.brickTableOddRow : ""
}
expandIcon={getCustomExpandIcon}
scroll={scroll}
showHeader={showHeader}
{...configProps}
/>
);
if (props.tableDraggable) {
table = <DndProvider backend={HTML5Backend}>{table}</DndProvider>;
}
if (!props.showCard) {
return table;
}
return <Card bordered={false}> {table} </Card>;
}
Example #21
Source File: new-canvas-controls.tsx From utopia with MIT License | 4 votes |
NewCanvasControls = React.memo((props: NewCanvasControlsProps) => {
const canvasControlProps = useEditorState(
(store) => ({
dispatch: store.dispatch,
editor: store.editor,
derived: store.derived,
canvasOffset: store.editor.canvas.roundedCanvasOffset,
controls: store.derived.controls,
scale: store.editor.canvas.scale,
focusedPanel: store.editor.focusedPanel,
transientCanvasState: store.derived.transientState,
}),
'NewCanvasControls',
)
const { localSelectedViews, localHighlightedViews, setSelectedViewsLocally } =
useLocalSelectedHighlightedViews(
canvasControlProps.editor.selectedViews,
canvasControlProps.editor.highlightedViews,
canvasControlProps.transientCanvasState,
)
const canvasScrollAnimation = useEditorState(
(store) => store.editor.canvas.scrollAnimation,
'NewCanvasControls scrollAnimation',
)
// Somehow this being setup and hooked into the div makes the `onDrop` call
// work properly in `editor-canvas.ts`. I blame React DnD for this.
const dropSpec: DropTargetHookSpec<FileBrowserItemProps, 'CANVAS', unknown> = {
accept: 'filebrowser',
canDrop: () => true,
}
const [_, drop] = useDrop(dropSpec)
const forwardedRef = React.useCallback(
(node: ConnectableElement) => {
return drop(node)
},
[drop],
)
if (isLiveMode(canvasControlProps.editor.mode) && !canvasControlProps.editor.keysPressed.cmd) {
return null
} else {
return (
<DndProvider backend={HTML5Backend}>
<div
key='canvas-controls'
ref={forwardedRef}
className={
canvasControlProps.focusedPanel === 'canvas'
? ' canvas-controls focused '
: ' canvas-controls '
}
id='canvas-controls'
style={{
pointerEvents: 'initial',
position: 'absolute',
top: 0,
left: 0,
transform: 'translate3d(0, 0, 0)',
width: `100%`,
height: `100%`,
zoom: canvasControlProps.scale >= 1 ? `${canvasControlProps.scale * 100}%` : 1,
cursor: props.cursor,
visibility: canvasScrollAnimation ? 'hidden' : 'initial',
}}
>
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: `${canvasControlProps.scale < 1 ? 100 / canvasControlProps.scale : 100}%`,
height: `${canvasControlProps.scale < 1 ? 100 / canvasControlProps.scale : 100}%`,
transformOrigin: 'top left',
transform: canvasControlProps.scale < 1 ? `scale(${canvasControlProps.scale}) ` : '',
}}
>
<NewCanvasControlsInner
windowToCanvasPosition={props.windowToCanvasPosition}
localSelectedViews={localSelectedViews}
localHighlightedViews={localHighlightedViews}
setLocalSelectedViews={setSelectedViewsLocally}
editor={canvasControlProps.editor}
transientState={canvasControlProps.transientCanvasState}
dispatch={canvasControlProps.dispatch}
canvasOffset={canvasControlProps.canvasOffset}
/>
</div>
<ElementContextMenu contextMenuInstance='context-menu-canvas' />
</div>
</DndProvider>
)
}
})
Example #22
Source File: Preview.tsx From datart with Apache License 2.0 | 4 votes |
StoryPagePreview: React.FC<{
orgId: string;
storyId: string;
allowShare?: boolean;
allowManage?: boolean;
}> = memo(({ orgId, storyId, allowShare, allowManage }) => {
const dispatch = useDispatch();
const history = useHistory();
const [currentPageIndex, setCurrentPageIndex] = useState(0);
const publishLoading = useSelector(selectPublishLoading);
const story = useSelector((state: { storyBoard: StoryBoardState }) =>
makeSelectStoryBoardById(state, storyId),
);
const pageMap = useSelector((state: { storyBoard: StoryBoardState }) =>
makeSelectStoryPagesById(state, storyId),
);
const sortedPages = useMemo(() => {
const sortedPages = Object.values(pageMap).sort(
(a, b) => a.config.index - b.config.index,
);
return sortedPages;
}, [pageMap]);
const onPageClick = useCallback(
(index: number, pageId: string, multiple: boolean) => {
setCurrentPageIndex(index);
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: false,
}),
);
},
[dispatch, storyId],
);
const currentPage = useMemo(() => {
const currentPage = sortedPages[currentPageIndex];
return currentPage;
}, [currentPageIndex, sortedPages]);
const toggleEdit = useCallback(() => {
history.push(`/organizations/${orgId}/vizs/storyEditor/${storyId}`);
}, [history, orgId, storyId]);
const playStory = useCallback(() => {
window.open(`storyPlayer/${storyId}`, '_blank');
}, [storyId]);
const { publishStory } = usePublishBoard(
storyId,
'STORYBOARD',
story?.status || 0,
);
const { sizes, setSizes } = useSplitSizes({
limitedSide: 0,
range: [150, 768],
});
const siderDragEnd = useCallback(
sizes => {
setSizes(sizes);
dispatchResize();
},
[setSizes],
);
// 点击在加载
useEffect(() => {
const curPage = sortedPages[currentPageIndex];
if (!curPage || !curPage.relId || !curPage.relType) {
return;
}
const { relId, relType } = curPage;
dispatch(getPageContentDetail({ relId, relType }));
}, [currentPageIndex, dispatch, sortedPages, pageMap]);
useEffect(() => {
dispatch(getStoryDetail(storyId));
}, [dispatch, storyId]);
useEffect(() => {
if (sortedPages.length === 0) {
return;
}
const pageId = sortedPages[currentPageIndex].id;
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: false,
}),
);
}, [dispatch, currentPageIndex, sortedPages, storyId]);
// 自动加载所有
// useEffect(() => {
// sortedPages.forEach(page => {
// try {
// const { relId, relType } = page;
// dispatch(getPageContentDetail({ relId, relType }));
// } catch (error) {}
// });
// }, [dispatch, sortedPages]);
return (
<DndProvider backend={HTML5Backend}>
<StoryContext.Provider
value={{
name: story?.name,
storyId: storyId,
editing: false,
orgId: orgId,
status: 1,
allowShare: allowShare || false,
}}
>
<Wrapper>
<StoryHeader
orgId={orgId}
name={story?.name}
playStory={playStory}
status={story?.status}
toggleEdit={toggleEdit}
publishLoading={publishLoading}
onPublish={publishStory}
allowShare={allowShare}
allowManage={allowManage}
/>
<Container
sizes={sizes}
minSize={[256, 0]}
maxSize={[768, Infinity]}
gutterSize={0}
onDragEnd={siderDragEnd}
className="datart-split"
>
<PageListWrapper>
<PageThumbnailList
sortedPages={sortedPages}
onPageClick={onPageClick}
/>
</PageListWrapper>
<Content>
{sortedPages.map(page => (
<PreviewPage key={page.id} show={page.id === currentPage.id}>
<StoryPageItem
key={page.id}
page={page}
showZoomCtrl={true}
renderMode="read"
/>
</PreviewPage>
))}
</Content>
</Container>
</Wrapper>
</StoryContext.Provider>
</DndProvider>
);
})
Example #23
Source File: index.tsx From datart with Apache License 2.0 | 4 votes |
StoryPlayer: React.FC<{}> = memo(() => {
useBoardSlice();
useEditBoardSlice();
useStoryBoardSlice();
const dispatch = useDispatch();
const { storyId } = useParams<{ storyId: string }>();
useEffect(() => {
dispatch(getStoryDetail(storyId));
}, [dispatch, storyId]);
const domId = useMemo(() => uuidv4(), []);
const revealRef = useRef<any>();
const [currentPageIndex, setCurrentPageIndex] = useState(0);
const fullRef: RefObject<HTMLDivElement> = useRef(null);
const storyBoard = useSelector((state: { storyBoard: StoryBoardState }) =>
makeSelectStoryBoardById(state, storyId),
);
const pageMap = useSelector((state: { storyBoard: StoryBoardState }) =>
makeSelectStoryPagesById(state, storyId),
);
const sortedPages = useMemo(() => {
const sortedPages = Object.values(pageMap).sort(
(a, b) => a.config.index - b.config.index,
);
return sortedPages;
}, [pageMap]);
const changePage = useCallback(
e => {
const { indexh: slideIdx } = e;
setCurrentPageIndex(slideIdx);
const pageId = sortedPages[slideIdx].id;
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: false,
}),
);
},
[dispatch, sortedPages, storyId],
);
useEffect(() => {
if (sortedPages.length === 0) {
return;
}
const pageId = sortedPages[0].id;
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: false,
}),
);
}, [dispatch, sortedPages, storyId]);
const autoSlide = useMemo(() => {
if (storyBoard?.config?.autoPlay?.auto) {
return storyBoard?.config?.autoPlay?.delay * 1000;
}
return null;
}, [storyBoard?.config?.autoPlay?.auto, storyBoard?.config?.autoPlay?.delay]);
useEffect(() => {
if (sortedPages.length > 0) {
revealRef.current = new Reveal(document.getElementById(domId), {
hash: false,
history: false,
controls: true,
controlsLayout: 'none',
slideNumber: 'c/t',
controlsTutorial: false,
progress: false,
loop: true,
width: '100%',
height: '100%',
margin: 0,
minScale: 1,
maxScale: 1,
autoSlide: autoSlide,
transition: 'convex',
// backgroundTransition: 'fade',
transitionSpeed: 'slow',
viewDistance: 100,
plugins: [RevealZoom],
keyboard: {
27: () => {
// disabled esc
}, // do something custom when ESC is pressed
},
});
revealRef.current?.initialize();
if (revealRef.current) {
revealRef.current.addEventListener('slidechanged', changePage);
}
return () => {
revealRef.current.removeEventListener('slidechanged', changePage);
};
}
}, [domId, changePage, sortedPages.length, autoSlide, dispatch]);
useEffect(() => {
const curPage = sortedPages[currentPageIndex];
if (!curPage || !curPage.relId || !curPage.relType) {
return;
}
const { relId, relType } = curPage;
dispatch(getPageContentDetail({ relId, relType }));
}, [currentPageIndex, dispatch, sortedPages, pageMap]);
return (
<DndProvider backend={HTML5Backend}>
<Wrapper ref={fullRef}>
<Content>
<div id={domId} className="reveal">
<div className="slides">
{sortedPages.map((page, index) => (
<StoryPageItem
key={page.id}
page={page}
autoFit={false}
renderMode="read"
/>
))}
</div>
</div>
</Content>
</Wrapper>
</DndProvider>
);
})
Example #24
Source File: index.tsx From datart with Apache License 2.0 | 4 votes |
StoryEditor: React.FC<{}> = memo(() => {
useBoardSlice();
useEditBoardSlice();
useStoryBoardSlice();
const dispatch = useDispatch();
const { orgId, storyId } = useParams<{ orgId: string; storyId: string }>();
useEffect(() => {
dispatch(getStoryDetail(storyId));
}, [dispatch, storyId]);
const t = useI18NPrefix(`viz.board.setting`);
const history = useHistory();
const histState = history.location.state as any;
const domId = useMemo(() => uuidv4(), []);
const revealRef = useRef<any>();
const [currentPageIndex, setCurrentPageIndex] = useState(0);
const story = useSelector((state: { storyBoard: StoryBoardState }) =>
makeSelectStoryBoardById(state, storyId),
);
const pageMap = useSelector((state: { storyBoard: StoryBoardState }) =>
makeSelectStoryPagesById(state, storyId),
);
const sortedPages = useMemo(() => {
const sortedPages = Object.values(pageMap).sort(
(a, b) => a.config.index - b.config.index,
);
return sortedPages;
}, [pageMap]);
const changePage = useCallback(
e => {
const { indexh: slideIdx } = e;
setCurrentPageIndex(slideIdx);
const pageId = sortedPages[slideIdx].id;
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: false,
}),
);
},
[dispatch, sortedPages, storyId],
);
const onPageClick = useCallback(
(index: number, pageId: string, multiple: boolean) => {
if (!multiple) {
revealRef.current.slide(index);
} else {
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: true,
}),
);
}
},
[dispatch, storyId],
);
const { sizes, setSizes } = useSplitSizes({
limitedSide: 0,
range: [150, 768],
});
const siderDragEnd = useCallback(
sizes => {
setSizes(sizes);
dispatchResize();
},
[setSizes],
);
const onDeletePages = useCallback(
(pageIds: string[]) => {
Modal.confirm({
title: pageIds.length > 1 ? t('delPagesTip') : t('delPageTip'),
onOk: () => {
pageIds.forEach(pageId => {
dispatch(deleteStoryPage({ storyId, pageId }));
});
},
});
},
[dispatch, storyId, t],
);
useEffect(() => {
if (sortedPages.length === 0) {
return;
}
if (!sortedPages[currentPageIndex]) {
return;
}
const pageId = sortedPages[currentPageIndex].id;
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: false,
}),
);
}, [dispatch, currentPageIndex, sortedPages, storyId]);
const onCloseEditor = useCallback(() => {
history.push(`/organizations/${orgId}/vizs/${storyId}`);
}, [history, orgId, storyId]);
useEffect(() => {
if (sortedPages.length > 0) {
revealRef.current = new Reveal(document.getElementById(domId), {
hash: false,
history: false,
controls: false,
controlsLayout: 'none',
slideNumber: 'c/t',
controlsTutorial: false,
progress: false,
loop: true,
width: '100%',
height: '100%',
margin: 0,
minScale: 1,
maxScale: 1,
autoSlide: null,
transition: 'convex',
// backgroundTransition: 'fade',
transitionSpeed: 'slow',
viewDistance: 100,
plugins: [RevealZoom],
keyboard: {
70: () => {},
},
});
revealRef.current?.initialize();
if (revealRef.current) {
revealRef.current.addEventListener('slidechanged', changePage);
}
return () => {
revealRef.current.removeEventListener('slidechanged', changePage);
};
}
// "none" | "fade" | "slide" | "convex" | "concave" | "zoom"
}, [domId, changePage, sortedPages.length]);
useEffect(() => {
const curPage = sortedPages[currentPageIndex];
if (!curPage || !curPage.relId || !curPage.relType) {
return;
}
const { relId, relType } = curPage;
dispatch(getPageContentDetail({ relId, relType }));
}, [currentPageIndex, dispatch, sortedPages]);
const addPages = useCallback(async () => {
if (histState && histState.addDashboardId) {
await dispatch(
addStoryPages({ storyId, relIds: [histState.addDashboardId] }),
);
//react router remove location state
if (history.location.state && histState.transaction) {
let state = { ...histState };
delete state.transaction;
history.replace({ ...history.location, state });
}
}
}, [dispatch, histState, storyId, history]);
useEffect(() => {
addPages();
}, [addPages]);
return (
<DndProvider backend={HTML5Backend}>
<StoryContext.Provider
value={{
name: story.name,
storyId: storyId,
editing: false,
orgId: orgId,
status: 1,
allowShare: false,
}}
>
<Wrapper>
<StoryToolBar onCloseEditor={onCloseEditor} />
<Container
sizes={sizes}
minSize={[256, 0]}
maxSize={[768, Infinity]}
gutterSize={0}
onDragEnd={siderDragEnd}
className="datart-split"
>
<PageListWrapper>
<PageThumbnailList
sortedPages={sortedPages}
onPageClick={onPageClick}
onDeletePages={onDeletePages}
/>
</PageListWrapper>
<Content>
<div id={domId} className="reveal">
<div className="slides">
{sortedPages.map((page, index) => (
<StoryPageItem
key={page.id}
page={page}
renderMode="read"
/>
))}
</div>
</div>
</Content>
</Container>
</Wrapper>
</StoryContext.Provider>
</DndProvider>
);
})
Example #25
Source File: StoryPlayerForShare.tsx From datart with Apache License 2.0 | 4 votes |
StoryPlayerForShare: React.FC<{
storyBoard: StoryBoard;
shareToken: string;
}> = memo(({ storyBoard, shareToken }) => {
const { id: storyId } = storyBoard;
const domId = useMemo(() => uuidv4(), []);
const revealRef = useRef<any>();
const dispatch = useDispatch();
const [currentPageIndex, setCurrentPageIndex] = useState(0);
const fullRef: RefObject<HTMLDivElement> = useRef(null);
const pageMap = useSelector((state: { storyBoard: StoryBoardState }) =>
makeSelectStoryPagesById(state, storyId),
);
const subVizTokenMap = useSelector(selectSubVizTokenMap);
const sortedPages = useMemo(() => {
const sortedPages = Object.values(pageMap).sort(
(a, b) => a.config.index - b.config.index,
);
return sortedPages;
}, [pageMap]);
const changePage = useCallback(
e => {
const { indexh: slideIdx } = e;
setCurrentPageIndex(slideIdx);
const pageId = sortedPages[slideIdx].id;
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: false,
}),
);
},
[dispatch, sortedPages, storyId],
);
useEffect(() => {
if (sortedPages.length === 0) {
return;
}
const pageId = sortedPages[0].id;
dispatch(
storyActions.changePageSelected({
storyId,
pageId,
multiple: false,
}),
);
}, [dispatch, sortedPages, storyId]);
const autoSlide = useMemo(() => {
if (storyBoard?.config?.autoPlay?.auto) {
return storyBoard?.config?.autoPlay?.delay * 1000;
}
return null;
}, [storyBoard?.config?.autoPlay?.auto, storyBoard?.config?.autoPlay?.delay]);
useEffect(() => {
if (sortedPages.length > 0) {
revealRef.current = new Reveal(document.getElementById(domId), {
hash: false,
history: false,
controls: true,
controlsLayout: 'none',
slideNumber: 'c/t',
controlsTutorial: false,
progress: false,
loop: true,
width: '100%',
height: '100%',
margin: 0,
minScale: 1,
maxScale: 1,
autoSlide: autoSlide,
transition: 'convex',
// backgroundTransition: 'fade',
transitionSpeed: 'slow',
viewDistance: 100,
plugins: [RevealZoom],
keyboard: {
27: () => {
// disabled esc
}, // do something custom when ESC is pressed
},
});
revealRef.current?.initialize();
if (revealRef.current) {
revealRef.current.addEventListener('slidechanged', changePage);
}
return () => {
revealRef.current.removeEventListener('slidechanged', changePage);
};
}
}, [domId, changePage, sortedPages.length, autoSlide, dispatch]);
useEffect(() => {
const curPage = sortedPages[currentPageIndex];
if (!curPage || !curPage.relId || !curPage.relType) {
return;
}
const { relId, relType, id } = curPage;
const vizToken = subVizTokenMap?.[id];
if (!vizToken) {
return;
}
dispatch(
getPageContentDetail({
shareToken,
relId,
relType,
vizToken: vizToken,
}),
);
}, [
currentPageIndex,
dispatch,
sortedPages,
pageMap,
subVizTokenMap,
shareToken,
]);
return (
<DndProvider backend={HTML5Backend}>
<Wrapper ref={fullRef}>
<Content>
<div id={domId} className="reveal">
<div className="slides">
{sortedPages.map(page => (
<StoryPageItem key={page.id} page={page} />
))}
</div>
</div>
</Content>
</Wrapper>
</DndProvider>
);
})
Example #26
Source File: BoardForShare.tsx From datart with Apache License 2.0 | 4 votes |
BoardForShare: React.FC<ShareBoardProps> = memo(
({
dashboard,
renderMode,
filterSearchUrl,
allowDownload,
loadVizData,
onMakeShareDownloadDataTask,
onLoadShareTask,
onDownloadFile,
}) => {
const dispatch = useDispatch();
const shareBoardInfo = useSelector(selectShareBoardInfo);
const { needFetchItems, hasFetchItems, boardWidthHeight } = shareBoardInfo;
const [allItemFetched, setAllItemFetched] = useState(false);
useEffect(() => {
if (needFetchItems.length === hasFetchItems.length) {
setAllItemFetched(true);
}
}, [hasFetchItems, needFetchItems]);
// for sever Browser
const { taskW, taskH } = useMemo(() => {
const taskWH = {
taskW: boardWidthHeight[0] || 0,
taskH: boardWidthHeight[1] || 0,
};
if (dashboard) {
if (dashboard?.config?.type === 'free') {
const { width, height } = dashboard.config;
const ratio = width / (height || 1) || 1;
const targetHeight = taskWH.taskW / ratio;
taskWH.taskH = targetHeight;
}
}
return taskWH;
}, [boardWidthHeight, dashboard]);
const boardDownLoadAction = useCallback(
(params: { boardId: string }) => async dispatch => {
const { boardId } = params;
const { requestParams, fileName } = await dispatch(
getBoardDownloadParams({ boardId }),
);
onMakeShareDownloadDataTask(requestParams, fileName);
},
[onMakeShareDownloadDataTask],
);
const onShareDownloadData = useCallback(() => {
dispatch(boardDownLoadAction({ boardId: dashboard.id }));
}, [boardDownLoadAction, dashboard.id, dispatch]);
const viewBoard = useMemo(() => {
let boardType = dashboard?.config?.type;
if (!dashboard || !boardType) return null;
return (
<BoardInitProvider
board={dashboard}
editing={false}
autoFit={false}
renderMode={renderMode}
allowDownload={allowDownload}
>
<Wrapper>
<TitleForShare
onShareDownloadData={onShareDownloadData}
loadVizData={loadVizData}
>
<DownloadTaskContainer
onLoadTasks={onLoadShareTask}
onDownloadFile={onDownloadFile}
></DownloadTaskContainer>
</TitleForShare>
{boardType === 'auto' && <AutoBoardCore boardId={dashboard.id} />}
{boardType === 'free' && <FreeBoardCore boardId={dashboard.id} />}
<FullScreenPanel />
</Wrapper>
</BoardInitProvider>
);
}, [
allowDownload,
dashboard,
loadVizData,
onDownloadFile,
onLoadShareTask,
onShareDownloadData,
renderMode,
]);
return (
<DndProvider backend={HTML5Backend}>
{viewBoard}
<HeadlessBrowserIdentifier
renderSign={allItemFetched}
width={Number(taskW)}
height={Number(taskH) + TitleHeight}
/>
</DndProvider>
);
},
)
Example #27
Source File: index.tsx From datart with Apache License 2.0 | 4 votes |
BoardEditor: React.FC<{
boardId: string;
}> = memo(({ boardId }) => {
const dispatch = useDispatch();
const history = useHistory();
const board = useSelector(selectEditBoard);
const boardLoading = useSelector(selectEditBoardLoading);
const boardChartEditorProps = useSelector(selectBoardChartEditorProps);
const onCloseChartEditor = useCallback(() => {
dispatch(editDashBoardInfoActions.changeChartEditorProps(undefined));
}, [dispatch]);
const onSaveToWidget = useCallback(
(chartType: WidgetContentChartType, dataChart: DataChart, view) => {
const widgetId = boardChartEditorProps?.widgetId!;
dispatch(editHasChartWidget({ widgetId, dataChart, view }));
onCloseChartEditor();
dispatch(addVariablesToBoard(view.variables));
},
[boardChartEditorProps?.widgetId, dispatch, onCloseChartEditor],
);
const boardEditor = useMemo(() => {
if (!board.id) return null;
if (board?.id !== boardId) {
return null;
}
const boardType = board.config?.type;
return (
<BoardInitProvider
board={board}
editing={true}
autoFit={false}
allowDownload={false}
allowShare={false}
allowManage={false}
renderMode="edit"
>
<EditorHeader />
{boardType === 'auto' && <AutoEditor />}
{boardType === 'free' && <FreeEditor />}
<ControllerWidgetPanel />
<LinkagePanel />
<SettingJumpModal />
{boardChartEditorProps && (
<ChartEditor
{...boardChartEditorProps}
onClose={onCloseChartEditor}
onSaveInWidget={onSaveToWidget}
/>
)}
</BoardInitProvider>
);
}, [
boardChartEditorProps,
board,
boardId,
onCloseChartEditor,
onSaveToWidget,
]);
const initialization = useCallback(async () => {
await dispatch(fetchEditBoardDetail(boardId));
const histState = history.location.state as any;
try {
if (histState?.widgetInfo) {
const widgetInfo = JSON.parse(histState.widgetInfo);
if (widgetInfo) {
let subType: 'widgetChart' | 'dataChart' = 'dataChart';
if (!widgetInfo.dataChart.id) {
widgetInfo.dataChart.id = 'widget_' + uuidv4();
subType = 'widgetChart';
}
dispatch(
addChartWidget({
boardId,
chartId: widgetInfo.dataChart.id,
boardType: widgetInfo.dashboardType,
dataChart: widgetInfo.dataChart,
view: widgetInfo.dataview,
subType: subType,
}),
);
}
}
} catch (error) {
console.log(error);
}
}, [dispatch, history.location.state, boardId]);
useEffect(() => {
initialization();
return () => {
// fix issue: #800
onCloseChartEditor();
dispatch(clearEditBoardState());
//销毁时 更新view界面数据
dispatch(fetchBoardDetail({ dashboardRelId: boardId }));
//
boardDrillManager.clearMapByBoardId(EDIT_PREFIX + boardId);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [onCloseChartEditor]);
return (
<Wrapper>
<DndProvider backend={HTML5Backend}>
{boardEditor}
{boardLoading && <BoardLoading />}
</DndProvider>
</Wrapper>
);
})
Example #28
Source File: index.tsx From firetable with Apache License 2.0 | 4 votes |
export default function Table() {
const classes = useStyles();
const {
tableState,
tableActions,
dataGridRef,
sideDrawerRef,
updateCell,
} = useFiretableContext();
const { userDoc } = useAppContext();
const userDocHiddenFields =
userDoc.state.doc?.tables?.[formatSubTableName(tableState?.tablePath)]
?.hiddenFields ?? [];
const [columns, setColumns] = useState<FiretableColumn[]>([]);
useEffect(() => {
if (!tableState?.loadingColumns && tableState?.columns) {
const _columns = _orderBy(
Object.values(tableState?.columns).filter(
(column: any) => !column.hidden && column.key
),
"index"
)
.map((column: any) => ({
draggable: true,
editable: true,
resizable: true,
frozen: column.fixed,
headerRenderer: ColumnHeader,
formatter:
getFieldProp(
"TableCell",
column.config?.renderFieldType ?? column.type
) ??
function InDev() {
return null;
},
editor:
getFieldProp(
"TableEditor",
column.config?.renderFieldType ?? column.type
) ??
function InDev() {
return null;
},
...column,
width: column.width ? (column.width > 380 ? 380 : column.width) : 150,
}))
.filter((column) => !userDocHiddenFields.includes(column.key));
setColumns([
// TODO: ENABLE ONCE BULK ACTIONS READY
// SelectColumn,
..._columns,
{
isNew: true,
key: "new",
name: "Add column",
type: FieldType.last,
index: _columns.length ?? 0,
width: 204,
headerRenderer: FinalColumnHeader,
headerCellClass: "final-column-header",
cellClass: "final-column-cell",
formatter: FinalColumn,
editable: false,
},
]);
}
}, [
tableState?.loadingColumns,
tableState?.columns,
JSON.stringify(userDocHiddenFields),
]);
const rows =
useMemo(
() =>
tableState?.rows.map((row) =>
columns.reduce(
(acc, currColumn) => {
if ((currColumn.key as string).includes(".")) {
return {
...acc,
[currColumn.key]: _get(row, currColumn.key),
};
} else return acc;
},
{ ...row, id: row.id as string, ref: row.ref }
)
),
[columns, tableState?.rows]
) ?? [];
const rowsContainerRef = useRef<HTMLDivElement>(null);
const [selectedRowsSet, setSelectedRowsSet] = useState<Set<React.Key>>();
const [selectedRows, setSelectedRows] = useState<any[]>([]);
// Gets more rows when scrolled down.
// https://github.com/adazzle/react-data-grid/blob/ead05032da79d7e2b86e37cdb9af27f2a4d80b90/stories/demos/AllFeatures.tsx#L60
const handleScroll = (event: React.UIEvent<HTMLDivElement>) => {
const target = event.target as HTMLDivElement;
const offset = 800;
const isAtBottom =
target.clientHeight + target.scrollTop >= target.scrollHeight - offset;
if (!isAtBottom) return;
// Prevent calling more rows when they’ve already been called
if (tableState!.loadingRows) return;
// Call for 30 more rows. Note we don’t know here if there are no more
// rows left in the database. This is done in the useTable hook.
tableActions?.row.more(30);
};
const windowSize = useWindowSize();
if (!windowSize || !windowSize.height) return <></>;
if (!tableActions || !tableState) return <></>;
const rowHeight = tableState.config.rowHeight;
return (
<>
{/* <Suspense fallback={<Loading message="Loading header" />}>
<Hotkeys selectedCell={selectedCell} />
</Suspense> */}
<div className={classes.tableWrapper} ref={rowsContainerRef}>
<TableHeader
rowHeight={rowHeight}
updateConfig={tableActions.table.updateConfig}
/>
{!tableState.loadingColumns ? (
<DndProvider backend={HTML5Backend}>
<DataGrid
onColumnResize={tableActions.column.resize}
onScroll={handleScroll}
ref={dataGridRef}
rows={rows}
columns={columns}
rowHeight={rowHeight ?? 43}
headerRowHeight={44}
className="rdg-light" // Handle dark mode in MUI theme
cellNavigationMode="LOOP_OVER_ROW"
rowKeyGetter={rowKeyGetter}
selectedRows={selectedRowsSet}
onSelectedRowsChange={(newSelectedSet) => {
const newSelectedArray = newSelectedSet
? [...newSelectedSet]
: [];
const prevSelectedRowsArray = selectedRowsSet
? [...selectedRowsSet]
: [];
const addedSelections = _difference(
newSelectedArray,
prevSelectedRowsArray
);
const removedSelections = _difference(
prevSelectedRowsArray,
newSelectedArray
);
addedSelections.forEach((id) => {
const newRow = _find(rows, { id });
setSelectedRows([...selectedRows, newRow]);
});
removedSelections.forEach((rowId) => {
setSelectedRows(
selectedRows.filter((row) => row.id !== rowId)
);
});
setSelectedRowsSet(newSelectedSet);
}}
onRowsChange={(rows) => {
//console.log('onRowsChange',rows)
}}
onFill={(e) => {
console.log("onFill", e);
const { columnKey, sourceRow, targetRows } = e;
if (updateCell)
targetRows.forEach((row) =>
updateCell(row.ref, columnKey, sourceRow[columnKey])
);
return [];
}}
onPaste={(e) => {
const copiedValue = e.sourceRow[e.sourceColumnKey];
if (updateCell) {
updateCell(e.targetRow.ref, e.targetColumnKey, copiedValue);
}
}}
onRowClick={(rowIdx, column) => {
if (sideDrawerRef?.current) {
sideDrawerRef.current.setCell({
row: rowIdx,
column: column.key as string,
});
}
}}
/>
</DndProvider>
) : (
<Loading message="Fetching columns" />
)}
</div>
<ColumnMenu />
<BulkActions
selectedRows={selectedRows}
columns={columns}
clearSelection={() => {
setSelectedRowsSet(new Set());
setSelectedRows([]);
}}
/>
</>
);
}
Example #29
Source File: index.tsx From datart with Apache License 2.0 | 4 votes |
Board: FC<BoardProps> = memo(
({
id,
hideTitle,
fetchData = true,
renderMode,
filterSearchUrl,
allowDownload,
allowShare,
allowManage,
autoFit,
showZoomCtrl,
}) => {
const boardId = id;
const dispatch = useDispatch();
const editingBoard = useSelector(selectEditBoard);
const readBoardHide = useMemo(
() => editingBoard?.id === boardId,
[boardId, editingBoard.id],
);
const { ref, width, height } = useResizeObserver<HTMLDivElement>({
refreshMode: 'debounce',
refreshRate: 2000,
});
const dashboard = useSelector((state: { board: BoardState }) =>
makeSelectBoardConfigById()(state, boardId),
);
const searchParams = useMemo(() => {
return filterSearchUrl
? urlSearchTransfer.toParams(filterSearchUrl)
: undefined;
}, [filterSearchUrl]);
const viewBoard = useMemo(() => {
let boardType = dashboard?.config?.type;
if (dashboard && boardType) {
return (
<div className="board-provider">
<BoardInitProvider
board={dashboard}
editing={false}
autoFit={autoFit}
renderMode={renderMode}
allowDownload={allowDownload}
allowShare={allowShare}
allowManage={allowManage}
>
{!hideTitle && <TitleHeader />}
{boardType === 'auto' && <AutoBoardCore boardId={dashboard.id} />}
{boardType === 'free' && (
<FreeBoardCore
boardId={dashboard.id}
showZoomCtrl={showZoomCtrl}
/>
)}
<FullScreenPanel />
</BoardInitProvider>
</div>
);
} else {
return <BoardLoading />;
}
}, [
dashboard,
autoFit,
renderMode,
allowDownload,
allowShare,
allowManage,
hideTitle,
showZoomCtrl,
]);
useEffect(() => {
if (width! > 0 && height! > 0 && dashboard?.id && !readBoardHide) {
dispatch(
boardActions.changeBoardVisible({ id: dashboard?.id, visible: true }),
);
} else {
dispatch(
boardActions.changeBoardVisible({
id: dashboard?.id as string,
visible: false,
}),
);
}
}, [readBoardHide, dashboard?.id, dispatch, height, width]);
useEffect(() => {
if (boardId && fetchData) {
dispatch(
fetchBoardDetail({
dashboardRelId: boardId,
filterSearchParams: searchParams,
}),
);
}
// 销毁组件 清除该对象缓存
return () => {
dispatch(boardActions.clearBoardStateById(boardId));
boardDrillManager.clearMapByBoardId(boardId);
};
}, [boardId, dispatch, fetchData, searchParams]);
return (
<Wrapper ref={ref} className="dashboard-box">
<DndProvider backend={HTML5Backend}>{viewBoard}</DndProvider>
</Wrapper>
);
},
)