| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Modal } from 'antd' |
| | | import { Modal, Button } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import { getCardCellForm } from './formconfig' |
| | | import { getActionForm } from '@/menu/components/share/actioncomponent/formconfig' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import MenuUtils from '@/utils/utils-custom.js' |
| | | import ElementForm from './elementform' |
| | | import DragElement from './dragaction' |
| | | import './index.scss' |
| | | |
| | | const { confirm } = Modal |
| | | |
| | | const ActionForm = asyncComponent(() => import('@/menu/components/share/actioncomponent/actionform')) |
| | | const VerifyCard = asyncComponent(() => import('@/templates/zshare/verifycard')) |
| | | const VerifyPrint = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyprint')) |
| | | const VerifyExcelIn = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelin')) |
| | | const VerifyExcelOut = asyncComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelout')) |
| | | |
| | | class CardCellComponent extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.object, // 菜单配置信息 |
| | | updateElement: PropTypes.func // 菜单配置更新 |
| | | cards: PropTypes.object, // 菜单配置信息 |
| | | cardCell: PropTypes.object, |
| | | side: PropTypes.string, |
| | | elements: PropTypes.array, // 元素集 |
| | | updateElement: PropTypes.func // 菜单配置更新 |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, // 编辑中元素 |
| | | formlist: null, // 表单信息 |
| | | elements: null, // 按钮组 |
| | | visible: false, // 模态框控制 |
| | | actvisible: false, // 按钮编辑模态框 |
| | | profVisible: false, // 验证信息编辑 |
| | | } |
| | | |
| | | /** |
| | | * @description 搜索条件初始化 |
| | | */ |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | const { elements } = this.props |
| | | let _elements = fromJS(elements).toJS() |
| | | |
| | | this.setState({ |
| | | elements: fromJS(config.elements).toJS() |
| | | elements: _elements.map(item => { |
| | | if (item.btnstyle) { // 兼容 |
| | | item.style = item.style || {} |
| | | item.style = {...item.style, ...item.btnstyle} |
| | | delete item.btnstyle |
| | | } |
| | | |
| | | return item |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('cardAddElement', this.cardAddElement) |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | MKEmitter.addListener('submitModal', this.handleSave) |
| | | MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props.config), fromJS(nextProps.config)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | return !is(fromJS(this.props.cards), fromJS(nextProps.cards)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps(nextProps) { |
| | | if (this.props.side !== nextProps.side) { |
| | | this.setState({ |
| | | elements: fromJS(nextProps.elements).toJS() |
| | | }) |
| | | } else if (!is(fromJS(this.props.elements), fromJS(nextProps.elements)) && nextProps.elements.length !== this.state.elements.length) { |
| | | this.setState({ |
| | | elements: fromJS(nextProps.elements).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | return |
| | | } |
| | | MKEmitter.removeListener('cardAddElement', this.cardAddElement) |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | MKEmitter.removeListener('submitModal', this.handleSave) |
| | | MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) |
| | | } |
| | | |
| | | cardAddElement = (cardId, element) => { |
| | | if (cardId !== this.props.config.uuid) return |
| | | updateComponentStyle = (parentId, keys, style) => { |
| | | const { cardCell } = this.props |
| | | |
| | | if (!cardCell || cardCell.uuid !== parentId) return |
| | | |
| | | const { elements } = this.state |
| | | |
| | | let _elements = elements.map(item => { |
| | | if (keys.includes(item.uuid)) { |
| | | return this.resetCardStyle(item, {...item.style, ...style}) |
| | | } |
| | | return item |
| | | }) |
| | | |
| | | this.setState({ |
| | | elements: _elements |
| | | }, () => { |
| | | this.props.updateElement(_elements) |
| | | }) |
| | | } |
| | | |
| | | cardAddElement = (ids, element) => { |
| | | const { cards, cardCell } = this.props |
| | | |
| | | if (!ids || ids.length !== 2 || ids[0] !== cards.uuid || ids[1] !== cardCell.uuid) return |
| | | |
| | | const { elements } = this.state |
| | | |
| | | this.setState({elements: [...elements, element]}) |
| | | |
| | | this.handleElement(element) |
| | | } |
| | | |
| | | handleStyle = (element) => { |
| | | const { cards, cardCell } = this.props |
| | | |
| | | let _style = element.style ? fromJS(element.style).toJS() : {} |
| | | let options = ['font', 'border', 'padding', 'margin', 'backgroundColor'] |
| | | |
| | | if (element.eleType === 'button') { |
| | | options.push('width') |
| | | } else if (element.eleType === 'picture') { |
| | | options = ['border', 'margin'] |
| | | } else if (element.eleType === 'slider') { |
| | | options = ['padding', 'margin'] |
| | | } else if (element.eleType === 'splitline') { |
| | | options = ['padding', 'margin'] |
| | | } |
| | | |
| | | this.setState({ |
| | | card: element |
| | | }) |
| | | |
| | | MKEmitter.emit('changeStyle', [cards.uuid, cardCell.uuid, element.uuid], options, _style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { cards, cardCell } = this.props |
| | | const { card, elements } = this.state |
| | | |
| | | if (comIds.length !== 3 || comIds[0] !== cards.uuid || comIds[1] !== cardCell.uuid || !card) return |
| | | |
| | | let _card = this.resetCardStyle(card, style) |
| | | |
| | | let _elements = elements.map(cell => { |
| | | if (cell.uuid === _card.uuid) return _card |
| | | return cell |
| | | }) |
| | | |
| | | this.setState({ |
| | | elements: _elements |
| | | }, () => { |
| | | this.props.updateElement(_elements) |
| | | }) |
| | | } |
| | | |
| | | resetCardStyle = (card, style) => { |
| | | let _card = fromJS(card).toJS() |
| | | |
| | | if (_card.eleType === 'text' || _card.eleType === 'number') { |
| | | _card.style = style |
| | | |
| | | let fontSize = 14 |
| | | let lineHeight = 1.5 |
| | | let line = _card.height || null |
| | | |
| | | if (_card.style.fontSize) { |
| | | fontSize = parseInt(_card.style.fontSize) |
| | | } |
| | | if (_card.style.lineHeight) { |
| | | lineHeight = parseFloat(_card.style.lineHeight) |
| | | } |
| | | |
| | | if (line) { |
| | | _card.innerHeight = fontSize * lineHeight * line |
| | | } |
| | | } else if (_card.eleType === 'sequence') { |
| | | _card.style = style |
| | | |
| | | let fontSize = 14 |
| | | let lineHeight = 1.5 |
| | | |
| | | if (_card.style.fontSize) { |
| | | fontSize = parseInt(_card.style.fontSize) |
| | | } |
| | | |
| | | _card.innerHeight = fontSize * lineHeight |
| | | } else if (_card.eleType === 'barcode') { |
| | | _card.style = style |
| | | |
| | | let fontSize = 14 |
| | | |
| | | if (_card.style.fontSize) { |
| | | fontSize = parseInt(_card.style.fontSize) |
| | | } |
| | | |
| | | _card.innerHeight = _card.barHeight + (_card.displayValue === 'true' ? fontSize + 2 : 0) |
| | | } else if (_card.eleType === 'button') { // 拆分style |
| | | _card.style = style |
| | | } else { |
| | | _card.style = style |
| | | } |
| | | |
| | | return _card |
| | | } |
| | | |
| | | /** |
| | | * @description 按钮顺序调整 |
| | | */ |
| | | handleList = (list) => { |
| | | const { config } = this.props |
| | | |
| | | this.setState({elements: list}, () => { |
| | | this.props.updateElement({...config, elements: list}) |
| | | this.props.updateElement(list) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 元素编辑,获取元素表单信息 |
| | | */ |
| | | handleElement = (card) => { |
| | | const { cards, cardCell } = this.props |
| | | |
| | | if (card.eleType === 'button') { |
| | | this.handleAction(card) |
| | | } else { |
| | | this.setState({ |
| | | visible: true, |
| | | card: card, |
| | | formlist: getCardCellForm(card, cards.type, cards.subtype, cardCell) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 按钮编辑,获取按钮表单信息 |
| | | */ |
| | | handleElement = (card) => { |
| | | handleAction = (card) => { |
| | | const { cards } = this.props |
| | | |
| | | let usefulFields = sessionStorage.getItem('permFuncField') |
| | | if (usefulFields) { |
| | | try { |
| | | usefulFields = JSON.parse(usefulFields) |
| | | } catch { |
| | | usefulFields = [] |
| | | } |
| | | } else { |
| | | usefulFields = [] |
| | | } |
| | | |
| | | let ableField = usefulFields.join(', ') |
| | | let functip = <div> |
| | | <p style={{marginBottom: '5px'}}>{this.state.dict['model.tooltip.func.innerface'].replace('@ableField', ableField)}</p> |
| | | </div> |
| | | |
| | | let menulist = sessionStorage.getItem('fstMenuList') |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | |
| | | let modules = MenuUtils.getSubModules(window.GLOB.customMenu.components, cards.uuid) |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | actvisible: true, |
| | | card: card, |
| | | formlist: getCardCellForm(card) |
| | | formlist: getActionForm(card, functip, cards.setting, usefulFields, 'card', menulist, modules, cards.columns) |
| | | }) |
| | | } |
| | | |
| | |
| | | this.setState({ |
| | | card: null, |
| | | elements: _elements, |
| | | visible: false |
| | | visible: false, |
| | | actvisible: false |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 搜索修改后提交保存 |
| | | * 1、去除系统默认搜索条件 |
| | | * 2、字段及提示文字重复校验 |
| | | * 3、更新下拉菜单可选集合 |
| | | * 4、下拉菜单数据源语法验证 |
| | | * @description 元素修改后提交保存 |
| | | */ |
| | | handleSubmit = () => { |
| | | const { config } = this.props |
| | | const { elements } = this.state |
| | | |
| | | this.elementFormRef.handleConfirm().then(ele => { |
| | | this.elementFormRef.handleConfirm().then(res => { |
| | | let _elements = elements.map(cell => { |
| | | if (cell.uuid === ele.uuid) return ele |
| | | if (cell.uuid === res.uuid) { |
| | | res.style = cell.style || {} |
| | | res.$type = cell.$type || '' |
| | | if (res.eleType === 'splitline' && cell.eleType !== 'splitline') { |
| | | res.style.paddingTop = '5px' |
| | | res.style.paddingBottom = '5px' |
| | | } else if (res.eleType === 'text' || res.eleType === 'number') { |
| | | let fontSize = 14 |
| | | let lineHeight = 1.5 |
| | | let line = res.height || null |
| | | |
| | | if (res.style && res.style.fontSize) { |
| | | fontSize = parseInt(res.style.fontSize) |
| | | } |
| | | if (res.style && res.style.lineHeight) { |
| | | lineHeight = parseFloat(res.style.lineHeight) |
| | | } |
| | | |
| | | if (line) { |
| | | res.innerHeight = fontSize * lineHeight * line |
| | | } |
| | | |
| | | if (res.eleType === 'text' && res.link && !res.style.color) { |
| | | res.style.color = '#2440B3' |
| | | } |
| | | } else if (res.eleType === 'barcode') { |
| | | let fontSize = 14 |
| | | |
| | | if (res.style && res.style.fontSize) { |
| | | fontSize = parseInt(res.style.fontSize) |
| | | } |
| | | |
| | | res.innerHeight = res.barHeight + (res.displayValue === 'true' ? fontSize + 2 : 0) |
| | | } |
| | | |
| | | return res |
| | | } |
| | | return cell |
| | | }) |
| | | |
| | |
| | | elements: _elements, |
| | | visible: false |
| | | }, () => { |
| | | this.props.updateElement({...config, elements: _elements}) |
| | | this.props.updateElement(_elements) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 元素修改后提交保存 |
| | | */ |
| | | handleActionSubmit = () => { |
| | | const { elements } = this.state |
| | | let color = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#666666' } |
| | | |
| | | this.actionFormRef.handleConfirm().then(res => { |
| | | let _elements = elements.map(cell => { |
| | | if (cell.uuid === res.uuid) { |
| | | res = {...cell, ...res} |
| | | delete res.focus |
| | | let style = {} |
| | | |
| | | if (res.class !== cell.class || res.show !== cell.show || !res.style) { |
| | | if (res.show === 'link' || res.show === 'icon') { |
| | | style.color = color[res.class] |
| | | style.backgroundColor = 'transparent' |
| | | } else { |
| | | style.color = '#ffffff' |
| | | style.backgroundColor = color[res.class] |
| | | } |
| | | } |
| | | res.style = {...res.style, ...style} |
| | | |
| | | return res |
| | | } |
| | | return cell |
| | | }) |
| | | |
| | | this.setState({ |
| | | elements: _elements, |
| | | actvisible: false |
| | | }, () => { |
| | | this.props.updateElement(_elements) |
| | | }) |
| | | }) |
| | | } |
| | |
| | | * @description 按钮删除 |
| | | */ |
| | | deleteElement = (card) => { |
| | | const { config } = this.props |
| | | const { cards, cardCell, side } = this.props |
| | | const { dict, elements } = this.state |
| | | let _this = this |
| | | |
| | |
| | | onOk() { |
| | | let _elements = elements.filter(item => item.uuid !== card.uuid) |
| | | |
| | | if (card.eleType === 'button') { |
| | | MKEmitter.emit('delButtons', [card.uuid]) |
| | | } |
| | | if (card.OpenType === 'popview' || card.verify || card.modal) { |
| | | card.$parentId = cardCell.uuid |
| | | card.$side = side || '' |
| | | |
| | | MKEmitter.emit('logButton', cards.uuid, card) |
| | | } |
| | | |
| | | _this.setState({ |
| | | elements: _elements |
| | | }, () => { |
| | | _this.props.updateElement({...config, elements: _elements}) |
| | | _this.props.updateElement(_elements) |
| | | }) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 验证信息配置 |
| | | */ |
| | | profileAction = (element) => { |
| | | this.setState({ |
| | | profVisible: true, |
| | | card: element |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 验证信息保存 |
| | | */ |
| | | verifySubmit = () => { |
| | | const { elements, card } = this.state |
| | | |
| | | this.verifyRef.handleConfirm().then(res => { |
| | | let _elements = elements.map(cell => { |
| | | if (cell.uuid === card.uuid) { |
| | | cell.verify = res |
| | | } |
| | | |
| | | return cell |
| | | }) |
| | | |
| | | this.setState({ |
| | | elements: _elements, |
| | | profVisible: false |
| | | }, () => { |
| | | this.props.updateElement(_elements) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubConfig = (item) => { |
| | | const { cards } = this.props |
| | | let btn = fromJS(item).toJS() |
| | | |
| | | if ((sessionStorage.getItem('style-control') && sessionStorage.getItem('style-control') === 'true')) return |
| | | |
| | | if (btn.eleType === 'button') { |
| | | if (btn.OpenType === 'pop') { |
| | | if (!btn.modal) { |
| | | btn.modal = { |
| | | setting: { title: btn.label, width: 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' }, |
| | | tables: [], |
| | | groups: [], |
| | | fields: [] |
| | | } |
| | | } |
| | | |
| | | MKEmitter.emit('changeModal', cards, btn) |
| | | } else if (btn.OpenType === 'popview') { |
| | | MKEmitter.emit('changePopview', cards, btn) |
| | | } else if (btn.OpenType === 'innerpage' && btn.pageTemplate === 'page') { |
| | | MKEmitter.emit('changeEditMenu', {MenuID: btn.uuid, copyMenuId: btn.copyMenuId}) |
| | | } else if (btn.OpenType === 'innerpage' && btn.pageTemplate === 'linkpage') { |
| | | MKEmitter.emit('changeEditMenu', {MenuID: btn.linkmenu}) |
| | | } |
| | | } else { |
| | | if (btn.link === 'page') { |
| | | MKEmitter.emit('changeEditMenu', {MenuID: btn.uuid, copyMenuId: btn.copyMenuId}) |
| | | } else if (btn.link === 'linkpage') { |
| | | MKEmitter.emit('changeEditMenu', {MenuID: btn.linkmenu}) |
| | | } |
| | | } |
| | | } |
| | | |
| | | handleSave = (_cards, btn, modal) => { |
| | | const { cards } = this.props |
| | | const { elements } = this.state |
| | | |
| | | if (cards.uuid !== _cards.uuid) return |
| | | |
| | | let _index = elements.findIndex(cell => cell.uuid === btn.uuid) |
| | | |
| | | if (_index === -1) return |
| | | |
| | | let _elements = elements.map(cell => { |
| | | if (cell.uuid === btn.uuid) { |
| | | cell.modal = modal |
| | | } |
| | | |
| | | return cell |
| | | }) |
| | | |
| | | this.setState({ |
| | | elements: _elements |
| | | }, () => { |
| | | this.props.updateElement(_elements) |
| | | }) |
| | | } |
| | | |
| | | updateMarks = (card) => { |
| | | const { elements } = this.state |
| | | |
| | | let _elements = elements.map(cell => { |
| | | if (cell.uuid === card.uuid) return card |
| | | return cell |
| | | }) |
| | | |
| | | this.setState({ |
| | | elements: _elements |
| | | }, () => { |
| | | this.props.updateElement(_elements) |
| | | }) |
| | | } |
| | | |
| | | dropButton = (id) => { |
| | | const { cards } = this.props |
| | | |
| | | if (!cards.action) return |
| | | |
| | | let index = cards.action.findIndex(item => item.uuid === id) |
| | | |
| | | if (index === -1) return |
| | | |
| | | let btn = cards.action[index] |
| | | btn.eleType = 'button' |
| | | |
| | | let _elements = [...this.state.elements, btn] |
| | | let _action = cards.action.filter(item => item.uuid !== id) |
| | | |
| | | this.setState({ |
| | | elements: _elements |
| | | }, () => { |
| | | this.props.updateElement(_elements, _action) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { config } = this.props |
| | | const { elements, visible, card, dict } = this.state |
| | | const { cards, cardCell } = this.props |
| | | const { elements, visible, actvisible, profVisible, card, dict } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-card-cell-list"> |
| | | <DragElement |
| | | list={elements} |
| | | parent={{...cardCell, components: elements}} |
| | | fields={cards.columns} |
| | | updateMarks={this.updateMarks} |
| | | handleList={this.handleList} |
| | | handleMenu={this.handleElement} |
| | | handleStyle={this.handleStyle} |
| | | dropButton={this.dropButton} |
| | | profileAction={this.profileAction} |
| | | handleSubConfig={this.handleSubConfig} |
| | | deleteMenu={this.deleteElement} |
| | | /> |
| | | {/* 编辑按钮:复制、编辑 */} |
| | |
| | | card={card} |
| | | formlist={this.state.formlist} |
| | | inputSubmit={this.handleSubmit} |
| | | config={config} |
| | | config={cards} |
| | | wrappedComponentRef={(inst) => this.elementFormRef = inst} |
| | | /> |
| | | </Modal> |
| | | {/* 编辑按钮:复制、编辑 */} |
| | | <Modal |
| | | title={dict['model.action'] + '-' + (card && card.copyType === 'action' ? dict['model.copy'] : dict['model.edit'])} |
| | | visible={actvisible} |
| | | width={800} |
| | | maskClosable={false} |
| | | onCancel={this.editModalCancel} |
| | | footer={[ |
| | | <Button key="cancel" onClick={this.editModalCancel}>{dict['model.cancel']}</Button>, |
| | | <Button key="confirm" type="primary" onClick={this.handleActionSubmit}>{dict['model.confirm']}</Button> |
| | | ]} |
| | | destroyOnClose |
| | | > |
| | | <ActionForm |
| | | dict={dict} |
| | | type="card" |
| | | card={card} |
| | | formlist={this.state.formlist} |
| | | inputSubmit={this.handleActionSubmit} |
| | | setting={cards.setting} |
| | | wrappedComponentRef={(inst) => this.actionFormRef = inst} |
| | | /> |
| | | </Modal> |
| | | {/* 按钮使用系统存储过程时,验证信息模态框 */} |
| | | <Modal |
| | | wrapClassName="model-table-action-verify-modal" |
| | | title={'验证信息'} |
| | | visible={profVisible} |
| | | width={'75vw'} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ profVisible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ? |
| | | <VerifyCard |
| | | card={card} |
| | | dict={dict} |
| | | config={cards} |
| | | columns={cards.columns} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> : null |
| | | } |
| | | {card && card.execMode ? |
| | | <VerifyPrint |
| | | card={card} |
| | | dict={dict} |
| | | columns={cards.columns} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> : null |
| | | } |
| | | {card && card.OpenType === 'excelIn' ? |
| | | <VerifyExcelIn |
| | | card={card} |
| | | dict={dict} |
| | | columns={cards.columns} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> : null |
| | | } |
| | | {card && card.OpenType === 'excelOut' ? |
| | | <VerifyExcelOut |
| | | card={card} |
| | | dict={dict} |
| | | config={cards} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> : null |
| | | } |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | |
| | | export default CardCellComponent |