增加行拖拽交换顺序,表头拖拽事件多次绑定优化 等问题
This commit is contained in:
parent
7c5c52b985
commit
0eaee06a5d
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @title 拖拽改变行顺序
|
||||||
|
* @parent 拖拽改变行顺序
|
||||||
|
* @description 拖拽改变行顺序
|
||||||
|
* Demo1201
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import {Button,Tooltip} from "tinper-bee";
|
||||||
|
import Table from "../../src";
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: "员工编号", dataIndex: "a", key: "a", width: 120, className: "rowClassName",
|
||||||
|
fixed:'left',
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Tooltip inverse overlay={text}>
|
||||||
|
<span tootip={text} style={{
|
||||||
|
display: "inline-block",
|
||||||
|
width: "80px",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
overflow: "hidden",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
verticalAlign: "middle",
|
||||||
|
}}>{text}</span>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ title: "员工姓名", dataIndex: "b", key: "b", width:200 },
|
||||||
|
{ title: "性别", dataIndex: "c", key: "c", width: 500 },
|
||||||
|
{ title: "部门", dataIndex: "d", key: "d", width: 100 },
|
||||||
|
{ title: "职级", dataIndex: "e", key: "e", width: 100,fixed:'right'}
|
||||||
|
];
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ a: "ASVAL_201903280005", b: "小张", c: "男", d: "财务二科", e: "M1", key: "1001" },
|
||||||
|
{ a: "ASVAL_201903200004", b: "小明", c: "男", d: "财务一科", e: "T1", key: "1002" },
|
||||||
|
{ a: "ASVAL_201903120002", b: "小红", c: "女", d: "财务一科", e: "T2", key: "1003" }
|
||||||
|
];
|
||||||
|
|
||||||
|
class Demo1201 extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleClick = () => {
|
||||||
|
console.log('这是第' , this.currentIndex , '行');
|
||||||
|
console.log('内容:' , this.currentRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
data={data}
|
||||||
|
rowDraggAble={true}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Demo1201;
|
|
@ -70,6 +70,8 @@ import 'bee-table/build/Table.css';
|
||||||
| height | 自定义表格行高 | number | - |
|
| height | 自定义表格行高 | number | - |
|
||||||
| headerHeight | 自定义表头行高 | number | - |
|
| headerHeight | 自定义表头行高 | number | - |
|
||||||
| size | 表格大小 | `sm | md | lg` | 'md' |
|
| size | 表格大小 | `sm | md | lg` | 'md' |
|
||||||
|
| rowDraggAble | 是否增加行交换顺序功能 | boolean| false
|
||||||
|
|
||||||
|
|
||||||
> 快捷键部分参考示例 (快捷键在table中的简单使用应用)
|
> 快捷键部分参考示例 (快捷键在table中的简单使用应用)
|
||||||
|
|
||||||
|
|
22
src/Table.js
22
src/Table.js
|
@ -54,6 +54,7 @@ const propTypes = {
|
||||||
tabIndex:PropTypes.string,
|
tabIndex:PropTypes.string,
|
||||||
hoverContent:PropTypes.func,
|
hoverContent:PropTypes.func,
|
||||||
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
||||||
|
rowDraggAble: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
|
@ -88,7 +89,8 @@ const defaultProps = {
|
||||||
setRowParentIndex:()=>{},
|
setRowParentIndex:()=>{},
|
||||||
tabIndex:'0',
|
tabIndex:'0',
|
||||||
heightConsistent:false,
|
heightConsistent:false,
|
||||||
size: 'md'
|
size: 'md',
|
||||||
|
rowDraggAble:false
|
||||||
};
|
};
|
||||||
|
|
||||||
class Table extends Component {
|
class Table extends Component {
|
||||||
|
@ -523,9 +525,24 @@ class Table extends Component {
|
||||||
expandable={false}
|
expandable={false}
|
||||||
store={this.store}
|
store={this.store}
|
||||||
dragborderKey={this.props.dragborderKey}
|
dragborderKey={this.props.dragborderKey}
|
||||||
|
rowDraggAble={props.rowDraggAble}
|
||||||
|
onDragRow={this.onDragRow}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDragRow = (currentIndex,targetIndex)=>{
|
||||||
|
let {data} = this.state,
|
||||||
|
currentObj = data[currentIndex],
|
||||||
|
targetObj = data[targetIndex];
|
||||||
|
console.log(currentIndex+" ----------onRowDragEnd-------- "+targetIndex);
|
||||||
|
data.splice(targetIndex, 0, data.splice(currentIndex, 1).shift());
|
||||||
|
console.log(" _data---- ",data);
|
||||||
|
this.setState({
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -660,6 +677,9 @@ class Table extends Component {
|
||||||
rootIndex = {rootIndex}
|
rootIndex = {rootIndex}
|
||||||
syncHover = {props.syncHover}
|
syncHover = {props.syncHover}
|
||||||
bodyDisplayInRow = {props.bodyDisplayInRow}
|
bodyDisplayInRow = {props.bodyDisplayInRow}
|
||||||
|
rowDraggAble={props.rowDraggAble}
|
||||||
|
onDragRow={this.onDragRow}
|
||||||
|
contentTable={this.contentTable}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
this.treeRowIndex++;
|
this.treeRowIndex++;
|
||||||
|
|
|
@ -30,6 +30,7 @@ class TableHeader extends Component {
|
||||||
this.minWidth = 80;//确定最小宽度就是80
|
this.minWidth = 80;//确定最小宽度就是80
|
||||||
this.table = null;
|
this.table = null;
|
||||||
this._thead = null;//当前对象
|
this._thead = null;//当前对象
|
||||||
|
this.event = false;//避免多次绑定问题
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -103,12 +104,20 @@ class TableHeader extends Component {
|
||||||
* 事件初始化
|
* 事件初始化
|
||||||
*/
|
*/
|
||||||
initEvent(){
|
initEvent(){
|
||||||
this.dragBorderEventInit();//列宽
|
let {dragborder,draggable} = this.props;
|
||||||
this.dragAbleEventInit();//交换列
|
if(!this.event){ //避免多次绑定问题。
|
||||||
if(this.table && this.table.tr){
|
this.event = true;
|
||||||
this.eventListen([{key:'mousedown',fun:this.onTrMouseDown}],'',this.table.tr[0]);//body mouseup
|
if(dragborder){
|
||||||
|
this.dragBorderEventInit();//列宽
|
||||||
|
}
|
||||||
|
if(dragborder){
|
||||||
|
this.dragAbleEventInit();//交换列
|
||||||
|
}
|
||||||
|
if(this.table && this.table.tr){
|
||||||
|
this.eventListen([{key:'mousedown',fun:this.onTrMouseDown}],'',this.table.tr[0]);//body mouseup
|
||||||
|
}
|
||||||
|
this.eventListen([{key:'mouseup',fun:this.bodyonLineMouseUp}],'',document.body);//body mouseup
|
||||||
}
|
}
|
||||||
this.eventListen([{key:'mouseup',fun:this.bodyonLineMouseUp}],'',document.body);//body mouseup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -398,6 +407,7 @@ class TableHeader extends Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
onDragOver = (e) => {
|
onDragOver = (e) => {
|
||||||
|
let event = Event.getEvent(e);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
170
src/TableRow.js
170
src/TableRow.js
|
@ -1,5 +1,6 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { Event,EventUtil} from "./utils";
|
||||||
import TableCell from './TableCell';
|
import TableCell from './TableCell';
|
||||||
import ExpandIcon from './ExpandIcon';
|
import ExpandIcon from './ExpandIcon';
|
||||||
|
|
||||||
|
@ -29,6 +30,8 @@ const propTypes = {
|
||||||
expandIconAsCell: PropTypes.bool,
|
expandIconAsCell: PropTypes.bool,
|
||||||
expandRowByClick: PropTypes.bool,
|
expandRowByClick: PropTypes.bool,
|
||||||
store: PropTypes.object.isRequired,
|
store: PropTypes.object.isRequired,
|
||||||
|
rowDraggAble: PropTypes.bool,
|
||||||
|
onDragRow: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
|
@ -39,7 +42,9 @@ const defaultProps = {
|
||||||
expandRowByClick: false,
|
expandRowByClick: false,
|
||||||
onHover() {},
|
onHover() {},
|
||||||
className:'',
|
className:'',
|
||||||
setRowParentIndex:()=>{}
|
setRowParentIndex:()=>{},
|
||||||
|
rowDraggAble:false,
|
||||||
|
// onDragRow:()=>{}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TableRow extends Component{
|
class TableRow extends Component{
|
||||||
|
@ -54,11 +59,12 @@ class TableRow extends Component{
|
||||||
this.onMouseEnter = this.onMouseEnter.bind(this);
|
this.onMouseEnter = this.onMouseEnter.bind(this);
|
||||||
this.onMouseLeave = this.onMouseLeave.bind(this);
|
this.onMouseLeave = this.onMouseLeave.bind(this);
|
||||||
this.expandHeight = 0;
|
this.expandHeight = 0;
|
||||||
|
this.event = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { store, hoverKey,treeType } = this.props;
|
const { store, hoverKey,treeType,rowDraggAble } = this.props;
|
||||||
this.unsubscribe = store.subscribe(() => {
|
this.unsubscribe = store.subscribe(() => {
|
||||||
if (store.getState().currentHoverKey === hoverKey) {
|
if (store.getState().currentHoverKey === hoverKey) {
|
||||||
this.setState({ hovered: true });
|
this.setState({ hovered: true });
|
||||||
|
@ -71,23 +77,174 @@ class TableRow extends Component{
|
||||||
if(treeType){
|
if(treeType){
|
||||||
this.setRowParentIndex();
|
this.setRowParentIndex();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件初始化
|
||||||
|
*/
|
||||||
|
initEvent=()=>{
|
||||||
|
let events = [
|
||||||
|
{key:'dragstart',fun:this.onDragStart},//用户开始拖动元素时触发
|
||||||
|
{key:'dragover', fun:this.onDragOver},//当某被拖动的对象在另一对象容器范围内拖动时触发此事件
|
||||||
|
{key:'drop', fun:this.onDrop}, //在一个拖动过程中,释放鼠标键时触发此事件
|
||||||
|
|
||||||
|
{key:'dragenter', fun:this.onDragEnter},
|
||||||
|
{key:'dragleave', fun:this.onDragLeave},
|
||||||
|
];
|
||||||
|
this.eventListen(events,'',this.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件移除,提供性能以及内存泄漏等问题。
|
||||||
|
*/
|
||||||
|
removeDragAbleEvent=()=>{
|
||||||
|
let events = [
|
||||||
|
{key:'dragstart',fun:this.onDragStart},
|
||||||
|
{key:'dragover', fun:this.onDragOver},
|
||||||
|
{key:'drop', fun:this.onDrop},
|
||||||
|
|
||||||
|
{key:'dragenter', fun:this.onDragEnter},
|
||||||
|
{key:'dragleave', fun:this.onDragLeave},
|
||||||
|
];
|
||||||
|
this.eventListen(events,'remove',this.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件绑定和移除函数
|
||||||
|
*/
|
||||||
|
eventListen(events,type,eventSource){
|
||||||
|
for (let i = 0; i < events.length; i++) {
|
||||||
|
const _event = events[i];
|
||||||
|
if(type === "remove"){
|
||||||
|
EventUtil.removeHandler(eventSource,_event.key,_event.fun);
|
||||||
|
}else{
|
||||||
|
EventUtil.addHandler(eventSource,_event.key,_event.fun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始调整交换列的事件
|
||||||
|
*/
|
||||||
|
onDragStart = (e) => {
|
||||||
|
if (!this.props.rowDraggAble) return;
|
||||||
|
let event = Event.getEvent(e) ,
|
||||||
|
target = Event.getTarget(event);
|
||||||
|
this.currentIndex = target.getAttribute("data-row-key");
|
||||||
|
this._dragCurrent = target;
|
||||||
|
event.dataTransfer.effectAllowed = "move";
|
||||||
|
event.dataTransfer.setData("Text", this.currentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragOver = (e) => {
|
||||||
|
let event = Event.getEvent(e);
|
||||||
|
event.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在一个拖动过程中,释放鼠标键时触发此事件。【目标事件】
|
||||||
|
* @memberof TableHeader
|
||||||
|
*/
|
||||||
|
onDrop = (e) => {
|
||||||
|
let {rowDraggAble,onDragRow} = this.props;
|
||||||
|
let event = Event.getEvent(e) ,
|
||||||
|
_target = Event.getTarget(event),target = _target.parentNode;
|
||||||
|
let currentIndex = target.getAttribute("data-row-key");
|
||||||
|
if(!currentIndex || currentIndex === this.currentIndex)return;
|
||||||
|
if(target.nodeName.toUpperCase() === "TR"){
|
||||||
|
this.synchronizeTableTr(this.currentIndex,null);
|
||||||
|
// target.setAttribute("style","");
|
||||||
|
// this.synchronizeTrStyle(this.currentIndex,false);
|
||||||
|
}
|
||||||
|
let _currentIndex = event.dataTransfer.getData("text");
|
||||||
|
onDragRow && onDragRow(parseInt(this.currentIndex--),parseInt(currentIndex--));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步自己,也需要同步当前行的行显示
|
||||||
|
*/
|
||||||
|
synchronizeTableTr = (currentIndex,type)=>{
|
||||||
|
let {contentTable} = this.props;
|
||||||
|
let _table_trs = contentTable.querySelector('.u-table-scroll table tbody'),
|
||||||
|
_table_fixed_left_trs = contentTable.querySelector('.u-table-fixed-left table tbody'),
|
||||||
|
_table_fixed_right_trs = contentTable.querySelector('.u-table-fixed-right table tbody');
|
||||||
|
|
||||||
|
this.synchronizeTrStyle(_table_trs,currentIndex,type);
|
||||||
|
if(_table_fixed_left_trs){
|
||||||
|
this.synchronizeTrStyle(_table_fixed_left_trs,currentIndex,type);
|
||||||
|
}
|
||||||
|
if(_table_fixed_right_trs){
|
||||||
|
this.synchronizeTrStyle(_table_fixed_right_trs,currentIndex,type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置同步的style
|
||||||
|
*/
|
||||||
|
synchronizeTrStyle = (_elementBody,id,type)=>{
|
||||||
|
let {contentTable} = this.props,
|
||||||
|
trs = _elementBody.getElementsByTagName("tr"),
|
||||||
|
currentObj;
|
||||||
|
for (let index = 0; index < trs.length; index++) {
|
||||||
|
const element = trs[index];
|
||||||
|
if(element.getAttribute("data-row-key") == id){
|
||||||
|
currentObj = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(type){
|
||||||
|
currentObj && currentObj.setAttribute("style","border-bottom:2px dashed rgba(5,0,0,0.25)");
|
||||||
|
}else{
|
||||||
|
currentObj && currentObj.setAttribute("style","");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragEnter = (e) => {
|
||||||
|
let event = Event.getEvent(e) ,
|
||||||
|
_target = Event.getTarget(event),target = _target.parentNode;
|
||||||
|
let currentIndex = target.getAttribute("data-row-key");
|
||||||
|
if(!currentIndex || currentIndex === this.currentIndex)return;
|
||||||
|
if(target.nodeName.toUpperCase() === "TR"){
|
||||||
|
this.synchronizeTableTr(currentIndex,true);
|
||||||
|
// target.setAttribute("style","border-bottom:2px dashed rgba(5,0,0,0.25)");
|
||||||
|
// // target.style.backgroundColor = 'rgb(235, 236, 240)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragLeave = (e) => {
|
||||||
|
let event = Event.getEvent(e) ,
|
||||||
|
_target = Event.getTarget(event),target = _target.parentNode;
|
||||||
|
let currentIndex = target.getAttribute("data-row-key");
|
||||||
|
if(!currentIndex || currentIndex === this.currentIndex)return;
|
||||||
|
if(target.nodeName.toUpperCase() === "TR"){
|
||||||
|
this.synchronizeTableTr(currentIndex,null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
const { rowDraggAble } = this.props;
|
||||||
|
if(!this.event){
|
||||||
|
this.event = true;
|
||||||
|
if(rowDraggAble){
|
||||||
|
this.initEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(this.props.treeType){
|
if(this.props.treeType){
|
||||||
this.setRowParentIndex();
|
this.setRowParentIndex();
|
||||||
}
|
}
|
||||||
this.setRowHeight()
|
this.setRowHeight()
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
const { record, onDestroy, index } = this.props;
|
const { record, onDestroy, index,rowDraggAble } = this.props;
|
||||||
onDestroy(record, index);
|
onDestroy(record, index);
|
||||||
if (this.unsubscribe) {
|
if (this.unsubscribe) {
|
||||||
this.unsubscribe();
|
this.unsubscribe();
|
||||||
}
|
}
|
||||||
|
if(rowDraggAble){
|
||||||
|
this.removeDragAbleEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,7 +255,6 @@ class TableRow extends Component{
|
||||||
}
|
}
|
||||||
setRowParentIndex(){
|
setRowParentIndex(){
|
||||||
const {index,setRowParentIndex,fixedIndex,rootIndex} = this.props;
|
const {index,setRowParentIndex,fixedIndex,rootIndex} = this.props;
|
||||||
// console.log('rootIndex',rootIndex<0?index:rootIndex,'index',fixedIndex);
|
|
||||||
setRowParentIndex(rootIndex<0?index:rootIndex,fixedIndex);
|
setRowParentIndex(rootIndex<0?index:rootIndex,fixedIndex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -163,7 +319,7 @@ class TableRow extends Component{
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
clsPrefix, columns, record, height, visible, index,
|
clsPrefix, columns, record, height, visible, index,
|
||||||
expandIconColumnIndex, expandIconAsCell, expanded, expandRowByClick,
|
expandIconColumnIndex, expandIconAsCell, expanded, expandRowByClick,rowDraggAble,
|
||||||
expandable, onExpand, needIndentSpaced, indent, indentSize,isHiddenExpandIcon,fixed,bodyDisplayInRow
|
expandable, onExpand, needIndentSpaced, indent, indentSize,isHiddenExpandIcon,fixed,bodyDisplayInRow
|
||||||
} = this.props;
|
} = this.props;
|
||||||
let showSum = false;
|
let showSum = false;
|
||||||
|
@ -171,7 +327,6 @@ class TableRow extends Component{
|
||||||
if (this.state.hovered) {
|
if (this.state.hovered) {
|
||||||
className += ` ${clsPrefix}-hover`;
|
className += ` ${clsPrefix}-hover`;
|
||||||
}
|
}
|
||||||
// console.log('className--'+className,index);
|
|
||||||
//判断是否为合计行
|
//判断是否为合计行
|
||||||
if(className.indexOf('sumrow')>-1){
|
if(className.indexOf('sumrow')>-1){
|
||||||
showSum = true;
|
showSum = true;
|
||||||
|
@ -223,14 +378,17 @@ class TableRow extends Component{
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
style.display = 'none';
|
style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
|
draggable={rowDraggAble}
|
||||||
onClick={this.onRowClick}
|
onClick={this.onRowClick}
|
||||||
onDoubleClick={this.onRowDoubleClick}
|
onDoubleClick={this.onRowDoubleClick}
|
||||||
onMouseEnter={this.onMouseEnter}
|
onMouseEnter={this.onMouseEnter}
|
||||||
onMouseLeave={this.onMouseLeave}
|
onMouseLeave={this.onMouseLeave}
|
||||||
className={`${clsPrefix} ${className} ${clsPrefix}-level-${indent}`}
|
className={`${clsPrefix} ${className} ${clsPrefix}-level-${indent}`}
|
||||||
style={style}
|
style={style}
|
||||||
|
data-row-key={record.key}
|
||||||
// key={hoverKey}
|
// key={hoverKey}
|
||||||
ref={this.bindElement}
|
ref={this.bindElement}
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue