update code

This commit is contained in:
huyt 2022-01-14 20:22:35 +07:00
parent 6ad59b245c
commit ad13ef2753
18 changed files with 994 additions and 141 deletions

BIN
app/public/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

View File

@ -34,7 +34,7 @@
<!--RTL version:<link href="assets/vendors/base/vendors.bundle.rtl.css" rel="stylesheet" type="text/css" />--> <!--RTL version:<link href="assets/vendors/base/vendors.bundle.rtl.css" rel="stylesheet" type="text/css" />-->
<link href="%PUBLIC_URL%/assets/demo/demo9/base/style.bundle.css" rel="stylesheet" type="text/css" /> <link href="%PUBLIC_URL%/assets/demo/demo9/base/style.bundle.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="%PUBLIC_URL%/css/core.css"> <link rel="stylesheet" href="%PUBLIC_URL%/css/core.css">
<title>FSI</title> <title>REVA - AI xử lý ảnh</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

View File

@ -473,3 +473,40 @@ button.close:hover {
font-weight: 600; font-weight: 600;
font-family: inherit !important; font-family: inherit !important;
} }
/* Scrollbar Modal DashBoard styles */
.scroll::-webkit-scrollbar {
width: 5px;
height: 0px;
}
.scroll::-webkit-scrollbar-track {
box-shadow: inset 0 0 10px #bdc3d4;
border-radius: 10px;
}
.scroll::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #9699a2c7;
box-shadow: inset 0 0 6px #00000020;
padding-left: 10px;
}
.scroll_customer_daily {
max-height: 700px;
overflow-y: scroll;
padding-right: 8px;
}
.scroll_customer_daily:hover {
overflow: overlay;
}
.scroll_customer_vip {
max-height: 100%;
overflow: hidden;
padding-right: 8px;
}
.scroll_customer_vip:hover {
overflow: overlay;
}
.scroll_staff {
max-height: 100%;
overflow: hidden;
padding-right: 8px;
}

View File

@ -3,11 +3,13 @@ import ListItem from './components/List/ListItem';
import Login from './components/Login/Login'; import Login from './components/Login/Login';
import LabelImage from './components/LabelImg/LabelImage'; import LabelImage from './components/LabelImg/LabelImage';
import SearchImage from './components/SearchImg/SearchImage'; import SearchImage from './components/SearchImg/SearchImage';
import Role from './components/Role/Role';
import User from './components/User/User'; import User from './components/User/User';
import ImportImage from './components/ImportImg/ImportImage'; import ImportImage from './components/ImportImg/ImportImage';
import Test from './components/Test/Test'; import Test from './components/Test/Test';
import MenuBar from './components/layouts/MenuBar' import MenuBar from './components/layouts/MenuBar'
import Header from './components/layouts/Header' import Header from './components/layouts/Header'
import Footer from './components/layouts/Footer'
import 'antd/dist/antd.css'; import 'antd/dist/antd.css';
import "./App.css"; import "./App.css";
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
@ -28,14 +30,15 @@ function App() {
<Route exact path='/' component={SearchImage} /> <Route exact path='/' component={SearchImage} />
<Route path='/import-image' component={ImportImage} /> <Route path='/import-image' component={ImportImage} />
<Route path='/user' component={User} /> <Route path='/user' component={User} />
<Route path='/role' component={Role} />
<Route path='/search-image' component={SearchImage} /> <Route path='/search-image' component={SearchImage} />
<Route path='/label-image' component={LabelImage} /> <Route path='/label-image' component={LabelImage} />
<Route path='/test' component={Test} /> <Route path='/test' component={Test} />
<Route path="/list-famous" component={ListItem} /> <Route path="/list-famous" component={ListItem} />
</div> </div>
{/* <Footer/> */}
</div> </div>
</Switch> </Switch>
</Router> </Router>
</Provider> </Provider>
); );

View File

@ -0,0 +1,9 @@
export const SETBOX = 'SETBOX';
export function setbox(id_company){
return {
type: SETBOX,
payload:{
id_company: id_company,
}
}
}

View File

@ -9,6 +9,7 @@ import { PulseLoader } from 'react-spinners';
import { HOST } from '../../config/index'; import { HOST } from '../../config/index';
import swal from 'sweetalert'; import swal from 'sweetalert';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { useSelector } from 'react-redux';
const initialDataPost = { const initialDataPost = {
index: 1, index: 1,
@ -25,13 +26,18 @@ export default function LabelImage() {
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const token = useSelector(state => state.isLogin.access_token);
const role = useSelector(state => state.role);
const idCompany = useSelector(state => state.boxai);
console.log(token)
const [activePage, setActivePage] = useState(1) const [activePage, setActivePage] = useState(1)
const [totalItems, setTotalItems] = useState(0) const [totalItems, setTotalItems] = useState(0)
const [dataPost, setDataPost] = useState(initialDataPost) const [dataPost, setDataPost] = useState(initialDataPost)
const itemsPerPage = 5 const itemsPerPage = 5
const [token, setToken] = useState('');
const location = useLocation(); const location = useLocation();
@ -43,8 +49,6 @@ export default function LabelImage() {
let arr = value.split('='); let arr = value.split('=');
obj[arr[0]] = arr[1] obj[arr[0]] = arr[1]
}) })
setToken(decodeURIComponent(obj.token))
setToken((obj.token))
} }
}, [location]) }, [location])
@ -218,8 +222,10 @@ export default function LabelImage() {
} }
return ( return (
<div> <>
{showModal && <ModalEditLabel data={dataEdit} onHide={onCloseModal} show={showModal} />} {showModal && <ModalEditLabel data={dataEdit} onHide={onCloseModal} show={showModal} />}
<div className="m-grid__item m-grid__item--fluid m-wrapper p-2" id="capture_form">
<div className="m-content p-2">
<div className="m-portlet m-portlet--mobile pb-3"> <div className="m-portlet m-portlet--mobile pb-3">
<div className="m-portlet__head"> <div className="m-portlet__head">
<div className="m-portlet__head-caption"> <div className="m-portlet__head-caption">
@ -330,5 +336,7 @@ export default function LabelImage() {
</div> </div>
</div> </div>
</div> </div>
</div>
</>
) )
} }

