\r\n {listColor.map(i => {\r\n return (\r\n
{onChangeColor(i)}}\r\n />\r\n );\r\n })}\r\n
\r\n );\r\n};\r\n\r\nexport default compose(connect(state => ({\r\n getCboDuty: state.general.getCboDuty2,\r\n getDataCboPosition: state.W09F4000.getDataCboPosition,\r\n }),\r\n (dispatch) => ({\r\n w09f4000Actions: bindActionCreators(W09F4000Actions, dispatch),\r\n generalActions: bindActionCreators(generalActions, dispatch),\r\n })\r\n), withStyles(styles, {withTheme: true}))(W09F4000);\r\n","\r\nimport React from \"react\";\r\nimport { withStyles } from \"@material-ui/core\";\r\nimport { useTheme } from \"diginet-core-ui/theme\";\r\nimport { Typography, Avatar, Tooltip } from 'diginet-core-ui/components'\r\nimport Config from '../../../../config';\r\n\r\nconst coreTheme = useTheme();\r\nconst { spacing, colors, colors: {white, system:{rest}, dark, dark6} } = coreTheme;\r\n\r\nconst styles = {\r\n wrapperItem: {\r\n position:'relative',\r\n boxShadow:'0px 2px 2px rgba(0, 0, 0, 0.25)',\r\n borderRadius: 4,\r\n minWidth:200,\r\n width: 240,\r\n backgroundColor: white,\r\n '&:hover':{\r\n boxShadow:'0px 4px 4px rgba(0, 0, 0, 0.25)'\r\n },\r\n '& .overflow-one-line':{\r\n whiteSpace:'pre !important',\r\n maxWidth:'100% !important'\r\n }\r\n },\r\n footerItem: {\r\n display: 'flex',\r\n textAlign:'left',},\r\n layerImg: {\r\n top: 45,\r\n left: '50%',\r\n transform: 'translate(-50%, 0)',\r\n zIndex: 1,\r\n position: 'absolute',\r\n },\r\n nodeNumber: {\r\n position: 'absolute',\r\n bottom: -14,\r\n minWidth: 28,\r\n height: 28,\r\n zIndex: 1,\r\n borderRadius: '50%',\r\n border:`2px solid ${white}`,\r\n cursor: \"pointer\",\r\n left: 'calc(50% - 14px)',\r\n display:'flex !important',\r\n boxShadow:'0px 2px 2px rgba(0, 0, 0, 0.25)'\r\n },\r\n styleOrgChartName: {\r\n display:'flex !important',\r\n alignItems:'flex-start',\r\n justifyContent: 'center',\r\n width: '100%'\r\n },\r\n styleOverFlowText: {\r\n whiteSpace: \"nowrap\",\r\n overflow: \"hidden\",\r\n textOverflow: \"ellipsis\",\r\n display:'block'\r\n },\r\n styleTooltip: {\r\n fontSize: 14\r\n },\r\n cursorPointer: {\r\n cursor: \"pointer\"\r\n },\r\n showMoreUser:{\r\n backgroundColor: rest,\r\n width: 40,\r\n minWidth: 40,\r\n height: 40,\r\n display: \"flex !important\",\r\n alignItems: \"center !important\",\r\n justifyContent: \"center\",\r\n color: white,\r\n borderRadius: 20,\r\n cursor: 'pointer'\r\n },\r\n\r\n};\r\n\r\nclass ItemOrgChart extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n iPermission: 0,\r\n tab: 0,\r\n showW09F4001Popup: false,\r\n itemDataNode: null,\r\n isHiddenW09F4010: false\r\n };\r\n }\r\n\r\n showPopup = () => {\r\n const {data, onW09F4001Popup} = this.props;\r\n if (onW09F4001Popup) onW09F4001Popup(data);\r\n };\r\n\r\n toggleShowItem = (e) => {\r\n e.stopPropagation();\r\n const {node, data, orgchart} = this.props;\r\n if (orgchart && data.countChildren > 0) {\r\n const nodeState = orgchart._getNodeState(node, \"children\");\r\n\r\n if (nodeState.exist && nodeState.visible) {\r\n orgchart.hideChildren(node);\r\n this._scrollToNode(node, orgchart);\r\n } else {\r\n orgchart.showChildren(node);\r\n this._scrollToNode(node, orgchart, 400);\r\n }\r\n }\r\n };\r\n\r\n _scrollToNode = (node, orgchart, timeout = 700) => {\r\n const wrapperChart = orgchart.closest(\"div\");\r\n if (wrapperChart && wrapperChart.offsetWidth && node) {\r\n setTimeout(() => {\r\n let lastTf = window.getComputedStyle(orgchart).transform;\r\n let containerPartWidth = orgchart.offsetWidth/2 - 100;\r\n let containerPartHeight = orgchart.offsetHeight/2 - 220;\r\n\r\n let newX = 0, newY = 0;\r\n if (lastTf === 'none') {\r\n orgchart.style.transform = 'matrix(1, 0, 0, 1, 0, 0)';\r\n newX = containerPartWidth - node.offsetLeft;\r\n newY = containerPartHeight - node.offsetTop;\r\n if (!lastTf.includes('3d')) {\r\n orgchart.style.transform = 'matrix(1, 0, 0, 1, ' + newX + ', ' + newY + ')';\r\n } else {\r\n orgchart.style.transform = 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + newX + ', ' + newY + ', 0, 1)';\r\n }\r\n } else {\r\n let matrix = lastTf.split(',');\r\n newX = containerPartWidth - node.offsetLeft;\r\n newY = containerPartHeight - node.offsetTop;\r\n if (!lastTf.includes('3d')) {\r\n matrix[4] = newX * matrix[3];\r\n matrix[5] = (newY * matrix[3]) + ')';\r\n } else {\r\n matrix[12] = newX * matrix[3];\r\n matrix[13] = (newY * matrix[3]);\r\n }\r\n orgchart.style.transform = matrix.join(',');\r\n }\r\n }, 700);\r\n }\r\n };\r\n\r\n render() {\r\n const {classes, data, showAvatar, colorOrg} = this.props;\r\n\r\n let levelColor = 5 - parseInt(data.level || 0);\r\n if(levelColor < 1) levelColor = 1;\r\n\r\n const bgColor = colors?.[`${colorOrg}${levelColor}`];\r\n const color = data.level > 2 ? dark : white;\r\n\r\n const headerTitle = (\r\n <>\r\n
\r\n {data?.OrgChartName || \"\"}\r\n \r\n \r\n {(Number(data?.Quantity) || Number(data?.Quantity) === 0) &&\r\n
\r\n {` (${Number(data?.Quantity)})`}\r\n \r\n }\r\n >\r\n );\r\n\r\n const lengthUser = data.OrgCharts?.length > 6 ? 7 : data.OrgCharts.length;\r\n const widthUser = lengthUser > 5 ? `calc(((100% - 20px) / ${lengthUser}))` : 40;\r\n\r\n let user = Config.getUser({EmployeeID: data?.OrgCharts?.[0].RepresentEmployeeID});\r\n\r\n return (\r\n <>\r\n
\r\n
0 ? \" \" + classes.cursorPointer : \"\")}\r\n style={{minHeight: 40 + (showAvatar ? 72 : 0)}}\r\n onClick={this.showPopup}\r\n >\r\n {/*Title*/}\r\n
\r\n \r\n \r\n {headerTitle}\r\n \r\n \r\n
\r\n {/*Content*/}\r\n
\r\n {showAvatar && data?.OrgCharts?.length > 1 && //TH không có RepresentEmployeeID thì hiện danh sách avatar\r\n
4 ? '100%' : lengthUser * 55,\r\n justifyContent: 'space-around',\r\n display:'flex'\r\n }}>\r\n {[...new Array(lengthUser).keys()].map(key => {\r\n const style = {width: widthUser, overflow: ' inherit', zIndex: key};\r\n user = Config.getUser({EmployeeID: data.OrgCharts?.[key].RepresentEmployeeID});\r\n if (key > 6) return null;\r\n if (key === 6) return (\r\n
\r\n \r\n {data.OrgCharts.length > 101 ? '99+' : `+${parseInt(data.OrgCharts.length || 0) - 6}`}\r\n \r\n
\r\n );\r\n\r\n return (\r\n
\r\n );\r\n })}\r\n
\r\n }\r\n {showAvatar && data?.OrgCharts?.length === 1 && data?.OrgCharts?.[0].RepresentEmployeeID && //TH có RepresentEmployeeID thì avatar + thông tin User\r\n
\r\n
\r\n
\r\n \r\n {user.EmployeeName || \"\"}\r\n \r\n \r\n {user.DutyName || \"\"}\r\n \r\n
\r\n
\r\n }\r\n {data?.countChildren > 0 &&\r\n
\r\n {parseInt(data?.countChildren || 0) > 99 ? '99+' : data?.countChildren}\r\n \r\n }\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n >\r\n );\r\n }\r\n\r\n}\r\n\r\nexport default withStyles(styles, {withTheme: true})(ItemOrgChart);\r\n","\r\nimport React from \"react\";\r\nimport {withStyles} from \"@material-ui/core\";\r\nimport \"./W09F4000.scss\";\r\nimport Config from \"../../../../config\";\r\nimport {Avatar, Typography} from \"diginet-core-ui/components\";\r\nimport {useTheme} from \"diginet-core-ui/theme\";\r\nimport {ButtonIcon, Typography as TypographyCore} from \"diginet-core-ui/components\";\r\nconst coreTheme = useTheme();\r\nconst {colors:{white, formal5, dark6, dark, system: { rest }}} = coreTheme;\r\nconst styles = {\r\n wrapperItem: {\r\n boxShadow: '0px 2px 2px rgba(0, 0, 0, 0.25)',\r\n borderRadius: 4,\r\n minWidth: 200,\r\n minHeight: 160,\r\n maxWidth: 400,\r\n backgroundColor: white,\r\n transition: 'all 0.1s',\r\n '&:hover':{\r\n boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',\r\n },\r\n '& .overflow-one-line':{\r\n whiteSpace:'pre !important',\r\n maxWidth:'100% !important'\r\n }\r\n },\r\n filterContainer: {\r\n padding: \"8px 16px\",\r\n borderLeft: `1px solid ${formal5}`,\r\n textAlign: 'left'\r\n },\r\n footerItem: {\r\n backgroundColor: '#FFFFFF',\r\n textAlign: 'center',\r\n padding: '8px 16px',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center'\r\n },\r\n layerImg: {\r\n top: 25,\r\n left: '50%',\r\n transform: 'translate(-50%, 0)',\r\n zIndex: 1,\r\n position: 'absolute',\r\n },\r\n userImageChild: {\r\n cursor: \"pointer\",\r\n border: '1px solid white',\r\n boxShadow: '1px 1px 2px #999',\r\n \"&:not(:first-child)\": {\r\n marginLeft: -8\r\n }\r\n },\r\n nodeNumber: {\r\n position: 'absolute',\r\n bottom: -14,\r\n minWidth: 28,\r\n height: 28,\r\n zIndex: 1,\r\n borderRadius: '50%',\r\n lineHeight: '24px',\r\n color: '#FFF',\r\n cursor: \"pointer\",\r\n left: 'calc(50% - 14px)',\r\n display:'flex !important',\r\n boxShadow:'0px 2px 2px rgba(0, 0, 0, 0.25)',\r\n border:`2px solid ${white}`\r\n },\r\n styleOrgChartName: {\r\n fontSize: 14,\r\n fontWeight: 700,\r\n color: \"#FFFFFF\",\r\n textTransform: \"uppercase\",\r\n overflow: \"hidden\",\r\n whiteSpace: \"nowrap\",\r\n textOverflow: \"ellipsis\",\r\n },\r\n styleTooltip: {\r\n fontSize: 14\r\n },\r\n iconNumberText: {\r\n width: 32,\r\n height: 32,\r\n zIndex: 100,\r\n border: \"1px solid #FFFFFF\",\r\n borderRadius: \"50%\",\r\n background: \"#7F828E\",\r\n display: \"flex\",\r\n justifyContent: \"center\",\r\n alignItems: \"center\"\r\n },\r\n buttonFilter:{\r\n position:'absolute',\r\n right: 4,\r\n top:8\r\n },\r\n showMoreUser:{\r\n backgroundColor: rest,\r\n border:`1px solid ${white}`,\r\n width: 72,\r\n minWidth: 72,\r\n height: 72,\r\n display: \"flex !important\",\r\n alignItems: \"center !important\",\r\n justifyContent: \"center\",\r\n color: white,\r\n borderRadius: 72,\r\n cursor: 'pointer'\r\n },\r\n};\r\n\r\nclass ItemPositionChart extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n iPermission: 0,\r\n tab: 0,\r\n showW09F4001Popup: false,\r\n itemDataNode: null,\r\n expanded: props.data ? props.data.expanded : true,\r\n isHiddenW09F4010: false,\r\n open: false,\r\n hoverImg: false,\r\n dataFilter: null\r\n };\r\n this.userImage = {};\r\n }\r\n\r\n showPopup = () => {\r\n const {data, onW09F4001Popup} = this.props;\r\n if (onW09F4001Popup && data && data.DutyGroup && data.DutyGroup.length > 0) onW09F4001Popup(data);\r\n };\r\n\r\n toggleShowItem = (e) => {\r\n e.stopPropagation();\r\n const {node, data, orgchart} = this.props;\r\n if (orgchart && data.countChildren > 0) {\r\n const nodeState = orgchart._getNodeState(node, \"children\");\r\n\r\n if (nodeState.exist && nodeState.visible) {\r\n orgchart.hideChildren(node);\r\n this._scrollToNode(node, orgchart);\r\n } else {\r\n orgchart.showChildren(node);\r\n this._scrollToNode(node, orgchart, 400);\r\n }\r\n this.setState({expanded: !this.state.expanded});\r\n }\r\n };\r\n\r\n _scrollToNode = (node, orgchart) => {\r\n const wrapperChart = orgchart.closest(\"div\");\r\n if (wrapperChart && wrapperChart.offsetWidth && node) {\r\n setTimeout(() => {\r\n let lastTf = window.getComputedStyle(orgchart).transform;\r\n let containerPartWidth = orgchart.offsetWidth/2 - 100;\r\n let containerPartHeight = orgchart.offsetHeight/2 - 180;\r\n\r\n let newX = 0, newY = 0;\r\n if (lastTf === 'none') {\r\n orgchart.style.transform = 'matrix(1, 0, 0, 1, 0, 0)';\r\n newX = containerPartWidth - node.offsetLeft;\r\n newY = containerPartHeight - node.offsetTop;\r\n if (!lastTf.includes('3d')) {\r\n orgchart.style.transform = 'matrix(1, 0, 0, 1, ' + newX + ', ' + newY + ')';\r\n } else {\r\n orgchart.style.transform = 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + newX + ', ' + newY + ', 0, 1)';\r\n }\r\n } else {\r\n let matrix = lastTf.split(',');\r\n newX = containerPartWidth - node.offsetLeft;\r\n newY = containerPartHeight - node.offsetTop;\r\n if (!lastTf.includes('3d')) {\r\n matrix[4] = newX * matrix[3];\r\n matrix[5] = newY + ')';\r\n } else {\r\n matrix[12] = newX * matrix[3];\r\n matrix[13] = newY;\r\n }\r\n orgchart.style.transform = matrix.join(',');\r\n }\r\n }, 700);\r\n }\r\n };\r\n \r\n componentDidMount() {\r\n if (this.userImage) {\r\n Object.keys(this.userImage).forEach(u => {\r\n this.userImage[u].userImage.addEventListener(\"mouseover\", () => this.onMouseOver(this.userImage[u].userImage));\r\n this.userImage[u].userImage.addEventListener(\"mouseleave\", () => this.onMouseLeave(this.userImage[u].userImage));\r\n });\r\n // u.userImage.addEventListener(\"mouseleave\", () => this.onMouseLeave(u.userImage));\r\n // });\r\n }\r\n\r\n const { listDutyFilter, data, isExpanded } = this.props;\r\n if((listDutyFilter.includes(data.DutyID) || isExpanded) && data?.IsFilter === 1){\r\n this._loadFilter(data);\r\n }\r\n }\r\n\r\n onMouseOver = (e) => {\r\n e.classList.add(\"w09f4000-user-image-hover-item\");\r\n };\r\n onMouseLeave = (e) => {\r\n e.classList.remove(\"w09f4000-user-image-hover-item\");\r\n };\r\n\r\n renderItemHover = (user) => {\r\n return (\r\n
\r\n {user && {`${user.UserName} - ${user.DutyName}`} }\r\n
\r\n )\r\n };\r\n\r\n _loadFilter = (data) => {\r\n if(this.loadingFilter) return;\r\n this.loadingFilter = true;\r\n\r\n const {loadFilter} = this.props;\r\n const {dataFilter} = this.state;\r\n\r\n if(dataFilter){\r\n this.setState({dataFilter: null},()=>{\r\n this.loadingFilter = false;\r\n if(this.refs[\"refBtnFilter\"]) {\r\n this.refs[\"refBtnFilter\"].blur();\r\n }\r\n });\r\n loadFilter(data, ()=>{}, true);\r\n return null;\r\n }\r\n loadFilter({DutyID: data.DutyID}, data => {\r\n this.setState({dataFilter: data},(()=>{\r\n this.loadingFilter = false;\r\n }))\r\n })\r\n };\r\n\r\n render() {\r\n const {classes, data, colorOrg} = this.props;\r\n const { dataFilter } = this.state;\r\n const DutyGroup = data && data.DutyGroup ? data.DutyGroup : [];\r\n\r\n let levelColor = 5 - parseInt(data.level || 0);\r\n if(levelColor < 1) levelColor = 1;\r\n\r\n const bgColor = coreTheme.colors?.[`${colorOrg}${levelColor}`];\r\n const color = data.level > 2 ? dark : white;\r\n\r\n const lengthUser = DutyGroup?.length > 2 ? 3 : DutyGroup?.length; // length > 2 ? 3 : length ( cái cuối là số 99+)\r\n const widthUser = lengthUser > 1 ? `calc(100% / ${lengthUser})` : 72;\r\n const user = Config.getUser({EmployeeID: DutyGroup?.[0]?.EmployeeID});\r\n\r\n return (\r\n <>\r\n
\r\n
\r\n {/*Content*/}\r\n
\r\n
2 ? '80%' : '100%',\r\n maxWidth: 200,\r\n justifyContent: 'space-around'\r\n }}\r\n >\r\n {[...new Array(lengthUser).keys()].map(key => {\r\n const style = { width:widthUser, overflow:' inherit', zIndex: key };\r\n if(key > 2) return null; // show maximum 2 Duty\r\n if(key === 2) return ( // show number length Duty if length > 2\r\n
\r\n \r\n {DutyGroup?.length > 101 ? '99+' : parseInt(DutyGroup?.length || 0) - 2}\r\n \r\n
\r\n );\r\n\r\n const user = Config.getUser({EmployeeID: DutyGroup[key].EmployeeID});\r\n return( // show avatar Duty\r\n
\r\n );\r\n })}\r\n
\r\n
\r\n \r\n {DutyGroup?.length === 1 && user.EmployeeName ? user.EmployeeName : \"\"}\r\n \r\n \r\n {user.DutyName || \"\"}\r\n \r\n
\r\n {data?.IsFilter === 1 &&\r\n
this._loadFilter(data)}\r\n />\r\n }\r\n \r\n {/*Filter*/}\r\n {dataFilter &&\r\n
\r\n \r\n {dataFilter[0]?.Label || ''}\r\n \r\n\r\n {!dataFilter.length && // Không có dữ liệu\r\n \r\n {Config.lang(\"Khong_co_du_lieu\")}\r\n \r\n }\r\n\r\n {dataFilter?.map(i => {\r\n return \r\n {`${i.FilterValueName}: ${i.Total}`}\r\n \r\n })}\r\n
\r\n }\r\n {DutyGroup.length > 0 && data.countChildren > 0 &&\r\n
\r\n {parseInt(data?.countChildren || 0) > 99 ? '99+' : data?.countChildren}\r\n \r\n }\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n >\r\n );\r\n }\r\n\r\n}\r\n\r\nexport default withStyles(styles, {withTheme: true})(ItemPositionChart);\r\n","/**\r\n * @copyright 2019 @ DigiNet\r\n * @author TRIHAO\r\n * @create 2/2/2021\r\n * @Example\r\n */\r\n\r\nimport React, {useCallback, useEffect, useMemo, useRef, useState} from \"react\";\r\nimport {bindActionCreators, compose} from \"redux\";\r\nimport {IconButton, makeStyles, Typography} from \"@material-ui/core\";\r\nimport {connect} from \"react-redux\";\r\nimport ActionToolbar from \"../../../common/toolbar/action-toolbar\";\r\nimport ButtonGeneral from \"../../../common/button/button-general\";\r\nimport UserImage from \"../../../common/user/user-image\";\r\nimport Icons from \"../../../common/icons/\";\r\nimport Config from \"../../../../config\";\r\nimport * as W09F3010Actions\r\n from \"../../../../redux/W0X/W09F3010/W09F3010_actions\";\r\nimport {Image, FormGroup, Row, Col} from \"react-bootstrap\";\r\nimport {browserHistory} from \"react-router\";\r\nimport _ from \"lodash\";\r\nimport {LoadPanel} from \"devextreme-react\";\r\nimport Popover\r\n from \"../../../../components/grid-container/popover-action\";\r\nimport History from \"../../../libs/history\";\r\nimport * as generalActions from \"../../../../redux/general/general_actions\";\r\nimport Tabs from \"@material-ui/core/Tabs\";\r\nimport Tab from \"@material-ui/core/Tab\";\r\nimport Divider from \"@material-ui/core/Divider\";\r\nimport TabContent, {TabPanel} from \"../../../common/tabs/tab-content\";\r\nimport W09F3010Member from \"./utils/W09F3010Member\";\r\nimport SelectEmployees from \"./utils/SelectEmployees\";\r\nimport CDN from \"../../../CDN\";\r\nimport DOMPurify from \"dompurify\";\r\n\r\nconst useStyles = makeStyles(() => ({\r\n root: {\r\n background: '#FFFFFF',\r\n boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',\r\n borderRadius: 4\r\n },\r\n divImage: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n position: 'relative',\r\n height: 200,\r\n '& img': {\r\n width: '100%',\r\n height: '100%',\r\n objectFit: 'contain'\r\n },\r\n '&:hover .icon-edit': {\r\n display: 'block'\r\n }\r\n },\r\n divContent: {\r\n padding: '0px 15px 15px 15px'\r\n },\r\n divMember: {\r\n minHeight: 40\r\n },\r\n divItemMember: {\r\n background: '#FFFFFF',\r\n boxShadow: '0px 2px 2px rgba(0, 0, 0, 0.25)',\r\n borderRadius: 4,\r\n padding: 15,\r\n marginBottom: 10,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n textAlign: 'center',\r\n minHeight: 180,\r\n position: 'relative',\r\n '& .divItemMember_button': {\r\n position: 'absolute',\r\n top: 5,\r\n right: 5\r\n }\r\n },\r\n iconEdit: {\r\n position: 'absolute',\r\n top: 10,\r\n right: 10,\r\n display: 'none',\r\n transition: 'all 0.4s',\r\n '& button': {\r\n backgroundColor: '#FFFFFF'\r\n }\r\n }\r\n}));\r\n\r\nconst W09F3010 = (props) => {\r\n const getInfo = useCallback((flag) => {\r\n const {location} = props;\r\n const {mode, GroupID} = Config.getUrlParams(props);\r\n if (location && location.state) {\r\n return {\r\n mode: mode || 'add',\r\n GroupID: GroupID || \"\"\r\n }\r\n } else {\r\n if (flag) {\r\n browserHistory.push(Config.getRootPath() + \"W09F3000\");\r\n return null;\r\n }\r\n return {};\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [props.location]);\r\n\r\n const classes = useStyles();\r\n\r\n const {GroupID} = getInfo() || {};\r\n const {getForm, getMembers} = props;\r\n const [tabKey, setTabKey] = useState(0);\r\n const [loading, setLoading] = useState(false);\r\n const [showSelectEmployees, setShowSelectEmployees] = useState(false);\r\n\r\n const refAvatar = useRef(null);\r\n const refAction = useRef(null);\r\n\r\n const loadForm = () => {\r\n const params = {\r\n Language: Config.language || \"84\",\r\n GroupID: GroupID || \"\"\r\n };\r\n setLoading(true);\r\n props.W09F3010Actions.loadForm(params, error => {\r\n setLoading(false);\r\n if (error) {\r\n Config.popup2.show(\"ERROR\", error);\r\n return false;\r\n }\r\n });\r\n };\r\n const loadMembers = () => {\r\n const params = {\r\n GroupID: GroupID || \"\"\r\n };\r\n setLoading(true);\r\n props.W09F3010Actions.loadMembers(params, error => {\r\n setLoading(false);\r\n if (error) {\r\n Config.popup2.show(\"ERROR\", error);\r\n return false;\r\n }\r\n });\r\n };\r\n\r\n useEffect(() => {\r\n if (!getInfo(true)) return;\r\n loadForm();\r\n loadMembers();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n const onClosePopover = () => {\r\n if (refAction && refAction.current) refAction.current.instance.hide();\r\n };\r\n\r\n const onOpenModal = () => {\r\n setShowSelectEmployees(true);\r\n };\r\n const onCloseModal = () => {\r\n setShowSelectEmployees(false);\r\n };\r\n\r\n const onBack = () => {\r\n browserHistory.goBack();\r\n };\r\n\r\n const onChangeTab = (e, value) => {\r\n setTabKey(value);\r\n };\r\n\r\n const checkFileType = filename => {\r\n const extension = filename.substr(filename.lastIndexOf(\".\")).toLowerCase();\r\n const allowedExtensions = [\".jpg\", \".png\"];\r\n if (extension.length > 0) {\r\n if (allowedExtensions.indexOf(extension) === -1) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n };\r\n\r\n const onUploadFile = (e) => {\r\n if (!e) return false;\r\n const arrFile = e.target.files;\r\n const sizeLimit = 5000000;\r\n for (let i = 0; i < arrFile.length; i++) {\r\n let message = '';\r\n if (arrFile[i].size / 1024 > Number(sizeLimit)) {\r\n message = Config.lang(\"Dung_luong_File_khong_duoc_lon_hon\") + \" \" + sizeLimit + ' KB
';\r\n Config.popup2.show(\"INFO\", message);\r\n } else if (checkFileType(arrFile[i].name) === false) {\r\n message = Config.lang(\"Dinh_dang_file_khong_hop_le\");\r\n Config.popup2.show(\"INFO\", message);\r\n } else {\r\n setLoading(true);\r\n CDN.uploadFile([arrFile[i]], null, (error, data) => {\r\n if (error) {\r\n setLoading(false);\r\n Config.popup2.show(\"ERROR\", error);\r\n return false;\r\n }\r\n if (data && data.paths && data.paths.length > 0) {\r\n const item = data.paths[0];\r\n const params = {\r\n GroupID,\r\n GroupPicture: _.get(item, 'url', _.get(item, 'filePath', ''))\r\n };\r\n props.W09F3010Actions.updatePicGroup(params, async (errors) => {\r\n setLoading(false);\r\n if (errors) {\r\n Config.popup2.show(\"ERROR\", errors);\r\n return false;\r\n } else {\r\n loadForm();\r\n Config.notify.show(\"success\", Config.lang(\"Luu_thanh_cong\"), 2000);\r\n }\r\n })\r\n } else {\r\n Config.popup2.show(\"INFO\", Config.lang(\"Co_loi_xay_ra_trong_qua_trinh_xu_ly\"));\r\n }\r\n });\r\n }\r\n }\r\n };\r\n\r\n const onShowAction = (e) => {\r\n if (refAction && refAction.current) refAction.current.instance.show(e.target);\r\n };\r\n\r\n const onAction = useCallback(async (mode, data) => {\r\n if (!mode) return false;\r\n const {MemberID} = data || {};\r\n onClosePopover();\r\n switch (mode) {\r\n case \"changeAvatar\":\r\n if (refAvatar && refAvatar.current) refAvatar.current.click();\r\n break;\r\n case \"addMember\":\r\n onOpenModal();\r\n break;\r\n case \"leaveGroup\":\r\n Config.popup2.show(\"YES_NO\", Config.lang(\"Ban_co_chac_muon_roi_nhom_khong\"), () => {\r\n const params = {\r\n GroupID,\r\n MemberID: Config.profile.UserID || \"\"\r\n };\r\n setLoading(true);\r\n props.W09F3010Actions.leaveGroup(params, async (errors) => {\r\n setLoading(false);\r\n if (errors) {\r\n Config.popup2.show(\"ERROR\", errors);\r\n return false;\r\n } else {\r\n Config.notify.show(\"success\", Config.lang(\"Xoa_thanh_cong\"), 2000);\r\n await saveHistory(data);\r\n loadMembers();\r\n }\r\n })\r\n });\r\n break;\r\n case \"isAdmin\":\r\n const params = {\r\n GroupID,\r\n MemberID: MemberID,\r\n Role: _.get(data, \"newRole\", \"\")\r\n };\r\n setLoading(true);\r\n props.W09F3010Actions.updateRole(params, async (errors) => {\r\n setLoading(false);\r\n if (errors) {\r\n Config.popup2.show(\"ERROR\", errors);\r\n return false;\r\n } else {\r\n await saveHistory(data, true);\r\n loadMembers();\r\n Config.notify.show(\"success\", Config.lang(\"Luu_thanh_cong\"), 2000);\r\n }\r\n })\r\n break;\r\n case \"removeFromGroup\":\r\n Config.popup2.show(\"YES_NO\", Config.lang(\"Ban_co_chac_muon_xoa_thanh_vien_nay_khoi_nhom_khong\"), () => {\r\n const params = {\r\n GroupID,\r\n MemberID: MemberID\r\n };\r\n setLoading(true);\r\n props.W09F3010Actions.leaveGroup(params, async (errors) => {\r\n setLoading(false);\r\n if (errors) {\r\n Config.popup2.show(\"ERROR\", errors);\r\n return false;\r\n } else {\r\n Config.notify.show(\"success\", Config.lang(\"Xoa_thanh_cong\"), 2000);\r\n await saveHistory(data);\r\n loadMembers();\r\n }\r\n })\r\n });\r\n break;\r\n default:\r\n break;\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n const onChosen = () => {\r\n loadMembers();\r\n };\r\n\r\n const saveHistory = async (data, isUpdateRole = false) => {\r\n const {Role, newRole, MemberID} = data;\r\n const {GroupID, GroupName} = props.getForm ?? {GroupID: _.get(data, \"GroupID\", \"\"), GroupName: \"\"};\r\n const {UserID, UserName} = Config.getUser({EmployeeID: MemberID}) ?? {UserID: \"\", UserName: \"\"};\r\n let _data = {\r\n GroupName,\r\n User: `${Config.profile.UseID} - ${Config.profile.UserName}`\r\n };\r\n\r\n let captions = {\r\n GroupName: \"Ten_nhom\",\r\n User: \"data_User\"\r\n };\r\n\r\n const captionOldRoles = [\"thanh_vien\", \"quan_tri\", \"thanh_vien_vai_tro_quan_tri\"];\r\n const captionNewRoles = [\"thanh_vien\", \"quan_tri_vien\", \"thanh_vien_vai_tro_quan_tri\"];\r\n\r\n let options = {\r\n data: _data,\r\n captions: captions,\r\n ModuleID: \"D09\",\r\n TransID: GroupID,\r\n action: 3,\r\n TransactionID: \"W09F3000\",\r\n TransactionName: \"Nhóm\",\r\n };\r\n\r\n if (GroupID) {\r\n if (isUpdateRole) {\r\n options = {\r\n ...options,\r\n data: {\r\n ..._data,\r\n NewRole: {\r\n \"add\": [{\r\n \"ma_nhan_vien\": UserID ?? \"\",\r\n \"ten_nhan_vien\": UserName ?? \"\"\r\n }]\r\n },\r\n OldRole: {\r\n \"removed\": [{\r\n \"ma_nhan_vien\": UserID ?? \"\",\r\n \"ten_nhan_vien\": UserName ?? \"\"\r\n }]\r\n }\r\n },\r\n dataCompare: {\r\n ..._data,\r\n NewRole: {\r\n \"add\": [{\r\n \"ma_nhan_vien\": UserID ?? \"\",\r\n \"ten_nhan_vien\": UserName ?? \"\"\r\n }]\r\n },\r\n OldRole: {\r\n \"removed\": [{\r\n \"ma_nhan_vien\": UserID ?? \"\",\r\n \"ten_nhan_vien\": UserName ?? \"\"\r\n }]\r\n }\r\n },\r\n captions: {\r\n ...captions,\r\n NewRole: captionNewRoles[newRole],\r\n OldRole: captionOldRoles[Role],\r\n },\r\n action: 1,\r\n TransactionID: \"W09F3000\",\r\n TransactionName: \"Chi tiết nhóm\",\r\n };\r\n }\r\n const history = new History(options);\r\n // const allData = await history.get();\r\n // history.createDetailHistory(\"Nhan_vien\", [], [], captions,\"key\", null, options ); //Create detail..\r\n // console.log('test', allData);\r\n await history.save();\r\n } else {\r\n Config.notify.show(\"error\", Config.lang(\"Luu_lich_su_khong_thanh_cong\"), 2000);\r\n }\r\n };\r\n\r\n const renderMembersWithRole = useCallback((role1 = 0, role2) => {\r\n const Members = getMembers || [];\r\n let listMembers = !_.isUndefined(role1) ? Members.filter(m => m.Role === role1) : Members;\r\n listMembers = !_.isUndefined(role2) ? listMembers.concat(Members.filter(m => m.Role === role2)) : listMembers;\r\n return (\r\n
\r\n {listMembers && listMembers.map((member, idx) => {\r\n return \r\n })}\r\n
\r\n );\r\n }, [getMembers]);\r\n\r\n const GroupPicture = useMemo(() => {\r\n let groupPicture = _.get(getForm, \"GroupPicture\", \"\");\r\n return groupPicture\r\n ? (groupPicture.includes('http') ? groupPicture : Config.getCDNPath() + groupPicture)\r\n : require(\"../../../../assets/images/general/no-image.svg\");\r\n }, [getForm]);\r\n return (\r\n <>\r\n
\r\n
\r\n
\r\n \r\n {_.get(getForm, \"IsAdmin\", 0) === 1 && onAction('addMember')}\r\n />}\r\n onAction(\"leaveGroup\", getForm)}\r\n />\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n {_.get(getForm, \"IsAdmin\", 0) !== 2 &&\r\n \r\n \r\n }\r\n
\r\n \r\n \r\n
\r\n \r\n \r\n \r\n {Config.lang(\"Gioi_thieu_ve_nhom\")} \r\n \r\n \r\n \r\n \r\n \r\n \r\n {Config.lang(\"Thanh_vien\")}
\r\n \r\n {renderMembersWithRole(0, 2)}\r\n
\r\n {Config.lang(\"Quan_tri\")}
\r\n \r\n {renderMembersWithRole(1, 2)}\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n \r\n
\r\n \r\n >\r\n );\r\n};\r\n\r\nexport default compose(\r\n connect(\r\n state => ({\r\n getForm: state.W09F3010.getForm,\r\n getMembers: state.W09F3010.getMembers,\r\n }),\r\n dispatch => ({\r\n generalActions: bindActionCreators(generalActions, dispatch),\r\n W09F3010Actions: bindActionCreators(W09F3010Actions, dispatch)\r\n })\r\n ),\r\n)(W09F3010);\r\n","/**\r\n * @copyright 2019 @ DigiNet\r\n * @author TRIHAO\r\n * @create 2/5/2021\r\n * @Example\r\n */\r\n\r\nimport React, {useMemo, useRef, useState} from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport {IconButton, makeStyles} from \"@material-ui/core\";\r\nimport Config from \"../../../../../config\";\r\nimport * as _ from \"lodash\";\r\nimport Grid from \"@material-ui/core/Grid\";\r\nimport UserImage from \"../../../../common/user/user-image\";\r\nimport Icons from \"../../../../common/icons\";\r\nimport ButtonGeneral from \"../../../../common/button/button-general\";\r\nimport Popover from \"../../../../../components/grid-container/popover-action\";\r\nimport {Key} from \"diginet-core-ui/icons\";\r\n\r\nconst useStyles = makeStyles(() => ({\r\n divItemMember: {\r\n background: '#FFFFFF',\r\n boxShadow: '0px 2px 2px rgba(0, 0, 0, 0.25)',\r\n borderRadius: 4,\r\n padding: 15,\r\n marginBottom: 10,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n textAlign: 'center',\r\n minHeight: 180,\r\n position: 'relative',\r\n '& .divItemMember_key': {\r\n position: 'absolute',\r\n top: 5,\r\n left: 5,\r\n \"&.primary_key\": {}\r\n },\r\n '& .divItemMember_button': {\r\n display: 'none',\r\n position: 'absolute',\r\n top: 5,\r\n right: 5\r\n },\r\n '&:hover .divItemMember_button': {\r\n display: 'block'\r\n }\r\n }\r\n}));\r\n\r\nconst W09F3010Member = React.memo((props) => {\r\n\r\n const classes = useStyles();\r\n const {data, members, onAction} = props;\r\n const [selectedMember, setSelectedMember] = useState(null);\r\n const refAction = useRef(null);\r\n\r\n const isAdmin = useMemo(() => _.get(data, \"IsAdmin\", 0), [data]);\r\n const listMembers = members || [];\r\n\r\n const onShowAction = (e, data) => {\r\n if (!e) return false;\r\n setSelectedMember(data);\r\n if (refAction && refAction.current) refAction.current.instance.show(e.target);\r\n };\r\n\r\n const _onAction = (key, data) => {\r\n if (refAction && refAction.current) refAction.current.instance.hide();\r\n if (onAction) onAction(key, data);\r\n\r\n };\r\n\r\n const getMenuRole = (role) => {\r\n if (_.isNull(role)) return \"\";\r\n const numberRole = _.toNumber(role);\r\n let menuRole = [];\r\n if (numberRole !== 0) {\r\n menuRole = [...menuRole, {name: Config.lang(\"Chi_dinh_lam_thanh_vien\"), role: 0}];\r\n }\r\n if (numberRole !== 1) {\r\n menuRole = [...menuRole, {name: Config.lang(\"Chi_dinh_lam_quan_tri_vien\"), role: 1}];\r\n }\r\n if (numberRole !== 2) {\r\n menuRole = [...menuRole, {name: Config.lang(\"Chi_dinh_lam_thanh_vien_vai_tro_quan_tri\"), role: 2}]\r\n }\r\n return menuRole;\r\n };\r\n\r\n const menuRole = getMenuRole(_.get(selectedMember, \"Role\", null));\r\n\r\n return (\r\n <>\r\n {Boolean(isAdmin) &&
\r\n \r\n {_.map(menuRole, (item, i) => _onAction('isAdmin', {...selectedMember, newRole: item.role})}\r\n />)}\r\n _onAction('removeFromGroup', selectedMember)}\r\n />\r\n
\r\n }\r\n {listMembers && listMembers.length > 0 &&
\r\n {listMembers && listMembers.map((member, idx) => {\r\n const isHide = isAdmin !== 1 || Config.profile.UserID === _.get(member, \"MemberID\", \"\");\r\n const user = Config.getUser({UserID: _.get(member, \"MemberID\", \"\")});\r\n const memberRole = _.get(member,\"Role\", 0);\r\n return \r\n \r\n {!!memberRole &&
\r\n \r\n
}\r\n
\r\n
{Config.sub_text(_.get(member, \"UserName\", _.get(user, \"UserName\", \"\")), 25)}
\r\n
{_.get(member, \"MemberID\", \"\")}
\r\n
\r\n {!isHide &&\r\n onShowAction(e, member)}>\r\n \r\n }\r\n
\r\n
\r\n \r\n })}\r\n }\r\n {listMembers && listMembers.length <= 0 &&\r\n
{Config.lang(\"DHR_Khong_co_du_lieu\")}
}\r\n >\r\n );\r\n}, (prevProps, nextProps) => {\r\n return JSON.stringify(prevProps.data) === JSON.stringify(nextProps.data)\r\n && JSON.stringify(prevProps.members) === JSON.stringify(nextProps.members);\r\n});\r\n\r\nW09F3010Member.propTypes = {\r\n data: PropTypes.object,\r\n members: PropTypes.array,\r\n\r\n onAction: PropTypes.func\r\n};\r\n\r\nexport default W09F3010Member;\r\n","/**\r\n * @copyright 2019 @ DigiNet\r\n * @author TRIHAO\r\n * @create 2/3/2021\r\n * @Example\r\n */\r\n\r\nimport React, {useCallback, useEffect, useMemo, useRef, useState} from \"react\";\r\nimport {connect} from \"react-redux\";\r\nimport {bindActionCreators, compose} from \"redux\";\r\nimport PropTypes from \"prop-types\";\r\nimport {FormGroup} from \"react-bootstrap\";\r\nimport {Grid} from \"@material-ui/core\";\r\nimport Modal from \"../../../../common/modal/modal\";\r\nimport ButtonGeneral from \"../../../../common/button/button-general\";\r\nimport * as generalActions from \"../../../../../redux/general/general_actions\";\r\nimport Config from \"../../../../../config\";\r\nimport * as _ from \"lodash\";\r\nimport {Column} from \"devextreme-react/data-grid\";\r\nimport GridContainer from \"../../../../grid-container/grid-container\";\r\nimport UserImage from \"../../../../common/user/user-image\";\r\nimport SearchIcon from '@material-ui/icons/Search';\r\nimport IconButton from \"@material-ui/core/IconButton\";\r\nimport TextField from \"../../../../common/form-material/textfield\";\r\nimport * as W09F3010Actions\r\n from \"../../../../../redux/W0X/W09F3010/W09F3010_actions\";\r\n\r\n// const useStyles = makeStyles(theme => ({}));\r\n\r\nconst SelectEmployees = React.memo((props) => {\r\n\r\n const _initDataSource = {\r\n total: 0,\r\n rows: []\r\n };\r\n const _initFilter = {\r\n search: \"\",\r\n limit: 20,\r\n skip: 0\r\n };\r\n const {open, title, data, allowSaveData, keyExpr, valueExpr, displayExpr, FormID, loadParams, autoSearch} = props;\r\n const [loading, setLoading] = useState(false);\r\n\r\n const keys = useMemo(() => {\r\n return data ? data.map(d => d[keyExpr]) : [];\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [data, open]);\r\n const [dataSource, setDataSource] = useState(_initDataSource);\r\n const filter = useRef(_initFilter);\r\n const tmpSelectedRowKeys = useRef([]);\r\n const tmpSelectedRowData = useRef([]);\r\n const dataGrid = useRef(null);\r\n const dataGridSelected = useRef(null);\r\n const changePage = useRef(false);\r\n const changeDataSource = useRef(false);\r\n const searchTimeout = useRef(null);\r\n\r\n const loadCboEmployees = (isReset) => {\r\n const params = {\r\n HostID: \"\",\r\n Type: \"EmployeeID\",\r\n FormID: FormID,\r\n ...loadParams,\r\n Language: Config.language || \"84\",\r\n skip: filter.current.skip,\r\n limit: filter.current.limit,\r\n search: filter.current.search,\r\n };\r\n if (!isReset) {\r\n changePage.current = true;\r\n }\r\n setLoading(true);\r\n props.generalActions.getCboEmployees(params, (error, data) => {\r\n setLoading(false);\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n return false;\r\n }\r\n if (data) {\r\n setDataSource(data);\r\n }\r\n });\r\n };\r\n\r\n useEffect(() => {\r\n if (open) {\r\n tmpSelectedRowKeys.current = keys;\r\n tmpSelectedRowData.current = data ? [...data] : [];\r\n loadCboEmployees(true);\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n changeDataSource.current = true;\r\n // _setSelected(true);\r\n }, [dataSource]);\r\n\r\n const onSave = () => {\r\n const {saveParams, onChosen} = props;\r\n if (allowSaveData) {\r\n const params = {\r\n ...saveParams,\r\n data: JSON.stringify(tmpSelectedRowKeys.current),\r\n };\r\n setLoading(true);\r\n props.W09F3010Actions.selectedEmployees(params, (errors) => {\r\n setLoading(false);\r\n if (errors) {\r\n Config.popup.show('ERROR', errors);\r\n return false;\r\n }\r\n if (onChosen) onChosen({\r\n selectedRowKeys: tmpSelectedRowKeys.current,\r\n selectedRowsData: tmpSelectedRowData.current\r\n });\r\n onClose();\r\n });\r\n } else {\r\n if (onChosen) onChosen({\r\n selectedRowKeys: tmpSelectedRowKeys.current,\r\n selectedRowsData: tmpSelectedRowData.current\r\n });\r\n onClose();\r\n }\r\n };\r\n\r\n const onChangePage = (page) => {\r\n filter.current.skip = page * filter.current.limit;\r\n loadCboEmployees();\r\n };\r\n\r\n const onChangePerPage = (per) => {\r\n filter.current.skip = 0;\r\n filter.current.limit = per;\r\n loadCboEmployees();\r\n };\r\n\r\n const onFilter = () => {\r\n filter.current.skip = 0;\r\n loadCboEmployees();\r\n };\r\n\r\n const onClose = () => {\r\n const {onClose} = props;\r\n if (onClose) onClose();\r\n };\r\n\r\n const _setSelected = (flag) => {\r\n if (dataGrid && dataGrid.current) {\r\n let selected = tmpSelectedRowKeys.current;\r\n if (flag) {\r\n selected = [];\r\n dataSource.rows.forEach(d => {\r\n if (tmpSelectedRowKeys.current.indexOf(d[keyExpr]) > -1) {\r\n selected.push(d[keyExpr]);\r\n }\r\n });\r\n if (changePage.current) {\r\n setTimeout(() => changePage.current = false, 200);\r\n }\r\n }\r\n dataGrid.current.instance.selectRows(selected);\r\n }\r\n };\r\n const _setDataSelected = () => {\r\n if (dataGridSelected && dataGridSelected.current) {\r\n dataGridSelected.current.instance.option(\"dataSource\", tmpSelectedRowData.current);\r\n }\r\n };\r\n\r\n const onContentReady = () => {\r\n if (changeDataSource.current) {\r\n _setSelected(true);\r\n _setDataSelected();\r\n changeDataSource.current = false;\r\n }\r\n };\r\n\r\n const onSelectionChanged = useCallback((e) => {\r\n const {currentSelectedRowKeys, selectedRowsData, currentDeselectedRowKeys} = e;\r\n if (currentDeselectedRowKeys.length > 0) {\r\n if (!changePage.current) {\r\n tmpSelectedRowData.current = tmpSelectedRowData.current.filter((item) => {\r\n return currentDeselectedRowKeys.indexOf(item[keyExpr]) < 0;\r\n });\r\n tmpSelectedRowKeys.current = tmpSelectedRowKeys.current.filter((item) => {\r\n return currentDeselectedRowKeys.indexOf(item) < 0;\r\n });\r\n }\r\n } else if (currentSelectedRowKeys.length > 0) {\r\n for (const val of currentSelectedRowKeys) {\r\n if (tmpSelectedRowKeys.current.indexOf(val) < 0) {\r\n tmpSelectedRowKeys.current.push(val);\r\n const data = selectedRowsData.find(d => d[keyExpr] === val);\r\n if (data) tmpSelectedRowData.current.push(data);\r\n }\r\n }\r\n }\r\n if (!changePage.current) {\r\n _setSelected();\r\n _setDataSelected();\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n const renderEmployee = (e) => {\r\n const {data} = e.rows || e;\r\n if (displayExpr && typeof displayExpr === \"function\") return displayExpr();\r\n return
\r\n
\r\n
{`${data[valueExpr]} - ${data[displayExpr]}`}
\r\n
;\r\n };\r\n\r\n const handleChangeSearchValue = (value = '') => {\r\n if (autoSearch) {\r\n if (searchTimeout.current) {\r\n clearTimeout(searchTimeout.current);\r\n }\r\n searchTimeout.current = setTimeout(() => {\r\n filter.current.search = value\r\n onFilter();\r\n }, 700);\r\n }\r\n };\r\n\r\n const disabled = Boolean(Object.keys(loading).find(l => loading[l]));\r\n return (\r\n <>\r\n
\r\n \r\n \r\n \r\n \r\n onFilter()}>\r\n \r\n \r\n ),\r\n onKeyDown: (e) => {\r\n if (!autoSearch && e && e.keyCode && e.keyCode === 13) onFilter();\r\n }\r\n }}\r\n onChange={(e) => handleChangeSearchValue(e.target.value)}\r\n fullWidth\r\n />\r\n \r\n dataGrid.current = ref}\r\n totalItems={_.get(dataSource, \"total\", [])}\r\n itemPerPage={_.get(filter, \"current.limit\", 50)}\r\n skipPerPage={_.get(filter, \"current.skip\", 0)}\r\n dataSource={_.get(dataSource, \"rows\", [])}\r\n loading={loading}\r\n keyExpr={keyExpr ? keyExpr : valueExpr}\r\n typePaging={\"remote\"}\r\n showColumnHeaders={false}\r\n pagerFullScreen={false}\r\n showBorders={false}\r\n columnAutoWidth={true}\r\n typeShort={window.innerWidth < 768}\r\n height={\"calc(100vh - 300px)\"}\r\n selection={{\r\n allowSelectAll: false,\r\n mode: 'multiple',\r\n selectAllMode: \"allPages\",\r\n showCheckBoxesMode: \"always\"\r\n }}\r\n allowColumnResizing={true}\r\n listPerPage={[50, 70, 90, 100]}\r\n // selectedRowKey={selectedRowKeys}\r\n onChangePage={onChangePage}\r\n onChangePerPage={onChangePerPage}\r\n onSelectionChanged={onSelectionChanged}\r\n onContentReady={() => {\r\n onContentReady();\r\n }}\r\n >\r\n \r\n \r\n \r\n \r\n {Config.lang(\"DHR_Thanh_vien_duoc_chon\")} \r\n dataGridSelected.current = ref}\r\n itemPerPage={50}\r\n // dataSource={[]}\r\n // loading={loading}\r\n keyExpr={keyExpr}\r\n typePaging={\"normal\"}\r\n showColumnHeaders={false}\r\n pagerFullScreen={false}\r\n showBorders={false}\r\n columnAutoWidth={true}\r\n typeShort={window.innerWidth < 768}\r\n height={\"calc(100vh - 220px)\"}\r\n allowColumnResizing={true}\r\n listPerPage={[50, 70, 90, 100]}\r\n // onSelectionChanged={onSelectionChanged}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n
\r\n \r\n \r\n >\r\n );\r\n}, (pProps, nProps) => {\r\n return pProps.open === nProps.open &&\r\n JSON.stringify(pProps.data) === JSON.stringify(nProps.data);\r\n});\r\n\r\nSelectEmployees.defaultProps = {\r\n allowSaveData: true,\r\n keyExpr: \"EmployeeID\",\r\n autoSearch: false,\r\n};\r\nSelectEmployees.propTypes = {\r\n open: PropTypes.bool,\r\n title: PropTypes.string.isRequired,\r\n maxWidth: PropTypes.string,\r\n fullWidth: PropTypes.bool,\r\n keyExpr: PropTypes.string,\r\n valueExpr: PropTypes.string,\r\n displayExpr: PropTypes.any,\r\n allowSaveData: PropTypes.bool,\r\n FormID: PropTypes.string,\r\n loadParams: PropTypes.object,\r\n saveParams: PropTypes.object,\r\n autoSearch: PropTypes.bool,\r\n\r\n onChosen: PropTypes.func,\r\n onClose: PropTypes.func\r\n};\r\n\r\nexport default compose(connect(null, dispatch => ({\r\n generalActions: bindActionCreators(generalActions, dispatch),\r\n W09F3010Actions: bindActionCreators(W09F3010Actions, dispatch)\r\n})))(SelectEmployees);\r\n","/**\r\n * @copyright 2019 @ DigiNet\r\n * @author TRIHAO\r\n * @create 12/19/2019\r\n * @Example\r\n */\r\nimport React from \"react\";\r\nimport {connect} from \"react-redux\";\r\nimport PropTypes from \"prop-types\";\r\nimport * as W09F6000Actions from \"../../../../redux/W0X/W09F6000/W09F6000_actions\";\r\nimport * as generalActions from \"../../../../redux/general/general_actions\";\r\nimport {bindActionCreators, compose} from \"redux\";\r\nimport Config from \"../../../../config\";\r\nimport ActionToolbar from \"../../../common/toolbar/action-toolbar\";\r\nimport {Column} from \"devextreme-react/data-grid\";\r\nimport GridContainer from \"../../../grid-container/grid-container\";\r\nimport {\r\n Modal,\r\n ModalHeader,\r\n ModalBody,\r\n Typography,\r\n DatePicker,\r\n Button,\r\n Checkbox,\r\n TextInput,\r\n Dropdown,\r\n TreeView,\r\n Label, ButtonIcon, Row, Col, Divider\r\n} from 'diginet-core-ui/components';\r\nimport _ from \"lodash\";\r\nimport {makeStyles} from \"diginet-core-ui/theme\";\r\nconst useStyles = makeStyles((theme) => ({\r\n panel: {\r\n transition: 'all .4s'\r\n },\r\n panelForm: {\r\n transition: 'all .5s',\r\n opacity: 1\r\n },\r\n hiddenOpacity: {\r\n opacity: 0\r\n },\r\n leftPanelMinimum: {\r\n maxWidth: '89px',\r\n paddingLeft: 0\r\n },\r\n rightPanelMinimum: {\r\n maxWidth: 'calc(100% - 89px)'\r\n },\r\n titleColorFilter: {\r\n backgroundColor: theme.colors.primary + ' !important',\r\n '& svg': {\r\n '& path': {\r\n fill: theme.colors.system.white\r\n }\r\n }\r\n },\r\n modalHeader:{\r\n \"& > div > .DGN-UI-Typography\":{\r\n width: \"100%\"\r\n }\r\n }\r\n}));\r\n\r\nclass W09F6000 extends React.PureComponent {\r\n constructor(props) {\r\n super(props);\r\n this.filter = {\r\n limit: 15,\r\n skip: 0,\r\n };\r\n const filters = this.getDataFilter(props.dataDefaults);\r\n this.filter = filters;\r\n this.state = {\r\n loading: false,\r\n loadingOrgChartID: false,\r\n loadingLaborObjectID: false,\r\n loadingCboDirectManager: false,\r\n loadingDutyID: false,\r\n loadingProject: false,\r\n loadingStatusID: false,\r\n isSaving: false,\r\n dataDepartments: [],\r\n dataOrgChart: [],\r\n dataTeam: [],\r\n dataCboProjects: {\r\n rows: [],\r\n total: 0\r\n },\r\n dataCboDirectManager: {\r\n rows: [],\r\n total: 0\r\n },\r\n filters,\r\n dataLaborObject: [],\r\n dataGrid: [],\r\n totalDataGrid: 0,\r\n minimum: false,\r\n\r\n DateJoinFrom: null,\r\n DateJoinTo: null,\r\n PreUsingPeriodFrom: null,\r\n PreUsingPeriodTo: null,\r\n\r\n selectedRowKeys: [],\r\n isShowSelected: false,\r\n };\r\n this.isSelecting = false;\r\n this.tmpSelectedRowKeys = [];\r\n this.tmpCurrentSelectedRowKeys = [];\r\n this.tmpSelectedRowData = [];\r\n this.tmpDataSelectedRowKeys = [];\r\n // this.tmpDataSaveSelectedEmployee = [];\r\n this.chooseOnSelect = false;\r\n this.selectAll = false;\r\n this.changePage = false;\r\n this.isChangeShow = false;\r\n this.filterCboProjects = {\r\n strSearch: \"\",\r\n skip: 0,\r\n limit: 50\r\n };\r\n this.filterCboDirectManager = {\r\n timer: null,\r\n skip: 0,\r\n limit: 50,\r\n strSearch: \"\"\r\n };\r\n this.genders = [\r\n {\r\n SexID: 0,\r\n SexName: Config.lang(\"NamU\")\r\n },\r\n {\r\n SexID: 1,\r\n SexName: Config.lang(\"Nu\")\r\n }\r\n ];\r\n this.dataGrid = null;\r\n }\r\n\r\n loadCboDuty = () => {\r\n this.setLoading('DutyID', true);\r\n this.props.generalActions.getCboDuty2((errors) => {\r\n this.setLoading('DutyID', false);\r\n if (errors) {\r\n Config.popup.show('ERROR', errors);\r\n return false;\r\n }\r\n });\r\n };\r\n\r\n _generateDataOrg = (dataSource, valueExpr, parentIdExpr) => {\r\n return dataSource.map((e) => {\r\n if (e[valueExpr] && e[parentIdExpr] && e[valueExpr] === e[parentIdExpr]) {\r\n delete e[parentIdExpr];\r\n e.expanded = true;\r\n } else if (!e[parentIdExpr]) {\r\n e.expanded = true;\r\n }\r\n return e;\r\n });\r\n };\r\n\r\n loadDataOrgChart = () => {\r\n this.props.generalActions.getOrgCharts({}, (error, data) => {\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n return false;\r\n }\r\n if (data) {\r\n const dataSource = this._generateDataOrg(data, \"OrgChartID\", \"OrgChartParentID\");\r\n this.setState({dataOrgChart: dataSource});\r\n }\r\n });\r\n };\r\n\r\n\r\n loadCboProjects = (isReset) => {\r\n const params = {\r\n HostID: \"\",\r\n FormID: \"W09F6000\",\r\n Language: Config.language || \"84\",\r\n skip: this.filterCboProjects.skip,\r\n limit: this.filterCboProjects.limit,\r\n search: this.filterCboProjects.strSearch\r\n };\r\n this.setLoading('Project', true);\r\n this.props.w09f6000Actions.getCboProjects(params, (errors, data) => {\r\n this.setLoading('Project', false);\r\n if (errors) {\r\n Config.popup.show('ERROR', errors);\r\n return false;\r\n }\r\n if (data) {\r\n const {dataCboProjects} = this.state;\r\n const rows = data && data.rows ? data.rows : data;\r\n const total = data && data.total ? data.total : data.length;\r\n this.setState({\r\n dataCboProjects: {\r\n rows: isReset ? rows : dataCboProjects.rows.concat(rows),\r\n total: total\r\n }\r\n })\r\n }\r\n });\r\n };\r\n\r\n loadCboDirectManager = (isReset = false) => {\r\n const {dataCboDirectManager} = this.state;\r\n const params = {\r\n Type: \"DirectManagerID\",\r\n FormID: _.get(this.props, \"FormID\", \"\"),\r\n Language: Config.language || \"84\",\r\n Mode: 0,\r\n skip: this.filterCboDirectManager.skip,\r\n limit: this.filterCboDirectManager.limit,\r\n SearchValue: this.filterCboDirectManager.strSearch,\r\n SearchValue2: \"\",\r\n SearchValueUnicodeCombine: \"\",\r\n TranMonth: 0,\r\n TranYear: 0,\r\n };\r\n this.setState({loadingCboDirectManager: true});\r\n this.props.w09f6000Actions.getCboDirectManager(params, (err, data) => {\r\n this.setState({loadingCboDirectManager: false});\r\n if (err) {\r\n Config.popup.show(\"ERROR\", err);\r\n return false;\r\n }\r\n if (data) {\r\n const dataRows = _.get(data, \"rows\", data) ?? [];\r\n const totalRows = _.get(data, \"total\", _.size(data)) ?? 0;\r\n this.setState({\r\n dataCboDirectManager: {\r\n rows: isReset ? dataRows : _.concat(dataCboDirectManager.rows, dataRows),\r\n total: totalRows\r\n }\r\n })\r\n }\r\n })\r\n };\r\n\r\n loadCboLaborObject = () => {\r\n this.setLoading('LaborObjectID', true);\r\n this.props.w09f6000Actions.getCboLaborObject({}, (errors, data) => {\r\n this.setLoading('LaborObjectID', false);\r\n if (errors) {\r\n Config.popup.show('ERROR', errors);\r\n return false;\r\n }\r\n if (data) {\r\n this.setState({dataLaborObject: data});\r\n }\r\n });\r\n };\r\n\r\n loadCboStatusWork = () => {\r\n this.setLoading('StatusID', true);\r\n this.props.generalActions.getCboStatusWork((errors) => {\r\n this.setLoading('StatusID', false);\r\n if (errors) {\r\n Config.popup.show('ERROR', errors);\r\n return false;\r\n }\r\n });\r\n };\r\n\r\n setLoading = (key, status = false) => {\r\n if (!key) return;\r\n this.setState({['loading' + key]: status});\r\n };\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n const {dataDefaults, open} = this.props;\r\n const arrayKeys = (dataDefaults && dataDefaults.dataSelected) ? dataDefaults.dataSelected.map(d => d.EmployeeID) : [];\r\n if (JSON.stringify(prevProps.dataDefaults) !== JSON.stringify(this.props.dataDefaults)\r\n || (JSON.stringify(arrayKeys) !== JSON.stringify(this.tmpSelectedRowKeys) && prevProps.open !== open && open)\r\n ) {\r\n const dataDefaults = this.props.dataDefaults;\r\n this.setState({filters: this.getDataFilter(dataDefaults)});\r\n if (dataDefaults && dataDefaults.selectedRowKeys) {\r\n this.tmpSelectedRowKeys = [];\r\n dataDefaults.selectedRowKeys.forEach(select => {\r\n if (this.tmpSelectedRowKeys.indexOf(select) < 0) {\r\n this.tmpSelectedRowKeys.push(select);\r\n }\r\n });\r\n }\r\n if (dataDefaults && dataDefaults.dataSelected) {\r\n this.tmpSelectedRowData = [];\r\n dataDefaults.dataSelected.forEach(select => {\r\n if (this.tmpSelectedRowData.indexOf(select) < 0) {\r\n this.tmpSelectedRowData.push(select);\r\n }\r\n });\r\n }\r\n // if (dataDefaults && dataDefaults.isLoaded) {\r\n this.loadGrid(true);\r\n // }\r\n }\r\n }\r\n\r\n componentDidMount() {\r\n const {dataDefaults} = this.props;\r\n this.loadCboDuty();\r\n this.loadCboProjects();\r\n this.loadDataOrgChart();\r\n this.loadCboLaborObject();\r\n this.loadCboStatusWork();\r\n this.loadCboDirectManager();\r\n\r\n if (dataDefaults) {\r\n if (dataDefaults.selectedRowKeys && dataDefaults.selectedRowKeys.length > 0) {\r\n dataDefaults.selectedRowKeys.forEach(select => {\r\n if (this.tmpSelectedRowKeys.indexOf(select) < 0) {\r\n this.tmpSelectedRowKeys.push(select);\r\n }\r\n });\r\n }\r\n if (dataDefaults && dataDefaults.dataSelected) {\r\n this.tmpSelectedRowData = [];\r\n dataDefaults.dataSelected.forEach(select => {\r\n if (this.tmpSelectedRowData.indexOf(select) < 0) {\r\n this.tmpSelectedRowData.push(select);\r\n }\r\n });\r\n }\r\n }\r\n this.loadGrid(true);\r\n }\r\n\r\n getDataFilter = (dataDefaults) => {\r\n return {\r\n ...this.filter,\r\n ...dataDefaults,\r\n strSearch: dataDefaults?.strSearch || \"\",\r\n OrgChartID: dataDefaults?.OrgChartID && dataDefaults.OrgChartID.length > 0 ? dataDefaults.OrgChartID : [],\r\n DirectManagerID: _.get(dataDefaults, \"DirectManagerID\", []) || [],\r\n LaborObjectID: dataDefaults?.LaborObjectID && dataDefaults.LaborObjectID.length > 0 ? dataDefaults.LaborObjectID : [],\r\n DutyID: dataDefaults?.DutyID && dataDefaults.DutyID.length > 0 ? dataDefaults.DutyID : [],\r\n ProjectID: dataDefaults?.ProjectID && dataDefaults.ProjectID.length > 0 ? dataDefaults.ProjectID : [],\r\n StatusID: dataDefaults?.StatusID && dataDefaults.StatusID.length > 0 ? dataDefaults.StatusID : [],\r\n SexID: dataDefaults?.SexID && dataDefaults.SexID.length > 0 ? dataDefaults.SexID : [],\r\n DateJoinFrom: dataDefaults?.DateJoinFrom || null,\r\n DateJoinTo: dataDefaults?.DateJoinTo || null,\r\n PreUsingPeriodFrom: dataDefaults?.PreUsingPeriodFrom || null,\r\n PreUsingPeriodTo: dataDefaults?.PreUsingPeriodTo || null,\r\n NotJoinTrain: dataDefaults?.NotJoinTrain || false,\r\n };\r\n };\r\n\r\n handleChange = (key, e) => {\r\n const {filters} = this.state;\r\n if (!key) return false;\r\n const value = _.get(e, \"value\", _.get(e, \"target.value\", \"\"));\r\n this.setState({filters: {...filters, [key]: value}}, () => {\r\n if (key === \"NotJoinTrain\") {\r\n setTimeout(() => {\r\n this.onFilter();\r\n if (this.props && this.props.onCheckedNotJoinTrain) {\r\n this.props.onCheckedNotJoinTrain(e.value);\r\n }\r\n })\r\n }\r\n })\r\n };\r\n\r\n loadGrid = (isReset) => {\r\n const {\r\n strSearch, LaborObjectID, OrgChartID, DutyID,\r\n ProjectID, StatusID, SexID, DateJoinFrom, DateJoinTo, PreUsingPeriodFrom, PreUsingPeriodTo, NotJoinTrain,\r\n DirectManagerID\r\n } = this.state.filters;\r\n const {limit, skip} = this.filter;\r\n const {FormID, loadParams, AttendanceDate, ShiftID} = this.props;\r\n // const ProjectID = Project ? Project.map(pro => pro.ProjectID && pro.ProjectID) : [];\r\n const params = {\r\n Employee: strSearch,\r\n LaborObjectID: LaborObjectID && LaborObjectID.length > 0 ? JSON.stringify(LaborObjectID) : \"\",\r\n OrgChartID: OrgChartID && OrgChartID.length > 0 ? JSON.stringify(OrgChartID) : \"\",\r\n DutyID: DutyID && DutyID.length > 0 ? JSON.stringify(DutyID) : \"\",\r\n ProjectID: ProjectID && ProjectID.length > 0 ? JSON.stringify(ProjectID) : \"\",\r\n StatusID: StatusID && StatusID.length > 0 ? JSON.stringify(StatusID) : \"\",\r\n SexID: SexID && SexID.length > 0 ? JSON.stringify(SexID) : \"\",\r\n DateJoinFrom: DateJoinFrom,\r\n DateJoinTo: DateJoinTo,\r\n DirectManagerID: !!_.size(DirectManagerID) ? JSON.stringify(DirectManagerID) : \"\",\r\n PreUsingPeriodFrom: PreUsingPeriodFrom,\r\n PreUsingPeriodTo: PreUsingPeriodTo,\r\n FormID: FormID,\r\n Language: Config.language || \"84\",\r\n ...loadParams,\r\n limit: limit,\r\n skip: skip\r\n };\r\n if (AttendanceDate) params.AttendanceDate = AttendanceDate;\r\n if (ShiftID) params.ShiftID = ShiftID;\r\n\r\n if (this.props && this.props.FormID === 'W38F2001') {\r\n params.NotJoinTrain = NotJoinTrain;\r\n params.TrainingCourseID = this.props.TrainingCourseID;\r\n }\r\n if (!isReset) {\r\n this.changePage = true;\r\n }\r\n this.setState({ loading: true });\r\n this.props.w09f6000Actions.getGridEmployees(params, (errors, data) => {\r\n this.setState({ loading: false });\r\n if (errors) {\r\n Config.popup.show('ERROR', errors);\r\n return false;\r\n }\r\n let selectedRowKeys = this.tmpSelectedRowKeys;\r\n this.setState({\r\n dataGrid: data.rows ? data.rows : data,\r\n totalDataGrid: data.total,\r\n selectedRowKeys: selectedRowKeys\r\n });\r\n });\r\n };\r\n\r\n onFilter = () => {\r\n this.filter.skip = 0;\r\n this.loadGrid();\r\n };\r\n\r\n onChangePage = (page) => {\r\n this.filter.skip = page * this.filter.limit;\r\n this.loadGrid();\r\n };\r\n\r\n onChangePerPage = (per) => {\r\n this.filter.skip = 0;\r\n this.filter.limit = per;\r\n this.loadGrid();\r\n };\r\n\r\n onSelect = () => {\r\n let selectedRowKeys = this.tmpSelectedRowKeys;\r\n if (this.selectAll) {\r\n //chạy api để lấy tất cả....\r\n //rồi mới insert được\r\n }\r\n this.tmpDataSelectedRowKeys = [];\r\n const {FormID, onChosen} = this.props;\r\n\r\n // list form không cần lưu bảng tạm. Lấy trực tiếp danh sách nhân viên đc từ popup.\r\n const exceptFormID = ['W39F1000'];\r\n if(exceptFormID.includes(FormID) && onChosen){\r\n onChosen(this.tmpSelectedRowKeys, this.tmpSelectedRowData);\r\n return;\r\n }\r\n\r\n if (selectedRowKeys && selectedRowKeys.length > 0) {\r\n this.setState({isSaving: true});\r\n const params = {\r\n EmployeeID: JSON.stringify(selectedRowKeys),\r\n HostID: \"\",\r\n FormID: FormID ? FormID : \"\"\r\n };\r\n this.props.w09f6000Actions.saveSelectedEmployee(params, (errors) => {\r\n this.setState({isSaving: false});\r\n if (errors) {\r\n errors.customMessage = {\r\n \"F6000E001\": \"EmployeeID \" + Config.lang(\"Bat_buoc\"),\r\n };\r\n Config.popup.show('INFO', errors);\r\n return false;\r\n }\r\n // this.tmpDataSaveSelectedEmployee = this.tmpSelectedRowKeys;\r\n if (onChosen) onChosen(this.tmpSelectedRowKeys);\r\n });\r\n }\r\n };\r\n\r\n // setSelectedEmployees = (e) => {\r\n // const currentSelectedRowKeys = e.currentSelectedRowKeys;\r\n // const currentDeselectedRowKeys = e.currentDeselectedRowKeys;\r\n // if (currentDeselectedRowKeys.length === 1) {\r\n // if (!this.selectAll) {\r\n // this.tmpSelectedRowKeys = this.tmpSelectedRowKeys.filter((e) => {\r\n // return e !== currentDeselectedRowKeys[0];\r\n // });\r\n // } else {\r\n // this.tmpDeselectedRowKeys.push(currentDeselectedRowKeys[0]);\r\n // }\r\n // } else if (currentDeselectedRowKeys.length > 1) {\r\n // this.tmpSelectedRowKeys = [];\r\n // this.tmpDeselectedRowKeys = [];\r\n // this.selectAll = false;\r\n // } else if (currentSelectedRowKeys.length === 1) {\r\n // if (!this.selectAll) {\r\n // this.tmpSelectedRowKeys.push(currentSelectedRowKeys[0]);\r\n // } else {\r\n // this.tmpDeselectedRowKeys = this.tmpDeselectedRowKeys.filter((e) => {\r\n // return e !== currentSelectedRowKeys[0];\r\n // });\r\n // }\r\n // } else if (currentSelectedRowKeys.length > 1) {\r\n // this.tmpSelectedRowKeys = [];\r\n // this.tmpDeselectedRowKeys = [];\r\n // this.selectAll = true;\r\n // }\r\n // };\r\n\r\n setSelectedEmployees = (e) => {\r\n const currentSelectedRowKeys = e.currentSelectedRowKeys;\r\n const currentSelectedRowData = e.selectedRowsData;\r\n const currentDeselectedRowKeys = e.currentDeselectedRowKeys;\r\n if (currentDeselectedRowKeys.length > 0) {\r\n if (this.changePage) {\r\n this.changePage = false;\r\n return false;\r\n }\r\n if (this.isChangeShow) {\r\n this.isChangeShow = false;\r\n return false;\r\n }\r\n\r\n this.tmpSelectedRowData = this.tmpSelectedRowData.filter((e) => {\r\n return currentDeselectedRowKeys.indexOf(e.EmployeeID) < 0;\r\n });\r\n this.tmpSelectedRowKeys = this.tmpSelectedRowKeys.filter((e) => {\r\n return currentDeselectedRowKeys.indexOf(e) < 0;\r\n });\r\n this.tmpDataSelectedRowKeys = this.tmpDataSelectedRowKeys.filter((e) => {\r\n return currentDeselectedRowKeys.indexOf(e) < 0;\r\n });\r\n } else if (currentSelectedRowKeys.length > 0) {\r\n currentSelectedRowKeys.forEach((val) => {\r\n if (this.tmpSelectedRowKeys.indexOf(val) < 0) {\r\n this.tmpSelectedRowKeys.push(val);\r\n const data = currentSelectedRowData.find(d => d.EmployeeID === val);\r\n if (data) this.tmpSelectedRowData.push(data);\r\n }\r\n\r\n if (this.tmpDataSelectedRowKeys.indexOf(val) < 0) {\r\n this.tmpDataSelectedRowKeys.push(val);\r\n }\r\n });\r\n }\r\n };\r\n\r\n onSelectionChanged = async (e) => {\r\n if (!this.isSelecting) {\r\n this.isSelecting = true;\r\n await this.setSelectedEmployees(e);\r\n this.setState({\r\n selectedRowKeys: e.selectedRowKeys\r\n }, () => {\r\n this.isSelecting = false;\r\n this.changePage = false;\r\n this.isChangeShow = false;\r\n });\r\n }\r\n };\r\n\r\n collapsePanel = (flag) => {\r\n if (typeof flag !== \"undefined\") {\r\n this.setState({minimum: !!flag});\r\n } else {\r\n this.setState({minimum: !this.state.minimum});\r\n }\r\n };\r\n\r\n changeTypeShow = (e) => {\r\n if (!e) return false;\r\n this.isChangeShow = true;\r\n this.setState({isShowSelected: e.target.checked});\r\n };\r\n\r\n getTotalSelectedRowKey = () => {\r\n return `(${this.tmpSelectedRowKeys.length})`;\r\n };\r\n\r\n onClose = () => {\r\n const {onClose, dataDefaults} = this.props;\r\n if (!this.chooseOnSelect) {\r\n if (dataDefaults && dataDefaults.selectedRowKeys) {\r\n this.tmpSelectedRowKeys = [];\r\n dataDefaults.selectedRowKeys.forEach(select => {\r\n if (this.tmpSelectedRowKeys.indexOf(select) < 0) {\r\n this.tmpSelectedRowKeys.push(select);\r\n }\r\n });\r\n }\r\n if (dataDefaults && dataDefaults.dataSelected) {\r\n this.tmpSelectedRowData = [];\r\n dataDefaults.dataSelected.forEach(select => {\r\n if (this.tmpSelectedRowData.indexOf(select) < 0) {\r\n this.tmpSelectedRowData.push(select);\r\n }\r\n });\r\n }\r\n this.setState({selectedRowKeys: this.tmpSelectedRowKeys});\r\n }\r\n if (onClose) onClose();\r\n };\r\n\r\n //true: Con key chua duoc select; false: da select het..\r\n _checkSelectedRowsKeys = (dataSource) => {\r\n let isCheck = false;\r\n if (dataSource && dataSource.length > 0 && this.tmpSelectedRowKeys.length > 0) {\r\n const dataKeys = dataSource.map(d => d.EmployeeID);\r\n for (let key of this.tmpSelectedRowKeys) {\r\n if (!dataKeys.includes(key)) {\r\n isCheck = true;\r\n break;\r\n }\r\n }\r\n }\r\n return isCheck;\r\n };\r\n\r\n render() {\r\n const {open, getCboDuty, FormID, getCboStatusWork} = this.props;\r\n const classes = useStyles();\r\n const {\r\n loading, isSaving, dataLaborObject, dataGrid, totalDataGrid,\r\n selectedRowKeys, dataCboProjects, minimum, DateJoinFrom, DateJoinTo, PreUsingPeriodFrom,\r\n PreUsingPeriodTo, isShowSelected, dataCboDirectManager, loadingCboDirectManager,\r\n filters\r\n } = this.state;\r\n const {\r\n loadingLaborObjectID,\r\n loadingDutyID,\r\n loadingProject,\r\n loadingStatusID,\r\n dataOrgChart\r\n } = this.state;\r\n const {\r\n OrgChartID,\r\n LaborObjectID,\r\n DirectManagerID,\r\n DutyID,\r\n ProjectID,\r\n StatusID,\r\n SexID,\r\n NotJoinTrain,\r\n strSearch\r\n } = filters;\r\n let _dataGrid = dataGrid;\r\n let _selectedRowKeys = selectedRowKeys;\r\n if (isShowSelected) {\r\n this.tmpCurrentSelectedRowKeys = selectedRowKeys;\r\n if (this.tmpSelectedRowData) {\r\n _dataGrid = this.tmpSelectedRowData;\r\n if (_selectedRowKeys.length === this.tmpSelectedRowKeys.length) this.isChangeShow = false;\r\n _selectedRowKeys = this.tmpSelectedRowKeys;\r\n }\r\n\r\n } else if (this.isChangeShow) {\r\n if (!this._checkSelectedRowsKeys(_dataGrid)) this.isChangeShow = false;\r\n // if (_selectedRowKeys.length === this.tmpSelectedRowKeys.length) this.isChangeShow = false;\r\n }\r\n return (\r\n <>\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n 768 ? classes.leftPanelMinimum : \"\")}>\r\n \r\n
\r\n \r\n this.collapsePanel()}\r\n />\r\n {!minimum && \r\n {Config.lang(\"Loc_chon_nhan_vien\")}\r\n }\r\n
\r\n {!minimum && this.collapsePanel()}\r\n />}\r\n \r\n
\r\n \r\n
\r\n \r\n \r\n {this.getTotalSelectedRowKey()}\r\n \r\n
\r\n
\r\n \r\n this.handleChange('strSearch', e)}\r\n />\r\n \r\n\r\n \r\n this.handleChange(\"OrgChartID\", data)}\r\n value={OrgChartID}\r\n viewType={'outlined'}\r\n placeholder={Config.lang(\"Co_cau_to_chuc\")}\r\n style={{margin: 0}}\r\n >\r\n this.handleChange(\"OrgChartID\", e)}\r\n parentID={\"OrgChartParentID\"}\r\n value={OrgChartID}\r\n valueExpr={\"OrgChartID\"}\r\n />\r\n \r\n \r\n\r\n \r\n this.handleChange(\"LaborObjectID\", e)}\r\n value={LaborObjectID}\r\n viewType={'outlined'}\r\n placeholder={Config.lang('Doi_tuong_lao_dong')}\r\n />\r\n \r\n\r\n \r\n this.handleChange(\"DutyID\", e)}\r\n value={DutyID}\r\n viewType={'outlined'}\r\n placeholder={Config.lang('Chuc_danh_cong_viec')}\r\n />\r\n \r\n\r\n \r\n this.handleChange(\"ProjectID\", e)}\r\n onInput={(e) => {\r\n if (this.filterCboProjects.timer) clearTimeout(this.filterCboProjects.timer);\r\n this.filterCboProjects.strSearch = e.target.value;\r\n this.filterCboProjects.timer = setTimeout(() => {\r\n this.filterCboProjects.skip = 0;\r\n this.filterCboProjects.limit = 50;\r\n this.loadCboProjects(true);\r\n }, 700);\r\n }}\r\n onLoadMore={(e) => {\r\n this.filterCboProjects.skip = e.skip;\r\n this.filterCboProjects.limit = e.limit;\r\n this.loadCboProjects();\r\n }}\r\n style={{margin: 0}}\r\n />\r\n \r\n\r\n \r\n this.handleChange(\"StatusID\", e)}\r\n value={StatusID}\r\n viewType={'outlined'}\r\n placeholder={Config.lang('Trang_thai_lam_viec')}\r\n />\r\n \r\n\r\n \r\n this.handleChange(\"SexID\", e)}\r\n value={SexID}\r\n viewType={'outlined'}\r\n placeholder={Config.lang('Gioi_tinh')}\r\n />\r\n \r\n\r\n \r\n this.handleChange(\"DirectManagerID\", e)}\r\n onInput={(e) => {\r\n if (this.filterCboDirectManager.timer) clearTimeout(this.filterCboDirectManager.timer);\r\n this.filterCboDirectManager.strSearch = e.target.value;\r\n this.filterCboDirectManager.timer = setTimeout(() => {\r\n this.filterCboDirectManager.skip = 0;\r\n this.filterCboDirectManager.limit = 50;\r\n this.loadCboDirectManager(true);\r\n }, 700);\r\n }}\r\n onLoadMore={(e) => {\r\n this.filterCboDirectManager.skip = e.skip;\r\n this.filterCboDirectManager.limit = e.limit;\r\n this.loadCboDirectManager();\r\n }}\r\n style={{margin: 0}}\r\n />\r\n \r\n\r\n \r\n {Config.lang(\"Ngay_vao_lam\")} \r\n \r\n\r\n \r\n this.handleChange(\"DateJoinFrom\", e)}\r\n />\r\n \r\n \r\n this.handleChange(\"DateJoinTo\", e)}\r\n />\r\n \r\n\r\n {FormID === \"W51F1001\" &&\r\n <>\r\n \r\n {Config.lang(\"Ngay_cap_phat_CCLD_truoc\")} \r\n \r\n\r\n \r\n this.handleChange(\"PreUsingPeriodFrom\", e)}\r\n value={PreUsingPeriodFrom}\r\n />\r\n \r\n \r\n this.handleChange(\"PreUsingPeriodTo\", e)}\r\n value={PreUsingPeriodTo}\r\n />\r\n \r\n >}\r\n {FormID === \"W38F2001\" &&\r\n \r\n this.handleChange('NotJoinTrain', {value: checked})}\r\n />\r\n \r\n }\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n 768 ? \"bdl \" + (minimum ? classes.rightPanelMinimum : \"\") : \"\")}>\r\n this.dataGrid = ref}\r\n totalItems={totalDataGrid}\r\n itemPerPage={this.filter.limit}\r\n skipPerPage={this.filter.skip}\r\n listPerPage={[15, 30, 45, 60]}\r\n dataSource={_dataGrid}\r\n disabled={isSaving}\r\n keyExpr={'EmployeeID'}\r\n gridProps={{\r\n style: {\r\n minHeight: 400,\r\n }\r\n }}\r\n pagerFullScreen={false}\r\n showBorders={false}\r\n columnAutoWidth={true}\r\n typeShort={window.innerWidth < 768}\r\n loading={loading}\r\n height={\"calc(100vh - 180px)\"}\r\n selection={{\r\n allowSelectAll: true,\r\n mode: \"multiple\",\r\n selectAllMode: \"allPages\",\r\n showCheckBoxesMode: \"always\"\r\n }}\r\n allowColumnResizing={true}\r\n selectedRowKey={_selectedRowKeys}\r\n onChangePage={this.onChangePage}\r\n onChangePerPage={this.onChangePerPage}\r\n onSelectionChanged={this.onSelectionChanged}\r\n >\r\n \r\n \r\n \r\n this.cellRenderPopupAction(cellData)}\r\n />\r\n this.cellRenderPopupAction(cellData)}\r\n />\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n this.cellRenderPopupAction(cellData)}\r\n />\r\n \r\n \r\n
\r\n \r\n \r\n >\r\n )\r\n }\r\n}\r\n\r\nW09F6000.propTypes = {\r\n FormID: PropTypes.string,\r\n open: PropTypes.bool,\r\n loadParams: PropTypes.object,\r\n\r\n /**\r\n * ProjectID: \"\"\r\n * DutyID: \"\"\r\n * ...\r\n * dataSelected: [{{EmployeeID: \"\", EmployeeName: \"\",...},{EmployeeID: \"\", EmployeeName: \"\",...}]\r\n * selectedRowKeys: [EmpID, EmpID]\r\n * isLoaded: false\r\n */\r\n dataDefaults: PropTypes.object,\r\n\r\n onClose: PropTypes.func,\r\n onChosen: PropTypes.func\r\n};\r\n\r\nexport default compose(connect((state) => ({\r\n getCboStatusWork: state.general.getCboStatusWork,\r\n getCboProjects: state.general.getCboProjects,\r\n getCboDuty: state.general.getCboDuty2\r\n}), (dispatch) => ({\r\n w09f6000Actions: bindActionCreators(W09F6000Actions, dispatch),\r\n generalActions: bindActionCreators(generalActions, dispatch),\r\n})))(W09F6000);\r\n","import React from \"react\";\r\nimport {connect} from \"react-redux\";\r\nimport PropTypes from \"prop-types\";\r\nimport {bindActionCreators, compose} from \"redux\";\r\nimport {Row} from \"react-bootstrap\";\r\nimport withStyles from \"@material-ui/core/styles/withStyles\";\r\nimport Modal from \"../../../common/modal/modal\";\r\nimport Config from \"../../../../config\";\r\nimport * as W09F4000Actions from \"../../../../redux/W0X/W09F4000/W09F4000_actions\";\r\nimport GridContainer from \"../../../grid-container/grid-container\";\r\nimport {Column} from \"devextreme-react/data-grid\";\r\nimport FormGroup from \"@material-ui/core/FormGroup\";\r\nimport {Typography} from \"@material-ui/core\";\r\nimport UserImage from \"../../../common/user/user-image\";\r\n\r\nconst styles = {\r\n imgAvatar: {\r\n maxWidth: \"100%\",\r\n maxHeight: \"100%\",\r\n objectFit: \"contain\"\r\n },\r\n};\r\n\r\nclass W09F4001Popup extends React.PureComponent {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n loading: false,\r\n dataEmployeeDepartment: {\r\n rows: [],\r\n total: 0\r\n },\r\n };\r\n this.filter = {\r\n skip: 0,\r\n limit: 10\r\n }\r\n\r\n }\r\n loadListEmployeeDepartment = () => {\r\n const { data, isHiddenW09F4010 } = this.props;\r\n const {SearchValue, skip, limit} = this.filter;\r\n const params = {\r\n UserID: Config.profile.UserID,\r\n FormID: isHiddenW09F4010 ? \"W09F4010\" : \"W09F4000\",\r\n Language: Config.language || 84,\r\n SearchValue: SearchValue,\r\n Value: \"\",\r\n OrgChartID: !isHiddenW09F4010 && data && data.OrgChartID ? data.OrgChartID : \"\",\r\n DutyID: isHiddenW09F4010 && data && data.DutyID ? data.DutyID : \"\",\r\n skip: String(skip),\r\n limit: String(limit)\r\n };\r\n this.setState({loading: true});\r\n this.props.w09f4000Actions.getListEmployeeDepartment(params, (error,data) => {\r\n if (error) {\r\n let message = error.message || Config.lang(\"Loi_chua_xac_dinh\");\r\n Config.popup.show(\"INFO\", message);\r\n return false;\r\n }\r\n if(data) {\r\n this.setState({\r\n dataEmployeeDepartment: {\r\n rows: data && data.rows ? data.rows : data,\r\n total: data && data.total ? data.total : 0\r\n }\r\n },() => {\r\n this.setState({loading: false});\r\n });\r\n }\r\n });\r\n };\r\n\r\n componentDidMount = () => {\r\n this.loadListEmployeeDepartment();\r\n };\r\n\r\n onChangePage = page => {\r\n this.filter.skip = page * this.filter.limit;\r\n this.loadListEmployeeDepartment();\r\n };\r\n\r\n onChangePerPage = perPage => {\r\n this.filter.skip = 0;\r\n this.filter.limit = perPage;\r\n this.loadListEmployeeDepartment();\r\n };\r\n\r\n cellRenderEmployeeID = (e) => {\r\n const {data} = e;\r\n\r\n return (\r\n
\r\n \r\n {data.EmployeeID} \r\n
\r\n )\r\n\r\n };\r\n\r\n onDetail = e => {\r\n if (e.rowType !== \"header\" && e.rowType !== \"filter\" && e.data) {\r\n window.open(Config.getRootPath() + `W09F2000?EmployeeID=${e.data.EmployeeID}`)\r\n }\r\n };\r\n\r\n render() {\r\n const { open, title, data, isHiddenW09F4010, onClose } = this.props;\r\n const { skip, limit } = this.filter;\r\n const { dataEmployeeDepartment, loading } = this.state;\r\n return (\r\n <>\r\n
\r\n \r\n {!isHiddenW09F4010 &&\r\n \r\n \r\n {`${data?.OrgChartID || \"\"} ${data && data.OrgChartName ? \" - \" + data.OrgChartName : \"\"}`}\r\n \r\n \r\n }\r\n {isHiddenW09F4010 &&\r\n \r\n \r\n {`${data?.DutyGroup[0]?.DutyID || \"\"} ${data?.DutyGroup[0]?.DutyName ? \" - \" + data?.DutyGroup[0]?.DutyName : \"\"}`}\r\n \r\n \r\n }\r\n \r\n \r\n \r\n \r\n {!isHiddenW09F4010 &&\r\n \r\n }\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n >\r\n );\r\n }\r\n}\r\n\r\nW09F4001Popup.propTypes = {\r\n open: PropTypes.bool,\r\n mode: PropTypes.string,\r\n data: PropTypes.any,\r\n onClose: PropTypes.func\r\n};\r\n\r\nexport default compose(\r\n connect(null,\r\n dispatch => ({\r\n w09f4000Actions: bindActionCreators(W09F4000Actions, dispatch),\r\n }), null, { forwardRef: true }\r\n ),\r\n withStyles(styles)\r\n)(W09F4001Popup);\r\n","\r\nimport React from \"react\";\r\nimport {withStyles} from \"@material-ui/core\";\r\nimport OrganizationChart from \"../../../libs/org-chart/orgchart-webcomponents\";\r\nimport Config from \"../../../../config\";\r\nimport {bindActionCreators, compose} from \"redux\";\r\nimport {connect} from \"react-redux\";\r\nimport * as W09F4000Actions from \"../../../../redux/W0X/W09F4000/W09F4000_actions\";\r\nimport {LoadPanel} from \"devextreme-react\";\r\nimport PropTypes from \"prop-types\";\r\nimport _ from \"lodash\";\r\nconst styles = {\r\n wrapperChart: {\r\n overflow: \"auto\",\r\n minHeight: 'calc(100vh - 135px)',\r\n \"& .orgchart\": {\r\n backgroundImage: 'none',\r\n '& ul > li > ul li::before': {\r\n borderTopColor: '#9597A1'\r\n },\r\n '& ul li .oc-node:not(:only-child)::after': {\r\n backgroundColor: '#9597A1'\r\n },\r\n '& ul > li > ul li > .oc-node::before': {\r\n backgroundColor: '#9597A1'\r\n },\r\n '& table':{\r\n margin:'auto'\r\n }\r\n }\r\n },\r\n\r\n};\r\n\r\nclass OrgChart extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n iPermission: 0,\r\n dataOrgChart: [],\r\n loading: false,\r\n };\r\n this.orgChart = null;\r\n this._dataOrgChart = [];\r\n this.dataOrgChart = [];\r\n this.depthOrgChart = props.depth || props.depth === 0 ? props.depth : 3 ;\r\n\r\n }\r\n\r\n loadDataFormOrgChart = () => {\r\n const { OrgChartID, valueExpr, FormID, DutyID, tabID } = this.props;\r\n const params = {\r\n FormID: FormID,\r\n Language: Config.language || 84,\r\n SearchValue: tabID === 0 ? OrgChartID ? OrgChartID : \"\" : DutyID || \"\",\r\n };\r\n this.setState({loading: true});\r\n this.props.w09f4000Actions.getDataForm(params, async (error,data) => {\r\n if (error) {\r\n let message = error.message || Config.lang(\"DHR_Loi_chua_xac_dinh\");\r\n Config.popup.show(\"INFO\", message);\r\n return false;\r\n }\r\n if(data) {\r\n const dataGroup = _.uniqBy(data, valueExpr);\r\n this._dataOrgChart = data; //store data chart original\r\n this.dataOrgChart = dataGroup;\r\n await this._createOrgChart(dataGroup, this.depthOrgChart);\r\n }\r\n });\r\n };\r\n\r\n recursionDataOrgChart = async (parentItem, data, depth, search, parentExpanded = false) => {\r\n const {dataForm} = this.state;\r\n const {valueExpr, parentIDExpr, search: _search} = this.props;\r\n const isSearch = !_.isEmpty(search) || !_.isEmpty(_search);\r\n let _data = data ? data : dataForm;\r\n let items = [];\r\n if (!parentItem) {\r\n items = _data.filter(d => d[parentIDExpr] === d[valueExpr]);\r\n } else {\r\n items = _data.filter(d => d[parentIDExpr] === parentItem[valueExpr]);\r\n\r\n }\r\n let _expanded = false;\r\n let _items = [];\r\n for(let item of items) {\r\n if (!parentItem) delete item[parentIDExpr];\r\n if (isSearch) {\r\n item.level = parentItem ? parentItem.level + 1 : 0;\r\n let check = false;\r\n item.expanded = false;\r\n if (search.includes(item[valueExpr])) {\r\n check = true;\r\n _expanded = true;\r\n item.expanded = true;\r\n }\r\n const {children, expanded} = await this.recursionDataOrgChart(item, _data, depth, search, check);\r\n if (expanded) {\r\n _expanded = true;\r\n item.expanded = true;\r\n if (children && children.length > 0) {\r\n item.children = children;\r\n item.countChildren = children.length;\r\n }\r\n }\r\n if (check || expanded) _items.push(item);\r\n } else {\r\n item.level = parentItem ? parentItem.level + 1 : 0;\r\n const {children} = await this.recursionDataOrgChart(item, _data, depth, search);\r\n item.expanded = item.level < depth - 1;\r\n if (children && children.length > 0) {\r\n item.children = children;\r\n item.countChildren = children.length;\r\n }\r\n }\r\n }\r\n return !parentItem ? items : {children: isSearch ? _items : items, expanded: _expanded};\r\n };\r\n\r\n _parseSearchParams = (search) => {\r\n search = search || this.props.search || null;\r\n const {valueExpr, childrenExpr} = this.props;\r\n let _search = [];\r\n if (!_.isEmpty(search)) {\r\n const data = this._dataOrgChart; //get data chart original\r\n for (let key of Object.keys(search)) {\r\n if (key === valueExpr) {\r\n if (!Array.isArray(search[key])) {\r\n _search.push(search[key]);\r\n } else {\r\n _search = _search.concat(search[key]);\r\n }\r\n } else {\r\n let _data = [];\r\n if (childrenExpr) {\r\n for (let d of data) {\r\n _data = _data.concat(d[childrenExpr]);\r\n }\r\n } else {\r\n _data = data;\r\n }\r\n const listItems = _data.filter(d => {\r\n return Array.isArray(search[key]) ? search[key].includes(d[key]) : search[key] === d[key];\r\n }).map(d => d[valueExpr]);\r\n _search = _search.concat(listItems);\r\n }\r\n }\r\n }\r\n return [...new Set(_search)];\r\n };\r\n\r\n _createOrgChart = async (dataSource, depth = 999) => {\r\n this.setState({loading: true}, async () => {\r\n let _data = JSON.parse(JSON.stringify(dataSource));\r\n const search = this._parseSearchParams();\r\n _data = await this.recursionDataOrgChart(null, _data, depth, search);\r\n const {id, valueExpr, displayExpr, orgChartProps, renderItem} = this.props;\r\n if (this.orgChart && _data.length > 0) {\r\n const obj = {\r\n data: _data[0],\r\n nodeId: valueExpr,\r\n nodeContent: displayExpr,\r\n // zoom: true,\r\n pan: true,\r\n depth: depth ? depth : 999,\r\n nodeTitle: displayExpr,\r\n chartContainer: \"#\" + id,\r\n ...orgChartProps\r\n };\r\n if (renderItem) {\r\n obj.createNode = (node, data) => {\r\n renderItem(node, data, orgchart);\r\n // setTimeout(() => {\r\n // const parent = node.closest(\"table\");\r\n // let line = parent.querySelectorAll(\"tr.lines\");\r\n // line = line && line.length > 0 ? line[0] : null;\r\n // if (line) {\r\n // const td = line.querySelector(\"td\");\r\n // const spanNum = document.createElement(\"div\");\r\n // spanNum.classList.add(\"spanNum\");\r\n // spanNum.innerHTML = '
'+data?.countChildren || 0 +' ';\r\n // td.appendChild(spanNum);\r\n // }\r\n // }, 500);\r\n };\r\n }\r\n let orgchart = new OrganizationChart(obj);\r\n this.orgChart.innerHTML = '';\r\n this.orgChart.appendChild(orgchart);\r\n orgchart.addEventListener(\"wheel\", (e) => this.onWheeling(e, orgchart));\r\n this.setState({loading: false});\r\n } else {\r\n this.orgChart.innerHTML = '';\r\n this.setState({loading: false});\r\n }\r\n });\r\n };\r\n\r\n setChartScale = (chart, newScale) => {\r\n let lastTf = window.getComputedStyle(chart).transform;\r\n if (lastTf === 'none') {\r\n chart.style.transform = 'scale(' + newScale + ',' + newScale + ')';\r\n chart.dataset.scale = newScale;\r\n } else {\r\n let matrix = lastTf.split(',');\r\n if (!lastTf.includes('3d')) {\r\n if ((newScale === 0.8 && matrix[3] >= 0.6) || (newScale === 1.2 && matrix[3] <= 2)) {\r\n chart.dataset.scale = matrix[3].trim();\r\n matrix[0] = 'matrix(' + newScale;\r\n matrix[3] = newScale;\r\n chart.style.transform = lastTf + ' scale(' + newScale + ',' + newScale + ')';\r\n }\r\n } else {\r\n chart.dataset.scale = matrix[3].trim();\r\n chart.style.transform = lastTf + ' scale3d(' + newScale + ',' + newScale + ', 1)';\r\n }\r\n }\r\n\r\n }\r\n\r\n onWheeling = (event, orgchart) => {\r\n event.preventDefault();\r\n\r\n let newScale = event.deltaY > 0 ? 0.8 : 1.2;\r\n\r\n this.setChartScale(orgchart, newScale);\r\n };\r\n\r\n refreshChart = (depth = 999) => {\r\n this.setState({loading: true}, () => {\r\n setTimeout(() => {\r\n this.depthOrgChart = depth;\r\n this._createOrgChart(this.dataOrgChart, depth);\r\n }, 100);\r\n });\r\n };\r\n\r\n componentDidMount = async () => {\r\n const {dataSource} = this.props;\r\n if (!dataSource) {\r\n this.loadDataFormOrgChart();\r\n } else {\r\n await this._createOrgChart(dataSource, this.depthOrgChart);\r\n }\r\n\r\n // libs.mouse.dragToScroll(this.orgChart);\r\n };\r\n\r\n render() {\r\n const {classes, id} = this.props;\r\n const {loading} = this.state;\r\n return (\r\n
\r\n
\r\n
this.orgChart = ref}\r\n id={id}\r\n className={\"custom-orgchart \" + classes.wrapperChart}/>\r\n
\r\n );\r\n }\r\n\r\n}\r\n\r\nOrgChart.propTypes = {\r\n valueExpr: PropTypes.string,\r\n displayExpr: PropTypes.string,\r\n orgChartProps: PropTypes.object,\r\n dataSource: PropTypes.any,\r\n id: PropTypes.string.isRequired,\r\n childrenExpr: PropTypes.string,\r\n\r\n renderItem: PropTypes.func,\r\n};\r\n\r\nexport default compose(connect(null,\r\n (dispatch) => ({\r\n w09f4000Actions: bindActionCreators(W09F4000Actions, dispatch),\r\n }), null, { forwardRef: true }), withStyles(styles))(OrgChart);\r\n","import React, { Component } from \"react\";\r\nimport { bindActionCreators, compose } from \"redux\";\r\nimport { connect } from \"react-redux\";\r\n\r\nimport Config from \"../../../../config\";\r\nimport * as mainActions from \"../../../../redux/main/main_actions\";\r\n\r\nimport _ from \"lodash\";\r\nimport moment from \"moment\";\r\nimport { browserHistory } from \"react-router\";\r\nimport { useTheme } from \"diginet-core-ui/theme\";\r\nimport {\r\n Accordion,\r\n AccordionSummary,\r\n AccordionDetails,\r\n Badge,\r\n ButtonIcon,\r\n Popover,\r\n PopoverBody,\r\n TabContainer,\r\n TabItem,\r\n TabHeader,\r\n CircularProgress,\r\n Icon,\r\n Row,\r\n Col,\r\n Typography,\r\n Button,\r\n Image,\r\n} from \"diginet-core-ui/components\";\r\nconst { spacing } = useTheme();\r\n\r\nclass W09F7000 extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n isOpenReminder: false,\r\n loadingReminderMaster: false,\r\n loadingReminderDetails: {},\r\n tabValue: 0,\r\n expanded: {},\r\n };\r\n this.scrollTypeReminder = 0;\r\n this.paramsLoadReminder = {\r\n Master: {\r\n limit: 20,\r\n skip: 0,\r\n },\r\n Details: {\r\n limit: 10,\r\n skip: 0,\r\n AlertBaseID: \"\",\r\n },\r\n };\r\n }\r\n\r\n getWidthText = (text = \"\", fontSize = 0) => {\r\n this.element = document.createElement(\"canvas\");\r\n this.context = this.element.getContext(\"2d\");\r\n this.context.font = `${fontSize}px Nunito sans-serif`;\r\n return this.context.measureText(text).width;\r\n };\r\n\r\n handleScroll = (e, type) => {\r\n const { dataListReminderMaster, dataListReminderDetails } = this.props;\r\n const target = e.target;\r\n const typeLoadReminder = [\"Master\", \"Details\"];\r\n const getTypeReminder = typeLoadReminder[type];\r\n const getDataListReminder = !!type ? dataListReminderDetails : dataListReminderMaster;\r\n if (_.eq(_.ceil(target.scrollHeight - target.scrollTop), target.clientHeight)) {\r\n if (!_.gte(_.size(getDataListReminder.rows), getDataListReminder.total)) {\r\n this.paramsLoadReminder[getTypeReminder].skip += this.paramsLoadReminder[getTypeReminder].limit;\r\n this.loadListReminder(type);\r\n }\r\n }\r\n };\r\n\r\n loadListReminder = (type = 0) => {\r\n const { tabValue, expanded } = this.state;\r\n const tabValueString = tabValue === 0 ? \"\" : tabValue === 1 ? \"today\" : \"delays\";\r\n const { Details } = this.paramsLoadReminder;\r\n const typeLoadReminder = [\"Master\", \"Details\"];\r\n const getAlertBaseIDCurrent = _.get(Details, \"AlertBaseID\", \"\");\r\n const getTypeReminder = typeLoadReminder[type];\r\n const keyLoading = `loadingReminder${getTypeReminder}`;\r\n const apiActions = `getListReminder${getTypeReminder}`;\r\n this.setState({ [keyLoading]: !!type ? { [getAlertBaseIDCurrent]: true } : true });\r\n this.props.mainActions[apiActions](tabValueString, this.paramsLoadReminder[getTypeReminder], err => {\r\n if (!!type) this.setState({ expanded: { ...expanded, [getAlertBaseIDCurrent]: true } });\r\n setTimeout(() => {\r\n this.setState({ [keyLoading]: !!type ? { [getAlertBaseIDCurrent]: false } : false });\r\n }, 250);\r\n if (err) {\r\n Config.popup.show(\"ERROR\", err);\r\n return false;\r\n }\r\n });\r\n };\r\n\r\n onClickIgnoreReminder = dataParams => {\r\n this.props.mainActions.ignoreReminder(dataParams, err => {\r\n if (err) {\r\n Config.popup.show(\"ERROR\", err);\r\n return false;\r\n }\r\n Config.notify.show(\"success\", Config.lang(\"Bo_qua_thong_bao_thanh_cong\"), 3000);\r\n this.props.mainActions.setReminderDetailsEmpty();\r\n this.loadListReminder(1);\r\n });\r\n };\r\n\r\n onClickVoucherAlert = data => {\r\n const { toggleMenuESS } = this.props;\r\n toggleMenuESS && toggleMenuESS(Number(data.Type ?? 0), false);\r\n browserHistory.push({\r\n pathname: Config.getRootPath() + _.get(data, \"FormID\", \"\"),\r\n state: { voucher_id: _.get(data, \"KeyID\", \"\") },\r\n });\r\n };\r\n\r\n onChangeTab = (_, tabValue) => {\r\n this.paramsLoadReminder = {\r\n Master: {\r\n limit: 20,\r\n skip: 0,\r\n },\r\n Details: {\r\n limit: 10,\r\n skip: 0,\r\n AlertBaseID: \"\",\r\n },\r\n };\r\n this.setState({ tabValue, expanded: {} }, () => {\r\n this.props.mainActions.setReminderDetailsEmpty();\r\n this.props.mainActions.setReminderMasterEmpty();\r\n this.loadListReminder();\r\n });\r\n };\r\n\r\n onClickExpand = (AlertBaseID = \"\", total) => {\r\n if(!Number(total)) return;\r\n const { expanded } = this.state;\r\n const { Details } = this.paramsLoadReminder;\r\n if (Details.AlertBaseID !== AlertBaseID) {\r\n this.paramsLoadReminder.Details = {\r\n skip: 0,\r\n limit: 10,\r\n AlertBaseID,\r\n };\r\n this.setState({ expanded: { ..._.mapValues(expanded, () => false), [AlertBaseID]: true } }, () => {\r\n setTimeout(() => {\r\n this.props.mainActions.setReminderDetailsEmpty();\r\n this.loadListReminder(1);\r\n }, 80);\r\n });\r\n } else {\r\n this.setState({ expanded: { ...expanded, [AlertBaseID]: !expanded[AlertBaseID] } });\r\n }\r\n };\r\n\r\n render() {\r\n const { tabValue, loadingReminderMaster, loadingReminderDetails, expanded } = this.state;\r\n const { dataListReminderMaster, dataListReminderDetails } = this.props;\r\n return (\r\n
{\r\n const { Master } = this.paramsLoadReminder;\r\n if (dataListReminderMaster.total > 0) {\r\n Master.skip = 0;\r\n Master.limit = 20;\r\n this.loadListReminder();\r\n }\r\n }}\r\n >\r\n \r\n \r\n }\r\n >\r\n \r\n \r\n \r\n \r\n \r\n {Config.lang(\"Nhac_nho1\")}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n {\r\n if (!_.includes(expanded, true)) {\r\n this.handleScroll(e, 0);\r\n }\r\n }}\r\n style={{ maxHeight: 395, overflowY: \"scroll\" }}\r\n >\r\n {!loadingReminderMaster &&\r\n dataListReminderMaster?.rows?.map((item, i) => {\r\n const getAlertBaseID = _.get(item, \"AlertBaseID\", \"\");\r\n const loadingListReminderDetails = _.get(loadingReminderDetails, getAlertBaseID, false);\r\n return (\r\n
this.onClickExpand(getAlertBaseID, item?.totalDetail)}\r\n >\r\n \r\n \r\n \r\n \r\n {item?.AlertBaseName}\r\n \r\n \r\n ({item?.totalDetail ?? 0})\r\n \r\n
\r\n \r\n \r\n this.handleScroll(e, 1)}\r\n style={{\r\n maxHeight: 270,\r\n overflowY: \"scroll\",\r\n overflowX: \"hidden\",\r\n }}\r\n >\r\n
\r\n {dataListReminderDetails?.rows?.map((itemAlert, iAlert) => {\r\n const isOutOfDate = moment().isAfter(itemAlert?.validDate);\r\n return (\r\n
this.onClickVoucherAlert(itemAlert)}\r\n >\r\n \r\n
\r\n
\r\n \r\n \r\n {itemAlert?.VoucherDes}:\r\n \r\n
\r\n
{itemAlert?.VoucherNo} \r\n
\r\n \r\n {Config.convertDate(\r\n itemAlert?.ValidDate,\r\n \"\",\r\n \"DD/MM/YYYY HH:mm\"\r\n )}\r\n \r\n {isOutOfDate && (\r\n <>\r\n \r\n .\r\n \r\n \r\n {Config.lang(\"Qua_han\")}\r\n \r\n >\r\n )}\r\n
\r\n
\r\n
\r\n this.onClickIgnoreReminder(itemAlert)\r\n }\r\n />\r\n \r\n \r\n );\r\n })}\r\n
\r\n
\r\n
\r\n \r\n \r\n );\r\n })}\r\n
\r\n
\r\n \r\n \r\n );\r\n }\r\n\r\n componentDidMount() {\r\n this.loadListReminder();\r\n }\r\n}\r\n\r\nconst LoadingContent = props => {\r\n const { loading, data } = props;\r\n return (\r\n <>\r\n {loading && (\r\n
\r\n \r\n
\r\n )}\r\n {!loading && !data?.length && (\r\n
\r\n {Config.lang(\"Khong_co_thong_bao_nhac_nho_nao\")}\r\n \r\n )}\r\n >\r\n );\r\n};\r\n\r\nexport default compose(\r\n connect(\r\n state => ({\r\n dataListReminderMaster: state.main.dataListReminderMaster,\r\n dataListReminderDetails: state.main.dataListReminderDetails,\r\n }),\r\n dispatch => ({\r\n mainActions: bindActionCreators(mainActions, dispatch),\r\n })\r\n )\r\n)(W09F7000);\r\n","/**\r\n * @copyright 2019 @ DigiNet\r\n * @author ANHTAI \r\n * @create 5/8/2020\r\n * @Example\r\n */\r\nimport { FormLabel as Label, Icon, Tooltip } from \"@material-ui/core\";\r\nimport IconButton from \"@material-ui/core/IconButton\";\r\nimport withStyles from \"@material-ui/core/styles/withStyles\";\r\nimport { Column } from \"devextreme-react/data-grid\";\r\nimport { Col, FormGroup, Row } from \"react-bootstrap\";\r\nimport moment from \"moment\";\r\nimport React from \"react\";\r\nimport { connect } from \"react-redux\";\r\nimport { bindActionCreators, compose } from \"redux\";\r\nimport ApprovalsPopover from \"../../../approvals/approvalspopover\";\r\nimport Config from \"../../../../config\";\r\nimport * as generalActions from \"../../../../redux/general/general_actions\";\r\nimport * as W21F2010Actions from \"../../../../redux/W2X/W21F2010/W21F2010_actions\";\r\nimport ButtonGeneral from \"../../../common/button/button-general\";\r\nimport { Combo } from \"../../../common/form-material\";\r\nimport DateBoxPicker from \"../../../common/form-material/date-box\";\r\nimport ActionToolbar from \"../../../common/toolbar/action-toolbar\";\r\nimport Filter from \"../../../filter/filter\";\r\nimport GridContainer from \"../../../grid-container/grid-container\";\r\nimport UserImage from \"../../../common/user/user-image\";\r\nimport UserName from \"../../../common/user/user-name\";\r\nimport Status from \"../../../common/status/status\";\r\n\r\nimport _ from \"lodash\";\r\nconst drawerWidth = '47%';\r\nconst styles = theme => {\r\n return {\r\n divAvatar: {\r\n width: 46,\r\n height: 46,\r\n borderRadius: '50%',\r\n overflow: 'hidden',\r\n marginRight: 8\r\n },\r\n imgAvatar: {\r\n maxWidth: '100%',\r\n maxHeight: '100%',\r\n height: '100%',\r\n objectFit: 'cover'\r\n },\r\n drawer: {\r\n width: drawerWidth,\r\n maxWidth: 700,\r\n flexShrink: 0,\r\n [theme.breakpoints.down('sm')]: {\r\n zIndex: '1502 !important',\r\n },\r\n },\r\n panel: {\r\n backgroundColor: \"#FFF\",\r\n padding: 15,\r\n overflowY: Config.isMobile ? 'auto' : 'hidden',\r\n '&:hover': {\r\n overflowY: 'auto'\r\n }\r\n },\r\n content: {\r\n transition: 'transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms'\r\n },\r\n contentDrawer: {\r\n width: '50%'\r\n },\r\n iconGreen: {\r\n \"&:disabled\": {\r\n color: '#FFF',\r\n backgroundColor: theme.palette.success.main,\r\n }\r\n },\r\n iconHoverGreen: {\r\n '&:hover': {\r\n color: theme.palette.primary.main,\r\n },\r\n }\r\n }\r\n};\r\n\r\nclass W21F2010 extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n FormID: \"W21F2010\",\r\n TransID: \"\",\r\n iPermission: 0,\r\n dataForm: {},\r\n Language: 84,\r\n confirming: false,\r\n gridLoading: false,\r\n mode: 0\r\n };\r\n this.filter = {\r\n Search: \"\",\r\n AppStatusID: \"\",\r\n DateFrom: null,\r\n DateTo: null,\r\n skip: 0,\r\n limit: 10\r\n };\r\n this.refApprovalPopover = null;\r\n }\r\n\r\n componentDidMount = async () => {\r\n const { dataSource } = this.props;\r\n await this.loadPermission();\r\n if (!this.state.iPermission) return;\r\n this.loadCboStatus();\r\n if (!dataSource) {\r\n this.loadGrid();\r\n }\r\n };\r\n\r\n loadPermission = async () => {\r\n await this.props.generalActions.getPermission(\"W21F2010\", (isPer) => {\r\n this.setState({ iPermission: isPer });\r\n });\r\n };\r\n\r\n loadCboStatus = () => {\r\n const { FormID } = this.state;\r\n const params = {\r\n FormID,\r\n Language: Config.language || '84'\r\n };\r\n this.props.w21f2010Actions.getCboStatus(params, (error) => {\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n return false;\r\n }\r\n });\r\n };\r\n\r\n loadGrid = () => {\r\n const { FormID, TransID, mode } = this.state;\r\n const { AppStatusID, DateFrom, DateTo, skip, limit } = this.filter;\r\n const params = {\r\n DivisionID: Config.getDivisionID(),\r\n FormID,\r\n Language: Config.language || '84',\r\n mode,\r\n skip: skip,\r\n limit: limit,\r\n AppStatusID,\r\n TransID,\r\n DateFrom,\r\n DateTo\r\n };\r\n this.setState({ gridLoading: true });\r\n this.props.w21f2010Actions.getGridConfirm(params, (error) => {\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n return false;\r\n }\r\n this.setState({ gridLoading: false });\r\n });\r\n };\r\n\r\n onReset = (resetData) => {\r\n this.setState({\r\n open: false,\r\n selectedRow: null,\r\n }, () => {\r\n this.panelLeft.style.width = '100%';\r\n if (resetData) {\r\n this.loadGrid();\r\n }\r\n });\r\n };\r\n\r\n handleFilterChange = (key, e) => {\r\n const { onTextFilterChanged } = this.props;\r\n switch (key) {\r\n case \"Search\":\r\n this.filter.Search = e.target.value;\r\n if (onTextFilterChanged) {\r\n if (this.timer) clearTimeout(this.timer);\r\n this.timer = setTimeout(() => {\r\n onTextFilterChanged(this.filter);\r\n }, 500);\r\n }\r\n break;\r\n case \"AppStatusID\":\r\n this.filter.AppStatusID = e.value;\r\n break;\r\n case \"DateFrom\":\r\n this.filter.DateFrom = e.value;\r\n break;\r\n case \"DateTo\":\r\n this.filter.DateTo = e.value;\r\n break;\r\n default:\r\n break;\r\n }\r\n };\r\n\r\n onFilter = () => {\r\n const { filterRender, onFilterChanged } = this.props;\r\n this.onReset();\r\n if (!filterRender) {\r\n this.loadGrid();\r\n }\r\n if (onFilterChanged) onFilterChanged(this.filter);\r\n if (this.toolFilter) {\r\n this.toolFilter.instance.close();\r\n }\r\n };\r\n\r\n onOpenApproval = (type, e, data) => {\r\n this.setState({\r\n anchorEl: e.currentTarget,\r\n type: type,\r\n selectedRow: data\r\n }, () => {\r\n if (this.refApprovalPopover) this.refApprovalPopover.onOpenPopover();\r\n });\r\n };\r\n\r\n onClosePopoverApproval = () => {\r\n this.setState({\r\n selectedRow: null,\r\n })\r\n };\r\n\r\n renderItem = (e) => {\r\n const { data } = e.row;\r\n return (\r\n
\r\n
\r\n
\r\n {Config.lang(\"Nhan_vien\")}:
\r\n {Config.lang(\"So_dien_thoai\")}: {data.Telephone}
\r\n {Config.lang(\"Du_An\")}: {data.ProjectName}
\r\n \r\n
\r\n );\r\n };\r\n\r\n renderInformation = (e) => {\r\n const { data } = e.row;\r\n return (\r\n
\r\n
\r\n {Config.lang(\"Noi_dung\")}: {data.Content} \r\n {Config.lang(\"So_the_bao_hiem_y_te\")}: {data.HealthInsBookNo} \r\n {Config.lang(\"So_so_bao_hiem_xa_hoi\")}: {data.SocInsBookNo} \r\n
\r\n
\r\n );\r\n };\r\n\r\n // _getStatusInfo = (ConfirmStatus) => {\r\n // const status = ConfirmStatus ? ConfirmStatus : 0;\r\n // const { getCboStatus } = this.props;\r\n // const color = Number(status) === 1 ? \"primary\" : \"default\";\r\n // const itemStatus = getCboStatus.filter((e) => {\r\n // return Number(e.ApprovalStatus) === Number(status);\r\n // });\r\n // return {\r\n // color: color,\r\n // ConfirmStatus: status,\r\n // ConfirmStatusName: itemStatus && itemStatus.length > 0 ? itemStatus[0].AppStatusName : Config.lang(\"Khong_trang_thai\")\r\n // };\r\n // };\r\n\r\n renderStatus = (e) => {\r\n const { data } = e.row;\r\n return
;\r\n };\r\n\r\n renderAction = (e) => {\r\n const { classes, labelBtnConfirm } = this.props;\r\n const { data } = e.row;\r\n return (\r\n
\r\n = 1 ? \"Da_xac_nhan\" : \"Xac_nhan\")}\r\n aria-label={labelBtnConfirm ? labelBtnConfirm : Config.lang(\"Xac_nhan\")}>\r\n \r\n = 1))}\r\n className={Number(data.AppStatusID) >= 1 ? classes.iconGreen : classes.iconHoverGreen}\r\n onClick={(e) => this.onOpenApproval(\"confirm\", e, data)}>\r\n \r\n \r\n \r\n \r\n
\r\n )\r\n };\r\n\r\n renderFilters = () => {\r\n const { getCboStatus } = this.props;\r\n return (\r\n
this.toolFilter = ref\r\n }}\r\n placeholder={Config.lang(\"Noi_dung_can_tim_kiem\")}\r\n openOnFieldClick={true}\r\n renderFilter={() => {\r\n return (\r\n <>\r\n \r\n \r\n \r\n this.handleFilterChange(\"AppStatusID\", e)}\r\n />\r\n \r\n
\r\n \r\n \r\n \r\n {Config.lang(\"Tu\")} \r\n this.handleFilterChange(\"DateFrom\", e)}\r\n />\r\n
\r\n \r\n \r\n \r\n {Config.lang(\"Den\")} \r\n \r\n this.handleFilterChange(\"DateTo\", e)\r\n }\r\n />\r\n
\r\n \r\n
\r\n \r\n \r\n \r\n \r\n >\r\n );\r\n }}\r\n />\r\n );\r\n };\r\n\r\n saveConfirm = (Status, Notes, arrIsBeingAttached) => {\r\n const { selectedRow, Language, FormID } = this.state;\r\n const { DateFrom, DateTo, skip, limit } = this.filter;\r\n if (!selectedRow || !selectedRow.TransID) {\r\n Config.popup.show('INFO', Config.lang(\"Khong_the_duyet\"));\r\n return false;\r\n }\r\n this.setState({ confirming: true });\r\n const params = {\r\n DivisionID: Config.getDivisionID(),\r\n FormID,\r\n ApproveNotes: Notes ? Notes : \"\",\r\n AppStatusID: Status ? Status : 1,\r\n TransID: selectedRow.TransID ? selectedRow.TransID : \"\",\r\n DateFrom,\r\n DateTo,\r\n Language,\r\n mode: 1,\r\n arrAttachment: JSON.stringify(arrIsBeingAttached),\r\n skip,\r\n limit\r\n };\r\n\r\n this.props.w21f2010Actions.saveConfirm(params, (error) => {\r\n this.setState({ confirming: false });\r\n if (error) {\r\n let message = Config.lang(\"Loi_chua_xac_dinh\");\r\n switch (error.code) {\r\n case \"F1002E007\":\r\n message = params.ConfirmStatus === 1 ? Config.lang(\"Duyet_khong_thanh_cong\") : \"\";\r\n break;\r\n default:\r\n break;\r\n }\r\n Config.popup.show('INFO', message);\r\n return false;\r\n }\r\n\r\n this.onReset(true);\r\n Config.notify.show('success', Config.lang(\"Thuc_hien_thanh_cong\"), 2000);\r\n });\r\n };\r\n\r\n onConfirm = (notes, arrIsBeingAttached = []) => {\r\n const { onConfirm } = this.props;\r\n if (onConfirm) {\r\n onConfirm(notes);\r\n } else {\r\n this.saveConfirm(1, notes, arrIsBeingAttached);\r\n }\r\n };\r\n onChangePage = (page) => {\r\n this.filter.skip = page * this.filter.limit;\r\n this.loadGrid();\r\n\r\n };\r\n\r\n onChangePerPage = (perPage) => {\r\n this.filter.skip = 0;\r\n this.filter.limit = perPage;\r\n this.loadGrid();\r\n };\r\n render() {\r\n const { open, iPermission,\r\n anchorEl, type, selectedRow, confirming, gridLoading\r\n } = this.state;\r\n const { classes, loading, getGridConfirm, disabled,\r\n dataSource, labelBtnConfirm, showFilters\r\n } = this.props;\r\n if (!iPermission) return null;\r\n const arrHasBeenAttached = getGridConfirm?.rows ? getGridConfirm.rows.filter((item) => item.TransID === _.get(selectedRow, \"TransID\", \"\")).map((item) => ({ arrAttachment: item.arrAttachment, AppStatusID: item.AppStatusID })) : [];\r\n\r\n return (\r\n \r\n \r\n {this.renderFilters()}
\r\n \r\n \r\n \r\n \r\n this.refApprovalPopover = ref}\r\n onClose={this.onClosePopoverApproval}\r\n loading={confirming}\r\n anchorEl={anchorEl}\r\n type={type}\r\n labelBtnConfirm={labelBtnConfirm}\r\n onConfirm={this.onConfirm}\r\n arrHasBeenAttached={arrHasBeenAttached}\r\n />\r\n \r\n
this.panelLeft = ref} className={classes.content + ' ' + (open ? classes.contentDrawer : \"\")}>\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n
\r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nexport default compose(\r\n connect(\r\n state => ({\r\n getCboStatus: state.W21F2010.getCboStatus,\r\n getGridConfirm: state.W21F2010.getGridConfirm\r\n }),\r\n dispatch => ({\r\n generalActions: bindActionCreators(generalActions, dispatch),\r\n w21f2010Actions: bindActionCreators(W21F2010Actions, dispatch)\r\n }), null, { forwardRef: true }\r\n ),\r\n withStyles(styles, { withTheme: true })\r\n)(W21F2010);","/**\r\n * @copyright 2019 @ DigiNet\r\n * @author TRIHAO\r\n * @create 1/8/2020\r\n * @Example\r\n */\r\nimport React from \"react\";\r\nimport {connect} from \"react-redux\";\r\nimport {bindActionCreators, compose} from \"redux\";\r\nimport Config from \"../../../../config\";\r\nimport {FormGroup, Image} from \"react-bootstrap\"\r\nimport withStyles from \"@material-ui/core/styles/withStyles\";\r\nimport Approvals from \"../../../approvals/approvals\";\r\nimport * as ApprovalActions from \"../../../../redux/approvals/approvals_actions\";\r\nimport LabelText from \"../../../common/label-text/label-text\";\r\nimport InlineSVG from \"react-inlinesvg\";\r\nimport {FormControl, Input, InputLabel} from \"@material-ui/core\";\r\nimport * as generalActions from \"../../../../redux/general/general_actions\";\r\nimport ActionToolbar from \"../../../common/toolbar/action-toolbar\";\r\nimport W13F1003 from \"../W13F1003/W13F1003\";\r\nimport {\r\n Row,\r\n Col,\r\n Button\r\n} from \"diginet-core-ui/components\";\r\n\r\nconst styles = {\r\n divAvatar: {\r\n width: 32,\r\n height: 32,\r\n borderRadius: '50%',\r\n border: '1px solid #ddd',\r\n overflow: 'hidden',\r\n marginRight: 8\r\n },\r\n imgAvatar: {\r\n maxWidth: '100%',\r\n maxHeight: '100%',\r\n objectFit: 'contain'\r\n },\r\n};\r\nclass W13F1000 extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n iPermission: 0,\r\n dataForm: {},\r\n VoucherID: \"\",\r\n loading: false,\r\n isShowW13F1003: false,\r\n };\r\n }\r\n\r\n loadPermission = async () => {\r\n await this.props.generalActions.getPermission(\"W13F1000\", (isPer) => {\r\n this.setState({iPermission: isPer});\r\n });\r\n };\r\n\r\n loadFormInfo = (VoucherID, cb) => {\r\n const params = {\r\n DivisionID: Config.getDivisionID(),\r\n FormID: \"W13F1000\",\r\n Language: Config.language || \"84\",\r\n VoucherID: VoucherID ? VoucherID : \"\",\r\n };\r\n this.setState({loading: true})\r\n this.props.approvalActions.getFormInfo(params, (error, data) => {\r\n this.setState({loading: false})\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n return false;\r\n }\r\n if (data) {\r\n this.setState({\r\n dataForm: data\r\n });\r\n cb && cb (data);\r\n }\r\n });\r\n };\r\n\r\n componentDidMount = async () => {\r\n await this.loadPermission();\r\n if (!this.state.iPermission) return;\r\n // this.checkNotify();\r\n };\r\n\r\n // UNSAFE_componentWillReceiveProps = () => {\r\n // this.checkNotify();\r\n // };\r\n //\r\n // checkNotify = () => {\r\n // const {VoucherID} = this.getInfo();\r\n // this.setState({VoucherID: VoucherID});\r\n // // if(VoucherID && !this.voucher_id){\r\n // // this.voucher_id = VoucherID;\r\n // // this.loadFormInfo(VoucherID,(data)=>{\r\n // // this.voucher_id=null;\r\n // // data.VoucherID=VoucherID;\r\n // // // this.refs['Approvals'].showPopup(data);\r\n // // });\r\n // // }\r\n // };\r\n //\r\n // getInfo = () => {\r\n // const {location} = this.props;\r\n // const url = new window.URLSearchParams(window.location.search);\r\n // if (url && url.get('voucher_id')) {\r\n // return {VoucherID: url.get('voucher_id')};\r\n // } else if (location && location.state) {\r\n // return {\r\n // VoucherID: location.state.voucher_id,\r\n // }\r\n // } else {\r\n // return {};\r\n // }\r\n // };\r\n\r\n //Form info..\r\n renderFormInfo = (data) => {\r\n const {classes} = this.props;\r\n return (\r\n <>\r\n \r\n {\r\n return (\r\n \r\n
\r\n {data && data.UserPictureURL ? (\r\n \r\n ) : (\r\n \r\n )}\r\n
\r\n
\r\n {/*
{data && data.EmployeeName ? data.EmployeeName : \"\"}
*/}\r\n
\r\n );\r\n }}\r\n fullWidth={true}\r\n />\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n {Config.lang(\"Loai_thu_nhap\")}\r\n \r\n {data && data.AbsentType && data.AbsentType.length > 0 ? (\r\n data.AbsentType.map((e, indx) => {\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n )\r\n })\r\n ) : (\r\n \r\n \r\n \r\n \r\n
\r\n )}\r\n \r\n \r\n \r\n \r\n \r\n {Config.lang(\"So_luong\")}\r\n \r\n {data && data.AbsentType && data.AbsentType.length > 0 ? (\r\n data.AbsentType.map((e, indx) => {\r\n return (\r\n \r\n \r\n \r\n \r\n
\r\n )\r\n })\r\n ) : (\r\n \r\n \r\n \r\n \r\n
\r\n )}\r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n >\r\n );\r\n };\r\n\r\n onSelectionChanged = (e) => {\r\n if (!e) return false;\r\n this.loadFormInfo(e.VoucherID);\r\n };\r\n\r\n onDrawerClosed = () => {\r\n this.setState({VoucherID: \"\"});\r\n };\r\n\r\n showW13F1003 = () => {\r\n this.setState({isShowW13F1003: true});\r\n }\r\n\r\n onCloseW13F1003 = () => {\r\n this.setState({isShowW13F1003: false});\r\n };\r\n\r\n render() {\r\n const {iPermission, dataForm, VoucherID, loading, isShowW13F1003} = this.state;\r\n if (!iPermission) return null;\r\n\r\n return (\r\n \r\n { isShowW13F1003 ?\r\n : \"\"}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nexport default compose(connect(null, (dispatch) => ({\r\n generalActions: bindActionCreators(generalActions, dispatch),\r\n approvalActions: bindActionCreators(ApprovalActions, dispatch),\r\n})), withStyles(styles))(W13F1000);\r\n","/**\r\n * @copyright 2022 @ DigiNet\r\n * @author THANHAN\r\n * @create 10/10/2022\r\n * @Example\r\n */\r\n\r\nimport React, { useState, useEffect, useRef, useMemo } from 'react';\r\nimport { useDispatch } from \"react-redux\";\r\nimport Config from \"../../../../config\";\r\nimport { makeStyles } from \"diginet-core-ui/theme\";\r\nimport {\r\n Row,\r\n Col,\r\n Modal,\r\n ModalHeader,\r\n ModalBody,\r\n ModalFooter,\r\n Button,\r\n Typography,\r\n Dropdown,\r\n ButtonIcon,\r\n Checkbox,\r\n TextInput,\r\n DateRangePicker,\r\n Attachment\r\n} from \"diginet-core-ui/components\";\r\nimport ActionToolbar from \"../../../common/toolbar/action-toolbar\";\r\nimport GridContainer from \"../../../grid-container/grid-container\";\r\nimport * as W13F1003Actions from \"../../../../redux/W1X/W13F1003/W13F1003_actions\";\r\nimport * as generalActions from \"../../../../redux/general/general_actions\";\r\n// import \"./W13F1003.scss\";\r\nimport { Column } from \"devextreme-react/data-grid\";\r\n\r\nconst useStyles = makeStyles((theme) => ({\r\n col: {\r\n height: \"100%\",\r\n },\r\n borderLeft: {\r\n borderLeft: `1px solid ${theme.colors?.line?.system}`,\r\n },\r\n leftColItem: {\r\n marginRight: theme.spacing(6),\r\n [theme.breakpoints.down('md')]: {\r\n marginRight: 0\r\n }\r\n },\r\n actionToolbar: {\r\n marginLeft: -24,\r\n width: \"unset\",\r\n marginTop: \"0px!important\",\r\n backgroundColor: `${theme.colors.brand24}`,\r\n [theme.breakpoints.down('md')]: {\r\n marginLeft: 0,\r\n }\r\n },\r\n grid: {\r\n marginBottom: -theme.spacing(4),\r\n paddingBottom: theme.spacing(4),\r\n }\r\n}))\r\n\r\n\r\nconst dataColumnGridExtra = () => [\r\n {\r\n caption: Config.lang('Ma_nhan_vien'),\r\n width: 150,\r\n dataField: 'EmployeeID',\r\n fixed: true,\r\n allowEditing: false\r\n },\r\n {\r\n caption: Config.lang('Ten_nhan_vien'),\r\n width: 200,\r\n dataField: 'EmployeeName',\r\n fixed: true,\r\n allowEditing: false\r\n },\r\n {\r\n caption: Config.lang('Du_an'),\r\n dataField: 'ProjectName',\r\n width: 300,\r\n allowEditing: false\r\n },\r\n {\r\n caption: Config.lang('Ky_luong'),\r\n dataField: 'Period',\r\n width: 100,\r\n allowEditing: false\r\n },\r\n];\r\n\r\nconst FormID = \"W13F1003\";\r\nconst Language = Config.language || \"84\";\r\n\r\nconst W13F1003 = React.memo((props) => {\r\n const {\r\n open,\r\n onClose,\r\n iPermission,\r\n } = props;\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n let errorMessage = \"\";\r\n let counter = 0;\r\n\r\n const [dataFilter, setDataFilter] = useState(() => ({\r\n ProjectID: \"\",\r\n DepartmentID: \"\",\r\n DateFrom: null,\r\n DateTo: null,\r\n }));\r\n\r\n const [rangeDate, setRangeDate] = useState([]);\r\n const [dataGrid, setDataGrid] = useState(() => ({rows: [], total: 0}));\r\n const [dataAttachmentPopup, setDataAttachmentPopup] = useState([]);\r\n const [dataCboDepartments, setDataCboDepartments] = useState([]);\r\n const [dataCboProjects, setDataCboProjects] = useState(() => ({ rows: [], total: 0 }));\r\n const [cboDepartmentsLoading, setCboDepartmentsLoading] = useState(false);\r\n const [cboProjectsLoading, setCboProjectsLoading] = useState(false);\r\n const [gridLoading, setGridLoading] = useState(false);\r\n const [isSaving, setIsSaving] = useState(false);\r\n const [isShowSelected, setIsShowSelected] = useState(false);\r\n const [showPopupAttachment, setShowPopupAttachment] = useState(false);\r\n\r\n const refGrid = useRef(null);\r\n const paramsPaging = useRef({\r\n skip: 0,\r\n limit: 20,\r\n });\r\n const filterCboProject = {\r\n strSearch: \"\",\r\n skip: 0,\r\n limit: 20\r\n };\r\n\r\n const isFilter = useRef(false);\r\n const refSelectedRowsData = useRef([]);\r\n const refSelectedRowKeys = useRef([]);\r\n const isSelectAll = useRef(false);\r\n const isChangePage = useRef(false);\r\n const isChangeShow = useRef(false);\r\n const timer = useRef(0);\r\n\r\n const [showDrawer, setShowDrawer] = useState(true);\r\n\r\n const loadGrid = (isLoadGrid = false) => {\r\n if (!isLoadGrid) {\r\n isChangePage.current = true;\r\n }\r\n const params = {\r\n FormID,\r\n Language,\r\n Employee: dataFilter?.EmployeeID ?? \"\",\r\n DepartmentID: dataFilter?.DepartmentID ? dataFilter?.DepartmentID.join(\";\") : \"\",\r\n ProjectID: dataFilter?.ProjectID ? dataFilter?.ProjectID.join(\";\") : \"\",\r\n DateFrom: rangeDate?.length > 0 ? rangeDate[0] : null,\r\n DateTo: rangeDate?.length > 0 ? rangeDate[1] : null,\r\n skip: paramsPaging.current.skip,\r\n limit: paramsPaging.current.limit,\r\n };\r\n setGridLoading(true);\r\n dispatch(W13F1003Actions.loadGrid(params, (error, data) => {\r\n setGridLoading(false);\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n return false;\r\n }\r\n data.rows.forEach(row => {\r\n row.ApprovalNotes = \"\"\r\n })\r\n setDataGrid({ rows: data?.rows || [], total: data?.total || 0 });\r\n if(isFilter.current) {\r\n isFilter.current = false;\r\n }\r\n }));\r\n };\r\n\r\n const loadCboDepartments = () => {\r\n const params = {\r\n HostID: \"\",\r\n FormID,\r\n Language,\r\n DivisionID: Config.getDivisionID(),\r\n };\r\n setCboDepartmentsLoading(true);\r\n dispatch(generalActions.getCboDepartments(params, (error, data) => {\r\n setCboDepartmentsLoading(false);\r\n if (error) {\r\n let message = error.message || Config.lang(\"DHR_Loi_chua_xac_dinh\");\r\n Config.popup.show(\"INFO\", message);\r\n return false;\r\n }\r\n setDataCboDepartments(data);\r\n }));\r\n };\r\n\r\n const loadCboProjects = (isReset) => {\r\n const param = {\r\n FormID,\r\n Language,\r\n skip: filterCboProject.skip,\r\n limit: filterCboProject.limit,\r\n search: filterCboProject.strSearch\r\n };\r\n setCboProjectsLoading(true);\r\n dispatch(generalActions.getCboProjects(param, (error, data) => {\r\n setCboProjectsLoading(false);\r\n if (error) {\r\n let message = error.message || Config.lang(\"DHR_Loi_chua_xac_dinh\");\r\n Config.popup.show('INFO', message);\r\n return false;\r\n }\r\n const rows = data?.rows || [];\r\n const total = data?.total || 0;\r\n setDataCboProjects({\r\n rows: isReset ? rows : dataCboProjects.rows.concat(rows),\r\n total: total,\r\n });\r\n }));\r\n };\r\n\r\n const loadAttachments = (KeyID) => {\r\n if (!KeyID) return;\r\n const params = {\r\n KeyID: KeyID ? KeyID : \"\",\r\n }\r\n dispatch(generalActions.getAttachmentsByTransID(params, (error, data) => {\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error)\r\n }\r\n else if (data) {\r\n setDataAttachmentPopup(data);\r\n }\r\n }));\r\n };\r\n\r\n const setDataSelectedRowKeys = (e = {}) => {\r\n const {currentSelectedRowKeys, selectedRowsData} = e;\r\n let deselectRowsKey = [];\r\n currentSelectedRowKeys.map(key => {\r\n if(refSelectedRowKeys.current.indexOf(key) < 0) {\r\n e.component.byKey(key).done(item => {\r\n // đk để bỏ chọn những dòng disabled\r\n const rowData = selectedRowsData.find(f => f.AbsentVoucherID === key);\r\n if(rowData) {\r\n refSelectedRowsData.current.push(rowData);\r\n }\r\n refSelectedRowKeys.current.push(key);\r\n \r\n });\r\n }\r\n return key;\r\n });\r\n if(deselectRowsKey.length > 0) {\r\n e.component.deselectRows(deselectRowsKey);\r\n }\r\n };\r\n\r\n const onSelectionChanged = (e) => {\r\n // khi change page khong cho DeselectedRowKeys\r\n if(isChangePage.current) {\r\n isChangePage.current = false;\r\n return false;\r\n }\r\n // case: khi có data SelectedRowKeys => changepage => click checkbox isShowSelected => changepage => thì khong cho DeselectedRowKeys\r\n if(isChangeShow.current) {\r\n isChangeShow.current = false;\r\n return false;\r\n }\r\n const {currentSelectedRowKeys, selectedRowKeys, currentDeselectedRowKeys} = e;\r\n const total = e.component.totalCount();\r\n // su ly SelectAll và deselectAll\r\n if ((selectedRowKeys.length === total || selectedRowKeys.length === 0) && isSelectAll.current) {\r\n if (selectedRowKeys.length === total) e.component.deselectAll();\r\n if (selectedRowKeys.length === 0) isSelectAll.current = false;\r\n }\r\n isSelectAll.current = selectedRowKeys.length && (selectedRowKeys.length + currentDeselectedRowKeys.length) === total;\r\n // su ly chon tung dong\r\n if(currentDeselectedRowKeys.length > 0) {\r\n currentDeselectedRowKeys.map(key => {\r\n if(refSelectedRowKeys.current.includes(key) && refSelectedRowsData.current.length > 0) {\r\n refSelectedRowsData.current = refSelectedRowsData.current.filter(f => f.AbsentVoucherID !== key);\r\n refSelectedRowKeys.current = refSelectedRowKeys.current.filter(f => f !== key);\r\n }\r\n return key;\r\n });\r\n }\r\n else if(currentSelectedRowKeys.length > 0) {\r\n setDataSelectedRowKeys(e);\r\n }\r\n };\r\n\r\n const onChangePage = (page) => {\r\n paramsPaging.current.skip = page * paramsPaging.current.limit;\r\n loadGrid();\r\n };\r\n\r\n const onChangePerPage = (perPage) => {\r\n paramsPaging.current.skip = 0;\r\n paramsPaging.current.limit = perPage;\r\n loadGrid(true);\r\n };\r\n\r\n const onAttachmentClick = (KeyID) => {\r\n setShowPopupAttachment(true);\r\n loadAttachments(KeyID);\r\n };\r\n\r\n const onLoadDataFilter = () => {\r\n loadCboDepartments();\r\n loadCboProjects();\r\n };\r\n\r\n const _onClose = () => {\r\n onClose && onClose();\r\n };\r\n\r\n const onClosePopupAttachment = () => {\r\n setShowPopupAttachment(false);\r\n };\r\n\r\n const resetData = () => {\r\n refSelectedRowsData.current = [];\r\n refSelectedRowKeys.current = [];\r\n isChangeShow.current = false;\r\n isChangePage.current = false;\r\n isSelectAll.current = false;\r\n isFilter.current = false;\r\n setIsShowSelected(false);\r\n };\r\n\r\n //true: Con key chua duoc select; false: da select het..\r\n const _checkSelectedRowsKeys = (dataSource) => {\r\n let isCheck = false;\r\n if (dataSource?.length > 0 && refSelectedRowKeys.current.length > 0) {\r\n const dataKeys = dataSource.map(d => d.AbsentVoucherID);\r\n for (let key of refSelectedRowKeys.current) {\r\n if (!dataKeys.includes(key)) {\r\n isCheck = true;\r\n break;\r\n }\r\n }\r\n }\r\n return isCheck;\r\n };\r\n\r\n const cellRenderAbsentTypeName = (cellData) => {\r\n if (!cellData) return null;\r\n const { data, column } = cellData;\r\n const dataField = column.dataField;\r\n const arrData = data[dataField].split(\";\");\r\n return (\r\n \r\n {arrData.map((data, index) => {\r\n return (\r\n \r\n {data}\r\n \r\n )\r\n })}\r\n
\r\n )\r\n }\r\n\r\n const cellRenderPopupAttachment = (cellData) => {\r\n if (!cellData) return null;\r\n const { data, column } = cellData;\r\n const dataField = column.dataField;\r\n return (\r\n onAttachmentClick(data?.AbsentVoucherID)}\r\n >\r\n {`( ${data[dataField] || 0} )`} \r\n
\r\n );\r\n };\r\n\r\n const _setDataFilter = (obj) => {\r\n setDataFilter({ ...dataFilter, ...obj });\r\n };\r\n\r\n const handleChange = (key, evt) => {\r\n if (!key || !evt) return;\r\n const value = evt?.value ?? evt?.target?.value ?? \"\";\r\n if (key === \"RangePicker\") {\r\n const DayFrom = Array.isArray(value) ? value[0] : null;\r\n const DayTo = Array.isArray(value) ? value[1] : null;\r\n setRangeDate([DayFrom, DayTo]);\r\n }\r\n else {\r\n _setDataFilter({ [key]: value });\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadGrid();\r\n resetData();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n useEffect(() => {\r\n onLoadDataFilter();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (refGrid.current){\r\n if (isShowSelected) refGrid.current.instance.filter('IsSelected','=',1);\r\n else refGrid.current.instance.filter('');\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n },[isShowSelected]);\r\n\r\n let _dataGrid = dataGrid.rows;\r\n\r\n if(isShowSelected) {\r\n if (refSelectedRowsData.current.length > 0) {\r\n const selectedRows = refGrid.current && refGrid.current.instance.getSelectedRowKeys();\r\n _dataGrid = refSelectedRowsData.current;\r\n // kiem tra hiển thị những dòng đã check và reset các biến bằng false cho Deselected Row Keys ở hàm onSelectionChanged\r\n if(selectedRows.length === refSelectedRowKeys.current.length) {\r\n isChangeShow.current = false;\r\n isSelectAll.current = false;\r\n }\r\n }\r\n } else if(isChangeShow.current) {\r\n // kiem tra trường hợp reset isChangeShow.current khi changepage chưa chọn dòng trên lưới sau đó click rồi bỏ click checkbox isShowSelected\r\n if(!_checkSelectedRowsKeys(_dataGrid)) isChangeShow.current = false;\r\n }\r\n _dataGrid = _dataGrid.map(d => ({...d, IsSelected: d.IsSelected ?? 0}));\r\n\r\n const renderGrid = useMemo(() => {\r\n return (\r\n refGrid.current = ref}\r\n dataSource={_dataGrid}\r\n totalItems={dataGrid.total}\r\n itemPerPage={paramsPaging.current.limit}\r\n skipPerPage={paramsPaging.current.skip}\r\n editing={{\r\n mode: \"cell\",\r\n allowUpdating: true,\r\n startEditAction: \"click\",\r\n }}\r\n selection={{\r\n allowSelectAll: true,\r\n mode: 'multiple',\r\n selectAllMode: 'allPages',\r\n showCheckBoxesMode: 'always',\r\n }}\r\n loading={gridLoading}\r\n pagerFullScreen={false}\r\n height={656}\r\n typePaging={\"remote\"}\r\n onSelectionChanged={onSelectionChanged}\r\n onChangePage={onChangePage}\r\n onChangePerPage={onChangePerPage}\r\n onContentReady={(e) => {\r\n if (timer.current) clearTimeout(timer.current);\r\n timer.current = setTimeout(() => {\r\n e.component.selectRows(refSelectedRowKeys.current)\r\n }, 600)\r\n }}\r\n onEditingStart={(e) => {\r\n const isCheck = refSelectedRowKeys.current.includes(e?.data?.AbsentVoucherID);\r\n if (!isCheck) e.cancel = true;\r\n }}\r\n onEditorPreparing={(e) => {\r\n if (!e || !e.row) return;\r\n if (\r\n e.parentType === \"dataRow\" &&\r\n e.dataField === \"ApprovalNotes\"\r\n ) {\r\n e.editorOptions.placeholder = Config.lang(\"Nhap_ghi_chu_duyet\");\r\n }\r\n else {\r\n e.editorOptions.onValueChanged = (evt) => {\r\n e.row.data.IsSelected = +evt.value;\r\n //refresh để chạy hàm filter lưới\r\n e.component.refresh();\r\n }\r\n }\r\n }}\r\n >\r\n {dataColumnGridExtra().map((item, idx) => {\r\n return (\r\n \r\n )\r\n })}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n )\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [_dataGrid, refSelectedRowKeys.current, gridLoading, isChangePage.current])\r\n\r\n const onSave = (mode) => {\r\n if (refSelectedRowsData.current.length > 0) {\r\n const confirmText = `Ban_co_chac_chan_muon_${mode === 0 ? \"duyet\" : \"tu_choi\"}`\r\n Config.popup.show(\r\n \"YES_NO\", // type\r\n Config.lang(confirmText), // message\r\n () => { // chon Dong y\r\n setGridLoading(true);\r\n setIsSaving(true);\r\n const approvalStatus = mode === 0 ? \"1\" : \"100\";\r\n const arrCheckParams = [];\r\n const arrApprovalParams = [];\r\n refSelectedRowsData.current.forEach((data) => {\r\n const {\r\n AbsentVoucherID,\r\n ApprovalLevel,\r\n ApprovalFlowID,\r\n ApprovalNotes\r\n } = data;\r\n const checkParams = {\r\n FormID: \"W13F1000\",\r\n AbsentVoucherID,\r\n Mode: mode,\r\n }\r\n const approvalParams = {\r\n FormID: \"W13F1000\",\r\n AbsentVoucherID,\r\n ApprovalLevel,\r\n ApprovalFlowID,\r\n ApprovalStatus: approvalStatus,\r\n ApprovalsNotes: ApprovalNotes,\r\n Mode: 0,\r\n };\r\n arrCheckParams.push(checkParams);\r\n arrApprovalParams.push(approvalParams);\r\n });\r\n let arrParams = { arrCheckParams, arrApprovalParams };\r\n const checkParamsLength = arrParams.arrCheckParams.length;\r\n const approvalTimeout = checkParamsLength < 5 ? 1000 : Math.ceil(checkParamsLength /10) * 1500;\r\n dispatch(W13F1003Actions.check(arrParams, (error, data) => {\r\n counter++;\r\n const isLastRequest = (counter === arrParams.arrCheckParams.length);\r\n const lastRequestHanlder = (data) => {\r\n if (isLastRequest) {\r\n if (errorMessage) {\r\n const lastMessage = Config.lang(`Ton_tai_nhung_don_tu_${mode === 0 ? \"duyet\" : \"tu_choi\"}_khong_thanh_cong:`) + `${errorMessage}\\n${data.Message}`;\r\n setTimeout(() => Config.popup.show(\"INFO\", lastMessage, () => {\r\n arrParams = [];\r\n loadGrid();\r\n resetData();\r\n }),approvalTimeout);\r\n }\r\n else {\r\n setTimeout(() => Config.popup.show(\"INFO\", Config.lang(`${mode === 0 ? \"Duyet\" : \"Tu_choi\"}_thanh_cong`), () => {\r\n arrParams = [];\r\n loadGrid();\r\n resetData();\r\n }),approvalTimeout);\r\n }\r\n }\r\n }\r\n if (isLastRequest) {\r\n setTimeout(()=> {\r\n setIsSaving(false);\r\n setGridLoading(false);\r\n },approvalTimeout);\r\n }\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n return false;\r\n }\r\n else if (data.Status === 1) {\r\n if (data.MsgAsk === 0) {\r\n errorMessage = `${errorMessage}\\n${data.Message}`; // MsgAsk = 0 thì UI giữ lại để sau khi thực hiện hết quy trình sẽ xuất ra Message = Message của các dòng có Status = 1 Và MsgAsk = 0 cộng lại cách nhau bởi dấu xuống dòng\r\n if (isLastRequest) {\r\n const lastMessage = Config.lang(`Ton_tai_nhung_đon_tu_${mode === 0 ? \"duyet\" : \"tu_choi\"}_khong_thanh_cong:`) + `${errorMessage}\\n${data.Message}`;\r\n Config.popup.show(\"INFO\", lastMessage, () => {\r\n arrParams=[];\r\n loadGrid();\r\n resetData();\r\n });\r\n }\r\n }\r\n else if (data.MsgAsk === 1) {\r\n Config.popup.show(\"YES_NO\", data?.Message, () => {\r\n (async () => {\r\n dispatch(W13F1003Actions.approval(arrParams.arrApprovalParams[counter - 1], error => {\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n }\r\n lastRequestHanlder(data);\r\n }))\r\n })();\r\n },() => {\r\n dispatch(W13F1003Actions.cancelApproval(() => {\r\n lastRequestHanlder(data);\r\n }))\r\n });\r\n }\r\n }\r\n else {\r\n lastRequestHanlder(data);\r\n }\r\n }));\r\n }, () => { // chon Huy\r\n })\r\n }\r\n else {\r\n Config.popup.show(\"INFO\", Config.lang(\"Ban_chua_chon_nhan_vien\"));\r\n }\r\n };\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {Config.lang(\"Duyet_dieu_chinh_thu_nhap_hang_loat\")}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n setShowDrawer(!showDrawer)}\r\n />\r\n {showDrawer &&\r\n {Config.lang(\"Tieu_chi_loc\")} \r\n }\r\n
\r\n {showDrawer &&\r\n setShowDrawer(false)}\r\n />\r\n }\r\n \r\n \r\n {showDrawer &&\r\n <>\r\n \r\n {\r\n isChangeShow.current = true;\r\n if(isChangePage.current) {\r\n isChangePage.current = false;\r\n }\r\n setIsShowSelected(e.value);\r\n }}\r\n disabled={isSaving || gridLoading}\r\n label={Config.lang(\"Chi_hien_thi_nhung_du_lieu_da_chon\")}\r\n />\r\n \r\n \r\n handleChange(\"EmployeeID\", e)}\r\n />\r\n \r\n \r\n handleChange(\"ProjectID\", e)}\r\n onInputChanged={(e) => {\r\n filterCboProject.strSearch = e.target.value;\r\n filterCboProject.skip = 0;\r\n loadCboProjects(true);\r\n }}\r\n onLoadMore={(e) => {\r\n filterCboProject.skip = e.skip;\r\n filterCboProject.limit = e.limit;\r\n loadCboProjects();\r\n }}\r\n />\r\n \r\n \r\n handleChange(\"DepartmentID\", e)}\r\n />\r\n \r\n \r\n handleChange(\"RangePicker\", evt)}\r\n placeholder={\"dd/mm/yyyy - dd/mm/yyyy\"}\r\n returnFormat={\"YYYY-MM-DD\"}\r\n />\r\n \r\n \r\n {\r\n isFilter.current = true;\r\n loadGrid();\r\n }}\r\n />\r\n \r\n >\r\n }\r\n
\r\n \r\n \r\n {renderGrid}\r\n \r\n
\r\n \r\n \r\n onSave(0)}\r\n />\r\n onSave(1)}\r\n />\r\n \r\n \r\n )\r\n});\r\n\r\nexport default W13F1003;","/**\r\n * @copyright 2020 @ DigiNet\r\n * @author DINHTHIEN\r\n * @create 4/9/2020\r\n * @Example\r\n */\r\n\r\nimport React, { Component } from \"react\";\r\nimport { connect } from \"react-redux\";\r\nimport * as W09F9000Actions from \"../../../../redux/W0X/W09F9000/W09F9000_actions\";\r\nimport * as generalActions from \"../../../../redux/general/general_actions\";\r\nimport { bindActionCreators, compose } from \"redux\";\r\nimport Config from \"../../../../config\";\r\nimport ButtonGeneral from \"../../../common/button/button-general\";\r\nimport { withStyles } from \"@material-ui/core\";\r\nimport ActionToolbar from \"../../../common/toolbar/action-toolbar\"\r\nimport Api from \"../../../../services/api\";\r\nimport _ from \"lodash\";\r\nimport W09F9000ManualLeft from \"./W09F9000ManualLeft\";\r\nimport W09F9000ManualRight from \"./W09F9000ManualRight\";\r\nimport Filter from \"../../../filter/filter\";\r\nimport {Col, Row} from \"react-bootstrap\";\r\nconst styles = (theme) => {\r\n return {\r\n colLeft: {\r\n [theme.breakpoints.up('sm')]: {\r\n maxWidth: 280\r\n }\r\n },\r\n header: {\r\n zIndex: 0,\r\n },\r\n };\r\n};\r\nclass W09F9000 extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n groupID: \"\",\r\n iPermission: 0,\r\n gridLoading: false,\r\n editRow: false,\r\n isNewRow: false,\r\n mode: \"\",\r\n searchValue: \"\"\r\n };\r\n this.refDataRow = null;\r\n }\r\n\r\n isValidURL = string => {\r\n // eslint-disable-next-line no-useless-escape\r\n let regex = /^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$/;\r\n return regex.test(string.trim())\r\n };\r\n\r\n\r\n onSearch = e => {\r\n if (this.timer) { clearTimeout(this.timer) };\r\n this.timer = setTimeout(() => {\r\n this.setState({\r\n searchValue: e.target.value\r\n })\r\n }, 500);\r\n }\r\n\r\n onChangeTabs = id => {\r\n this.setState({ groupID: id }, () => { this.loadDataManualRight(id) })\r\n }\r\n\r\n onEditRow = (e, type) => {\r\n const { isNewRow } = this.state;\r\n this.setState({ editRow: true, mode: type }, () => {\r\n setTimeout(() => {\r\n if (type === \"add\" && this.refDataRow) {\r\n !isNewRow && this.refDataRow.instance.addRow();\r\n this.setState({ isNewRow: true })\r\n } else if (e) {\r\n if (type === \"edit\") {\r\n e.component.editRow(e.rowIndex);\r\n } else {\r\n Config.popup.show(\"YES_NO\", Config.lang(\"DHR_Ban_co_chac_muon_xoa?\"), () => { e.component.deleteRow(e.rowIndex); this.onRowUpdated(e) });\r\n };\r\n }\r\n }, 300);\r\n });\r\n };\r\n\r\n onRowUpdated = async e => {\r\n if (!e) return false;\r\n const { data } = e;\r\n const { mode, groupID } = this.state;\r\n const ItemID = _.get(data, \"ItemID\", \"\");\r\n if (!ItemID && (mode === \"edit\" || mode === \"delete\")) {\r\n Config.popup.show(\"INFO\", `ItemID ${Config.lang(\"DHR_Bat_buoc\")}`);\r\n return false;\r\n }\r\n if (!groupID && mode === \"add\") {\r\n Config.popup.show(\"INFO\", `GroupID ${Config.lang(\"DHR_Bat_buoc\")}`);\r\n return false;\r\n };\r\n const params = {\r\n GroupID: groupID,\r\n ItemID,\r\n URL: _.get(data, \"URL\", \"\").trim(),\r\n ItemDes: _.get(data, \"ItemDes\", \"\").trim(),\r\n OrderNo: _.get(data, \"OrderNo\", \"\")\r\n }\r\n this.setState({ gridLoading: true });\r\n mode && await Api.put(`/w09f9000/${mode}`, params).then(({ code = \"\" }) => {\r\n let sMessage = \"\";\r\n let type = \"\";\r\n switch (code) {\r\n case 200:\r\n type = \"success\"\r\n sMessage = Config.lang(\"DHR_Luu_thanh_cong\")\r\n break;\r\n default:\r\n type = \"INFO\"\r\n sMessage = Config.lang(\"DHR_Loi_chua_xac_dinh\")\r\n break;\r\n }\r\n Config.notify.show(type, sMessage, 2000);\r\n this.setState({ isNewRow: false, editRow: false, gridLoading: false, searchValue: \"\" }, () => this.loadDataManualRight(groupID))\r\n }).catch(err => { this.setState({ gridLoading: false }); });\r\n\r\n }\r\n\r\n loadPermission = async () => {\r\n await this.props.generalActions.getPermission(\"W09F9000\", isPer => {\r\n this.setState({ iPermission: isPer });\r\n });\r\n };\r\n\r\n loadDataManualLeft = () => {\r\n this.setState({ gridLoading: true });\r\n return new Promise((rl, rj) => {\r\n this.props.w09f9000Actions.loadUserManualLeft((error, data) => {\r\n if (error) {\r\n rj(error);\r\n } else {\r\n const firstId = _.get(data, \"[0]GroupID\", \"\");\r\n this.setState({ groupID: firstId, gridLoading: false });\r\n rl(firstId);\r\n }\r\n this.setState({ gridLoading: false });\r\n })\r\n })\r\n }\r\n\r\n loadDataManualRight = id => {\r\n this.setState({ gridLoading: true });\r\n this.props.w09f9000Actions.loadUserManualRight({ GroupID: id }, error => {\r\n if (error) {\r\n Config.popup.show(\"ERROR\", error);\r\n return false;\r\n }\r\n this.setState({ gridLoading: false });\r\n });\r\n }\r\n\r\n componentDidMount = async () => {\r\n await this.loadPermission();\r\n // if (this.state.iPermission <= 0) return;\r\n this.loadDataManualLeft().then(id => { this.loadDataManualRight(id) }).catch(err => {\r\n let message = err.message || Config.lang(\"DHR_Loi_chua_xac_dinh\");\r\n Config.popup.show(\"INFO\", message);\r\n });\r\n }\r\n\r\n render() {\r\n const { classes, getManualLeftPanel } = this.props;\r\n const { groupID, iPermission, editRow, gridLoading, searchValue, isNewRow } = this.state;\r\n return (\r\n <>\r\n \r\n this.onEditRow(null, \"add\")} />\r\n \r\n \r\n
\r\n \r\n
\r\n
\r\n \r\n { this.setState({ isNewRow: false }, () => { this.onChangeTabs(id); }) }} />\r\n \r\n \r\n \r\n
\r\n this.isValidURL(e.value)}\r\n onNewRow={() => { this.setState({ isNewRow: false }) }}\r\n refDataRow={ref => this.refDataRow = ref}\r\n onEditRow={this.onEditRow}\r\n onCanCelEdit={() => this.onCanCelEditing()}\r\n onRowUpdated={this.onRowUpdated}\r\n />\r\n
\r\n
\r\n \r\n
\r\n
\r\n >\r\n )\r\n }\r\n}\r\n\r\nexport default compose(connect((state) => ({\r\n getManualLeftPanel: state.W09F9000.getManualLeftPanel,\r\n getManualRightPanel: state.W09F9000.getManualRightPanel\r\n}), (dispatch) => ({\r\n generalActions: bindActionCreators(generalActions, dispatch),\r\n w09f9000Actions: bindActionCreators(W09F9000Actions, dispatch)\r\n})), withStyles(styles, {withTheme: true}))(W09F9000);\r\n"],"sourceRoot":""}