update nhan anh

This commit is contained in:
huyt 2022-01-12 17:40:54 +07:00
parent 2b8ec4f708
commit 121aab8463
11 changed files with 875 additions and 16 deletions

View File

@ -23,6 +23,7 @@
"react-loading-overlay": "^1.0.1",
"react-router-dom": "5.2.0",
"react-scripts": "5.0.0",
"react-select": "^5.2.1",
"react-spinners": "^0.11.0",
"sweetalert": "^2.1.2",
"web-vitals": "^2.1.2"

View File

@ -1,8 +1,10 @@
import React from 'react'
import ListItem from './components/List/ListItem';
import Login from './components/Login/Login';
import LabelImage from './components/LabelImg/LabelImage';
import SearchImage from './components/SearchImg/SearchImage';
import ImportImage from './components/ImportImg/ImportImage';
import Test from './components/Test/Test';
import MenuBar from './components/layouts/MenuBar'
import Header from './components/layouts/Header'
import 'antd/dist/antd.css';
@ -19,10 +21,12 @@ function App() {
<Header />
<MenuBar />
<div>
{/* <Redirect exact from='/' to='/search-image' /> */}
<Redirect exact from='/' to='/search-image' />
<Route path='/login' component={Login} />
<Route path='/import-image' component={ImportImage} />
<Route path='/search-image' component={SearchImage} />
<Route path='/label-image' component={LabelImage} />
<Route path='/test' component={Test} />
<Route path="/list-famous" component={ListItem} />
</div>
</div>

View File

@ -8,9 +8,10 @@ import { PulseLoader } from 'react-spinners';
import Modalupload from '../Modal/ModalUpload';
import ModalEditImg from '../Modal/ModalEditImg';
import axios from 'axios';
import { Avatar, Tooltip } from 'antd';
import { Avatar, Tooltip, Image } from 'antd';
import {UserOutlined} from '@ant-design/icons';
import momment from 'moment';
import Select from "react-select";
class ImportImage extends Component {
constructor(props) {
super(props);
@ -28,7 +29,9 @@ class ImportImage extends Component {
modalShow: false,
dataEdit: null,
modalUploadShow: false,
dataSearch: ""
dataSearch: "",
optionSelect: [{value: 1, label:"Facebook"}, {value: 2, label: "Tải lên"}],
valueSelected: {value: 2, label:"Tải lên"},
}
this.itemsPerPage = 5;
}
@ -52,7 +55,8 @@ class ImportImage extends Component {
data: {
index: page,
item_per_page: this.itemsPerPage,
search_data: this.state.dataSearch
search_data: this.state.dataSearch,
import_type: this.state.valueSelected.value
},
})
@ -149,11 +153,20 @@ class ImportImage extends Component {
this.setState({
activePage: 1,
dataSearch: "",
valueSelected: {value: 2, label:"Tải lên"},
}, () => {
this.getListImg(1);
})
}
changeHandleFilter = (e) => {
this.setState({
valueSelected: e,
activePage: 1
}, () => {
this.getListImg(1);
});
}
render() {
// if (this.state.isLogin == false) {
@ -162,9 +175,9 @@ class ImportImage extends Component {
// )
// }
let bulletedListImg = this.state.listImgImport.map((value, index) => {
var listImg
listImg = <img key={index} style={{ width: "80px", height: "80px" }} alt="" src={`${value.image_host}`} />
listImg = <Image style={{ width: "80px", height: "auto", objectFit: "contain"}} alt="" src={`${value.image_host}`} />
return (
@ -172,6 +185,7 @@ class ImportImage extends Component {
<td>{(index + this.state.offset + 1)}</td>
<td>{listImg}</td>
<td>{value.origin_name}</td>
<td>{value.import_type === 1 ? "Facebook" : "Tải lên"}</td>
<td>{momment(value.created_time).format("DD-MM-YYYY")}</td>
<td>
<Tooltip placement="top" title={"Sửa"}>
@ -235,6 +249,14 @@ class ImportImage extends Component {
data-col-index={0}
/>
</div>
<div className="form-group m-form__group col-xl-2">
<Select
placeholder={'Loại ảnh'}
value={this.state.valueSelected}
onChange={this.changeHandleFilter}
options={this.state.optionSelect}
/>
</div>
<div className="pl-3">
<button
onClick={() => {
@ -285,6 +307,7 @@ class ImportImage extends Component {
<th style={{width: "50px"}}>STT</th>
<th>Ảnh</th>
<th>Tên ảnh</th>
<th>Loại ảnh</th>
<th>Ngày tải lên</th>
<th>Thao tác</th>
</tr>

View File

@ -0,0 +1,334 @@
import { UserOutlined } from '@ant-design/icons';
import { Avatar, Tooltip } from 'antd';
import axios from 'axios';
import ModalEditLabel from '../Modal/ModaEditLabel';
import momment from 'moment';
import React, { useEffect, useState } from 'react';
import Pagination from "react-js-pagination";
import { PulseLoader } from 'react-spinners';
import { HOST } from '../../config/index';
import swal from 'sweetalert';
import { useLocation } from 'react-router-dom';
const initialDataPost = {
index: 1,
item_per_page: 5,
search_data: "",
person_type: 4,
}
export default function LabelImage() {
const [data, setData] = useState(null)
const [showModal, setShowModal] = useState(false)
const [dataEdit, setDataEdit] = useState(null)
const [loading, setLoading] = useState(true)
const [activePage, setActivePage] = useState(1)
const [totalItems, setTotalItems] = useState(0)
const [dataPost, setDataPost] = useState(initialDataPost)
const itemsPerPage = 5
const [token, setToken] = useState('');
const location = useLocation();
useEffect(() => {
if (location.search) {
let path = location.search.replace('?', '').split('&');
let obj = {}
path.forEach(value => {
let arr = value.split('=');
obj[arr[0]] = arr[1]
})
setToken(decodeURIComponent(obj.token))
setToken((obj.token))
}
}, [location])
useEffect(() => {
getData()
}, [])
const onClickEdit = (data) => {
setDataEdit(data)
setShowModal(true)
}
const onDelete = async (value) => {
let dataDel = {
obj_id: value._id,
id: value.id,
name: value.name,
birthday: value.birthday,
gender: value.gender,
is_deleted : 1
}
try {
const result = await axios({
method: 'POST',
url: `${HOST}/api/famous_persons/insert_or_update`,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
// 'Authorization': token,
},
data: dataDel,
})
if (result.data.status === 10000) {
if (data.length === 1) {
setActivePage(activePage - 1)
setDataPost({ ...dataPost, index: activePage - 1 })
}
swal({
icon: 'success',
title: 'Thành công',
text: 'Xoá thành công',
timer: 1500,
buttons: false,
})
getData(dataPost)
} else {
swal("Thất bại", "Xoá thất bại!", "error");
}
} catch (error) {
setLoading(false)
console.log(error);
}
}
const handlePageChange = (pageNumber) => {
setActivePage(pageNumber);
const data = {
...dataPost,
index: pageNumber,
}
getData(data);
}
const getData = async (data) => {
try {
const result = await axios({
method: 'POST',
url: `${HOST}/api/famous_persons/search`,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
// 'Authorization': token
},
data: data ? data : dataPost,
})
if (result.data.status === 10000) {
setData(result.data.data)
setTotalItems(result.data.count)
setLoading(false)
}
} catch (error) {
setLoading(false)
console.log(error);
}
}
const handleOnKeyDown = e => {
if (e.key === 'Enter') {
setActivePage(1)
getData(dataPost);
}
}
const tableRows = (dataAll) => dataAll.map((value, index) => {
var gender = ""
if (value.gender === "1") {
gender = "Nam"
} else if (value.gender === "2") {
gender = "Nữ"
} else if (value.gender === "3") {
gender = "Giới tính khác"
} else {
gender = ""
}
var listImg
if (value.sample_images.length > 0) {
let getDateImg = value.sample_images[0].split("_")
let dataImg = getDateImg.length > 0 && getDateImg[1].slice(0,6)
listImg = <img key={index} style={{ width: "80px", height: "80px" }} alt="" src={`${value.sample_images.length > 0 && value.image_host +dataImg+ "/" +value.sample_images[0]}`} />
} else {
listImg = <Avatar shape="square" size={80} icon={<UserOutlined />} />
}
return (
<tr key={index}>
<td>{listImg}</td>
<td>{value.name}</td>
<td>{value.id}</td>
<td>{gender}</td>
<td>{value.birthday !== "" ? momment(value.birthday).format("DD-MM-YYYY") : ""}</td>
<td>
<Tooltip placement="top" title={"Sửa"}>
<button
onClick={() => onClickEdit(value)}
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>
</Tooltip>
<Tooltip placement="top" title={"Xoá"}>
<button
onClick={f => {
f.preventDefault();
swal({
// title: "Are you sure?",
text: "Bạn có chắc muốn xoá " + value.name,
icon: "warning",
buttons: ["Huỷ", "Xoá"],
dangerMode: true,
})
.then(willDelete => {
if (willDelete) {
onDelete(value);
}
});
}}
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="Edit" >
<i className="la la-trash" />
</button>
</Tooltip>
</td>
</tr>
)
})
const onCloseModal = () => {
setShowModal(false)
// setActivePage(activePage)
const data = {
...dataPost,
index: activePage,
}
getData(data);
}
const reset = () => {
setActivePage(1)
setDataPost({...dataPost, search_data: ""})
getData(initialDataPost)
}
return (
<div>
{showModal && <ModalEditLabel data={dataEdit} onHide={onCloseModal} show={showModal} />}
<div className="m-portlet m-portlet--mobile pb-3">
<div className="m-portlet__head">
<div className="m-portlet__head-caption">
<div className="m-portlet__head-title">
<h3 className="m-portlet__head-text">
Gán nhãn
</h3>
</div>
</div>
</div>
<div className="m-portlet__body pt-2">
<div className="row pl-4">
<div className="row p-3 col-xl-11">
<div className="col-lg-2 p-0 m--margin-bottom-10-tablet-and-mobile">
<input type="text"
onKeyPress={(e) => handleOnKeyDown(e)}
onChange={(e) => {
setDataPost({ ...dataPost, search_data: e.target.value })
}}
value={dataPost.search_data}
id="inputSearch" className="form-control m-input"
placeholder="Họ tên..."
data-col-index={0}
/>
</div>
<div className="pl-3">
<button
onClick={() => {
setActivePage(1)
getData(dataPost)
}}
className="btn btn-accent m-btn m-btn--icon" id="m_search">
<span>
<i className="la la-search" />
<span>Tìm kiếm</span>
</span>
</button>
</div>
<div className="pl-3">
<button
onClick={() => {
reset()
}}
className="btn btn-secondary m-btn m-btn--icon" id="m_reset">
<span>
<i className="la la-rotate-left" />
<span>Tải lại</span>
</span>
</button>
</div>
</div>
<div className="m-portlet__head-tools col-xl-1 d-flex align-items-center">
<button
onClick={(e) => {
let dataEdit = {
obj_id: "",
id: "",
name: "",
birthday: "",
gender: "",
sample_images: [],
image_host: ""
};
setDataEdit(dataEdit)
setShowModal(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>
</div>
</div>
{/*begin: Datatable */}
<table className="table table-striped- table-bordered table-hover table-checkable" id="m_table_1">
<thead>
<tr>
<th>Ảnh</th>
<th>Họ tên</th>
<th>FacebookID</th>
<th>Giới tính</th>
<th>Ngày sinh</th>
<th>Thao tác</th>
</tr>
</thead>
<tbody>{data && tableRows(data)}</tbody>
</table>
<PulseLoader
// css={override}
sizeUnit={"px"}
size={12}
margin={'2px'}
color={'#36D7B7'}
loading={loading}
/>
<Pagination
prevPageText='Trang trước'
nextPageText='Trang sau'
firstPageText='Trang đầu'
lastPageText='Trang cuối'
activePage={activePage}
itemsCountPerPage={itemsPerPage}
totalItemsCount={totalItems}
pageRangeDisplayed={5}
onChange={handlePageChange}
/>
</div>
</div>
</div>
)
}

View File

@ -13,7 +13,8 @@ import { useLocation } from 'react-router-dom';
const initialDataPost = {
index: 1,
item_per_page: 5,
search_data: ""
search_data: "",
person_type: 2,
}
export default function ListItem() {

View File

@ -0,0 +1,406 @@
import { UploadOutlined, UserOutlined } from '@ant-design/icons';
import { Avatar, Button as ButtonAntd, DatePicker, Form, Input, Radio, Upload } from 'antd';
import { useLocation } from 'react-router-dom';
import viVN from 'antd/lib/locale/vi_VN';
import axios from 'axios';
import moment from 'moment';
import 'moment/locale/vi';
import React, { useEffect, useRef, useState } from 'react';
import { Button, Modal } from 'react-bootstrap';
import swal from 'sweetalert';
import { HOST } from '../../config/index';
const ModalEditLabel = (props) => {
const { show, onHide, data } = props;
const [crrImages, setCrrImages] = useState([]);
const [form] = Form.useForm()
const [birthday, setBirthday] = useState(moment())
const [crrData, setCrrData] = useState(null);
const [checkDeleteMulti, setCheckDeleteMulti] = useState(false);
const [crrIdx, setCrrIdx] = useState(0)
const [listChecked, setListChecked] = useState({ url: [] });
const [disableBtn, setDisableBtn] = useState(true);
const [dateImage, setDateImg] = useState("")
const [hostImg, setHostImg] = useState('');
useEffect(() => {
setCrrData(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]);
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(() => {
if (crrImages.length > 0) {
let crrDateImg = crrImages[crrIdx]
let getDateImg = crrDateImg !== "" && crrDateImg.split("_")
let dataImg = getDateImg.length > 0 && getDateImg[1].slice(0,6)
setDateImg(dataImg)
}
},[crrImages,crrIdx])
const click_handle = async () => {
let dataPost = {
obj_id: crrData._id ? crrData._id : "",
name: crrData.name,
birthday: crrData.birthday,
gender: crrData.gender ? crrData.gender : "",
id: crrData.id ? crrData.id : "",
person_type: 4
}
const result = await axios({
method: 'POST',
url: `${HOST}/api/famous_persons/insert_or_update`,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
// 'Authorization': token,
},
data: dataPost,
})
if (result.data.status === 10000) {
if (crrData._id) {
swal({
icon: 'success',
title: 'Thành công',
text: 'Sửa thông tin thành công',
timer: 1500,
buttons: false,
})
} else {
swal({
icon: 'success',
title: 'Thành công',
text: 'Thêm mới thành công',
timer: 1500,
buttons: false,
})
setCrrData({...crrData, _id: result.data.data})
setDisableBtn(false)
}
} else if (result.data.status === 10002) {
swal("Thất bại", "Lỗi hệ thống!", "error");
} else {
swal("Thất bại", "Sửa thông tin thất bại!", "error");
}
}
const bulletedImg = crrImages.map((value, index) => {
let getDateImg = value.split("_")
let dataImg = getDateImg.length > 0 && getDateImg[1].slice(0,6)
let renderImg = value.includes("data:image") ? value : hostImg +dataImg+ "/" + value
return (
<div className="img-res col-md-4 pl-0 mb-3" key={index + 1}>
<div style={{ 'height': 80 }}>
{
checkDeleteMulti === false ?
<img alt="" src={renderImg} onClick={() => { setCrrIdx(index) }} className={"opacity_img_click img_check " + (crrIdx === index ? 'active' : '')} />
:
<label className="m-checkbox img-checkbox m-checkbox-day pl-0 mb-0" style={{ 'width': '100%' }}>
<input type="checkbox"
defaultValue={value}
name="img_checked"
checked={listChecked.url.indexOf(value) === -1 ? false : true}
onClick={e => {
handleCheckedImg(e, value)
}} readOnly />
<img alt="" src={renderImg} className="opacity_img img_check" />
<span />
</label>
}
</div>
</div>
)
})
const uploadImage = async (options) => {
if (crrImages.length >= 3) {
swal("Cảnh báo", "Bạn chỉ được tải lên tối đa 3 ảnh!", "warning");
return
} else {
const { file } = options;
const base64 = await convertBase64(file)
let dataUploadImg = {
obj_id: crrData._id ? crrData._id : "",
base64_image_list: [base64.split(',')[1]]
}
fetch(`${HOST}/api/face_images/famous_person`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
// 'Authorization': token
},
body: JSON.stringify(dataUploadImg)
})
.then(res => res.json())
.then(data => {
if (data.status === 10000) {
setHostImg(data.image_host)
let listImg = [...crrImages]
listImg.unshift(data.data.toString())
setCrrImages(listImg)
setCheckDeleteMulti(false)
} else if (data.status === 10003) {
if (data.message === "Too many face in image") {
swal("Thất bại", "Ảnh có nhiều khuôn mặt!", "error");
} else {
swal("Thất bại", "Ảnh không hợp lệ", "error");
}
}
})
}
};
const convertBase64 = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file)
fileReader.onload = () => {
resolve(fileReader.result);
}
fileReader.onerror = (error) => {
reject(error);
}
})
}
const deleteFaceMulti = () => {
let listDelImg = listChecked.url
fetch(`${HOST}/api/face_images/ignore_face`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
// 'Authorization': token
},
body: JSON.stringify({
person_obj_id: crrData._id ? crrData._id : "",
images: listDelImg
})
})
.then(res => res.json())
.then(data => {
if (data.status === 10000) {
let listDetele = crrImages.filter(item => !listDelImg.includes(item));
if (crrIdx >= 1) {
setCrrIdx(crrIdx - 1)
}
setCrrImages(listDetele)
}
})
}
const UserHandle = (e) => {
setCrrData({ ...crrData, [e.target.name]: e.target.value })
}
const onChangeBirthday = (date) => {
setBirthday(date)
setCrrData({ ...crrData, birthday: moment(date).format("YYYY-MM-DD") })
}
if (!crrData) return <></>;
return (
<Modal
{...props}
animation={false}
size="lg"
// keyboard={false}
dialogClassName={`${window.innerWidth >= 1920 ? "modal-size-res" : "modal-size"}`}
aria-labelledby="contained-modal-title-vcenter"
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">{crrData._id ? "Sửa thông tin" : "Thêm mới"}
</Modal.Title>
</Modal.Header>
{crrData &&
<Modal.Body>
<div id="formUpdateMeeting">
<div className="m-widget14 p-0">
<div className="row">
<div className="col-md-7 boder-right d-flex flex-column justify-content-between ">
<div className="row justify-content-center pb-3">
{
crrImages[crrIdx] ?
<Avatar shape="square" src={crrImages[crrIdx].includes("data:image") ? crrImages[crrIdx] : hostImg +dateImage+"/"+ crrImages[crrIdx]} size={180} icon={<UserOutlined />} /> :
<Avatar shape="square" size={180} icon={<UserOutlined />} />
}
</div>
<div className="row mr-4 ml-4">
{
crrImages.length > 0
?
<div className="col-md-12 mt-2 mb-2 p-0">
<label className="m-checkbox m-checkbox--success mt-3 ml-1">
<input type="checkbox"
onClick={(e) => {
setCheckDeleteMulti(!checkDeleteMulti)
setListChecked({
url: [],
})
}}
checked={checkDeleteMulti} /> <div style={{ 'paddingTop': '2px' }}>Chọn</div>
<span />
</label>
{
checkDeleteMulti === true
?
<div style={{ 'display': 'inline-flex' }} className="pull-right">
<button
onClick={(e) => {
e.preventDefault();
if (listChecked.url.length > 0) {
swal({
title: "Bạn chắc chắn muốn xóa ảnh này",
icon: "warning",
buttons: ["Huỷ", "Oke!"],
dangerMode: false,
})
.then((willDelete) => {
if (!willDelete) throw null;
deleteFaceMulti();
})
} else {
swal("Cảnh báo!", "Bạn chưa chọn ảnh để xóa", "warning");
}
}}
className="btn btn-sm btn-danger width-mobie--100 m-loader--light m-loader--right" id="btn_deleteMulti">
Xóa ảnh đã chọn
</button>
</div>
:
""
}
</div>
:
""
}
<div className="row col-md-12 pr-0 image_capture_small pull-left">
{
bulletedImg
}
</div>
<Upload
customRequest = {uploadImage}
accept="image/*"
showUploadList={false}
disabled={disableBtn}
>
<ButtonAntd className={`${disableBtn ? "disable-btn-upload" : ""}`} icon={<UploadOutlined />}>Tải ảnh lên</ButtonAntd>
</Upload>
</div>
</div>
<div className="col-md-5 d-flex flex-column justify-content-between">
<Form
id="formEdit"
form={form}
layout="vertical"
onFinish={() => click_handle()}
// onFinishFailed={onFinishFailed}
autoComplete="off"
initialValues={{
name: crrData.name,
id: crrData.id,
}}
>
<Form.Item
label="Họ tên"
name="name"
rules={[{ required: true, message: '' }]}
>
<Input placeholder="Họ tên" value={crrData.name} onChange={e => UserHandle(e)} name='name' />
</Form.Item>
<Form.Item
label="FacebookID"
name="id"
>
<Input placeholder="FacebookID" value={crrData.id} onChange={e => UserHandle(e)} name='id' />
</Form.Item>
<Form.Item name="radio-group" label="Giới tính">
<Radio.Group name="gender" onChange={e => UserHandle(e)} defaultValue={crrData.gender}>
<Radio name="gender" value={"1"}>Nam</Radio>
<Radio name="gender" value={"2"}>Nữ</Radio>
<Radio name="gender" value={"3"}>Giới tính khác</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
label="Ngày sinh"
name="birthday"
>
<DatePicker className="form-control m-input"
locale={viVN}
defaultValue={birthday !== null ? moment(birthday, 'DD-MM-YYYY') : null}
format={'DD-MM-YYYY'}
onChange={e => onChangeBirthday(e)}
placeholder="Ngày sinh"
/>
</Form.Item>
</Form>
<div className="row d-flex justify-content-end mr-1">
<Button variant="accent" className={"m-loader--light m-loader--right "}
// disabled={loading}
onClick={() => form.submit()}
>Lưu</Button>
</div>
</div>
</div>
</div>
</div>
</Modal.Body>
}
{/* <Modal.Footer>
<Button variant="accent" className={"m-loader--light m-loader--right "}
// disabled={loading}
onClick={() => form.submit()}
>Lưu</Button>
<Button variant="secondary" onClick={onHide}>Đóng</Button>
</Modal.Footer> */}
</Modal>
);
}
export default ModalEditLabel;

View File

@ -73,7 +73,8 @@ const Modaledit = (props) => {
id: crrData.id,
name: crrData.name,
birthday: crrData.birthday,
gender: crrData.gender ? crrData.gender : ""
gender: crrData.gender ? crrData.gender : "",
person_type: 2
}
const result = await axios({
method: 'POST',

View File

@ -84,7 +84,7 @@ class ModalEditImg extends Component {
<div className="col-md-6 boder-right d-flex flex-column justify-content-between ">
<div className="d-flex justify-content-center">
<Image
width={240}
style={{ width: "350px", height: "auto", objectFit: "contain"}}
src={this.state.valueImg.image_host}
/>
</div>

View File

@ -0,0 +1,44 @@
import { UserOutlined } from '@ant-design/icons';
import { Avatar, Tooltip } from 'antd';
import axios from 'axios';
import ModalEditLabel from '../Modal/ModaEditLabel';
import momment from 'moment';
import React, { useEffect, useState } from 'react';
import Pagination from "react-js-pagination";
import { PulseLoader } from 'react-spinners';
import { HOST } from '../../config/index';
import swal from 'sweetalert';
import { useLocation } from 'react-router-dom';
export default function Test() {
return (
<div>
<div className="m-portlet m-portlet--mobile pb-3">
<div className="m-portlet__head">
<div className="m-portlet__head-caption">
<div className="m-portlet__head-title">
<h3 className="m-portlet__head-text">
Test
</h3>
</div>
</div>
</div>
<div className="m-portlet__body pt-2">
<PulseLoader
// css={override}
sizeUnit={"px"}
size={12}
margin={'2px'}
color={'#36D7B7'}
// loading={loading}
/>
</div>
</div>
</div>
)
}

View File

@ -67,7 +67,27 @@ class MenuBar extends Component {
</NavLink>
</li>
<li className="m-menu__item m-menu__item--submenu" aria-haspopup="true" m-menu-submenu-toggle="hover">
<NavLink to="/label-image" className={"m-menu__link " + active} activeClassName="m-menu__item--active" onClick={() => this.onClickClose()}>
<i className="m-menu__link-icon flaticon-delete" />
<span className="m-menu__link-title">
<span className="m-menu__link-wrap">
<span className="m-menu__link-text">Gán nhãn</span>
</span>
</span>
</NavLink>
</li>
<li className="m-menu__item m-menu__item--submenu" aria-haspopup="true" m-menu-submenu-toggle="hover">
<NavLink to="/test" className={"m-menu__link " + active} activeClassName="m-menu__item--active" onClick={() => this.onClickClose()}>
<i className="m-menu__link-icon flaticon-edit" />
<span className="m-menu__link-title">
<span className="m-menu__link-wrap">
<span className="m-menu__link-text">Test</span>
</span>
</span>
</NavLink>
</li>
</ul>
</div>
{/* END: Aside Menu */}

View File

@ -1049,7 +1049,7 @@
core-js-pure "^3.20.2"
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.16.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa"
integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==
@ -1114,7 +1114,7 @@
"@emotion/utils" "0.11.3"
"@emotion/weak-memoize" "0.2.5"
"@emotion/cache@^11.7.1":
"@emotion/cache@^11.4.0", "@emotion/cache@^11.7.1":
version "11.7.1"
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.7.1.tgz#08d080e396a42e0037848214e8aa7bf879065539"
integrity sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==
@ -1140,7 +1140,7 @@
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50"
integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==
"@emotion/react@^11.1.4":
"@emotion/react@^11.1.1", "@emotion/react@^11.1.4":
version "11.7.1"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.7.1.tgz#3f800ce9b20317c13e77b8489ac4a0b922b2fe07"
integrity sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw==
@ -1948,7 +1948,14 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
"@types/react@>=16.9.11":
"@types/react-transition-group@^4.4.0":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.4.tgz#acd4cceaa2be6b757db61ed7b432e103242d163e"
integrity sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@>=16.9.11":
version "17.0.38"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.38.tgz#f24249fefd89357d5fa71f739a686b8d7c7202bd"
integrity sha512-SI92X1IA+FMnP3qM5m4QReluXzhcmovhZnLNm3pyeQlooi02qI7sLiepEYqT678uNiyc25XfCqxREFpy3W7YhQ==
@ -6597,6 +6604,11 @@ memfs@^3.1.2, memfs@^3.2.2:
dependencies:
fs-monkey "1.0.3"
memoize-one@^5.0.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
memoize-one@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
@ -7944,7 +7956,7 @@ prop-types-extra@^1.1.0:
react-is "^16.3.2"
warning "^4.0.0"
"prop-types@15.x.x - 16.x.x", prop-types@^15.5.0, prop-types@^15.6.2, prop-types@^15.7.2:
"prop-types@15.x.x - 16.x.x", prop-types@^15.5.0, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -8643,6 +8655,19 @@ react-scripts@5.0.0:
optionalDependencies:
fsevents "^2.3.2"
react-select@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.2.1.tgz#416c25c6b79b94687702374e019c4f2ed9d159d6"
integrity sha512-OOyNzfKrhOcw/BlembyGWgdlJ2ObZRaqmQppPFut1RptJO423j+Y+JIsmxkvsZ4D/3CpOmwIlCvWbbAWEdh12A==
dependencies:
"@babel/runtime" "^7.12.0"
"@emotion/cache" "^11.4.0"
"@emotion/react" "^11.1.1"
"@types/react-transition-group" "^4.4.0"
memoize-one "^5.0.0"
prop-types "^15.6.0"
react-transition-group "^4.3.0"
react-spinners@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/react-spinners/-/react-spinners-0.11.0.tgz#186fd150cc9f7ab1436227f70d5d113b47e9e43d"
@ -8660,7 +8685,7 @@ react-transition-group@^2.5.0:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"
react-transition-group@^4.0.0:
react-transition-group@^4.0.0, react-transition-group@^4.3.0:
version "4.4.2"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470"
integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==