Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

code #147

Open
dlrandy opened this issue Oct 18, 2020 · 1 comment
Open

code #147

dlrandy opened this issue Oct 18, 2020 · 1 comment

Comments

@dlrandy
Copy link
Owner

dlrandy commented Oct 18, 2020

`
import React, { useReducer, useState } from "react";
import ReactDOM, { findDOMNode } from "react-dom";
import ReactDataGrid from "react-data-grid";
import { range } from "lodash";
import { Icon } from 'antd'
// import { Menu } from "react-data-grid-addons";

import createRowData, { createFakeRow } from "./createRowData";

// import "./styles.css";

class RecordsTable extends React.Component {
constructor(props) {
super(props);
this.canvas = null;
this.copyRef = React.createRef();
this.scrollListener = () => {
if (
this.canvas.scrollHeight === this.canvas.scrollTop + this.canvas.clientHeight
) {
this.props.loadNextPage();
}
};
}

canvas = null;
state = {
copyData: {}
};

componentDidMount() {
this.canvas = findDOMNode(this).querySelector(".react-grid-Canvas");
this.canvas.addEventListener("scroll", this.scrollListener);
// document.addEventListener("copy", this.handleCopy);
}

componentWillUnmount() {
if (this.canvas) {
this.canvas.removeEventListener("scroll", this.scrollListener);
}
document.removeEventListener("copy", this.handleCopy);
}

parseCopyData = (copyData) => {
console.log(copyData, "-------");
const { topLeft, bottomRight } = copyData;
if (!topLeft || !bottomRight) {
return;
}
// Loop through each row
const text = range(topLeft.rowIdx, bottomRight.rowIdx + 1)
.map(
// Loop through each column 这里有和没有选择框索引是不一样的
(rowIdx) =>
columns
.slice(topLeft.idx - 1, bottomRight.idx)
.map(
// Grab the row values and make a text string
(col) => this.rowGetter(rowIdx)[col.key]
)
.join("\t")
)
.join("\n");
return text;
};

executeCopy = (copyData) => {
const text = this.parseCopyData(copyData);
console.log(text);
this.copyRef.current.value = text;
this.copyRef.current.select();
document.execCommand("copy");
};

handleCopy = (e) => {
console.debug("handleCopy Called");
e.preventDefault();
const text = this.parseCopyData(this.state.copyData);
console.debug("text", text);
e.clipboardData.setData("text/plain", text);
};

rowGetter = (i) => this.props.records[i];

render() {
return (


<textarea ref={this.copyRef} style={{ width: 0, height: 0, opacity:0 }} />
<ReactDataGrid
ref={"grid"}
minHeight={this.props.minHeight}
rowHeight={30}
headerRowHeight={40}
enableCellSelect={true}
cellRangeSelection={{
// onStart: (args) => console.log('start',args),
// onUpdate: (args) => console.log('update',args),
onComplete: (args) => {
console.log("complete", args);
this.setState((state) => ({
copyData: args
}));
this.executeCopy(args);
}
}}
columns={this.props.columns}
rowGetter={this.rowGetter}
rowsCount={this.props.records.length}
rowSelection={{
showCheckbox: true,
enableShiftSelect: true,
onRowsSelected: (rows) => {
const ids = rows.map(({ row }) => row.id);
const records = this.props.records.filter(
(r) => ids.indexOf(r.id) > -1
);
this.props.selectRecords(records);
},
onRowsDeselected: (rows) => {
const ids = rows.map(({ row }) => row.id);
const records = this.props.records.filter(
(r) => ids.indexOf(r.id) > -1
);
this.props.deselectRecords(records);
},
selectBy: {
// indexes: this.props.selectedRecords.map((r) =>
// this.props.records.indexOf(r)
// )
}
}}
getCellActions={this.props.getCellActions}
/>

);
}
}

const defaultColumnProperties = {
// sortable: true,
width: 120,
resizable: true
};

const columns = [
{
key: "id",
name: "ID",
sortDescendingFirst: true
},
{
key: "title",
name: "Title"
},
{
key: "firstName",
name: "First Name"
},
{
key: "lastName",
name: "Last Name"
},
{
key: "email",
name: "Email"
},
{
key: "street",
name: "Street"
},
{
key: "zipCode",
name: "ZipCode"
},
{
key: "date",
name: "Date"
},
{
key: "jobTitle",
name: "Job Title"
},
{
key: "catchPhrase",
name: "Catch Phrase"
},
{
key: "jobArea",
name: "Job Area"
},
{
key: "jobType",
name: "Job Type"
}
].map((c) => ({ ...c, ...defaultColumnProperties }));

const ROW_COUNT = 50;
let pages = 1;
const firstNameActions = [
{
icon:,
callback: () => {
alert("Deleting");
}
},
{
icon: ,
actions: [
{
text: "Option 1",
callback: () => {
alert("Option 1 clicked");
}
},
{
text: "Option 2",
callback: () => {
alert("Option 2 clicked");
}
}
]
}
];
export default function Example({ rows = createRowData(50 * pages), loadNextPage=() => createRowData(50 * ++pages) }) {
const [state, dispatch] = React.useReducer(
(state, action) => state.concat(action),
rows
);
function getCellActions(column, row) {
const cellActions = {
jobType: firstNameActions
};
return cellActions[column.key];
}
return (


<RecordsTable
columns={columns}
rowGetter={(i) => rows[i]}
rowsCount={ROW_COUNT}
minHeight={500}
records={state}
loadNextPage={() => dispatch(loadNextPage())}
cellRangeSelection={{
onStart: (args) => console.log(rows),
onUpdate: (args) => console.log(rows),
onComplete: (args) => console.log(rows)
}}
getCellActions={getCellActions}
/>

);
}

`