View File

@ -9,6 +9,7 @@ import { PulseLoader } from 'react-spinners';
import { HOST } from '../../config/index'; import { HOST } from '../../config/index';
import swal from 'sweetalert'; import swal from 'sweetalert';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { useSelector } from 'react-redux';
const initialDataPost = { const initialDataPost = {
index: 1, index: 1,
@ -28,10 +29,11 @@ export default function ListItem() {
const [activePage, setActivePage] = useState(1) const [activePage, setActivePage] = useState(1)
const [totalItems, setTotalItems] = useState(0) const [totalItems, setTotalItems] = useState(0)
const token = useSelector(state => state.isLogin.access_token);
const [dataPost, setDataPost] = useState(initialDataPost) const [dataPost, setDataPost] = useState(initialDataPost)
const itemsPerPage = 5 const itemsPerPage = 5
const [token, setToken] = useState('');
const location = useLocation(); const location = useLocation();
@ -43,8 +45,6 @@ export default function ListItem() {
let arr = value.split('='); let arr = value.split('=');
obj[arr[0]] = arr[1] obj[arr[0]] = arr[1]
}) })
setToken(decodeURIComponent(obj.token))
setToken((obj.token))
} }
}, [location]) }, [location])

View File

@ -5,7 +5,8 @@ import $ from 'jquery';
import { HOST } from '../../config'; import { HOST } from '../../config';
import Store from '../../store'; import Store from '../../store';
import { login } from '../../actions/isLogin'; import { login } from '../../actions/isLogin';
import { role } from '../../actions/role';
import { setbox } from '../../actions/boxai';
class Login extends Component { class Login extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -13,7 +14,7 @@ class Login extends Component {
error: 0, error: 0,
loadingbtn: false, loadingbtn: false,
datalogin: { datalogin: {
email: "", username: "",
password: "", password: "",
} }
} }
@ -38,7 +39,7 @@ class Login extends Component {
loadingbtn: false loadingbtn: false
}) })
} else { } else {
fetch(`${HOST}/api/login`, { fetch(`${HOST}/api/users/login`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
@ -57,14 +58,19 @@ class Login extends Component {
return response.json() return response.json()
}).then((data) => { }).then((data) => {
if (data.status === 10000) { if (data.status === 10000) {
console.log(data)
console.log(data.data.roles)
this.setState({ this.setState({
error: 0, error: 0,
loadingbtn: false loadingbtn: false
}, () => {
Store.dispatch(role(data.data.roles));
}) })
localStorage.setItem("access_token", "Bearer " + data.access_token); localStorage.setItem("access_token", "Bearer " + data.access_token);
Store.dispatch(login("Bearer " + data.access_token)); Store.dispatch(login("Bearer " + data.access_token));
localStorage.setItem("api_url", data.api_url); Store.dispatch(setbox(data.data.company_id));
localStorage.setItem("api2_url", data.api2_url); localStorage.setItem("username", data.data.username);
localStorage.setItem("obj_id", data.data._id);
window.location.href = "/"; window.location.href = "/";
// return; // return;
} else if (data.status === 10003) { } else if (data.status === 10003) {
@ -125,11 +131,11 @@ class Login extends Component {
</div> </div>
<div className="login-form" id="formLogin"> <div className="login-form" id="formLogin">
<label id="label_check" className={"form-check-label pb-2" + (this.state.error === 1 ? "" : " d-none")}> <label id="label_check" className={"form-check-label pb-2" + (this.state.error === 1 ? "" : " d-none")}>
<div className="text-danger">* Sai email hoặc mật khẩu</div> <div className="text-danger">* Sai tên đăng nhập hoặc mật khẩu</div>
</label> </label>
< div className="form-group"> < div className="form-group">
<label htmlFor="exampleInputEmail1" className="text-uppercase">Email</label> <label htmlFor="exampleInputEmail1" className="text-uppercase">Tên đăng nhập</label>
<input type="text" name="email" id="exampleInputEmail1" className="form-control" value={this.state.datalogin.email} placeholder="Nhập email..." required onKeyDown={this.onEnterPress} onChange={(e) => { <input type="text" name="username" id="exampleInputEmail1" className="form-control" value={this.state.datalogin.username} placeholder="Nhập tên đăng nhập..." required onKeyDown={this.onEnterPress} onChange={(e) => {
this.HandleLogin(e) this.HandleLogin(e)
}} /> }} />
</div> </div>

View File

@ -0,0 +1,399 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Button, Modal } from 'react-bootstrap';
import Switch from "react-switch";
import swal from 'sweetalert';
import $ from 'jquery';
import Select from "react-select";
import { HOST } from '../../config/index';
class ModalRole extends Component {
constructor(props) {
super(props);
this.state = {
listStaff: [],
listStaffDefault: [],
listLicense: [],
listCheckOperation: [],
listRoleTemplate: [],
crrRole: {
name: "",
active: 1,
roles: [],
id_company: "",
is_default: 0,
},
isChecked: true,
valueRoleTemplate: null,
access_token_cloud: '',
}
}
// componentWillMount() {
// var access_token_cloud = localStorage.getItem("access_token_cloud")
// this.setState({
// access_token_cloud: access_token_cloud,
// })
// }
updateRole = async (dataRole, event) => {
console.log(dataRole)
let dataPost = {
is_default: 0,
name: dataRole.name,
roles: dataRole.roles,
obj_id: this.state.crrRole.id ? this.state.crrRole.id : ""
}
dataRole.name.trim()
var form = $("#formAddRole")
if (form[0].checkValidity() === false) {
event.preventDefault()
event.stopPropagation()
form.addClass('was-validated')
} else {
//Insert
if (dataRole.roles.length > 0) {
$('#button_addRole').addClass('m-loader');
$('#button_addRole').attr('disabled', true);
if (dataRole.id === undefined) {
await fetch(`${HOST}/api/levels/insert_or_update`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 'Authorization': token
},
body: JSON.stringify(dataPost)
}).then((response) => {
return response.json()
}).then((data) => {
if (data.status === 10000) {
swal("Thành công", "Tạo mới thành công!", "success", {
buttons: false,
timer: 1500,
});
return this.props.onHide();
} else if (data.status === 10001) {
$('#button_addRole').removeClass('m-loader');
$('#button_addRole').removeAttr('disabled', true);
swal("Cảnh báo", "Tên quyền đã tồn tại", "warning");
} else {
$('#button_addRole').removeClass('m-loader');
$('#button_addRole').removeAttr('disabled', true);
swal("Lỗi", "Tạo mới thất bại!", "error");
}
}).catch((error) => {
if (error) {
$('#button_addRole').removeClass('m-loader');
$('#button_addRole').removeAttr('disabled', true);
swal("Lỗi", "Tạo mới thất bại!", "error");
}
});
} else {
//Update
$('#button_addRole').addClass('m-loader');
$('#button_addRole').attr('disabled', true);
await fetch(`${HOST}/api/levels/insert_or_update`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 'Authorization': token
},
body: JSON.stringify(dataPost)
}).then((response) => {
return response.json()
}).then((data) => {
if (data.status === 10000) {
swal("Thành công", "Bạn đã sửa thành công!", "success", {
buttons: false,
timer: 1500,
});
return this.props.onHide();
} else if (data.status === 10001) {
$('#button_addRole').removeClass('m-loader');
$('#button_addRole').removeAttr('disabled', true);
swal("Cảnh báo", "Tên quyền đã tồn tại", "warning");
} else {
$('#button_addRole').removeClass('m-loader');
$('#button_addRole').removeAttr('disabled', true);
swal("Lỗi", "Sửa thất bại!", "error");
}
}).catch((error) => {
if (error) {
$('#button_addRole').removeClass('m-loader');
$('#button_addRole').removeAttr('disabled', true);
swal("Lỗi", "Sửa thất bại!", "error");
}
});
}
} else {
swal("Cảnh báo", "Bạn chưa chọn quyền", "warning");
}
}
}
RoleHandle(e) {
var dataRole = this.state.crrRole;
dataRole[e.target.name] = e.target.value;
this.setState({ crrRole: dataRole });
}
// handleChangeIsDefault(event) {
// var dataRole = this.state.crrRole;
// if (event.target.value == 0) {
// dataRole['is_default'] = 1
// } else {
// dataRole['is_default'] = 0
// }
// this.setState({
// crrRole: dataRole
// })
// }
// handleChangeRoleTemplate(value) {
// var listCheckOperation = []
// if (value.roles.length > 0) {
// for (let index = 0; index < value.roles.length; index++) {
// listCheckOperation.push(value.roles[index].code_operation)
// }
// }
// var roles = this.state.crrRole;
// roles['roles'] = listCheckOperation;
// roles['name'] = value.label;
// this.setState({
// valueRoleTemplate: value,
// crrRole: roles,
// listCheckOperation: listCheckOperation,
// listLicense: []
// }, () => {
// this.getLicense()
// })
// }
getLicense = () => {
fetch(`${HOST}/api/roles/company/1`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
// 'Authorization': token
},
}).then((response) => {
return response.json()
}).then((data) => {
if (data.status === 10000) {
this.setState({
listLicense: data.data
})
}
})
}
getRoleTemplate = (HOST) => {
fetch(`${HOST}/api/roles/company/1`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
// 'Authorization': token
},
}).then((response) => {
return response.json()
}).then((data) => {
if (data.status === 10000) {
var optionRoleTemplate = [];
if (data.data.length > 0) {
for (let index = 0; index < data.data.length; index++) {
optionRoleTemplate.push({ 'value': data.data[index].id, 'label': data.data[index].name, 'roles': data.data[index].roles })
}
}
this.setState({
optionRoleTemplate: optionRoleTemplate
})
}
})
}
componentWillReceiveProps(nextProps) {
if (nextProps.show === true) {
console.log(nextProps)
//Staff
var listCheckOperation = []
console.log(nextProps.data)
if (nextProps.data.roles.length > 0) {
for (let index = 0; index < nextProps.data.roles.length; index++) {
listCheckOperation.push(nextProps.data.roles[index])
}
}
var crrRole = nextProps.data
crrRole.roles = listCheckOperation
this.setState({
crrRole: crrRole,
listCheckOperation: listCheckOperation,
valueRoleTemplate: null,
}, () => {
this.getLicense()
// this.getRoleTemplate(nextProps.data.HOST)
});
}
}
handleEnter = (event) => {
if (event.keyCode === 13) {
const form = event.target.form;
const index = Array.prototype.indexOf.call(form, event.target);
form.elements[index + 1].focus();
event.preventDefault();
}
}
handleCheckOperation = (event) => {
const checkedArr = [];
let value;
if (event.target.type !== 'checkbox') {
value = event.target.value;
} else {
const checkeds = document.getElementsByName('operation');
for (let i = 0; i < checkeds.length; i++) {
if (checkeds[i].checked) {
checkedArr.push(checkeds[i].value);
}
}
value = checkedArr;
}
var roles = this.state.crrRole;
console.log(value)
roles['roles'] = value;
this.setState({
crrRole: roles
})
}
render() {
let click_handle = (event) => {
this.updateRole(this.state.crrRole, event);
}
const dataModule = this.state.listLicense.map((value, index) => {
var lengthChecked = 0
console.log(this.state.listCheckOperation)
if (value !== null) {
var checkboxOperation = value.operations.map((val, i) => {
let codeOperation = val.split(':')
if (this.state.listCheckOperation.indexOf(val) !== -1) {
lengthChecked++
}
return (
<label className="m-checkbox m-checkbox-day col-md-3 text_white_space pr-0" key={val}>
<input type="checkbox" name="operation" defaultValue={val} onChange={e => this.handleCheckOperation(e)} defaultChecked={this.state.listCheckOperation.indexOf(val) === -1 ? false : true} /> {codeOperation[1]}
<span />
</label>
)
})
return (
<div className="m-accordion__item" key={index}>
<div className="m-accordion__item-head">
<span className="m-accordion__item-title">{value.name}</span>
{/* <span className="m-accordion__item-title">{value.module.code} --- {lengthChecked} / {value.module.operation.length}</span> */}
{/* <span className="m-accordion__item-mode" /> */}
</div>
<div className="m-accordion__item-body collapse show">
<div className="m-accordion__item-content">
<div className="m-form__group form-group">
<div className="m-checkbox-inline row m-0">
{checkboxOperation}
</div>
</div>
</div>
</div>
</div>
)
}
})
if (this.state.crrRole.active === 1) {
this.state.isChecked = true
} else {
this.state.isChecked = false
}
return (
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
</Modal.Title>
</Modal.Header>
<Modal.Body>
<form id="formAddRole">
<div className="col-xl-12">
<div className="m-widget14">
<div className="form-group m-form__group">
<label htmlFor="Name">Tên <span className="text-danger"> *</span></label>
<input className="form-control m-input" id="Name" name='name' value={this.state.crrRole.name === '' ? '' : this.state.crrRole.name} onKeyDown={(event) => this.handleEnter(event)} onChange={e => this.RoleHandle(e)} placeholder="Tên" required />
</div>
{/* <div className="form-group m-form__group ">
<label>Trạng thái</label>
<div className="pt-2 pb-2">
<Switch
onChange={() => {
var active;
if (!this.state.isChecked == true) {
active = 1
} else {
active = 0
}
var crrRole = this.state.crrRole;
crrRole['active'] = active;
this.setState({
crrRole: crrRole,
isChecked: !this.state.isChecked
});
}}
checked={this.state.isChecked}
handleDiameter={17}
offColor="#969696"
onColor="#00c5dc"
offHandleColor="#ffffff"
onHandleColor="#08f"
height={25}
width={55}
className="react-switch"
id="small-radius-switch"
/>
</div>
</div> */}
<div className="form-group m-form__group col-md-12 p-0 m-scrollable scroll scroll_customer_daily" style={{ 'height': '450px' }}>
<div className="m-accordion m-accordion--bordered" id="m_accordion_2" role="tablist">
{dataModule}
</div>
</div>
</div>
</div>
</form>
</Modal.Body>
<Modal.Footer>
<Button variant="accent" id="button_addRole" className="m-loader--light m-loader--right" onClick={click_handle}>Lưu</Button>
<Button variant="secondary" onClick={this.props.onHide}>Đóng</Button>
</Modal.Footer>
</Modal>
);
}
}
ModalRole.propTypes = {
data: PropTypes.object,
liststaff: PropTypes.array,
onHide: PropTypes.func.isRequired,
show: PropTypes.bool,
}
export default ModalRole;

