| | |
| | | import React, {Component} from 'react' |
| | | import { DndProvider } from 'react-dnd' |
| | | import { is, fromJS } from 'immutable' |
| | | import HTML5Backend from 'react-dnd-html5-backend' |
| | | import { Card } from 'antd' |
| | | import { Card, notification, Row, Button, Modal } from 'antd' |
| | | import DragElement from './dragelement' |
| | | import MutilForm from './mutilform' |
| | | import SourceElement from './dragelement/source' |
| | | import { |
| | | printItems, |
| | | originConfig, |
| | | getpageform, |
| | | getTextForm, |
| | | getBarcodeForm, |
| | | getQrcodeForm, |
| | | getImageForm, |
| | | getElement, |
| | | barurl, |
| | | qrurl, |
| | | imgurl |
| | | } from './option.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import printCtrl from './print.js' |
| | | import Api from '@/api' |
| | | import './index.scss' |
| | | |
| | | const printItems = [ |
| | | { |
| | | type: 'print', |
| | | label: '文本', |
| | | subType: 'text', |
| | | icon: 'file-text' |
| | | }, |
| | | { |
| | | type: 'print', |
| | | label: '条形码', |
| | | subType: 'barcode', |
| | | icon: 'barcode' |
| | | }, |
| | | { |
| | | type: 'print', |
| | | label: '二维码', |
| | | subType: 'qrcode', |
| | | icon: 'qrcode' |
| | | }, |
| | | { |
| | | type: 'print', |
| | | label: '图片', |
| | | subType: 'picture', |
| | | icon: 'file-image' |
| | | } |
| | | ] |
| | | const { confirm } = Modal |
| | | let dropPoint = null |
| | | let origin = null |
| | | let timer = null |
| | | let preorigin = null |
| | | let nextorigin = null |
| | | |
| | | class PrintTemplate extends Component { |
| | | state = { |
| | | ID: null |
| | | config: null, |
| | | ID: null, |
| | | editItemId: '', |
| | | editItemType: '', |
| | | fields: [], |
| | | formlist: null, |
| | | saveloading: false |
| | | } |
| | | |
| | | componentDidMount () { |
| | | getclickpoint = (e) => { |
| | | const { config } = this.state |
| | | let scrollTop = document.documentElement.scrollTop || document.body.scrollTop |
| | | let screenX = e.clientX |
| | | let screenY = e.clientY + scrollTop |
| | | let offsetT = screenY - document.getElementById('darea').offsetTop |
| | | let offsetL = screenX - document.getElementById('darea').offsetLeft |
| | | |
| | | let cx = Math.floor(offsetL / parseInt(document.getElementById('darea').style.width) * config.width) |
| | | let cy = Math.floor(offsetT / parseInt(document.getElementById('darea').style.height) * config.height) |
| | | |
| | | return { |
| | | cx: cx, |
| | | cy: cy |
| | | } |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | let _param = window.atob(this.props.match.params.param) |
| | | let _params = {} |
| | | _param.split('&').forEach(cell => { |
| | |
| | | |
| | | this.setState({ |
| | | ID: _params.ID |
| | | }) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | // 点击切换编辑元素 |
| | | document.getElementById('darea').addEventListener('click', (e) => { |
| | | e.stopPropagation() |
| | | let position = this.getclickpoint(e) |
| | | let cx = position.cx |
| | | let cy = position.cy |
| | | let _selectItem = null |
| | | |
| | | let _config = JSON.parse(JSON.stringify(this.state.config)) |
| | | |
| | | _config.elements.forEach(element => { |
| | | let x = +element.left |
| | | let y = +element.top |
| | | let width = +element.width |
| | | let height = +element.height |
| | | let rotate = +element.rotate |
| | | if (rotate === 90 || rotate === 270) { |
| | | let _c = width |
| | | x = x + width / 2 - height / 2 |
| | | y = y + height / 2 - width / 2 |
| | | width = height |
| | | height = _c |
| | | } |
| | | if (width === 0) { |
| | | x -= 4 |
| | | width = 8 |
| | | } |
| | | if (height === 0) { |
| | | y -= 4 |
| | | height = 8 |
| | | } |
| | | if (cx > x && cx < x + width && cy > y && cy < y + height) { |
| | | _selectItem = element |
| | | } |
| | | }) |
| | | if (!_selectItem) { |
| | | _selectItem = _config |
| | | } else { |
| | | _config.elements = _config.elements.filter(ele => ele.uuid !== _selectItem.uuid) |
| | | _config.elements.push(_selectItem) |
| | | } |
| | | |
| | | let _formlist = null |
| | | |
| | | if (_selectItem.type === 'Template') { |
| | | _formlist = getpageform(_selectItem) |
| | | } else if (_selectItem.type === 'text') { |
| | | _formlist = getTextForm(_selectItem, this.state.fields) |
| | | } else if (_selectItem.type === 'barcode') { |
| | | _formlist = getBarcodeForm(_selectItem, this.state.fields) |
| | | } else if (_selectItem.type === 'qrcode') { |
| | | _formlist = getQrcodeForm(_selectItem, this.state.fields) |
| | | } else if (_selectItem.type === 'image') { |
| | | _formlist = getImageForm(_selectItem, this.state.fields) |
| | | } |
| | | |
| | | this.setState({ |
| | | config: _config, |
| | | editItemId: _selectItem.uuid, |
| | | editItemType: _selectItem.type, |
| | | formlist: _formlist |
| | | }, () => { |
| | | this.resetview() |
| | | }) |
| | | }) |
| | | |
| | | // 触发拖动事件 |
| | | document.getElementById('darea').addEventListener('mousedown', (e) => { |
| | | const { config } = this.state |
| | | |
| | | if (!this.state.editItemType || this.state.editItemType === 'Template') { |
| | | origin = null |
| | | return |
| | | } |
| | | |
| | | let _selectItem = JSON.parse(JSON.stringify(this.state.config.elements.filter(ele => ele.uuid === this.state.editItemId)[0])) |
| | | let _preItem = JSON.parse(JSON.stringify(_selectItem)) |
| | | |
| | | let position = this.getclickpoint(e) |
| | | let cx = position.cx |
| | | let cy = position.cy |
| | | let x = +_selectItem.left |
| | | let y = +_selectItem.top |
| | | let width = +_selectItem.width |
| | | let height = +_selectItem.height |
| | | let rotate = +_selectItem.rotate |
| | | if (rotate === 90 || rotate === 270) { |
| | | let _c = width |
| | | x = x + width / 2 - height / 2 |
| | | y = y + height / 2 - width / 2 |
| | | width = height |
| | | height = _c |
| | | } |
| | | if (width === 0) { |
| | | x -= 4 |
| | | width = 8 |
| | | } |
| | | if (height === 0) { |
| | | y -= 4 |
| | | height = 8 |
| | | } |
| | | |
| | | if (cx > x && cx < x + width && cy > y && cy < y + height) { |
| | | if (width > 3 && height > 3 && cx > x + width - 3 && cx < x + width + 2 && cy > y + height - 3 && cy < y + height + 2) { |
| | | origin = { |
| | | cx: cx, |
| | | cy: cy, |
| | | width: +_selectItem.width, |
| | | height: +_selectItem.height |
| | | } |
| | | timer = setInterval(() => { |
| | | if (JSON.stringify(preorigin) !== JSON.stringify(nextorigin)) { |
| | | preorigin = nextorigin |
| | | let _width = origin.width + (nextorigin.cx - origin.cx) |
| | | let _height = origin.height + (nextorigin.cy - origin.cy) |
| | | |
| | | if (_width < 0) { |
| | | _width = 0 |
| | | } else if (_selectItem.left + _width > config.width) { |
| | | _width = config.width - _selectItem.left |
| | | } |
| | | if (_height < 0) { |
| | | _height = 0 |
| | | } else if (_height + _selectItem.top > config.height) { |
| | | _height = config.height - _selectItem.top |
| | | } |
| | | |
| | | _selectItem.width = _width |
| | | _selectItem.height = _height |
| | | |
| | | let result = this.resetItem(_selectItem) |
| | | |
| | | if (!is(fromJS(result), fromJS(_preItem))) { |
| | | _preItem = JSON.parse(JSON.stringify(result)) |
| | | this.FormRef.resetForm(result) |
| | | |
| | | config.elements = config.elements.map(item => { |
| | | if (item.uuid === result.uuid) return result |
| | | |
| | | return item |
| | | }) |
| | | |
| | | this.setState({ |
| | | config: config |
| | | }, () => { |
| | | this.resetview() |
| | | }) |
| | | } |
| | | } |
| | | }, 100) |
| | | } else { |
| | | origin = { |
| | | cx: cx, |
| | | cy: cy, |
| | | left: +_selectItem.left, |
| | | top: +_selectItem.top |
| | | } |
| | | timer = setInterval(() => { |
| | | if (JSON.stringify(preorigin) !== JSON.stringify(nextorigin)) { |
| | | preorigin = nextorigin |
| | | let _left = origin.left + (nextorigin.cx - origin.cx) |
| | | let _top = origin.top + (nextorigin.cy - origin.cy) |
| | | |
| | | if (_left < 0) { |
| | | _left = 0 |
| | | } else if (_left + _selectItem.width > config.width) { |
| | | _left = config.width - _selectItem.width |
| | | } |
| | | if (_top < 0) { |
| | | _top = 0 |
| | | } else if (_top + _selectItem.height > config.height) { |
| | | _top = config.height - _selectItem.height |
| | | } |
| | | |
| | | _selectItem.left = _left |
| | | _selectItem.top = _top |
| | | |
| | | let result = this.resetItem(_selectItem) |
| | | |
| | | if (!is(fromJS(result), fromJS(_preItem))) { |
| | | _preItem = JSON.parse(JSON.stringify(result)) |
| | | this.FormRef.resetForm(result) |
| | | |
| | | config.elements = config.elements.map(item => { |
| | | if (item.uuid === result.uuid) return result |
| | | |
| | | return item |
| | | }) |
| | | |
| | | this.setState({ |
| | | config: config |
| | | }, () => { |
| | | this.resetview() |
| | | }) |
| | | } |
| | | } |
| | | }, 100) |
| | | } |
| | | } else { |
| | | origin = null |
| | | } |
| | | }) |
| | | document.getElementById('darea').addEventListener('mousemove', (e) => { |
| | | if (!this.state.editItemType || this.state.editItemType === 'Template' || !origin) { |
| | | return |
| | | } |
| | | let position = this.getclickpoint(e) |
| | | nextorigin = { |
| | | cx: position.cx, |
| | | cy: position.cy |
| | | } |
| | | }) |
| | | document.getElementById('darea').addEventListener('mouseup', (e) => { |
| | | origin = null |
| | | clearInterval(timer) |
| | | }) |
| | | document.getElementById('darea').addEventListener('mouseleave', (e) => { |
| | | origin = null |
| | | clearInterval(timer) |
| | | }) |
| | | |
| | | // 元素添加 |
| | | document.getElementById('darea').addEventListener('drop', (e) => { |
| | | dropPoint = this.getclickpoint(e) |
| | | }) |
| | | |
| | | if (document.body.offsetWidth < 1360) { |
| | | document.getElementById('darea').style.width = '600px' |
| | | } else if (document.body.offsetWidth < 1500) { |
| | | document.getElementById('darea').style.width = '700px' |
| | | } else if (document.body.offsetWidth < 1920) { |
| | | document.getElementById('darea').style.width = '800px' |
| | | } |
| | | |
| | | this.loadconfig() |
| | | } |
| | | |
| | | resetbox = () => { |
| | | const { config } = this.state |
| | | |
| | | let ratio = (config.height || 1) / (config.width || 1) |
| | | |
| | | document.getElementById('darea').style.height = parseInt(document.getElementById('darea').style.width) * ratio + 'px' |
| | | |
| | | printCtrl.sketch(config, null) |
| | | } |
| | | |
| | | resetview () { |
| | | const { config, editItemId } = this.state |
| | | |
| | | printCtrl.sketch(config, editItemId) |
| | | } |
| | | |
| | | /** |
| | | * @description 获取模板配置信息 |
| | | */ |
| | | async loadconfig () { |
| | | let param = { |
| | | func: 's_PrintTemplateMGetData', |
| | | ID: this.state.ID |
| | | } |
| | | |
| | | let result = await Api.getCloudConfig(param) |
| | | |
| | | if (result.status) { |
| | | let _config = '' |
| | | if (result.ConfigParam) { |
| | | try { |
| | | _config = JSON.parse(window.decodeURIComponent(window.atob(result.ConfigParam))) |
| | | } catch (e) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '配置信息解析错误!', |
| | | duration: 10 |
| | | }) |
| | | _config = '' |
| | | } |
| | | } |
| | | |
| | | if (!_config) { |
| | | _config = originConfig |
| | | } |
| | | |
| | | _config.name = result.PrintTempName || '' |
| | | _config.remark = result.Remark || '' |
| | | _config.PrintTempNO = result.PrintTempNO || '' |
| | | _config.type = 'Template' |
| | | _config.uuid = Utils.getuuid() |
| | | |
| | | if (result.data && result.data[0] && result.data[0].TableName) { |
| | | this.loadFields(result.data[0].TableName) |
| | | } |
| | | |
| | | this.setState({ |
| | | config: _config, |
| | | editItemId: _config.uuid, |
| | | editItemType: _config.type, |
| | | formlist: getpageform(_config) |
| | | }, () => { |
| | | this.resetbox() |
| | | }) |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.ErrMesg, |
| | | duration: 10 |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 获取可用字段 |
| | | */ |
| | | async loadFields (TBName) { |
| | | let param = { |
| | | func: 'sPC_Get_FieldName', |
| | | TBName: TBName |
| | | } |
| | | |
| | | let result = await Api.getCloudConfig(param) |
| | | |
| | | if (result.status) { |
| | | let _fields = [{ |
| | | value: '', |
| | | text: '空', |
| | | type: '' |
| | | }] |
| | | let _f = new Map() |
| | | |
| | | result.FDName.forEach(item => { |
| | | if (item.FieldName && !_f.has(item.FieldName)) { |
| | | _f.set(item.FieldName, true) |
| | | |
| | | _fields.push({ |
| | | value: item.FieldName, |
| | | text: item.FieldDec, |
| | | type: item.FieldType |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | this.setState({ |
| | | fields: _fields |
| | | }) |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.ErrMesg, |
| | | duration: 10 |
| | | }) |
| | | } |
| | | } |
| | | |
| | | dropcard = (item) => { |
| | | const { config } = this.state |
| | | |
| | | let position = null |
| | | |
| | | if (dropPoint) { |
| | | position = dropPoint |
| | | dropPoint = null |
| | | } else { |
| | | return |
| | | } |
| | | |
| | | let _width = Math.floor(config.width / 4) |
| | | let _height = Math.floor(_width / 2) |
| | | let _cx = Math.floor(position.cx - _width / 2) |
| | | let _cy = Math.floor(position.cy - _height / 2) |
| | | |
| | | if (_cx < 0) { // 元素添加时,避免超出边界 |
| | | _cx = 0 |
| | | } else if (_cx + _width > config.width) { |
| | | _cx = Math.floor(config.width - _width) |
| | | } |
| | | |
| | | if (_cy < 0) { |
| | | _cy = 0 |
| | | } else if (_cy + _height > config.height) { |
| | | _cy = Math.floor(config.height - _height) |
| | | } |
| | | |
| | | let _selectItem = null |
| | | let _formlist = null |
| | | if (item.subType === 'text') { |
| | | _selectItem = getElement(item.subType, Utils.getuuid(), _cx, _cy, _width, _height) |
| | | _formlist = getTextForm(_selectItem, this.state.fields) |
| | | } else if (item.subType === 'barcode') { |
| | | _selectItem = getElement(item.subType, Utils.getuuid(), _cx, _cy, _width, _height, barurl, config.width) |
| | | _formlist = getBarcodeForm(_selectItem, this.state.fields) |
| | | } else if (item.subType === 'qrcode') { |
| | | _selectItem = getElement(item.subType, Utils.getuuid(), _cx, _cy, _width, _height, qrurl) |
| | | _formlist = getQrcodeForm(_selectItem, this.state.fields) |
| | | } else if (item.subType === 'image') { |
| | | _selectItem = getElement(item.subType, Utils.getuuid(), _cx, _cy, _width, _height, imgurl) |
| | | _formlist = getImageForm(_selectItem, this.state.fields) |
| | | } |
| | | |
| | | config.elements.push(_selectItem) |
| | | |
| | | this.setState({ |
| | | config: config, |
| | | editItemId: _selectItem.uuid, |
| | | editItemType: _selectItem.type, |
| | | formlist: _formlist |
| | | }, () => { |
| | | this.resetview() |
| | | }) |
| | | |
| | | } |
| | | |
| | | resetItem = (item) => { |
| | | let _item = JSON.parse(JSON.stringify(item)) |
| | | const { config } = this.state |
| | | |
| | | let _boxwidth = +config.width |
| | | let _boxheight = +config.height |
| | | let _left = +_item.left |
| | | let _top = +_item.top |
| | | let _width = +_item.width |
| | | let _height = +_item.height |
| | | |
| | | if (_left < 0) { |
| | | _item.left = 0 |
| | | } |
| | | if (_top < 0) { |
| | | _item.top = 0 |
| | | } |
| | | |
| | | if (_left + _width > _boxwidth) { |
| | | _item.width = _boxwidth - _left |
| | | } |
| | | |
| | | if (_top + _height > _boxheight) { |
| | | _item.height = _boxheight - _top |
| | | } |
| | | |
| | | if (_item.type === 'barcode') { |
| | | if (+_item.barcodeWidth > +_item.width) { |
| | | _item.barcodeWidth = +_item.width |
| | | } |
| | | if (+_item.barcodeHeight > +_item.height) { |
| | | _item.barcodeHeight = +_item.height |
| | | } |
| | | } else if (_item.type === 'qrcode') { |
| | | if (+_item.qrcodeWidth > +_item.width) { |
| | | _item.qrcodeWidth = +_item.width |
| | | } |
| | | if (+_item.qrcodeWidth > +_item.height) { |
| | | _item.qrcodeWidth = +_item.height |
| | | } |
| | | } else if (_item.type === 'image') { |
| | | if (+_item.imgWidth > +_item.width) { |
| | | _item.imgWidth = +_item.width |
| | | } |
| | | if (+_item.imgHeight > +_item.height) { |
| | | _item.imgHeight = +_item.height |
| | | } |
| | | } |
| | | |
| | | return _item |
| | | } |
| | | |
| | | handleSubmit = () => { |
| | | const { config } = this.state |
| | | |
| | | this.FormRef.handleConfirm().then(res => { |
| | | if (res.type === 'Template') { |
| | | res.width = parseInt(res.width) |
| | | res.height = parseInt(res.height) |
| | | |
| | | if (res.width < 1) { |
| | | res.width = 1 |
| | | this.FormRef.resetForm({width: 1}) |
| | | } else if (res.height < 1) { |
| | | res.height = 1 |
| | | this.FormRef.resetForm({height: 1}) |
| | | } |
| | | |
| | | this.setState({ |
| | | config: {...config, ...res} |
| | | }, () => { |
| | | if (res.width !== config.width || res.height !== config.height) { |
| | | this.resetbox() |
| | | } |
| | | }) |
| | | } else { |
| | | if (res.type === 'barcode') { |
| | | res.url = barurl |
| | | } else if (res.type === 'qrcode') { |
| | | res.url = qrurl |
| | | } else if (res.type === 'image') { |
| | | res.url = imgurl |
| | | } |
| | | |
| | | let result = this.resetItem(res) |
| | | |
| | | if (!is(fromJS(result), fromJS(res))) { |
| | | this.FormRef.resetForm(result) |
| | | } |
| | | |
| | | config.elements = config.elements.map(item => { |
| | | if (item.uuid === result.uuid) return result |
| | | |
| | | return item |
| | | }) |
| | | |
| | | this.setState({ |
| | | config: config |
| | | }, () => { |
| | | this.resetview() |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | deleteItem = () => { |
| | | const _this = this |
| | | const { editItemId, config } = this.state |
| | | |
| | | confirm({ |
| | | title: '确定删除该元素吗?', |
| | | okText: '确定', |
| | | cancelText: '取消', |
| | | onOk() { |
| | | config.elements = config.elements.filter(item => item.uuid !== editItemId) |
| | | |
| | | _this.setState({ |
| | | config: config, |
| | | editItemId: config.uuid, |
| | | editItemType: config.type, |
| | | formlist: getpageform(config) |
| | | }, () => { |
| | | _this.resetview() |
| | | }) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | submitConfig = () => { |
| | | const { config } = this.state |
| | | |
| | | if (config.height / config.width > 10 || config.width / config.height > 10) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '纸张纵横比不可超过10!', |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | this.setState({ |
| | | saveloading: true |
| | | }) |
| | | |
| | | let _config = '' |
| | | |
| | | try { |
| | | _config = window.btoa(window.encodeURIComponent(JSON.stringify(config))) |
| | | } catch { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '编译错误!', |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let param = { |
| | | func: 's_PrintTemplateMSub', |
| | | ID: this.state.ID, |
| | | ConfigParam: _config, |
| | | Images: '', |
| | | PrintTempName: config.name, |
| | | Remark: config.remark, |
| | | PrintTempNO: config.PrintTempNO |
| | | } |
| | | |
| | | new Promise(resolve => { |
| | | printCtrl.sketch(config, null).then(res => { |
| | | Api.fileuploadbase64(res, 'cloud').then(result => { // 图片上传,并获取图片路径 |
| | | if (result.status) { |
| | | resolve(Utils.getcloudurl(result.Images)) |
| | | } else { |
| | | // notification.warning({ |
| | | // top: 92, |
| | | // message: result.ErrMesg, |
| | | // duration: 10 |
| | | // }) |
| | | // this.setState({ |
| | | // saveloading: false |
| | | // }) |
| | | // resolve(false) |
| | | resolve(true) |
| | | } |
| | | }) |
| | | }) |
| | | }).then(res => { |
| | | if (!res) return |
| | | param.Images = 'http://css.positecgroup.com/Content/Upload/2020-01-08/2020010810525808769824_U000000001.png' |
| | | |
| | | return Api.getCloudConfig(param) |
| | | }).then(res => { |
| | | if (!res) return |
| | | |
| | | if (res.status) { |
| | | notification.success({ |
| | | top: 92, |
| | | message: '保存成功', |
| | | duration: 2 |
| | | }) |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.ErrMesg, |
| | | duration: 10 |
| | | }) |
| | | } |
| | | this.setState({ |
| | | saveloading: false |
| | | }) |
| | | }) |
| | | } |
| | | |
| | |
| | | })} |
| | | </Card> |
| | | </aside> |
| | | <DragElement dropcard={this.dropcard} /> |
| | | <aside className="setting"> |
| | | <Card title="状态栏"> |
| | | |
| | | </Card> |
| | | {this.state.editItemId ? |
| | | <Card title="状态栏"> |
| | | {this.state.formlist ? |
| | | <MutilForm |
| | | config={this.state.config} |
| | | formlist={this.state.formlist} |
| | | inputSubmit={this.handleSubmit} |
| | | editItem={{uuid: this.state.editItemId, type: this.state.editItemType}} |
| | | wrappedComponentRef={(inst) => this.FormRef = inst} |
| | | /> : null |
| | | } |
| | | <div className="operation"> |
| | | {this.state.editItemType === 'Template' ? |
| | | <Row gutter={24}> |
| | | <Button type="primary" onClick={this.submitConfig} loading={this.state.saveloading}>保存</Button> |
| | | </Row> : null |
| | | } |
| | | {this.state.editItemType !== 'Template' ? |
| | | <Row gutter={24}> |
| | | <Button type="danger" onClick={this.deleteItem}>删除</Button> |
| | | </Row> : null |
| | | } |
| | | </div> |
| | | </Card> : null |
| | | } |
| | | </aside> |
| | | </DndProvider> |
| | | </div> |