@dlrandy
Copy link
Owner Author

dlrandy commented Oct 26, 2020

import React from 'react';
import { findDOMNode } from 'react-dom';
import ReactDataGrid from 'react-data-grid-6-revision';
import { range, debounce } from 'lodash';
import { Spin } from 'antd';

import Toolbar from './components/Toolbar';
import { formatDate, PRIORITY_MAP } from './../TableUtils/helpers';
function formatCellCopyData(cellData, key) {
if (key.toLowerCase().indexOf('date') >= 0) {
return formatDate(cellData[key]);
} else if (key == 'isLock') {
return cellData[key] == 1 ? '是' : '否';
} else if (key == 'priority') {
return PRIORITY_MAP[cellData[key]];
}
return cellData[key];
}
export default class RecordsTable extends React.Component {
constructor(props) {
super(props);
this.canvas = null;
this.copyRef = React.createRef();
this.scrollListener = debounce(() => {
if (this.canvas.scrollHeight === this.canvas.scrollTop + this.canvas.clientHeight) {
this.props.loadNextPage();
}
}, 200);
this.state = {};
}

componentDidMount() {
    this.canvas = findDOMNode(this).querySelector('.react-grid-Canvas');
    this.canvas.addEventListener('scroll', this.scrollListener);
    document.addEventListener('copy', this.handleCopy);
}

componentWillUnmount() {
    if (this.canvas) {
        this.canvas.removeEventListener('scroll', this.scrollListener);
    }
    document.removeEventListener('copy', this.handleCopy);
}
handleCopy = e => {
    console.debug('handleCopy Called');
    e.preventDefault();
    const text = this.parseCopyData(this.state.copyData);
    console.debug('text', text);
    e.clipboardData.setData('text/plain', text);
};

parseCopyData = copyData => {
    const { topLeft, bottomRight } = copyData;
    if (!topLeft || !bottomRight) {
        return;
    }
    console.log(topLeft, bottomRight, '00000999999999');
    const copyDataKeyTransformer = this.props.copyDataKeyTransformer || (key => key);
    const text = range(topLeft.rowIdx, bottomRight.rowIdx + 1)
        .map(rowIdx =>
            this.props.columns
                .slice(topLeft.idx, bottomRight.idx + 1)
                .map(col =>
                    this.rowGetter(rowIdx)
                        ? formatCellCopyData(
                              this.rowGetter(rowIdx),
                              copyDataKeyTransformer(col.key)
                          )
                        : ''
                )
                .join('\t')
        )
        .join('\n');
    return text;
};

executeCopy = copyData => {
    const text = this.parseCopyData(copyData);
    this.copyRef.current.value = text;
    this.copyRef.current.select();
    document.execCommand('copy');
};
onGridRowsUpdated = ({ fromRow, toRow, updated }) => {
    this.setState(state => {
        const rows = state.rows.slice();
        for (let i = fromRow; i <= toRow; i++) {
            rows[i] = { ...rows[i], ...updated };
        }
        return { rows };
    });
};
rowGetter = i => this.props.records[i];
rowRenderer = ({ renderBaseRow, ...props }) => {
    const { validateFn = () => void 0 } = this.props;
    return <div style={validateFn(props)}>{renderBaseRow(props)}</div>;
};
render() {
    return (
        <div>
            <textarea ref={this.copyRef} style={{ width: 0, height: 0, opacity: 0 }} />
            <Spin tip="加载中..." spinning={this.props.loading}>
                {this.props.showToolBar && <Toolbar onAddRow={this.props.addLine} />}
                <ReactDataGrid
                    ref={'grid'}
                    minHeight={this.props.minHeight}
                    rowHeight={this.props.rowHeight || 30}
                    enableCellSelect={true}
                    headerRowHeight={this.props.headerRowHeight || 40}
                    rowRenderer={this.rowRenderer}
                    cellRangeSelection={
                        this.props.enableCellRangeSelection
                            ? {
                                  onComplete: args => {
                                      //   this.executeCopy(args);
                                      this.setState(state => ({
                                          copyData: args
                                      }));
                                  }
                              }
                            : undefined
                    }
                    onGridRowsUpdated={this.props.onGridRowsUpdated}
                    columns={this.props.columns}
                    rowGetter={this.props.rowGetter || this.rowGetter}
                    rowsCount={this.props.records.length}
                    rowSelection={
                        this.props.enableRowSelection
                            ? {
                                  showCheckbox: true,
                                  enableShiftSelect: true,
                                  onRowsSelected: rows => {
                                      const ids = rows.map(({ row }) => row.id);
                                      const records = this.props.records.filter(
                                          r => ids.indexOf(r.id) > -1
                                      );
                                      this.props.selectRecords(records);
                                  },
                                  onRowsDeselected: rows => {
                                      const ids = rows.map(({ row }) => row.id);
                                      const records = this.props.records.filter(
                                          r => ids.indexOf(r.id) > -1
                                      );
                                      this.props.deselectRecords(records);
                                  },
                                  selectBy: {
                                      // indexes: this.props.selectedRecords.map((r) =>
                                      //   this.props.records.indexOf(r)
                                      // )
                                  }
                              }
                            : undefined
                    }
                    getCellActions={this.props.getCellActions}
                />{' '}
            </Spin>
        </div>
    );
}

}
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { debounce } from 'lodash';
import { useAbortableEffect } from '../../../common/Hooks';
import { useGetApi, getApi } from '../../../common/Api';

import { Select } from 'antd';
const Option = Select.Option;
export class SelectEditor extends React.Component {
constructor(props) {
super(props);
const data =
typeof props.column.data === 'function'
? props.column.data(props.rowData)
: props.column.data || [];
this.state = {
value: props.value,
relateData: {},
options: data.map(option => ({ ...option, text: option.text || option.label }))
};
const { onChange, url, placeholder = '请选择' } = this.props.column;
this.onChange = onChange;
this.url = url;
this.placeholder = placeholder;
this.status = { aborted: false };
this.searchVal = '';
}

getValue = async () => {
    return {
        ...this.state.relateData,
        [this.props.column.key]: this.state.value
    };
};

getInputNode = () => {
    return ReactDOM.findDOMNode(this).querySelector('.ant-select-selection-selected-value');
};
disableContainerStyles = () => {
    return true;
};
handleChangeComplete = async (value, option) => {
    const data = this.props.column.onChange
        ? await this.props.column.onChange(
              option.props,
              this.props.rowData,
              this.state.options.find(op => op.value === value)
          )
        : {};
    this.setState({ value, relateData: data }, () => {
        this.props.onCommit();
    });
};

async componentDidMount() {}
componentWillUnmount() {
    this.status.aborted = true;
}

searchData = debounce(_value => {
    this.searchVal = _value;
    this.getOptions();
}, 500);

getOptions = async () => {
    if (!this.url) {
        return;
    }
    const url = typeof this.url === 'function' ? this.url(this.props.rowData) : this.url;
    const data = await getApi(url, { key: this.searchVal });
    this.setState({
        options: data.map(m => {
            return {
                ...m,
                value: m.fvalue || m.value,
                label: m.text || m.ftext || m.fvalue,
                text: m.text || m.ftext || m.fvalue
            };
        })
    });
};

render() {
    return (
        <Select
            autoFocus
            style={{ width: '100%' }}
            defaultValue={this.state.value && String(this.state.value)}
            onChange={this.handleChangeComplete}
            onFocus={() => this.getOptions()}
            filterOption={false}
            onSearch={
                this.props.column.showSearch //&& onSearch
                    ? this.searchData
                    : undefined
            }
            showSearch
        >
            {this.state.options.map(option => (
                <Option value={option.value} key={option.value}>
                    {option.text}
                </Option>
            ))}
        </Select>
    );
}

}
import React, { useRef, useLayoutEffect } from 'react';
import ReactDOM from 'react-dom';