View File

@ -19,6 +19,9 @@ const ModalUser = (props) => {
const [form] = Form.useForm() const [form] = Form.useForm()
const [listOptions, setListOption] = useState([])
const [birthday, setBirthday] = useState(moment()) const [birthday, setBirthday] = useState(moment())
const [crrData, setCrrData] = useState(null); const [crrData, setCrrData] = useState(null);
@ -40,39 +43,28 @@ const ModalUser = (props) => {
useEffect(() => { useEffect(() => {
setCrrData(data); setCrrData(data);
console.log(data)
// setCrrImages(data.sample_images)
// setBirthday(data.birthday !== "" ? moment(data.birthday) : null)
// setDisableBtn(data._id ? false : true)
// setHostImg(data.image_host)
// return () => {
// setCrrData(null);
// }
}, [data]); }, [data]);
useEffect(() => {
getLevel()
}, [])
// const handleCheckedImg = (event, value) => {
// let newListChecked = { ...listChecked }
// if (newListChecked.url.indexOf(event.target.value) === -1) {
// newListChecked.url.push(event.target.value)
// } else {
// var i = newListChecked.url.indexOf(event.target.value);
// if (i !== -1) {
// newListChecked.url.splice(i, 1);
// }
// }
// setListChecked(newListChecked)
// }
// useEffect(() => { const getLevel = async () => {
// if (crrImages.length > 0) { let result = await axios.get(`${HOST}/api/levels/company/1`)
// let crrDateImg = crrImages[crrIdx] if (result.data.status === 10000) {
// let getDateImg = crrDateImg !== "" && crrDateImg.split("_") var listOptions = []
// let dataImg = getDateImg.length > 0 && getDateImg[1].slice(0,6) for (let i = 0; i < result.data.data.length; i++) {
// setDateImg(dataImg) const element = result.data.data[i];
// } console.log(element.name)
// },[crrImages,crrIdx]) listOptions.push(<Option key={element._id}>{element.name}</Option>);
}
setListOption(listOptions)
}
}
const click_handle = async () => { const click_handle = async () => {
let dataPost = { let dataPost = {
@ -84,7 +76,7 @@ const ModalUser = (props) => {
birthday: crrData.birthday, birthday: crrData.birthday,
gender: crrData?.gender ? crrData.gender : "", gender: crrData?.gender ? crrData.gender : "",
phone_number: crrData?.phone_number ? crrData?.phone_number : "", phone_number: crrData?.phone_number ? crrData?.phone_number : "",
role_id_list: selectedRole level_obj_id: selectedRole
} }
const result = await axios({ const result = await axios({
method: 'POST', method: 'POST',
@ -105,6 +97,7 @@ const ModalUser = (props) => {
timer: 1500, timer: 1500,
buttons: false, buttons: false,
}) })
onHide()
} else { } else {
swal({ swal({
icon: 'success', icon: 'success',
@ -140,10 +133,7 @@ const ModalUser = (props) => {
setCrrData({ ...crrData, birthday: moment(date).format("YYYY-MM-DD") }) setCrrData({ ...crrData, birthday: moment(date).format("YYYY-MM-DD") })
} }
const listOptions = [];
for (let i = 10; i < 36; i++) {
listOptions.push(<Option key={i.toString(36) + i + "key"}>{i.toString(36) + i + "value"}</Option>);
}
const handleChangeSelect = (value) => { const handleChangeSelect = (value) => {
setSelectedRole(value) setSelectedRole(value)
@ -185,7 +175,7 @@ const ModalUser = (props) => {
full_name: crrData?.full_name, full_name: crrData?.full_name,
gender: crrData?.gender, gender: crrData?.gender,
username: crrData?.username, username: crrData?.username,
role_id_list: crrData?.role_id_list, level_obj_id: crrData?.level_obj_id,
phone_number: crrData?.phone_number phone_number: crrData?.phone_number
}} }}
> >
@ -196,8 +186,8 @@ const ModalUser = (props) => {
required: true, required: true,
message: "" message: ""
},{ },{
pattern: /^(?=.{5,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+$/, pattern: /^(?=.{3,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+$/,
message: 'Tên đăng nhập có độ dài từ 5-20 ký tự,không có khoảng trắng và ký tự đặc biệt', message: 'Tên đăng nhập có độ dài từ 3-20 ký tự,không có khoảng trắng và ký tự đặc biệt',
} }
]} ]}
> >
@ -244,7 +234,7 @@ const ModalUser = (props) => {
defaultValue={crrData?.birthday ? moment(birthday, 'DD-MM-YYYY') : null} defaultValue={crrData?.birthday ? moment(birthday, 'DD-MM-YYYY') : null}
format={'DD-MM-YYYY'} format={'DD-MM-YYYY'}
onChange={e => onChangeBirthday(e)} onChange={e => onChangeBirthday(e)}
placeholder="Ngày sinh" placeholder="DD-MM-YYY"
/> />
</Form.Item> </Form.Item>
@ -257,12 +247,12 @@ const ModalUser = (props) => {
<Form.Item <Form.Item
label="Quyền" label="Quyền"
name="role_id_list" name="level_obj_id"
> >
<Select <Select
mode="multiple" // mode="multiple"
allowClear // allowClear
style={{ width: '100%' }} style={{ width: '100%' }}
placeholder="Chọn quyền" placeholder="Chọn quyền"
defaultValue={[]} defaultValue={[]}

View File

@ -0,0 +1,295 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import swal from 'sweetalert';
import ModalRole from "../Modal/ModalRole";
import { PulseLoader } from 'react-spinners';
import Pagination from "react-js-pagination";
import $ from 'jquery';
import { HOST } from '../../config/index';
class Role extends Component {
constructor(props) {
super(props);
this.state = {
modalRole: false,
listRole: [],
listStaff: [],
crrDatas: [],
activePage: 1,
offset: 0,
crrRole: {
name: "",
description: ""
},
};
this.itemsPerPage = 10;
}
componentDidMount() {
this.getData();
}
getData = () => {
this.getRole()
}
getRole = () => {
fetch(`${HOST}/api/levels/company/1`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
// 'Authorization': token
},
}).then((response) => {
return response.json()
}).then((data) => {
if (data.status === 10000) {
this.setState({
listRole: data.data
});
this.FilterRole(this.state.activePage)
}
})
}
FilterRole(activePage) {
const { listRole } = this.state;
const offset = (activePage - 1) * this.itemsPerPage;
const crrDatas = listRole.slice(offset, offset + this.itemsPerPage);
console.log(crrDatas)
this.setState({
crrDatas,
offset: offset
})
}
handlePageChange = (pageNumber) => {
this.setState({
...this.state,
activePage: pageNumber
})
this.FilterRole(pageNumber);
}
DeleteRole = async (Role) => {
if (Role.is_default === 1) {
swal("Cảnh báo", "Bạn không được xóa quyền mặc định", "warning");
return;
}
let data = await fetch(`${HOST}/api/role/delete`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 'Authorization': token,
},
body: JSON.stringify({
'id': Role.id
})
}).then((response) => {
return response.json()
});
if (data.status === 10000) {
swal("Thành công", "Bạn đã xóa thành công!", "success", {
buttons: false,
timer: 1500,
});
this.getRole();
}
else {
swal("Lỗi", "Xóa thất bại!", "error");
}
}
modalClose = () => {
this.setState({
modalRole: false,
});
this.getRole();
}
render() {
if (this.state.isLogin === false) {
return (
<Redirect to={'/login'} />
)
}
let bulletedRole = this.state.crrDatas.map((e, i) => {
console.log(e)
var is_default = ""
if (e.is_default === 1) {
is_default = " (Default)"
}
return (
<tr key={(i + 1)}>
<td>{(i + this.state.offset + 1)}</td>
<td>{e.name}</td>
<td>
{
e.active === 0
?
<span className="m-badge m-badge--secondary m-badge--wide">Inactive {is_default}</span>
:
<span className="m-badge m-badge--accent m-badge--wide">Active {is_default}</span>
}
</td>
<td>
<button onClick={(e) => {
var data = this.state.crrDatas
var dataRole = {
id: data[i]._id,
name: data[i].name,
roles: data[i].roles,
is_default: data[i].is_default,
};
this.setState({
crrRole: dataRole,
modalRole: true,
});
}} className="m-portlet__nav-link btn m-btn m-btn--hover-warning m-btn--icon m-btn--icon-only m-btn--pill" data-tip data-for='Edit'>
<i className="la la-edit" />
</button>
{/* <ReactTooltip id='Edit' type='dark' effect='solid'>
<span>{language[this.props.indexLanguage].tooltip.open_edit}</span>
</ReactTooltip> */}
<button className="m-portlet__nav-link btn m-btn m-btn--hover-danger m-btn--icon m-btn--icon-only m-btn--pill" data-tip data-for='Delete'
onClick={v => {
v.preventDefault();
swal({
title: "Bạn có chắc chắn?",
text: "Bạn có chắc chắn muốn xóa quyền" + e.name,
icon: "warning",
buttons: true,
dangerMode: true,
})
.then(willDelete => {
if (willDelete) {
this.DeleteRole(e);
}
});
}}
><i className="la la-trash"></i></button>
{/* <ReactTooltip id='Delete' type='dark' effect='solid'>
<span>{language[this.props.indexLanguage].tooltip.open_delete}</span>
</ReactTooltip> */}
</td>
</tr>
)
});
var pageRangeDisplayed = 1;
if ($(window).width() < 768) {
pageRangeDisplayed = 3
} else {
pageRangeDisplayed = 5
}
return (
<div className="m-grid__item m-grid__item--fluid m-wrapper">
<div className="m-content p-2">
<div className="m-portlet m-portlet--tab mb-0">
<div className="m-portlet__head p-3">
<div className="m-portlet__head-caption pl-3">
<div className="m-portlet__head-title">
<h3 className="m-portlet__head-text">
Quyền
</h3>
</div>
</div>
<div className="m-portlet__head-tools pr-3">
<ul className="m-portlet__nav">
<li className="m-portlet__nav-item">
<button onClick={(e) => {
this.setState({
crrRole: {
name: "",
active: 1,
// id_company: this.state.box_engine_cf.idCompany,
roles: [],
is_default: 0,
HOST: this.state.crrApi2
},
modalRole: true,
});
}} className="btn btn-accent m-btn m-btn--custom m-btn--icon m-btn--pill m-btn--air">
<span>
<i className="la la-plus" />
<span>Thêm mới</span>
</span>
</button>
</li>
</ul>
</div>
</div>
<div className="m-portlet__body m-portlet__body--no-padding">
<div className="row m-row--no-padding m-row--col-separator-xl">
<div className="col-xl-12">
<div className="m-widget1 col-xl-8 mx-auto">
<div className="table-responsive text-nowrap">
<table className="table table-bordered table-hover table-checkable dataTable no-footer dtr-inline collapsed">
<thead>
<tr>
<th style={{ 'verticalAlign': 'middle', 'width': '100px' }}>STT</th>
<th style={{ 'verticalAlign': 'middle' }}>Tên</th>
<th style={{ 'verticalAlign': 'middle', 'width': '200px' }}>Trạng thái</th>
<th style={{ 'verticalAlign': 'middle', 'width': '150px' }}>Thao tác</th>
</tr>
</thead>
<tbody>
{bulletedRole}
</tbody>
</table>
{/* <PulseLoader
css={override}
sizeUnit={"px"}
size={12}
margin={'2px'}
color={'#36D7B7'}
loading={this.state.loading}
/> */}
<ModalRole
data={this.state.crrRole}
show={this.state.modalRole}
onHide={this.modalClose}
/>
</div>
{/* <span>
Showing {this.state.showFirst} to {this.state.showLast} of {this.state.totalLength} entries
</span> */}
<Pagination
prevPageText='Trang trước'
nextPageText='Trang sau'
firstPageText='Trang đầu'
lastPageText='Trang cuối'
activePage={this.state.activePage}
itemsCountPerPage={this.itemsPerPage}
totalItemsCount={this.state.listRole.length}
pageRangeDisplayed={pageRangeDisplayed}
onChange={this.handlePageChange}
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Role;

View File

@ -9,6 +9,7 @@ import { PulseLoader } from 'react-spinners';
import { HOST } from '../../config/index'; import { HOST } from '../../config/index';
import swal from 'sweetalert'; import swal from 'sweetalert';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { useSelector } from 'react-redux';
export default function Test() { export default function Test() {
@ -16,6 +17,9 @@ export default function Test() {
const [text, setText] = useState("") const [text, setText] = useState("")
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const token = useSelector(state => state.isLogin.access_token);
const test = () => { const test = () => {
setLoading(true) setLoading(true)

View File

@ -12,6 +12,7 @@ import swal from 'sweetalert';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import Switch from "react-switch"; import Switch from "react-switch";
import Select from "react-select"; import Select from "react-select";
import { useSelector } from 'react-redux';
const initialDataPost = { const initialDataPost = {
index: 1, index: 1,
@ -27,6 +28,9 @@ export default function User() {
const [showModalPassword, setShowModalPassword] = useState(false) const [showModalPassword, setShowModalPassword] = useState(false)
const [dataEdit, setDataEdit] = useState(null) const [dataEdit, setDataEdit] = useState(null)
const token = useSelector(state => state.isLogin.access_token);
const [optionSelect, setOptionSelect] = useState([ const [optionSelect, setOptionSelect] = useState([
{value: -1, label: "Tất cả"}, {value: -1, label: "Tất cả"},
@ -46,7 +50,6 @@ export default function User() {
const [dataPost, setDataPost] = useState(initialDataPost) const [dataPost, setDataPost] = useState(initialDataPost)
const itemsPerPage = 5 const itemsPerPage = 5
const [token, setToken] = useState('');
const location = useLocation(); const location = useLocation();
@ -58,8 +61,6 @@ export default function User() {
let arr = value.split('='); let arr = value.split('=');
obj[arr[0]] = arr[1] obj[arr[0]] = arr[1]
}) })
setToken(decodeURIComponent(obj.token))
setToken((obj.token))
} }
}, [location]) }, [location])
@ -298,7 +299,7 @@ export default function User() {
gender: "1", gender: "1",
is_deleted: 0, is_deleted: 0,
phone_number: "", phone_number: "",
role_id_list: [], level_obj_id: [],
username: "" username: ""
} }
setDataEdit(defaultData) setDataEdit(defaultData)
@ -331,7 +332,7 @@ export default function User() {
value={dataPost.search_data} value={dataPost.search_data}
id="inputSearch" id="inputSearch"
className="form-control m-input" className="form-control m-input"
placeholder="Tên đăng nhập..." placeholder="Tên đăng nhập/Họ tên..."
data-col-index={0} /> data-col-index={0} />
</div> </div>
<div className="form-group m-form__group col-xl-2"> <div className="form-group m-form__group col-xl-2">

View File

@ -0,0 +1,45 @@
import React, { Component } from 'react';
import Store from '../../store';
import { withRouter } from 'react-router';
class Footer extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<footer className="m-grid__ite m-footer">
<div className="m-container m-container--fluid m-container--full-height m-page__container">
<div className="m-stack m-stack--flex-tablet-and-mobile m-stack--ver m-stack--desktop">
<div className="m-stack__item m-stack__item--left m-stack__item--middle m-stack__item--last">
<span className="m-footer__copyright">
2019 © BeetInnovators
</span>
</div>
<div className="m-stack__item m-stack__item--right m-stack__item--middle m-stack__item--first">
<ul className="m-footer__nav m-nav m-nav--inline m--pull-right">
<li className="m-nav__item">
<a href="http://reva.com.vn" target="blank" className="m-nav__link">
<span className="m-nav__link-text">Giới thiệu</span>
</a>
</li>
<li className="m-nav__item">
<a href="http://reva.com.vn#contact" target="blank" className="m-nav__link">
<span className="m-nav__link-text">Trung tâm hỗ trợ</span>
</a>
</li>
</ul>
</div>
</div>
</div>
</footer>
);
}
}
export default withRouter(Footer);

View File

@ -1,17 +1,45 @@
import $ from 'jquery'; import $ from 'jquery';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
import Store from '../../store';
import { HOST } from '../../config';
class Header extends Component { class Header extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
username : localStorage.getItem('username'),
obj_id : localStorage.getItem('obj_id'),
isLogin: Store.getState().isLogin.isLogin,
access_token: Store.getState().isLogin.access_token,
}; };
} }
componentDidMount() {
this.getUser()
}
getUser = () => {
fetch(`${HOST}/api/users/${this.state.obj_id}`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
})
.then(response => {
return response.json()
}).then(data => {
if (data.status === 10000) {
// Store.dispatch(setbox(data.data.company_id));
console.log(data)
}
}).catch((error) => {
console.log(error)
});
}
onClickOpen = () => { onClickOpen = () => {
$('#m_aside_left').addClass('m-aside-left--on') $('#m_aside_left').addClass('m-aside-left--on')
$('#body_form').addClass('m-aside-left--on') $('#body_form').addClass('m-aside-left--on')
@ -42,9 +70,9 @@ class Header extends Component {
<div className="m-stack__item m-brand m-brand--mobile"> <div className="m-stack__item m-brand m-brand--mobile">
<div className="m-stack m-stack--ver m-stack--general"> <div className="m-stack m-stack--ver m-stack--general">
<div className="m-stack__item m-stack__item--middle m-brand__logo"> <div className="m-stack__item m-stack__item--middle m-brand__logo">
{/* <a href="/dashboard" className="m-brand__logo-wrapper"> <a href="/" className="m-brand__logo-wrapper">
<img alt="" src={this.state.logo_link} style={{ 'width': '160px' }} /> <img src="/img/logo.png" alt="imglogo" className="col-xl-12 pl-0" />
</a> */} </a>
</div> </div>
<div className="m-stack__item m-stack__item--middle m-brand__tools"> <div className="m-stack__item m-stack__item--middle m-brand__tools">
{/* BEGIN: Responsive Aside Left Menu Toggler */} {/* BEGIN: Responsive Aside Left Menu Toggler */}
@ -71,7 +99,7 @@ class Header extends Component {
</div> </div>
<div className="m-stack__item m-stack__item--middle m-stack__item--center" style={{ 'width': '160px' }}> <div className="m-stack__item m-stack__item--middle m-stack__item--center" style={{ 'width': '160px' }}>
<a href="/" className="m-brand m-brand--desktop"> <a href="/" className="m-brand m-brand--desktop">
{/* <img alt="" src="/img/BI_Logo.png" className="logo_img" /> */} <img alt="" src="/img/logo.png" className="logo_img" />
</a> </a>
</div> </div>
<div className="m-stack__item m-stack__item--right"> <div className="m-stack__item m-stack__item--right">
@ -103,10 +131,10 @@ class Header extends Component {
<div className="m-card-user__pic"> <div className="m-card-user__pic">
<img src="/img/photo-placeholder.png" className="m--img-rounded m--marginless" alt="" /> <img src="/img/photo-placeholder.png" className="m--img-rounded m--marginless" alt="" />
</div> </div>
{/* <div class="m-card-user__details"> <div className="m-card-user__details">
<span class="m-card-user__name m--font-weight-500">{this.state.user !== null && this.state.user.first_name + ' ' + this.state.user.last_name}</span> <span className="m-card-user__name m--font-weight-500">{this.state.username}</span>
<a href="#/" class="m-card-user__email m--font-weight-300 m-link">{this.state.user !== null && this.state.user.email}</a> <div href="#/" className="m-card-user__email m--font-weight-300 m-link">{this.state.full_name}</div>
</div> */} </div>
</div> </div>
</div> </div>
<div className="m-dropdown__body"> <div className="m-dropdown__body">
@ -116,10 +144,10 @@ class Header extends Component {
</li> </li>
<li className="m-nav__item"> <li className="m-nav__item">
<a className="btn m-btn--pill btn-secondary m-btn m-btn--custom m-btn--label-brand m-btn--bolder" <a className="btn m-btn--pill btn-secondary m-btn m-btn--custom m-btn--label-brand m-btn--bolder"
// onClick={() => { onClick={() => {
// localStorage.removeItem("access_token"); localStorage.removeItem("access_token");
// window.location.href = "/login"; window.location.href = "/login";
// }} }}
>Đăng Xuất</a> >Đăng Xuất</a>
</li> </li>
</ul> </ul>

View File

@ -1,14 +1,24 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { NavLink } from 'react-router-dom'; import { NavLink } from 'react-router-dom';
import $ from 'jquery'; import $ from 'jquery';
import Store from '../../store';
class MenuBar extends Component { class MenuBar extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
type: '', type: '',
dataRole: Store.getState().role,
} }
Store.subscribe(() => {
this.setState({
isLogin: Store.getState().isLogin.isLogin,
dataRole: Store.getState().role,
}, () => {
});
});
} }
@ -24,6 +34,7 @@ class MenuBar extends Component {
render() { render() {
var active = ''; var active = '';
console.log(this.state.dataRole)
return ( return (
<div id="m_aside_left" className="m-aside-left m-aside-left--skin-dark"> <div id="m_aside_left" className="m-aside-left m-aside-left--skin-dark">

View File

@ -0,0 +1,15 @@
import { SETBOX } from '../../actions/boxai';
const initialState = {
id_company: null,
};
export default function boxai(state = initialState, action) {
switch(action.type){
case SETBOX:
return{
id_company: action.payload.id_company,
};
default:
return state;
}
}

View File

@ -1,7 +1,9 @@
import {combineReducers} from 'redux'; import {combineReducers} from 'redux';
import role from './role' import role from './role'
import isLogin from './isLogin'; import isLogin from './isLogin';
import boxai from './boxai';
export default combineReducers({ export default combineReducers({
role, role,
isLogin isLogin,
boxai,
}); });