import { debounce } from 'lodash';
import { Input, InputNumber, DatePicker } from 'antd';

const InputArea = Input.TextArea;

export class TextEditor extends React.Component {
constructor(props) {
super(props);
this.state = { value: props.value };
}

getValue = () => {
    return { [this.props.column.key]: this.state.value };
};

getInputNode() {
    return ReactDOM.findDOMNode(this).getElementsByTagName('input')[0];
}
disableContainerStyles = () => {
    return true;
};
handleChangeComplete = e => {
    this.setState({ value: e });
};
// handleChangeComplete = debounce(e => {
//     this.setState({ value: e }, () => this.props.onCommit());
// }, 2000);
render() {
    return (
        <Input
            autoFocus
            onPressEnter={() => this.props.onCommit()}
            defaultValue={this.state.value}
            onChange={e => this.handleChangeComplete(e.target.value)}
        />
    );
}

}

export class TextNumEditor extends React.Component {
constructor(props) {
super(props);
this.state = { value: props.value, relateData: {} };
}

getValue = () => {
    return { [this.props.column.key]: this.state.value, ...this.state.relateData };
};

getInputNode = () => {
    return ReactDOM.findDOMNode(this).getElementsByTagName('input')[0];
};
disableContainerStyles = () => {
    return true;
};
// handleChangeComplete = debounce(async e => {
//     const data = this.props.column.onChange
//         ? await this.props.column.onChange(e, this.props.rowData)
//         : {};
//     this.setState({ value: e, relateData: data }, () => this.props.onCommit());
// }, 2000);
handleChangeComplete = async e => {
    const data = this.props.column.onChange
        ? await this.props.column.onChange(e, this.props.rowData)
        : {};
    this.setState({ value: e, relateData: data });
};
render() {
    return (
        <InputNumber
            autoFocus
            onPressEnter={() => this.props.onCommit()}
            style={{ width: '80%', paddingLeft: 6, fontSize: 14 }}
            defaultValue={this.state.value}
            onChange={val => this.handleChangeComplete(val)}
        />
    );
}

}

const dateFormat = 'YYYY-MM-DD HH:mm:ss';
export class TextDateEditor extends React.Component {
constructor(props) {
super(props);
this.state = { value: props.value };
}

getValue = () => {
    return { [this.props.column.key]: this.state.value };
};

getInputNode() {
    return ReactDOM.findDOMNode(this).getElementsByTagName('input')[0];
}
disableContainerStyles = () => {
    return true;
};
handleChangeComplete = (value, dateString) => {
    this.setState({ value: dateString }, () => this.props.onCommit());
};
render() {
    return (
        <DatePicker
            placeholder="选择时间"
            format={dateFormat}
            onChange={this.handleChangeComplete}
        />
    );
}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant