farhantock
11 months ago
61 changed files with 6459 additions and 2985 deletions
File diff suppressed because it is too large
Load Diff
@ -1,33 +0,0 @@ |
|||||||
import React, { Component } from 'react'; |
|
||||||
import { Button, Col, Container, Input, InputGroup, InputGroupAddon, InputGroupText, Row } from 'reactstrap'; |
|
||||||
|
|
||||||
class Page403 extends Component { |
|
||||||
|
|
||||||
logOut = () => { |
|
||||||
window.localStorage.clear(); |
|
||||||
this.props.history.push('/login') |
|
||||||
} |
|
||||||
|
|
||||||
render() { |
|
||||||
return ( |
|
||||||
<div className="app flex-row align-items-center"> |
|
||||||
<Container> |
|
||||||
<Row className="justify-content-center"> |
|
||||||
<Col md="6"> |
|
||||||
<div className="clearfix"> |
|
||||||
<h1 className="float-left display-3 mr-4">403</h1> |
|
||||||
<h4 className="pt-3">Oops! <br></br>Kamu pergi ke halaman yang terlarang!</h4> |
|
||||||
<p className="text-muted float-left">Halaman tidak bisa di akses!</p> |
|
||||||
</div> |
|
||||||
<div style={{alignItems:'center'}}> |
|
||||||
<Button size="sm" color="warning" onClick={() => this.logOut()}>Back To Login</Button> |
|
||||||
</div> |
|
||||||
</Col> |
|
||||||
</Row> |
|
||||||
</Container> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default Page403; |
|
@ -1,9 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import ReactDOM from 'react-dom'; |
|
||||||
import Page404 from './Page403'; |
|
||||||
|
|
||||||
it('renders without crashing', () => { |
|
||||||
const div = document.createElement('div'); |
|
||||||
ReactDOM.render(<Page403 />, div); |
|
||||||
ReactDOM.unmountComponentAtNode(div); |
|
||||||
}); |
|
@ -1,6 +0,0 @@ |
|||||||
{ |
|
||||||
"name": "Page403", |
|
||||||
"version": "0.0.0", |
|
||||||
"private": true, |
|
||||||
"main": "./Page403.js" |
|
||||||
} |
|
@ -1,35 +0,0 @@ |
|||||||
import React, { Component } from 'react'; |
|
||||||
import { Button, Col, Container, Input, InputGroup, InputGroupAddon, InputGroupText, Row } from 'reactstrap'; |
|
||||||
|
|
||||||
class Page404 extends Component { |
|
||||||
render() { |
|
||||||
return ( |
|
||||||
<div className="app flex-row align-items-center"> |
|
||||||
<Container> |
|
||||||
<Row className="justify-content-center"> |
|
||||||
<Col md="6"> |
|
||||||
<div className="clearfix"> |
|
||||||
<h1 className="float-left display-3 mr-4">404</h1> |
|
||||||
<h4 className="pt-3">Oops! You're lost.</h4> |
|
||||||
<p className="text-muted float-left">The page you are looking for was not found.</p> |
|
||||||
</div> |
|
||||||
<InputGroup className="input-prepend"> |
|
||||||
<InputGroupAddon addonType="prepend"> |
|
||||||
<InputGroupText> |
|
||||||
<i className="fa fa-search"></i> |
|
||||||
</InputGroupText> |
|
||||||
</InputGroupAddon> |
|
||||||
<Input size="16" type="text" placeholder="What are you looking for?" /> |
|
||||||
<InputGroupAddon addonType="append"> |
|
||||||
<Button color="info">Search</Button> |
|
||||||
</InputGroupAddon> |
|
||||||
</InputGroup> |
|
||||||
</Col> |
|
||||||
</Row> |
|
||||||
</Container> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default Page404; |
|
@ -1,9 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import ReactDOM from 'react-dom'; |
|
||||||
import Page404 from './Page404'; |
|
||||||
|
|
||||||
it('renders without crashing', () => { |
|
||||||
const div = document.createElement('div'); |
|
||||||
ReactDOM.render(<Page404 />, div); |
|
||||||
ReactDOM.unmountComponentAtNode(div); |
|
||||||
}); |
|
@ -1,6 +0,0 @@ |
|||||||
{ |
|
||||||
"name": "Page404", |
|
||||||
"version": "0.0.0", |
|
||||||
"private": true, |
|
||||||
"main": "./Page404.js" |
|
||||||
} |
|
@ -1,35 +0,0 @@ |
|||||||
import React, { Component } from 'react'; |
|
||||||
import { Button, Col, Container, Input, InputGroup, InputGroupAddon, InputGroupText, Row } from 'reactstrap'; |
|
||||||
|
|
||||||
class Page500 extends Component { |
|
||||||
render() { |
|
||||||
return ( |
|
||||||
<div className="app flex-row align-items-center"> |
|
||||||
<Container> |
|
||||||
<Row className="justify-content-center"> |
|
||||||
<Col md="6"> |
|
||||||
<span className="clearfix"> |
|
||||||
<h1 className="float-left display-3 mr-4">500</h1> |
|
||||||
<h4 className="pt-3">Houston, we have a problem!</h4> |
|
||||||
<p className="text-muted float-left">The page you are looking for is temporarily unavailable.</p> |
|
||||||
</span> |
|
||||||
<InputGroup className="input-prepend"> |
|
||||||
<InputGroupAddon addonType="prepend"> |
|
||||||
<InputGroupText> |
|
||||||
<i className="fa fa-search"></i> |
|
||||||
</InputGroupText> |
|
||||||
</InputGroupAddon> |
|
||||||
<Input size="16" type="text" placeholder="What are you looking for?" /> |
|
||||||
<InputGroupAddon addonType="append"> |
|
||||||
<Button color="info">Search</Button> |
|
||||||
</InputGroupAddon> |
|
||||||
</InputGroup> |
|
||||||
</Col> |
|
||||||
</Row> |
|
||||||
</Container> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default Page500; |
|
@ -1,9 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import ReactDOM from 'react-dom'; |
|
||||||
import Page500 from './Page500'; |
|
||||||
|
|
||||||
it('renders without crashing', () => { |
|
||||||
const div = document.createElement('div'); |
|
||||||
ReactDOM.render(<Page500 />, div); |
|
||||||
ReactDOM.unmountComponentAtNode(div); |
|
||||||
}); |
|
@ -1,6 +0,0 @@ |
|||||||
{ |
|
||||||
"name": "Page500", |
|
||||||
"version": "0.0.0", |
|
||||||
"private": true, |
|
||||||
"main": "./Page500.js" |
|
||||||
} |
|
@ -1,68 +0,0 @@ |
|||||||
import React, { Component } from 'react'; |
|
||||||
import { Button, Card, CardBody, CardFooter, Col, Container, Form, Input, InputGroup, InputGroupAddon, InputGroupText, Row } from 'reactstrap'; |
|
||||||
|
|
||||||
class Register extends Component { |
|
||||||
render() { |
|
||||||
return ( |
|
||||||
<div className="app flex-row align-items-center"> |
|
||||||
<Container> |
|
||||||
<Row className="justify-content-center"> |
|
||||||
<Col md="9" lg="7" xl="6"> |
|
||||||
<Card className="mx-4"> |
|
||||||
<CardBody className="p-4"> |
|
||||||
<Form> |
|
||||||
<h1>Register</h1> |
|
||||||
<p className="text-muted">Create your account</p> |
|
||||||
<InputGroup className="mb-3"> |
|
||||||
<InputGroupAddon addonType="prepend"> |
|
||||||
<InputGroupText> |
|
||||||
<i className="icon-user"></i> |
|
||||||
</InputGroupText> |
|
||||||
</InputGroupAddon> |
|
||||||
<Input type="text" placeholder="Username" autoComplete="username" /> |
|
||||||
</InputGroup> |
|
||||||
<InputGroup className="mb-3"> |
|
||||||
<InputGroupAddon addonType="prepend"> |
|
||||||
<InputGroupText>@</InputGroupText> |
|
||||||
</InputGroupAddon> |
|
||||||
<Input type="text" placeholder="Email" autoComplete="email" /> |
|
||||||
</InputGroup> |
|
||||||
<InputGroup className="mb-3"> |
|
||||||
<InputGroupAddon addonType="prepend"> |
|
||||||
<InputGroupText> |
|
||||||
<i className="icon-lock"></i> |
|
||||||
</InputGroupText> |
|
||||||
</InputGroupAddon> |
|
||||||
<Input type="password" placeholder="Password" autoComplete="new-password" /> |
|
||||||
</InputGroup> |
|
||||||
<InputGroup className="mb-4"> |
|
||||||
<InputGroupAddon addonType="prepend"> |
|
||||||
<InputGroupText> |
|
||||||
<i className="icon-lock"></i> |
|
||||||
</InputGroupText> |
|
||||||
</InputGroupAddon> |
|
||||||
<Input type="password" placeholder="Repeat password" autoComplete="new-password" /> |
|
||||||
</InputGroup> |
|
||||||
<Button color="success" block>Create Account</Button> |
|
||||||
</Form> |
|
||||||
</CardBody> |
|
||||||
<CardFooter className="p-4"> |
|
||||||
<Row> |
|
||||||
<Col xs="12" sm="6"> |
|
||||||
<Button className="btn-facebook mb-1" block><span>facebook</span></Button> |
|
||||||
</Col> |
|
||||||
<Col xs="12" sm="6"> |
|
||||||
<Button className="btn-twitter mb-1" block><span>twitter</span></Button> |
|
||||||
</Col> |
|
||||||
</Row> |
|
||||||
</CardFooter> |
|
||||||
</Card> |
|
||||||
</Col> |
|
||||||
</Row> |
|
||||||
</Container> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default Register; |
|
@ -1,9 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import ReactDOM from 'react-dom'; |
|
||||||
import Register from './Register'; |
|
||||||
|
|
||||||
it('renders without crashing', () => { |
|
||||||
const div = document.createElement('div'); |
|
||||||
ReactDOM.render(<Register />, div); |
|
||||||
ReactDOM.unmountComponentAtNode(div); |
|
||||||
}); |
|
@ -1,6 +0,0 @@ |
|||||||
{ |
|
||||||
"name": "Register", |
|
||||||
"version": "0.0.0", |
|
||||||
"private": true, |
|
||||||
"main": "./Register.js" |
|
||||||
} |
|
@ -0,0 +1,201 @@ |
|||||||
|
import React, { useEffect, useState } from 'react' |
||||||
|
import { |
||||||
|
Modal, ModalHeader, ModalBody, ModalFooter, |
||||||
|
Button, Form, FormGroup, Label, Input, Col, Row |
||||||
|
} from 'reactstrap'; |
||||||
|
import { Select } from 'antd'; |
||||||
|
import 'antd/dist/antd.css'; |
||||||
|
import { useTranslation } from 'react-i18next'; |
||||||
|
import "rc-color-picker/assets/index.css"; |
||||||
|
const { Option } = Select |
||||||
|
const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdit }) => { |
||||||
|
const [id, setId] = useState(0) |
||||||
|
const [name, setName] = useState('') |
||||||
|
const [email, setEmail] = useState('') |
||||||
|
const [message, setMessage] = useState('') |
||||||
|
const [phoneNumber, setPhoneNumber] = useState('') |
||||||
|
const [role, setRole] = useState(null) |
||||||
|
const [status, setStatus] = useState('') |
||||||
|
const { t } = useTranslation() |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (typeDialog === "Edit") { |
||||||
|
setId(dataEdit.id) |
||||||
|
setName(dataEdit.name) |
||||||
|
setEmail(dataEdit.email) |
||||||
|
setMessage(dataEdit.message) |
||||||
|
setPhoneNumber(dataEdit.number_phone) |
||||||
|
setStatus(dataEdit.status) |
||||||
|
setRole(dataEdit.role) |
||||||
|
} else { |
||||||
|
setId(0) |
||||||
|
setName('') |
||||||
|
setEmail('') |
||||||
|
setMessage('') |
||||||
|
setStatus('') |
||||||
|
setRole('') |
||||||
|
setPhoneNumber('') |
||||||
|
} |
||||||
|
}, [dataEdit, openDialog]) |
||||||
|
|
||||||
|
const validation = () => { |
||||||
|
if (!name || name === "") { |
||||||
|
alert("Name cannot be empty!"); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
const handleSave = () => { |
||||||
|
let data = ''; |
||||||
|
const err = validation(); |
||||||
|
|
||||||
|
if (!err) { |
||||||
|
if (typeDialog === "Save") { |
||||||
|
data = { |
||||||
|
name, |
||||||
|
email, |
||||||
|
message, |
||||||
|
number_phone: phoneNumber, |
||||||
|
role, |
||||||
|
status |
||||||
|
} |
||||||
|
closeDialog('save', data); |
||||||
|
} else { |
||||||
|
data = { |
||||||
|
id, |
||||||
|
name, |
||||||
|
email, |
||||||
|
message, |
||||||
|
number_phone: phoneNumber, |
||||||
|
role, |
||||||
|
status |
||||||
|
} |
||||||
|
closeDialog('edit', data); |
||||||
|
} |
||||||
|
setId(0) |
||||||
|
setName('') |
||||||
|
} |
||||||
|
} |
||||||
|
const handleCancel = () => { |
||||||
|
closeDialog('cancel', 'none') |
||||||
|
setId(0) |
||||||
|
setName('') |
||||||
|
} |
||||||
|
const onChangeStatus = (val) => { |
||||||
|
setStatus(val) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const renderForm = () => { |
||||||
|
return ( |
||||||
|
<Form> |
||||||
|
<Row> |
||||||
|
<Col md={12}> |
||||||
|
<span style={{ color: "red" }}>*</span> Wajib diisi. |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<Col md={6}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">{t('name')}<span style={{ color: "red" }}>*</span></Label> |
||||||
|
<Input |
||||||
|
type="text" |
||||||
|
value={name} |
||||||
|
onChange={(e) => setName(e.target.value)} |
||||||
|
placeholder={t('inputName')} |
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={6}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">{t('email')}<span style={{ color: "red" }}>*</span></Label> |
||||||
|
<Input |
||||||
|
type="text" |
||||||
|
value={email} |
||||||
|
onChange={(e) => setEmail(e.target.value)} |
||||||
|
placeholder={t('inputEmail')} |
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<Col md={6}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">{t('phoneNumber')}<span style={{ color: "red" }}>*</span></Label> |
||||||
|
<Input |
||||||
|
type="text" |
||||||
|
value={phoneNumber} |
||||||
|
onChange={(e) => setName(e.target.value)} |
||||||
|
placeholder={t('inputNoPhone')} |
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={6}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">{t('role')}<span style={{ color: "red" }}>*</span></Label> |
||||||
|
<Input |
||||||
|
type="text" |
||||||
|
value={role} |
||||||
|
onChange={(e) => setRole(e.target.value)} |
||||||
|
placeholder={t('inputRole')} |
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize"> |
||||||
|
{t('status')}<span style={{ color: "red" }}>*</span> |
||||||
|
</Label> |
||||||
|
<Select |
||||||
|
showSearch |
||||||
|
filterOption={(inputValue, option) => |
||||||
|
option.children.toLowerCase().includes(inputValue.toLowerCase()) |
||||||
|
} |
||||||
|
value={status} |
||||||
|
defaultValue={status} |
||||||
|
onChange={onChangeStatus} |
||||||
|
style={{ width: "100%" }} |
||||||
|
> |
||||||
|
<Option value="New Request">New Request</Option> |
||||||
|
<Option value="Presentation">Presentation</Option> |
||||||
|
<Option value="Live Demo">Live Demo</Option> |
||||||
|
<Option value="Trial">Trial</Option> |
||||||
|
<Option value="Go-Live">Go-Live</Option> |
||||||
|
<Option value="Postpone">Postpone</Option> |
||||||
|
|
||||||
|
</Select> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">{t('message')}</Label> |
||||||
|
<Input row="4" type="textarea" value={message} onChange={(e) => setMessage(e.target.value)} placeholder={t('inputMessage')} /> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</Form> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<Modal size="lg" isOpen={openDialog} toggle={toggleDialog}> |
||||||
|
<ModalHeader className="capitalize" toggle={closeDialog}>{typeDialog == "Save" ? `Add` : "Edit"} {t('Demo')}</ModalHeader> |
||||||
|
<ModalBody> |
||||||
|
{renderForm()} |
||||||
|
</ModalBody> |
||||||
|
<ModalFooter> |
||||||
|
<Button color="primary" onClick={() => handleSave()}>{typeDialog}</Button>{' '} |
||||||
|
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>{t('cancel')}</Button> |
||||||
|
</ModalFooter> |
||||||
|
</Modal> |
||||||
|
</> |
||||||
|
) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
export default DialogForm; |
@ -0,0 +1,367 @@ |
|||||||
|
import * as XLSX from 'xlsx'; |
||||||
|
import DialogForm from './DialogForm'; |
||||||
|
import React, { useState, useEffect } from 'react'; |
||||||
|
import SweetAlert from 'react-bootstrap-sweetalert'; |
||||||
|
import axios from "../../../const/interceptorApi" |
||||||
|
import { Card, CardBody, CardHeader, Col, Row, Input, Table } from 'reactstrap'; |
||||||
|
import { DEMO_MANAGEMENT_EDIT, DEMO_MANAGEMENT_SEARCH, DEMO_MANAGEMENT_LIST, DEMO_MANAGEMENT_GET_ID, DEMO_MANAGEMENT_ADD, DEMO_MANAGEMENT_DELETE } from '../../../const/ApiConst'; |
||||||
|
import { NotificationContainer, NotificationManager } from 'react-notifications'; |
||||||
|
import { Pagination, Button, Tooltip } from 'antd'; |
||||||
|
import { useTranslation } from 'react-i18next'; |
||||||
|
|
||||||
|
|
||||||
|
const ProjectType = ({ params, ...props }) => { |
||||||
|
let role_id = 0, user_id = 0, isLogin = false, token = '', company_id = 0, all_project = null, role_name = '', hierarchy = [], user_name = ''; |
||||||
|
if (props && props.role_id && props.user_id) { |
||||||
|
role_id = props.role_id; |
||||||
|
user_id = props.user_id; |
||||||
|
token = props.token; |
||||||
|
isLogin = props.isLogin; |
||||||
|
company_id = props.company_id; |
||||||
|
all_project = props.all_project; |
||||||
|
role_name = props.role_name; |
||||||
|
isLogin = props.isLogin; |
||||||
|
hierarchy = props.hierarchy; |
||||||
|
user_name = props.user_name; |
||||||
|
} |
||||||
|
|
||||||
|
const HEADER = { |
||||||
|
headers: { |
||||||
|
"Content-Type": "application/json", |
||||||
|
"Authorization": `Bearer ${token}` |
||||||
|
} |
||||||
|
} |
||||||
|
const pageName = params.name; |
||||||
|
|
||||||
|
const [alertDelete, setAlertDelete] = useState(false) |
||||||
|
const [allDataMenu, setAllDataMenu] = useState([]) |
||||||
|
const [clickOpenModal, setClickOpenModal] = useState(false) |
||||||
|
const [currentPage, setCurrentPage] = useState(1) |
||||||
|
const [dataEdit, setDataEdit] = useState([]) |
||||||
|
const [dataExport, setDataExport] = useState([]) |
||||||
|
const [dataTable, setDatatable] = useState([]) |
||||||
|
const [idDelete, setIdDelete] = useState(0) |
||||||
|
const [openDialog, setOpenDialog] = useState(false) |
||||||
|
const [rowsPerPage, setRowsPerPage] = useState(10) |
||||||
|
const [search, setSearch] = useState("") |
||||||
|
const [totalPage, setTotalPage] = useState(0) |
||||||
|
const [typeDialog, setTypeDialog] = useState('Save') |
||||||
|
const [dataDemo, setDataDemo] = useState([]) |
||||||
|
const [listCompany, setListCompany] = useState([]) |
||||||
|
const { t } = useTranslation() |
||||||
|
const column = [ |
||||||
|
{ name: t('name') }, |
||||||
|
{ name: t('email') }, |
||||||
|
{ name: t('roles') }, |
||||||
|
{ name: t('phoneNumber') }, |
||||||
|
{ name: t('status') }, |
||||||
|
{ name: t('message') }, |
||||||
|
].filter(column => column && column.name); |
||||||
|
useEffect(() => { |
||||||
|
getDataDemo(); |
||||||
|
}, [currentPage, rowsPerPage, search]) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
const cekData = dataExport || [] |
||||||
|
if (cekData.length > 0) { |
||||||
|
exportExcel() |
||||||
|
} |
||||||
|
}, [dataExport]) |
||||||
|
|
||||||
|
const getDataDemo = async () => { |
||||||
|
let start = 0; |
||||||
|
if (currentPage !== 1 && currentPage > 1) { |
||||||
|
start = currentPage * rowsPerPage - rowsPerPage; |
||||||
|
} |
||||||
|
const payload = { |
||||||
|
group_column: { |
||||||
|
"operator": "AND", |
||||||
|
"group_operator": "OR", |
||||||
|
"where": [ |
||||||
|
{ |
||||||
|
"name": "name", |
||||||
|
"logic_operator": "~*", |
||||||
|
"value": search, |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
columns: [], |
||||||
|
"orders": { |
||||||
|
"ascending": true, |
||||||
|
"columns": [ |
||||||
|
'id' |
||||||
|
] |
||||||
|
}, |
||||||
|
"paging": { |
||||||
|
"length": rowsPerPage, |
||||||
|
"start": start |
||||||
|
}, |
||||||
|
'joins': [] |
||||||
|
} |
||||||
|
|
||||||
|
const result = await axios |
||||||
|
.post(DEMO_MANAGEMENT_SEARCH, payload, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code == 200) { |
||||||
|
setDatatable(result.data.data); |
||||||
|
setTotalPage(result.data.totalRecord); |
||||||
|
} else { |
||||||
|
NotificationManager.error('Gagal Mengambil Data!!', 'Failed'); |
||||||
|
} |
||||||
|
} |
||||||
|
const handleExportExcel = async () => { |
||||||
|
let start = 0; |
||||||
|
|
||||||
|
if (currentPage !== 1 && currentPage > 1) { |
||||||
|
start = (currentPage * rowsPerPage) - rowsPerPage |
||||||
|
} |
||||||
|
|
||||||
|
const payload = { |
||||||
|
group_column: { |
||||||
|
"operator": "AND", |
||||||
|
"group_operator": "OR", |
||||||
|
"where": [ |
||||||
|
{ |
||||||
|
"name": "name", |
||||||
|
"logic_operator": "~*", |
||||||
|
"value": search, |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"columns": [], |
||||||
|
"orders": { |
||||||
|
"ascending": true, |
||||||
|
"columns": [ |
||||||
|
'id' |
||||||
|
] |
||||||
|
}, |
||||||
|
"paging": { |
||||||
|
"length": rowsPerPage, |
||||||
|
"start": start |
||||||
|
}, |
||||||
|
'joins': [] |
||||||
|
} |
||||||
|
|
||||||
|
const result = await axios |
||||||
|
.post(DEMO_MANAGEMENT_SEARCH, payload, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
if (result && result.data && result.data.code == 200) { |
||||||
|
let resData = result.data.data; |
||||||
|
const excelData = []; |
||||||
|
resData.map((val, index) => { |
||||||
|
let dataRow = {}; |
||||||
|
dataRow["Nama"] = val.name; |
||||||
|
dataRow["Email"] = val.email; |
||||||
|
dataRow["Role"] = val.role; |
||||||
|
dataRow["No Telepon"] = val.number_phone; |
||||||
|
dataRow["Status"] = val.message; |
||||||
|
dataRow["Message"] = val.message; |
||||||
|
excelData.push(dataRow) |
||||||
|
}) |
||||||
|
await setDataExport(excelData) |
||||||
|
} else { |
||||||
|
NotificationManager.error('Gagal Export Data!!', 'Failed'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const exportExcel = () => { |
||||||
|
const dataExcel = dataExport || []; |
||||||
|
const fileName = `Data ${pageName}.xlsx`; |
||||||
|
const ws = XLSX.utils.json_to_sheet(dataExcel); |
||||||
|
const wb = XLSX.utils.book_new(); |
||||||
|
XLSX.utils.book_append_sheet(wb, ws, `Data ${pageName}`); |
||||||
|
XLSX.writeFile(wb, fileName); |
||||||
|
setDataExport([]) |
||||||
|
} |
||||||
|
|
||||||
|
const handleSearch = e => { |
||||||
|
const value = e.target.value |
||||||
|
setSearch(value); |
||||||
|
setCurrentPage(1) |
||||||
|
}; |
||||||
|
|
||||||
|
const handleOpenDialog = (type) => { |
||||||
|
setOpenDialog(true) |
||||||
|
setTypeDialog(type) |
||||||
|
} |
||||||
|
|
||||||
|
const handleEdit = (data) => { |
||||||
|
setDataEdit(data) |
||||||
|
handleOpenDialog('Edit'); |
||||||
|
} |
||||||
|
|
||||||
|
const handleDelete = async (id) => { |
||||||
|
await setAlertDelete(true) |
||||||
|
await setIdDelete(id) |
||||||
|
} |
||||||
|
|
||||||
|
const handleCloseDialog = (type, data) => { |
||||||
|
if (type === "save") { |
||||||
|
saveDemo(data); |
||||||
|
} else if (type === "edit") { |
||||||
|
editMaterialR(data); |
||||||
|
} |
||||||
|
setDataEdit([]) |
||||||
|
setOpenDialog(false) |
||||||
|
} |
||||||
|
|
||||||
|
const saveDemo = async (data) => { |
||||||
|
const formData = data |
||||||
|
const result = await axios.post(DEMO_MANAGEMENT_ADD, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataDemo() |
||||||
|
NotificationManager.success(`Data berhasil ditambahkan`, 'Success!!'); |
||||||
|
} else { |
||||||
|
NotificationManager.error(`Data gagal ditambahkan`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const editMaterialR = async (data) => { |
||||||
|
let urlEdit = DEMO_MANAGEMENT_EDIT(data.id) |
||||||
|
const formData = data |
||||||
|
const result = await axios.put(urlEdit, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataDemo(); |
||||||
|
NotificationManager.success(`Data berhasil diubah`, 'Success!!'); |
||||||
|
} else { |
||||||
|
NotificationManager.error(`Data gagal diubah`, `Failed!!`); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const toggleAddDialog = () => { |
||||||
|
setOpenDialog(!openDialog) |
||||||
|
} |
||||||
|
|
||||||
|
const onConfirmDelete = async () => { |
||||||
|
let url = DEMO_MANAGEMENT_DELETE(idDelete); |
||||||
|
const result = await axios.delete(url, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataDemo() |
||||||
|
setIdDelete(0) |
||||||
|
setAlertDelete(false) |
||||||
|
NotificationManager.success(`Data berhasil dihapus!`, 'Success!!'); |
||||||
|
} else { |
||||||
|
setIdDelete(0) |
||||||
|
setAlertDelete(false) |
||||||
|
NotificationManager.error(`Data gagal dihapus!}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const cancelDelete = () => { |
||||||
|
setAlertDelete(false) |
||||||
|
setIdDelete(0) |
||||||
|
} |
||||||
|
|
||||||
|
const onShowSizeChange = (current, pageSize) => { |
||||||
|
setRowsPerPage(pageSize) |
||||||
|
} |
||||||
|
|
||||||
|
const onPagination = (current, pageSize) => { |
||||||
|
setCurrentPage(current) |
||||||
|
} |
||||||
|
|
||||||
|
const dataNotAvailable = () => { |
||||||
|
if (dataTable.length === 0) { |
||||||
|
return ( |
||||||
|
<tr> |
||||||
|
<td align="center" colSpan="7">{t('noData')}</td> |
||||||
|
</tr> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<NotificationContainer /> |
||||||
|
<SweetAlert |
||||||
|
show={alertDelete} |
||||||
|
warning |
||||||
|
showCancel |
||||||
|
confirmBtnText="Delete" |
||||||
|
confirmBtnBsStyle="danger" |
||||||
|
title={t('deleteConfirm')} |
||||||
|
onConfirm={onConfirmDelete} |
||||||
|
onCancel={cancelDelete} |
||||||
|
focusCancelBtn |
||||||
|
> |
||||||
|
{t('deleteMsg')} |
||||||
|
</SweetAlert> |
||||||
|
<DialogForm |
||||||
|
openDialog={openDialog} |
||||||
|
closeDialog={handleCloseDialog} |
||||||
|
toggleDialog={() => toggleAddDialog} |
||||||
|
typeDialog={typeDialog} |
||||||
|
dataEdit={dataEdit} |
||||||
|
clickOpenModal={clickOpenModal} |
||||||
|
dataParent={allDataMenu} |
||||||
|
/> |
||||||
|
<Card> |
||||||
|
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}> |
||||||
|
<h4 className="capitalize">{pageName}</h4> |
||||||
|
<Row> |
||||||
|
<Col> |
||||||
|
<Input onChange={handleSearch} value={search} type="text" name="search" id="search" placeholder={t('searchDemo')} /> |
||||||
|
</Col> |
||||||
|
<Col> |
||||||
|
<Tooltip title={t('demoAdd')}> |
||||||
|
<Button style={{ background: "#4caf50", color: "#fff" }} onClick={() => handleOpenDialog('Save')}><i className="fa fa-plus"></i></Button> |
||||||
|
</Tooltip> |
||||||
|
<Tooltip title={t('exportExcel')}> |
||||||
|
<Button style={{ marginLeft: "5px" }} onClick={() => handleExportExcel()}><i className="fa fa-print"></i></Button> |
||||||
|
</Tooltip> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</CardHeader> |
||||||
|
<CardBody> |
||||||
|
<Table responsive striped hover> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th>Aksi</th> |
||||||
|
{column.map((i, index) => { |
||||||
|
return ( |
||||||
|
<th key={index} scope="row">{i.name}</th> |
||||||
|
) |
||||||
|
})} |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
{dataNotAvailable()} |
||||||
|
{dataTable.map((n, index) => { |
||||||
|
return ( |
||||||
|
<tr key={n.id}> |
||||||
|
<td className='nowrap'> |
||||||
|
<Tooltip title={t('delete')}> |
||||||
|
<i id="TooltipDelete" className="fa fa-trash" style={{ color: 'red', marginRight: 10, cursor: "pointer" }} onClick={() => handleDelete(n.id)}></i> |
||||||
|
</Tooltip> |
||||||
|
<Tooltip title={t('edit')}> |
||||||
|
<i id="TooltipEdit" className="fa fa-edit" style={{ color: 'green', cursor: "pointer" }} onClick={() => handleEdit(n)}></i> |
||||||
|
</Tooltip> |
||||||
|
</td> |
||||||
|
<td>{n.name}</td> |
||||||
|
<td>{n.email}</td> |
||||||
|
<td>{n.role}</td> |
||||||
|
<td>{n.number_phone}</td> |
||||||
|
<td>{n.status}</td> |
||||||
|
<td>{n.message}</td> |
||||||
|
</tr> |
||||||
|
) |
||||||
|
})} |
||||||
|
</tbody> |
||||||
|
</Table> |
||||||
|
</CardBody> |
||||||
|
</Card> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default ProjectType; |
@ -0,0 +1,130 @@ |
|||||||
|
import React, { Fragment } from 'react' |
||||||
|
import './Kanban.css'; |
||||||
|
import { Card, Row, Col, Button, Avatar, Tooltip, Popover, Divider, Space, Menu, Dropdown } from 'antd'; |
||||||
|
import Task from './Task'; |
||||||
|
import { Droppable } from 'react-beautiful-dnd'; |
||||||
|
import styled from 'styled-components'
|
||||||
|
import {
|
||||||
|
AntDesignOutlined, |
||||||
|
UserOutlined, |
||||||
|
EditOutlined, |
||||||
|
DeleteOutlined, |
||||||
|
SettingOutlined, |
||||||
|
EllipsisOutlined, |
||||||
|
MoreOutlined |
||||||
|
} from '@ant-design/icons'; |
||||||
|
|
||||||
|
const Container = styled.div` |
||||||
|
margin: 8px; |
||||||
|
border: 1px solid lightgrey; |
||||||
|
border-radius: 2px; |
||||||
|
width: 220px; |
||||||
|
|
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
` |
||||||
|
|
||||||
|
const TaskList = styled.div` |
||||||
|
transition: background-color 0.2s ease; |
||||||
|
background-color: ${props => |
||||||
|
props.isDraggingOver ? 'skyblue' : 'white'} |
||||||
|
flex-grow: 1; |
||||||
|
min-height: 100px; |
||||||
|
` |
||||||
|
|
||||||
|
const Column = ({
|
||||||
|
column,
|
||||||
|
tasks,
|
||||||
|
index,
|
||||||
|
handleOpenDialogActivity,
|
||||||
|
handleOpenDialogChild,
|
||||||
|
handleDelete,
|
||||||
|
handleEditBoard,
|
||||||
|
loadingCard,
|
||||||
|
handleDeleteCard,
|
||||||
|
handleEditCard |
||||||
|
}) => { |
||||||
|
|
||||||
|
|
||||||
|
const menu = (column) => ( |
||||||
|
<Menu |
||||||
|
items={[ |
||||||
|
{ |
||||||
|
key: '3', |
||||||
|
label: ( |
||||||
|
<a rel="noopener noreferrer" > |
||||||
|
status is {column.status_progress} |
||||||
|
</a> |
||||||
|
), |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: '1', |
||||||
|
label: ( |
||||||
|
<a rel="noopener noreferrer" onClick={() => handleEditBoard(column)} > |
||||||
|
<EditOutlined style={{marginRight: "5px"}} /> Edit |
||||||
|
</a> |
||||||
|
), |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: '2', |
||||||
|
label: ( |
||||||
|
<a rel="noopener noreferrer" onClick={() => handleDelete(column.id)} > |
||||||
|
<DeleteOutlined style={{marginRight: "5px"}} /> Hapus |
||||||
|
</a> |
||||||
|
), |
||||||
|
}, |
||||||
|
]} |
||||||
|
/> |
||||||
|
); |
||||||
|
|
||||||
|
return ( |
||||||
|
<Col className="gutter-row" span={6}> |
||||||
|
<div className='board' style={{backgroundColor: column.header_color}}> |
||||||
|
<div className='title-board' style={{color: column.body_color}}> |
||||||
|
<b>{column.name_board}</b> |
||||||
|
{/* <a style={{color: column.body_color, marginRight: "7px", float: 'right'}} onClick={() => handleEditBoard(column)}><EditOutlined /></a> */} |
||||||
|
{/* <a style={{color: column.body_color, marginRight: "7px", float: 'right'}} onClick={() => handleDelete(column.id)}><DeleteOutlined /></a> */} |
||||||
|
<div style={{float: 'right', marginRight: "5px"}}> |
||||||
|
<Dropdown overlay={menu(column)}> |
||||||
|
<a onClick={(e) => e.preventDefault()}> |
||||||
|
<MoreOutlined style={{fontSize:"20px"}} /> |
||||||
|
</a> |
||||||
|
</Dropdown> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<Divider/> |
||||||
|
<div className='destination'> |
||||||
|
{ tasks.length === 0 &&
|
||||||
|
<p className='add-card' onClick={()=> handleOpenDialogActivity("Save", column.id)}>+ Add Activity</p> |
||||||
|
} |
||||||
|
<Droppable droppableId={column.key} type='TASK'> |
||||||
|
{(provided, snapshot) => ( |
||||||
|
<TaskList |
||||||
|
ref={provided.innerRef} |
||||||
|
{...provided.droppableProps} |
||||||
|
isDraggingOver={snapshot.isDraggingOver} |
||||||
|
> |
||||||
|
{tasks.map((task, index) => ( |
||||||
|
<Task
|
||||||
|
key={task.id}
|
||||||
|
task={task}
|
||||||
|
index={index}
|
||||||
|
bodyColor={column.body_color}
|
||||||
|
loadingCard={loadingCard}
|
||||||
|
handleDeleteCard={handleDeleteCard}
|
||||||
|
handleEditCard={handleEditCard} />
|
||||||
|
))} |
||||||
|
{provided.placeholder} |
||||||
|
</TaskList> |
||||||
|
)} |
||||||
|
</Droppable> |
||||||
|
{ tasks.length > 0 &&
|
||||||
|
<p className='add-card' onClick={()=> handleOpenDialogActivity("Save", column.id)}>+ Add Activity</p> |
||||||
|
} |
||||||
|
</div> |
||||||
|
</Col> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Column; |
@ -0,0 +1,72 @@ |
|||||||
|
import React, { useEffect, useState } from 'react' |
||||||
|
import { |
||||||
|
ModalHeader, ModalBody, ModalFooter, |
||||||
|
Button, Form, FormGroup, Label, Input, Col, Row |
||||||
|
} from 'reactstrap'; |
||||||
|
import { DatePicker, Tooltip, Select, Modal } from 'antd'; |
||||||
|
import { formatRupiah, formatNumber } from '../../../const/CustomFunc' |
||||||
|
import moment from 'moment'; |
||||||
|
import 'antd/dist/antd.css'; |
||||||
|
const { Option } = Select |
||||||
|
|
||||||
|
const DialogCard = ({
|
||||||
|
openDialogChild, |
||||||
|
closeDialogChild, |
||||||
|
toggleDialogChild, |
||||||
|
typeDialogChild, |
||||||
|
task,
|
||||||
|
}) => { |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
|
||||||
|
}, [openDialogChild]) |
||||||
|
|
||||||
|
const handleCancel = () => { |
||||||
|
closeDialogChild('cancel', 'none') |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
{/* <Modal size="lg" isOpen={openDialogChild} toggle={toggleDialogChild} centered> |
||||||
|
<ModalHeader className="capitalize" toggle={closeDialogChild}></ModalHeader> |
||||||
|
<ModalBody> |
||||||
|
</ModalBody> |
||||||
|
<ModalFooter> |
||||||
|
<Button color="primary" onClick={() => handleSave()}>{typeDialogChild == "Edit" ? `Edit` : "Save"}</Button>{' '} |
||||||
|
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Batal</Button> |
||||||
|
</ModalFooter> |
||||||
|
</Modal> */} |
||||||
|
<Modal title="Card" open={openDialogChild} onOk={handleCancel} onCancel={handleCancel}
|
||||||
|
footer={[ |
||||||
|
<Button key="back" onClick={handleCancel}> |
||||||
|
Close |
||||||
|
</Button> |
||||||
|
]} |
||||||
|
> |
||||||
|
<Row style={{padding: "20px"}}> |
||||||
|
<Col md={6} style={{fontWeight: "bold"}} >Activity</Col> |
||||||
|
<Col md={6}>{task.activity}</Col> |
||||||
|
</Row> |
||||||
|
<Row style={{padding: "20px"}}> |
||||||
|
<Col md={6} style={{fontWeight: "bold"}}>Start Date</Col> |
||||||
|
<Col md={6}>{moment(task.start_date).format('DD-MM-YYYY HH:mm')}</Col> |
||||||
|
</Row> |
||||||
|
<Row style={{padding: "20px"}}> |
||||||
|
<Col md={6} style={{fontWeight: "bold"}}>End Date</Col> |
||||||
|
<Col md={6}>{moment(task.end_date).format('DD-MM-YYYY HH:mm')}</Col> |
||||||
|
</Row> |
||||||
|
<Row style={{padding: "20px"}}> |
||||||
|
<Col md={6} style={{fontWeight: "bold"}}>Bobot Planning </Col> |
||||||
|
<Col md={6}>{task.bobot_planning}</Col> |
||||||
|
</Row> |
||||||
|
<Row style={{padding: "20px"}}> |
||||||
|
<Col md={6} style={{fontWeight: "bold"}}>Presentase Progress </Col> |
||||||
|
<Col md={6}>{task.persentase_progress}</Col> |
||||||
|
</Row> |
||||||
|
</Modal> |
||||||
|
</> |
||||||
|
) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
export default DialogCard; |
@ -0,0 +1,347 @@ |
|||||||
|
import React, { useEffect, useState } from 'react' |
||||||
|
import { |
||||||
|
Modal, ModalHeader, ModalBody, ModalFooter, |
||||||
|
Form, FormGroup, Label, Input, Col, Row |
||||||
|
} from 'reactstrap'; |
||||||
|
import { DatePicker, Tooltip, Drawer, Divider, Layout, Button, Space, Progress } from 'antd'; |
||||||
|
import { |
||||||
|
CloseOutlined, |
||||||
|
MinusOutlined,
|
||||||
|
PlusOutlined |
||||||
|
} from '@ant-design/icons'; |
||||||
|
import { formatRupiah, formatNumber } from '../../../const/CustomFunc' |
||||||
|
import moment from 'moment'; |
||||||
|
import Select from 'react-select'; |
||||||
|
import axios from "../../../const/interceptorApi"; |
||||||
|
import { BASE_SIMPRO_LUMEN } from '../../../const/ApiConst'; |
||||||
|
import { |
||||||
|
NotificationManager |
||||||
|
} from "react-notifications"; |
||||||
|
import 'antd/dist/antd.css'; |
||||||
|
// const { Option } = Select
|
||||||
|
|
||||||
|
const DialogFormActivity = ({
|
||||||
|
activityProject, |
||||||
|
openDialogActivity,
|
||||||
|
closeDialogActivity,
|
||||||
|
handleOpenDialogReport, |
||||||
|
toggleDialogActivity,
|
||||||
|
typeDialogActivity,
|
||||||
|
proyek_id,
|
||||||
|
version_gantt_id,
|
||||||
|
idBoard,
|
||||||
|
dataHr,
|
||||||
|
dataEditCard, |
||||||
|
userToActivityDelete, |
||||||
|
userToActivityAdd |
||||||
|
}) => { |
||||||
|
const [id, setId] = useState('') |
||||||
|
const [text, setText] = useState('') |
||||||
|
const [startDate, setStartDate] = useState('') |
||||||
|
const [progress, setProgress] = useState(0) |
||||||
|
const [volumePlan, setVolumePlan] = useState(0) |
||||||
|
const [endDate, setEndDate] = useState('') |
||||||
|
const [nativeeditorStatus, setNativeeditorStatus] = useState('') |
||||||
|
const [hr, setHr] = useState(null); |
||||||
|
const [hrTemporary, setHrTemporary] = useState(); |
||||||
|
const [hrTemporaryAdd, setHrTemporaryAdd] = useState([]); |
||||||
|
const [IdDeleteHrTemporary, setIdDeleteHrTemporary] = useState([]); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
|
||||||
|
setText('') |
||||||
|
setStartDate('') |
||||||
|
setProgress(0) |
||||||
|
setEndDate('') |
||||||
|
setVolumePlan(0) |
||||||
|
setHr('') |
||||||
|
setHrTemporaryAdd([]) |
||||||
|
setHrTemporary([]) |
||||||
|
setIdDeleteHrTemporary([]) |
||||||
|
|
||||||
|
if (typeDialogActivity === "Edit") { |
||||||
|
|
||||||
|
setId(dataEditCard.id) |
||||||
|
setText(dataEditCard.activity) |
||||||
|
setProgress(dataEditCard.persentase_progress)
|
||||||
|
setStartDate(moment(dataEditCard.start_date)) |
||||||
|
setEndDate(moment(dataEditCard.end_date))
|
||||||
|
dataEditCard.assign_hr.map((item) => { |
||||||
|
item.value = item.id_hr |
||||||
|
item.label = item.name |
||||||
|
}) |
||||||
|
setVolumePlan(dataEditCard.jumlah_pekerjaan) |
||||||
|
setHr(dataEditCard.assign_hr) |
||||||
|
setHrTemporary(dataEditCard.assign_hr) |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
setId(0) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
dataHr.map((item) => { |
||||||
|
item.value = item.id |
||||||
|
item.label = item.name |
||||||
|
}) |
||||||
|
|
||||||
|
}, [openDialogActivity]) |
||||||
|
|
||||||
|
const handleCancel = () => { |
||||||
|
closeDialogActivity('cancel', 'none') |
||||||
|
setVolumePlan(0) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const handleSave = () => { |
||||||
|
let data = ''; |
||||||
|
|
||||||
|
if (!text || text === "") { |
||||||
|
alert("text cannot be empty!"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (!startDate || startDate === "") { |
||||||
|
alert("startDate cannot be empty!"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (!endDate || endDate === "") { |
||||||
|
alert("endDate cannot be empty!"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (!hr || hr === "") { |
||||||
|
alert("hr cannot be empty!"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (typeDialogActivity === "Save") { |
||||||
|
|
||||||
|
data = { |
||||||
|
"text" : text, |
||||||
|
"start_date": startDate, |
||||||
|
"jumlah_pekerjaan" : volumePlan, |
||||||
|
"end_date" : endDate, |
||||||
|
"proyek_id" : proyek_id, |
||||||
|
"version_gantt_id": version_gantt_id, |
||||||
|
"board_id" : idBoard, |
||||||
|
"parent_id" : activityProject |
||||||
|
} |
||||||
|
closeDialogActivity('save', data, hr, id); |
||||||
|
} else if (typeDialogActivity === "Edit") { |
||||||
|
|
||||||
|
hrTemporaryAdd.map((item)=> { |
||||||
|
let dataSaveHr = { |
||||||
|
"user_id": item.id, |
||||||
|
"role_proyek_id": item.proyek_role, |
||||||
|
"version_gantt_id": version_gantt_id, |
||||||
|
"proyek_id": proyek_id, |
||||||
|
"activity_id": id |
||||||
|
} |
||||||
|
userToActivityAdd(dataSaveHr) |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
IdDeleteHrTemporary.map((item)=>{ |
||||||
|
|
||||||
|
userToActivityDelete(item) |
||||||
|
|
||||||
|
}) |
||||||
|
|
||||||
|
setHrTemporaryAdd([]) |
||||||
|
setIdDeleteHrTemporary([]) |
||||||
|
setHrTemporary([]) |
||||||
|
|
||||||
|
progress == 100 ? |
||||||
|
data = { |
||||||
|
"text": text, |
||||||
|
"start_date": startDate, |
||||||
|
"jumlah_pekerjaan": volumePlan, |
||||||
|
"end_date": endDate, |
||||||
|
"proyek_id": proyek_id, |
||||||
|
"version_gantt_id": version_gantt_id, |
||||||
|
"board_id": idBoard, |
||||||
|
"progress": parseFloat(progress / 100).toFixed(2) |
||||||
|
} |
||||||
|
: |
||||||
|
data = { |
||||||
|
"text": text, |
||||||
|
"start_date": startDate, |
||||||
|
"jumlah_pekerjaan": volumePlan, |
||||||
|
"end_date": endDate, |
||||||
|
"proyek_id": proyek_id, |
||||||
|
"version_gantt_id": version_gantt_id, |
||||||
|
"board_id": idBoard, |
||||||
|
"progress": parseFloat(progress / 100).toFixed(2) |
||||||
|
} |
||||||
|
|
||||||
|
closeDialogActivity('edit', data, hr, id); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
const onChangeHr = (newValue, actionMeta) => {
|
||||||
|
if (typeDialogActivity === "Edit") {
|
||||||
|
if (actionMeta.action === 'select-option') { |
||||||
|
const item = actionMeta.option |
||||||
|
// console.log("actionMeta", item);
|
||||||
|
// let dataSaveHr = {
|
||||||
|
// "user_id": item.id,
|
||||||
|
// "role_proyek_id": item.proyek_role,
|
||||||
|
// "version_gantt_id": version_gantt_id,
|
||||||
|
// "proyek_id": proyek_id,
|
||||||
|
// "activity_id": id
|
||||||
|
// }
|
||||||
|
// userToActivityAdd(dataSaveHr)
|
||||||
|
setHrTemporaryAdd([...hrTemporaryAdd, item]) |
||||||
|
} else if (actionMeta.action === 'remove-value') { |
||||||
|
const id = actionMeta.removedValue.id |
||||||
|
// userToActivityDelete(id)
|
||||||
|
for (let k in hrTemporary) {
|
||||||
|
if (hrTemporary[k].id == id) { |
||||||
|
setIdDeleteHrTemporary([...IdDeleteHrTemporary, id]) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
}
|
||||||
|
} |
||||||
|
|
||||||
|
setHr(newValue) |
||||||
|
}; |
||||||
|
|
||||||
|
const increase = () => { |
||||||
|
let newPercent = progress + 10; |
||||||
|
if (newPercent > 100) { |
||||||
|
newPercent = 100; |
||||||
|
} |
||||||
|
setProgress(newPercent); |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
const decline = () => { |
||||||
|
let newPercent = progress - 10; |
||||||
|
if (newPercent < 0) { |
||||||
|
newPercent = 0; |
||||||
|
} |
||||||
|
setProgress(newPercent); |
||||||
|
}; |
||||||
|
|
||||||
|
const renderForm = () => { |
||||||
|
return ( |
||||||
|
<Form> |
||||||
|
<Row> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Text</Label> |
||||||
|
<Input type="text" value={text} onChange={(e) => setText(e.target.value)} /> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Start Date</Label> |
||||||
|
<DatePicker style={{ width: "100%" }} value={startDate} onChange={(dateItem, dateString) => { |
||||||
|
dateItem.set({hour:0,minute:0,second:0}) |
||||||
|
setStartDate(dateItem)}}
|
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">End date</Label> |
||||||
|
<DatePicker style={{ width: "100%" }} value={endDate} onChange={(dateItem, dateString) => { |
||||||
|
dateItem.set({hour:23,minute:59,second:59}) |
||||||
|
setEndDate(dateItem)}} |
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
{/* <Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Duration</Label> |
||||||
|
<Input type="number" value={duration} onChange={(e) => setDuration(e.target.value)}/> |
||||||
|
</FormGroup> |
||||||
|
</Col> */} |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Presentase Progress</Label> |
||||||
|
{/* <Input type="number" value={progress} onChange={(e) => setProgress(e.target.value)}/> */} |
||||||
|
<Progress percent={Math.round(progress)} /> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Volume Plan</Label> |
||||||
|
<Input type="number" value={volumePlan} onChange={(e) => setVolumePlan(e.target.value)} /> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Human Resource</Label> |
||||||
|
{/* <Select |
||||||
|
showSearch |
||||||
|
filterOption={(inputValue, option) => |
||||||
|
option.children.toLowerCase().includes(inputValue.toLowerCase()) |
||||||
|
} |
||||||
|
value={hr} |
||||||
|
defaultValue={hr} |
||||||
|
onChange={onChangeHr} |
||||||
|
style={{ width: "100%" }} |
||||||
|
> |
||||||
|
{dataHr.map((res) => ( |
||||||
|
<Option key={res.id} value={res.id}> |
||||||
|
{res.name} |
||||||
|
</Option> |
||||||
|
))} |
||||||
|
</Select> */} |
||||||
|
<Select |
||||||
|
value={hr} |
||||||
|
defaultValue={hr} |
||||||
|
isClearable={false} |
||||||
|
isMulti |
||||||
|
name="colors" |
||||||
|
options={dataHr} |
||||||
|
className="basic-multi-select" |
||||||
|
classNamePrefix="select" |
||||||
|
onChange={onChangeHr} |
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Volume Actual : {Math.round(parseInt(progress) / 100 * volumePlan)}</Label> |
||||||
|
<div> |
||||||
|
<Button onClick={() => handleOpenDialogReport("Save")} type="primary">Detail Report</Button> |
||||||
|
</div> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</Form> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<Drawer title="Basic Drawer" placement="right" onClose={() => handleCancel()} open={openDialogActivity}> |
||||||
|
<div className='top'> |
||||||
|
<Space> |
||||||
|
<Button type='text' onClick={() => handleCancel()}><CloseOutlined /></Button> |
||||||
|
</Space> |
||||||
|
<Space style={{float:"right"}}> |
||||||
|
<Button onClick={() => handleCancel()}>Cancel</Button> |
||||||
|
<Button onClick={() => handleSave()} type="primary"> |
||||||
|
{typeDialogActivity == "Edit" ? `Edit` : "Add"} Activity |
||||||
|
</Button> |
||||||
|
</Space> |
||||||
|
<Divider /> |
||||||
|
</div> |
||||||
|
<div className='content' style={{alignContent:'center'}}> |
||||||
|
{renderForm()} |
||||||
|
</div> |
||||||
|
<div className='bottom' style={{float:'bottom'}}> |
||||||
|
</div> |
||||||
|
</Drawer> |
||||||
|
</> |
||||||
|
) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
export default DialogFormActivity; |
@ -0,0 +1,176 @@ |
|||||||
|
import React, { useEffect, useState } from 'react' |
||||||
|
import { |
||||||
|
Modal, ModalHeader, ModalBody, ModalFooter, |
||||||
|
Form, FormGroup, Label, Input, Col, Row, FormFeedback |
||||||
|
} from 'reactstrap'; |
||||||
|
import { DatePicker, Tooltip, Select, Drawer, Divider, Layout, Button, Space } from 'antd'; |
||||||
|
import 'antd/dist/antd.css'; |
||||||
|
import { |
||||||
|
CloseOutlined |
||||||
|
} from '@ant-design/icons'; |
||||||
|
const { Option } = Select |
||||||
|
const { Header, Footer, Sider, Content } = Layout; |
||||||
|
|
||||||
|
|
||||||
|
const DialogFormBoard = ({ openDialogBoard, closeDialogBoard, toggleDialogBoard, typeDialogBoard, dataEditBoard, proyek_id, version_gantt_id }) => { |
||||||
|
const [id, setId] = useState(0) |
||||||
|
const [nameBoard, setNameBoard] = useState('') |
||||||
|
const [statusProgress, setStatusProgress] = useState('none') |
||||||
|
const [headerColor, setHeaderColor] = useState('#000000') |
||||||
|
const [bodyColor, setBodyColor] = useState('#ffffff') |
||||||
|
|
||||||
|
// validation
|
||||||
|
const [nameBoardVal, setNameBoardVal] = useState(false) |
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
|
||||||
|
setNameBoard('') |
||||||
|
setStatusProgress('') |
||||||
|
setHeaderColor('#000000') |
||||||
|
setBodyColor('#ffffff') |
||||||
|
|
||||||
|
if (typeDialogBoard === "Edit") { |
||||||
|
setId(dataEditBoard.id) |
||||||
|
setNameBoard(dataEditBoard.name_board) |
||||||
|
setHeaderColor(dataEditBoard.header_color) |
||||||
|
setBodyColor(dataEditBoard.body_color) |
||||||
|
setStatusProgress(dataEditBoard.status_progress) |
||||||
|
} else { |
||||||
|
setId(0) |
||||||
|
} |
||||||
|
}, [dataEditBoard, openDialogBoard]) |
||||||
|
|
||||||
|
const handleCancel = () => { |
||||||
|
closeDialogBoard('cancel', 'none') |
||||||
|
} |
||||||
|
|
||||||
|
const handleSave = () => { |
||||||
|
let data = ''; |
||||||
|
|
||||||
|
if (!nameBoard || nameBoard === "") { |
||||||
|
alert("nameBoard cannot be empty!"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (!statusProgress || statusProgress === "") { |
||||||
|
alert("statusProgress cannot be empty!"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (typeDialogBoard === "Save") { |
||||||
|
data = { |
||||||
|
name_board: nameBoard, |
||||||
|
status_progress: statusProgress, |
||||||
|
header_color: headerColor, |
||||||
|
body_color: bodyColor, |
||||||
|
proyek_id: proyek_id, |
||||||
|
version_gantt_id: version_gantt_id |
||||||
|
} |
||||||
|
closeDialogBoard('save', data); |
||||||
|
} else if (typeDialogBoard === "Edit") { |
||||||
|
data = { |
||||||
|
id: id, |
||||||
|
name_board: nameBoard, |
||||||
|
status_progress: statusProgress, |
||||||
|
header_color: headerColor, |
||||||
|
body_color: bodyColor, |
||||||
|
proyek_id: proyek_id, |
||||||
|
version_gantt_id: version_gantt_id |
||||||
|
} |
||||||
|
closeDialogBoard('edit', data); |
||||||
|
} |
||||||
|
|
||||||
|
setNameBoard('') |
||||||
|
setStatusProgress('') |
||||||
|
setHeaderColor('#000000') |
||||||
|
setBodyColor('#ffffff') |
||||||
|
} |
||||||
|
|
||||||
|
const onChangeStatusProgress = (val) => { |
||||||
|
setStatusProgress(val) |
||||||
|
}; |
||||||
|
|
||||||
|
const renderForm = () => { |
||||||
|
return ( |
||||||
|
<Form> |
||||||
|
<Row> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Name Board</Label> |
||||||
|
<Input type="text" value={nameBoard} onChange={(e) => setNameBoard(e.target.value)} /> |
||||||
|
{/* <Input type="text" value={nameBoard} onChange={(e) => setNameBoard(e.target.value)} invalid={nameBoardVal} /> |
||||||
|
<FormFeedback> |
||||||
|
Required!
|
||||||
|
</FormFeedback> */} |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Status Progress</Label> |
||||||
|
{/* <Input type="text" value={statusProgress} onChange={(e) => setStatusProgress(e.target.value)}/> */} |
||||||
|
<Select |
||||||
|
showSearch |
||||||
|
filterOption={(inputValue, option) => |
||||||
|
option.children.toLowerCase().includes(inputValue.toLowerCase()) |
||||||
|
} |
||||||
|
value={statusProgress} |
||||||
|
defaultValue={statusProgress} |
||||||
|
onChange={onChangeStatusProgress} |
||||||
|
style={{ width: "100%" }} |
||||||
|
> |
||||||
|
<Option value="none">none</Option> |
||||||
|
<Option value="open">open</Option> |
||||||
|
<Option value="on-progress">on-progress</Option> |
||||||
|
<Option value="done">done</Option> |
||||||
|
</Select> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
<Row> |
||||||
|
<Col md={6}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Header Color</Label> |
||||||
|
<Input type="color" value={headerColor} onChange={(e) => setHeaderColor(e.target.value)} /> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={6}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Text Header Color</Label> |
||||||
|
<Input type="color" value={bodyColor} onChange={(e) => setBodyColor(e.target.value)} /> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</Form> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<Drawer title="Basic Drawer" placement="right" onClose={() => handleCancel()} open={openDialogBoard}> |
||||||
|
<div className='top'> |
||||||
|
<Space> |
||||||
|
<Button type='text' onClick={() => handleCancel()}><CloseOutlined /></Button> |
||||||
|
</Space> |
||||||
|
<Space style={{ float: "right" }}> |
||||||
|
<Button onClick={() => handleCancel()}>Cancel</Button> |
||||||
|
<Button onClick={() => handleSave()} type="primary"> |
||||||
|
{typeDialogBoard == "Edit" ? `Edit` : "Add"} Board |
||||||
|
</Button> |
||||||
|
</Space> |
||||||
|
<Divider /> |
||||||
|
</div> |
||||||
|
<div className='content' style={{ alignContent: 'center' }}> |
||||||
|
{renderForm()} |
||||||
|
</div> |
||||||
|
<div className='bottom' style={{ float: 'bottom' }}> |
||||||
|
</div> |
||||||
|
</Drawer> |
||||||
|
</> |
||||||
|
) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
export default DialogFormBoard; |
@ -0,0 +1,69 @@ |
|||||||
|
import React, { useEffect, useState } from 'react' |
||||||
|
import { |
||||||
|
Modal, ModalHeader, ModalBody, ModalFooter, |
||||||
|
Button, Form, FormGroup, Label, Input, Col, Row |
||||||
|
} from 'reactstrap'; |
||||||
|
import { DatePicker, Tooltip, Select } from 'antd'; |
||||||
|
import { formatRupiah, formatNumber } from '../../../const/CustomFunc' |
||||||
|
import moment from 'moment'; |
||||||
|
import 'antd/dist/antd.css'; |
||||||
|
const { Option } = Select |
||||||
|
|
||||||
|
const DialogFormChild = ({ openDialogChild, closeDialogChild, toggleDialogChild, typeDialogChild }) => { |
||||||
|
const [activity, setActivity] = useState('') |
||||||
|
const [name, setName] = useState('') |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
|
||||||
|
}, [openDialogChild]) |
||||||
|
|
||||||
|
const handleCancel = () => { |
||||||
|
closeDialogChild('cancel', 'none') |
||||||
|
} |
||||||
|
|
||||||
|
const handleSave = () => { |
||||||
|
let data = ''; |
||||||
|
if (typeDialogChild === "Save") { |
||||||
|
data = { |
||||||
|
name,
|
||||||
|
} |
||||||
|
closeDialogChild('save', data); |
||||||
|
}
|
||||||
|
|
||||||
|
setActivity('') |
||||||
|
} |
||||||
|
|
||||||
|
const renderForm = () => { |
||||||
|
return ( |
||||||
|
<Form> |
||||||
|
<Row> |
||||||
|
<Col md={6}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Name</Label> |
||||||
|
<Input type="text" value={name} onChange={(e) => setName(e.target.value)}/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</Form> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<Modal size="lg" isOpen={openDialogChild} toggle={toggleDialogChild}> |
||||||
|
<ModalHeader className="capitalize" toggle={closeDialogChild}>{typeDialogChild == "Edit" ? `Edit` : "Add"} Child</ModalHeader> |
||||||
|
<ModalBody> |
||||||
|
{renderForm()} |
||||||
|
</ModalBody> |
||||||
|
<ModalFooter> |
||||||
|
<Button color="primary" onClick={() => handleSave()}>{typeDialogChild == "Edit" ? `Edit` : "Save"}</Button>{' '} |
||||||
|
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Batal</Button> |
||||||
|
</ModalFooter> |
||||||
|
</Modal> |
||||||
|
</> |
||||||
|
) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
export default DialogFormChild; |
@ -0,0 +1,438 @@ |
|||||||
|
import React, { useEffect, useState } from 'react' |
||||||
|
import { |
||||||
|
Modal, ModalHeader, ModalBody, ModalFooter, |
||||||
|
Form, FormGroup, Label, Input, Col, Row |
||||||
|
} from 'reactstrap'; |
||||||
|
import { DatePicker, Table, Drawer, Divider, Tooltip, Button, Space, Progress } from 'antd'; |
||||||
|
import { |
||||||
|
CloseOutlined, |
||||||
|
MinusOutlined, |
||||||
|
PlusOutlined |
||||||
|
} from '@ant-design/icons'; |
||||||
|
import { |
||||||
|
NotificationManager |
||||||
|
} from "react-notifications"; |
||||||
|
import SweetAlert from 'react-bootstrap-sweetalert'; |
||||||
|
import { formatRupiah, formatNumber } from '../../../const/CustomFunc' |
||||||
|
import moment from 'moment'; |
||||||
|
import Select from 'react-select'; |
||||||
|
import 'antd/dist/antd.css'; |
||||||
|
import axios from "../../../const/interceptorApi"; |
||||||
|
import { BASE_SIMPRO_LUMEN } from '../../../const/ApiConst'; |
||||||
|
// const { Option } = Select
|
||||||
|
|
||||||
|
const DialogFormReport = ({ |
||||||
|
activityProject, |
||||||
|
openDialogReport, |
||||||
|
closeDialogReport, |
||||||
|
toggleDialogActivity, |
||||||
|
typeDialogReport, |
||||||
|
proyek_id, |
||||||
|
version_gantt_id, |
||||||
|
idBoard, |
||||||
|
dataHr, |
||||||
|
dataEditCard, |
||||||
|
userToActivityDelete, |
||||||
|
userToActivityAdd |
||||||
|
}) => { |
||||||
|
const [id, setId] = useState('') |
||||||
|
const [idDelete, setIdDelete] = useState('') |
||||||
|
const [alertDelete, setAlertDelete] = useState(false) |
||||||
|
const [text, setText] = useState('') |
||||||
|
const [description, setDescription] = useState('') |
||||||
|
const [startDate, setStartDate] = useState('') |
||||||
|
const [reportDate, setReportDate] = useState('') |
||||||
|
const [progress, setProgress] = useState(0) |
||||||
|
const [volumePlan, setVolumePlan] = useState(0) |
||||||
|
const [volumeActual, setVolumeActual] = useState(0) |
||||||
|
const [nativeeditorStatus, setNativeeditorStatus] = useState('') |
||||||
|
const [hr, setHr] = useState(null); |
||||||
|
const [hrTemporary, setHrTemporary] = useState(); |
||||||
|
const [hrTemporaryAdd, setHrTemporaryAdd] = useState([]); |
||||||
|
const [IdDeleteHrTemporary, setIdDeleteHrTemporary] = useState([]); |
||||||
|
const [reportActivity, setReportActivity] = useState([]) |
||||||
|
const token = localStorage.getItem("token"); |
||||||
|
|
||||||
|
const HEADER = { |
||||||
|
headers: { |
||||||
|
"Content-Type": "application/json", |
||||||
|
Authorization: `Bearer ${token}`, |
||||||
|
}, |
||||||
|
}; |
||||||
|
useEffect(() => { |
||||||
|
|
||||||
|
setText('') |
||||||
|
setStartDate('') |
||||||
|
setProgress(0) |
||||||
|
setVolumePlan(0) |
||||||
|
setHr('') |
||||||
|
setHrTemporaryAdd([]) |
||||||
|
setHrTemporary([]) |
||||||
|
setIdDeleteHrTemporary([]) |
||||||
|
if (dataEditCard.id) { |
||||||
|
handleGetReportActivity(dataEditCard.id) |
||||||
|
} |
||||||
|
|
||||||
|
if (typeDialogReport === "Edit") { |
||||||
|
|
||||||
|
setId(dataEditCard.id) |
||||||
|
setText(dataEditCard.activity) |
||||||
|
setProgress(dataEditCard.persentase_progress) |
||||||
|
setStartDate(moment(dataEditCard.start_date)) |
||||||
|
dataEditCard.assign_hr.map((item) => { |
||||||
|
item.value = item.id_hr |
||||||
|
item.label = item.name |
||||||
|
}) |
||||||
|
setVolumePlan(dataEditCard.jumlah_pekerjaan) |
||||||
|
setHr(dataEditCard.assign_hr) |
||||||
|
setHrTemporary(dataEditCard.assign_hr) |
||||||
|
|
||||||
|
} else { |
||||||
|
|
||||||
|
setId(0) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
dataHr.map((item) => { |
||||||
|
item.value = item.id |
||||||
|
item.label = item.name |
||||||
|
}) |
||||||
|
|
||||||
|
}, [openDialogReport]) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (dataEditCard.id) { |
||||||
|
handleGetReportActivity(dataEditCard.id) |
||||||
|
} |
||||||
|
}, [idDelete]) |
||||||
|
|
||||||
|
const handleCancel = () => { |
||||||
|
closeDialogReport('cancel', 'none') |
||||||
|
} |
||||||
|
|
||||||
|
const handleReport = () => { |
||||||
|
console.log('Button Triggered') |
||||||
|
} |
||||||
|
|
||||||
|
const handleGetReportActivity = async (id) => { |
||||||
|
const payload = { |
||||||
|
columns: [ |
||||||
|
{ |
||||||
|
name: "activity_id", |
||||||
|
logic_operator: "=", |
||||||
|
value: id, |
||||||
|
operator: "AND", |
||||||
|
} |
||||||
|
], |
||||||
|
}; |
||||||
|
|
||||||
|
const result = await axios |
||||||
|
.post(`${BASE_SIMPRO_LUMEN}/report-activity/search`, payload, HEADER) |
||||||
|
.then((res) => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code == 200) { |
||||||
|
let dataRes = result.data.data || []; |
||||||
|
dataRes.map((item) => { |
||||||
|
let formattedDate = moment(item.report_date, "YYYY-MM-DD HH:mm:ssZ").format('YYYY-MM-DD'); |
||||||
|
item.report_date = formattedDate; |
||||||
|
|
||||||
|
}) |
||||||
|
setReportActivity(dataRes) |
||||||
|
} else { |
||||||
|
NotificationManager.error("Gagal Mengambil Data!!", "Failed"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const handleDeleteReport = (id) => { |
||||||
|
setIdDelete(id) |
||||||
|
setAlertDelete(true) |
||||||
|
} |
||||||
|
|
||||||
|
const cancelDelete = () => { |
||||||
|
setAlertDelete(false) |
||||||
|
} |
||||||
|
|
||||||
|
const onConfirmDelete = async () => { |
||||||
|
let url = `${BASE_SIMPRO_LUMEN}/report-activity/delete/${idDelete}`; |
||||||
|
setAlertDelete(false) |
||||||
|
const result = await axios.delete(url, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
setIdDelete('') |
||||||
|
closeDialogReport("Delete") |
||||||
|
NotificationManager.success(`Data berhasil dihapus!`, 'Success!!'); |
||||||
|
} else { |
||||||
|
setIdDelete('') |
||||||
|
NotificationManager.error(`Data gagal dihapus!}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const handleSave = () => { |
||||||
|
let data = ''; |
||||||
|
|
||||||
|
if (!reportDate || reportDate === "") { |
||||||
|
alert("reportDate cannot be empty!"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (!hr || hr === "") { |
||||||
|
alert("hr cannot be empty!"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (typeDialogReport === "Save") { |
||||||
|
|
||||||
|
data = { |
||||||
|
"activity_id": dataEditCard.id, |
||||||
|
"report_date": reportDate, |
||||||
|
"jumlah_pekerjaan": volumeActual, |
||||||
|
"description": description |
||||||
|
} |
||||||
|
setReportDate(''); |
||||||
|
setVolumeActual(0); |
||||||
|
setHr(null); |
||||||
|
setDescription(''); |
||||||
|
closeDialogReport('Save', data, hr); |
||||||
|
handleCancel() |
||||||
|
} else if (typeDialogReport === "Edit") { |
||||||
|
|
||||||
|
hrTemporaryAdd.map((item) => { |
||||||
|
let dataSaveHr = { |
||||||
|
"user_id": item.id, |
||||||
|
"role_proyek_id": item.proyek_role, |
||||||
|
"version_gantt_id": version_gantt_id, |
||||||
|
"proyek_id": proyek_id, |
||||||
|
"activity_id": id |
||||||
|
} |
||||||
|
userToActivityAdd(dataSaveHr) |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
IdDeleteHrTemporary.map((item) => { |
||||||
|
|
||||||
|
userToActivityDelete(item) |
||||||
|
|
||||||
|
}) |
||||||
|
|
||||||
|
setHrTemporaryAdd([]) |
||||||
|
setIdDeleteHrTemporary([]) |
||||||
|
setHrTemporary([]) |
||||||
|
|
||||||
|
progress == 100 ? |
||||||
|
data = { |
||||||
|
"text": text, |
||||||
|
"start_date": startDate, |
||||||
|
"jumlah_pekerjaan": volumePlan, |
||||||
|
"proyek_id": proyek_id, |
||||||
|
"version_gantt_id": version_gantt_id, |
||||||
|
"board_id": idBoard |
||||||
|
} |
||||||
|
: |
||||||
|
data = { |
||||||
|
"text": text, |
||||||
|
"start_date": startDate, |
||||||
|
"jumlah_pekerjaan": volumePlan, |
||||||
|
"proyek_id": proyek_id, |
||||||
|
"version_gantt_id": version_gantt_id, |
||||||
|
"board_id": idBoard |
||||||
|
} |
||||||
|
|
||||||
|
closeDialogReport('edit', data, hr, id); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
const onChangeHr = (newValue, actionMeta) => { |
||||||
|
if (typeDialogReport === "Edit") { |
||||||
|
if (actionMeta.action === 'select-option') { |
||||||
|
const item = actionMeta.option |
||||||
|
// console.log("actionMeta", item);
|
||||||
|
// let dataSaveHr = {
|
||||||
|
// "user_id": item.id,
|
||||||
|
// "role_proyek_id": item.proyek_role,
|
||||||
|
// "version_gantt_id": version_gantt_id,
|
||||||
|
// "proyek_id": proyek_id,
|
||||||
|
// "activity_id": id
|
||||||
|
// }
|
||||||
|
// userToActivityAdd(dataSaveHr)
|
||||||
|
setHrTemporaryAdd([...hrTemporaryAdd, item]) |
||||||
|
} else if (actionMeta.action === 'remove-value') { |
||||||
|
const id = actionMeta.removedValue.id |
||||||
|
// userToActivityDelete(id)
|
||||||
|
for (let k in hrTemporary) { |
||||||
|
if (hrTemporary[k].id == id) { |
||||||
|
setIdDeleteHrTemporary([...IdDeleteHrTemporary, id]) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
setHr(newValue) |
||||||
|
}; |
||||||
|
|
||||||
|
const increase = () => { |
||||||
|
let newPercent = progress + 10; |
||||||
|
if (newPercent > 100) { |
||||||
|
newPercent = 100; |
||||||
|
} |
||||||
|
setProgress(newPercent); |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
const decline = () => { |
||||||
|
let newPercent = progress - 10; |
||||||
|
if (newPercent < 0) { |
||||||
|
newPercent = 0; |
||||||
|
} |
||||||
|
setProgress(newPercent); |
||||||
|
}; |
||||||
|
|
||||||
|
const columns = [ |
||||||
|
{ |
||||||
|
title: 'Created By', |
||||||
|
dataIndex: 'created_by', |
||||||
|
key: 'created_by', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Report Date', |
||||||
|
dataIndex: 'report_date', |
||||||
|
key: 'report_date', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Actual', |
||||||
|
dataIndex: 'job_count_report', |
||||||
|
key: 'job_count_report', |
||||||
|
render: (text) => Math.round(text), |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Action', |
||||||
|
dataIndex: 'id', |
||||||
|
key: 'actions', |
||||||
|
render: (id) => ( |
||||||
|
<Tooltip title="Delete Report" placement="top"> |
||||||
|
<Button onClick={() => handleDeleteReport(id)} type="danger" style={{ backgroundColor:'transparent', color:'red', border:'none' }}> |
||||||
|
<i class="nav-icon icon-trash"></i> |
||||||
|
</Button> |
||||||
|
</Tooltip> |
||||||
|
), |
||||||
|
}, |
||||||
|
]; |
||||||
|
|
||||||
|
const renderForm = () => { |
||||||
|
return ( |
||||||
|
<Form> |
||||||
|
<Row> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Report Date</Label> |
||||||
|
<DatePicker style={{ width: "100%" }} value={reportDate} onChange={(dateItem, dateString) => { |
||||||
|
dateItem.set({ hour: 0, minute: 0, second: 0 }) |
||||||
|
setReportDate(dateItem) |
||||||
|
}} |
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
{/* <Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Duration</Label> |
||||||
|
<Input type="number" value={duration} onChange={(e) => setDuration(e.target.value)}/> |
||||||
|
</FormGroup> |
||||||
|
</Col> */} |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Volume Actual</Label> |
||||||
|
<Input type="number" value={volumeActual} onChange={(e) => setVolumeActual(e.target.value)} /> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Human Resource</Label> |
||||||
|
{/* <Select |
||||||
|
showSearch |
||||||
|
filterOption={(inputValue, option) => |
||||||
|
option.children.toLowerCase().includes(inputValue.toLowerCase()) |
||||||
|
} |
||||||
|
value={hr} |
||||||
|
defaultValue={hr} |
||||||
|
onChange={onChangeHr} |
||||||
|
style={{ width: "100%" }} |
||||||
|
> |
||||||
|
{dataHr.map((res) => ( |
||||||
|
<Option key={res.id} value={res.id}> |
||||||
|
{res.name} |
||||||
|
</Option> |
||||||
|
))} |
||||||
|
</Select> */} |
||||||
|
<Select |
||||||
|
value={hr} |
||||||
|
defaultValue={hr} |
||||||
|
isClearable={false} |
||||||
|
name="colors" |
||||||
|
options={dataHr} |
||||||
|
className="basic-multi-select" |
||||||
|
classNamePrefix="select" |
||||||
|
onChange={onChangeHr} |
||||||
|
/> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<Col md={12}> |
||||||
|
<FormGroup> |
||||||
|
<Label className="capitalize">Description</Label> |
||||||
|
<Input type="textarea" value={description} onChange={(e) => setDescription(e.target.value)} /> |
||||||
|
</FormGroup> |
||||||
|
</Col> |
||||||
|
<div> |
||||||
|
{reportActivity.length > 0 ? ( |
||||||
|
<Table dataSource={reportActivity} columns={columns} /> |
||||||
|
) : null} |
||||||
|
</div> |
||||||
|
</Row> |
||||||
|
</Form> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<Drawer title="Basic Drawer" placement="right" onClose={() => handleCancel()} open={openDialogReport}> |
||||||
|
<SweetAlert |
||||||
|
show={alertDelete} |
||||||
|
warning |
||||||
|
showCancel |
||||||
|
confirmBtnText="Delete" |
||||||
|
confirmBtnBsStyle="danger" |
||||||
|
title={`Are you sure?`} |
||||||
|
onConfirm={onConfirmDelete} |
||||||
|
onCancel={() => cancelDelete()} |
||||||
|
focusCancelBtn |
||||||
|
> |
||||||
|
Delete this data |
||||||
|
</SweetAlert> |
||||||
|
<div className='top'> |
||||||
|
<Space> |
||||||
|
<Button type='text' onClick={() => handleCancel()}><CloseOutlined /></Button> |
||||||
|
</Space> |
||||||
|
<Space style={{ float: "right" }}> |
||||||
|
<Button onClick={() => handleCancel()}>Cancel</Button> |
||||||
|
<Button onClick={() => handleSave()} type="primary"> |
||||||
|
{typeDialogReport == "Edit" ? `Edit` : "Add"} Report |
||||||
|
</Button> |
||||||
|
</Space> |
||||||
|
<Divider /> |
||||||
|
</div> |
||||||
|
<div className='content' style={{ alignContent: 'center' }}> |
||||||
|
{renderForm()} |
||||||
|
</div> |
||||||
|
<div className='bottom' style={{ float: 'bottom' }}> |
||||||
|
</div> |
||||||
|
</Drawer> |
||||||
|
</> |
||||||
|
) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
export default DialogFormReport; |
@ -0,0 +1,136 @@ |
|||||||
|
.App { |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
.App-header { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
font-size: calc(10px + 1.5vmin); |
||||||
|
} |
||||||
|
|
||||||
|
.App-link { |
||||||
|
color: #61dafb; |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes App-logo-spin { |
||||||
|
from { |
||||||
|
transform: rotate(0deg); |
||||||
|
} |
||||||
|
to { |
||||||
|
transform: rotate(360deg); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.characters { |
||||||
|
list-style: none; |
||||||
|
padding-left: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.characters li { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
border: solid 2px #d0d0d0; |
||||||
|
border-radius: .2em; |
||||||
|
padding: .5em .8em .5em .5em; |
||||||
|
margin-bottom: 1em; |
||||||
|
} |
||||||
|
|
||||||
|
/* .characters p { |
||||||
|
max-width: none; |
||||||
|
font-weight: bold; |
||||||
|
margin: 0; |
||||||
|
} */ |
||||||
|
|
||||||
|
.characters-thumb { |
||||||
|
overflow: hidden; |
||||||
|
flex-shrink: 0; |
||||||
|
width: 2em; |
||||||
|
height: 2em; |
||||||
|
background-color: #e8e8e8; |
||||||
|
padding: .5em; |
||||||
|
margin-right: .5em; |
||||||
|
} |
||||||
|
|
||||||
|
.characters-thumb img { |
||||||
|
display: block; |
||||||
|
width: 100%; |
||||||
|
height: auto; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* body */ |
||||||
|
.body { |
||||||
|
background-color: #f4f4f4; |
||||||
|
border-radius: 10px; |
||||||
|
padding: 20px; |
||||||
|
} |
||||||
|
|
||||||
|
.board { |
||||||
|
width: 19rem; |
||||||
|
height: 3rem; |
||||||
|
padding: 5px; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 8px; |
||||||
|
/* border: 0.5px solid silver; */ |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
|
||||||
|
.board-add{ |
||||||
|
width: 15rem; |
||||||
|
height: 3rem; |
||||||
|
padding: 5px; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 8px; |
||||||
|
/* border: 0.5px solid silver; */ |
||||||
|
text-align: left; |
||||||
|
cursor: pointer; |
||||||
|
background-color: #f4f4f4; |
||||||
|
} |
||||||
|
|
||||||
|
.board-add:hover { |
||||||
|
background-color: rgb(255, 255, 255); |
||||||
|
} |
||||||
|
|
||||||
|
.title-board-add { |
||||||
|
font-weight: normal; |
||||||
|
margin-top: 5px; |
||||||
|
margin-left: 10px; |
||||||
|
/* font-size: 20px; */ |
||||||
|
color: silver; |
||||||
|
} |
||||||
|
|
||||||
|
.title-board { |
||||||
|
font-weight: normal; |
||||||
|
margin-top: 5px; |
||||||
|
margin-left: 10px; |
||||||
|
/* font-size: 20px; */ |
||||||
|
/* color: rgb(81, 80, 80); */ |
||||||
|
} |
||||||
|
|
||||||
|
.board .title-option { |
||||||
|
float: right; |
||||||
|
} |
||||||
|
|
||||||
|
.board { |
||||||
|
border-radius: 8px; |
||||||
|
height: 3rem; |
||||||
|
width: 270px; |
||||||
|
} |
||||||
|
|
||||||
|
.cards { |
||||||
|
margin-bottom: 10px; |
||||||
|
border-radius: 8px; |
||||||
|
} |
||||||
|
/* border-top: 5px solid #65D3B3; */ |
||||||
|
|
||||||
|
.add-card { |
||||||
|
color: #f4f4f4; |
||||||
|
cursor: pointer; |
||||||
|
/* visibility: hidden; */ |
||||||
|
} |
||||||
|
|
||||||
|
.destination:hover .add-card{ |
||||||
|
color: silver; |
||||||
|
} |
@ -0,0 +1,206 @@ |
|||||||
|
import React, {Fragment, useState} from 'react' |
||||||
|
import './Kanban.css'; |
||||||
|
import { Draggable, DragDropContext, Droppable } from 'react-beautiful-dnd'; |
||||||
|
import styled from 'styled-components' |
||||||
|
import moment from 'moment'; |
||||||
|
import DialogCard from './DialogCard'; |
||||||
|
import { Card, Row, Col, Button, Avatar, Tooltip, Popover, Progress, Dropdown, Menu, Space } from 'antd'; |
||||||
|
import {
|
||||||
|
AntDesignOutlined, |
||||||
|
UserOutlined, |
||||||
|
EditOutlined, |
||||||
|
DeleteOutlined, |
||||||
|
EllipsisOutlined, |
||||||
|
DownOutlined, |
||||||
|
MoreOutlined, |
||||||
|
SmileOutlined |
||||||
|
} from '@ant-design/icons'; |
||||||
|
|
||||||
|
const Container = styled.div` |
||||||
|
border: 1px solid lightgrey; |
||||||
|
border-radius: 2px; |
||||||
|
padding: 8px; |
||||||
|
margin-bottom: 8px; |
||||||
|
transition: background-color 0.2s ease; |
||||||
|
background-color: ${props => |
||||||
|
props.isDragDisabled |
||||||
|
? 'lightgrey' |
||||||
|
: props.isDragging |
||||||
|
? 'lightgreen' |
||||||
|
: 'white'}; |
||||||
|
` |
||||||
|
|
||||||
|
const gridStyle = { |
||||||
|
// width: '25%',
|
||||||
|
// textAlign: 'center',
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
const Task = ({
|
||||||
|
task,
|
||||||
|
index,
|
||||||
|
stateKanban,
|
||||||
|
bodyColor,
|
||||||
|
loadingCard,
|
||||||
|
handleDeleteCard,
|
||||||
|
handleEditCard |
||||||
|
}) => { |
||||||
|
// const Task = ({ task, index, children, stateKanban , handleOpenDialogChild , handleDelete}) => {
|
||||||
|
const isDragDisabled = false |
||||||
|
|
||||||
|
const [openDialogChild, setOpenDialogChild] = useState(false) |
||||||
|
const [typeDialogChild, setTypeDialogChild] = useState('Save') |
||||||
|
const [clickOpenModalChild, setClickOpenModalChild] = useState(false) |
||||||
|
|
||||||
|
|
||||||
|
function onDragEnd(result) { |
||||||
|
const { destination, source, draggableId } = result |
||||||
|
|
||||||
|
|
||||||
|
if (!destination) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if ( |
||||||
|
destination.droppableId === source.droppableId && |
||||||
|
destination.index === source.index |
||||||
|
) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
const start = source.droppableId; |
||||||
|
const finish = destination.droppableId; |
||||||
|
|
||||||
|
if (start === finish) { |
||||||
|
const newTaskIds = stateKanban.columns[0].tasks[0].children; |
||||||
|
let newObj = stateKanban.columns[0].tasks[0].children.find(x => x.id === draggableId); |
||||||
|
newTaskIds.splice(source.index, 1) |
||||||
|
newTaskIds.splice(destination.index, 0, newObj) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const handleCloseDialogChild = (type, data) => { |
||||||
|
if (type === "save") { |
||||||
|
// saveItem(data);
|
||||||
|
}
|
||||||
|
setOpenDialogChild(false) |
||||||
|
} |
||||||
|
|
||||||
|
const toggleAddDialogChild = () => { |
||||||
|
setOpenDialogChild(!openDialogChild) |
||||||
|
} |
||||||
|
|
||||||
|
const handleOpenDialogChild = (type) => { |
||||||
|
setOpenDialogChild(true) |
||||||
|
setTypeDialogChild(type) |
||||||
|
} |
||||||
|
|
||||||
|
const menu = (task) => ( |
||||||
|
<Menu |
||||||
|
items={[ |
||||||
|
{ |
||||||
|
key: '1', |
||||||
|
label: ( |
||||||
|
<a rel="noopener noreferrer" onClick={()=>handleEditCard(task)}> |
||||||
|
<EditOutlined style={{marginRight: "5px"}} /> Edit |
||||||
|
</a> |
||||||
|
), |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: '2', |
||||||
|
label: ( |
||||||
|
<a rel="noopener noreferrer" onClick={()=> handleDeleteCard(task.id)}> |
||||||
|
<DeleteOutlined style={{marginRight: "5px"}} /> Hapus |
||||||
|
</a> |
||||||
|
), |
||||||
|
}, |
||||||
|
]} |
||||||
|
/> |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<DialogCard |
||||||
|
openDialogChild={openDialogChild} |
||||||
|
closeDialogChild={handleCloseDialogChild} |
||||||
|
toggleDialogChild={() => toggleAddDialogChild} |
||||||
|
typeDialogChild={typeDialogChild} |
||||||
|
clickOpenModalChild={clickOpenModalChild} |
||||||
|
task={task}
|
||||||
|
/> |
||||||
|
<Draggable |
||||||
|
draggableId={task.id} |
||||||
|
index={index} |
||||||
|
isDragDisabled={isDragDisabled} |
||||||
|
> |
||||||
|
{(provided, snapshot) => ( |
||||||
|
<Card
|
||||||
|
className='cards' |
||||||
|
{...provided.draggableProps} |
||||||
|
{...provided.dragHandleProps} |
||||||
|
ref={provided.innerRef} |
||||||
|
isDragging={snapshot.isDragging} |
||||||
|
isDragDisabled={isDragDisabled} |
||||||
|
loading={loadingCard} |
||||||
|
onDoubleClick={()=> handleEditCard(task)} |
||||||
|
> |
||||||
|
<div className='contents' > |
||||||
|
<div style={{float: 'right'}}> |
||||||
|
<Dropdown overlay={menu(task)}> |
||||||
|
<a onClick={(e) => e.preventDefault()}> |
||||||
|
<MoreOutlined style={{fontSize:"20px"}} /> |
||||||
|
</a> |
||||||
|
</Dropdown> |
||||||
|
</div> |
||||||
|
<div><b>{task.activity}</b></div> |
||||||
|
</div> |
||||||
|
<div className='status' style={{marginTop: "15px"}}> |
||||||
|
<Progress percent={Math.round(task.persentase_progress)} /> |
||||||
|
</div> |
||||||
|
<div style={{marginTop: "20px"}}> |
||||||
|
<div style={{float: 'left'}}> |
||||||
|
<Avatar.Group> |
||||||
|
{ |
||||||
|
task.assign_hr.map( (item, index) => { |
||||||
|
if (index < 8) { |
||||||
|
return <Tooltip title={item.name} placement="top"> |
||||||
|
<Avatar |
||||||
|
style={{ |
||||||
|
backgroundColor: '#87d', |
||||||
|
}} |
||||||
|
icon={<UserOutlined />} size="small" |
||||||
|
/> |
||||||
|
</Tooltip> |
||||||
|
} else if(index == 8) { |
||||||
|
return <Avatar |
||||||
|
style={{ |
||||||
|
backgroundColor: '#f56a00', |
||||||
|
}} |
||||||
|
size="small"> |
||||||
|
{/* + {["1","1","1","1","1","1","1","1"].length - 3} */} |
||||||
|
+ {task.assign_hr.length - 8} |
||||||
|
</Avatar> |
||||||
|
} |
||||||
|
|
||||||
|
}) |
||||||
|
}
|
||||||
|
</Avatar.Group> |
||||||
|
</div> |
||||||
|
<div style={{float: 'right'}}> |
||||||
|
<p style={{color: "grey", fontSize: "12px", marginTop: "3px"}}>{moment(task.start_date).format('DD-MM-YYYY HH:mm')}</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</Card> |
||||||
|
)} |
||||||
|
</Draggable> |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Task; |
@ -0,0 +1,912 @@ |
|||||||
|
import React, { Fragment, useEffect, useMemo, useState } from 'react'; |
||||||
|
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'; |
||||||
|
import { |
||||||
|
Row, |
||||||
|
Col, |
||||||
|
Button, |
||||||
|
Tooltip, |
||||||
|
Popover, |
||||||
|
Select |
||||||
|
} from 'antd'; |
||||||
|
import { Card, CardBody, CardHeader, Input } from "reactstrap"; |
||||||
|
|
||||||
|
import './Kanban.css'; |
||||||
|
import Column from './Column'; |
||||||
|
import styled from 'styled-components' |
||||||
|
import { |
||||||
|
PlusOutlined |
||||||
|
} from '@ant-design/icons'; |
||||||
|
import { BASE_SIMPRO_LUMEN, VERSION_GANTT_SEARCH, KANBAN_BOARD_LIST, KANBAN_BOARD_ADD, KANBAN_BOARD_DELETE, KANBAN_BOARD_EDIT, KANBAN_CARD_LIST, KANBAN_CARD_ADD, KANBAN_CARD_EDIT, USER_TO_ACTIVITY_ADD, HUMAN_RESOURCE_LIST, USER_TO_ACTIVITY_DELETE, PROYEK_SEARCH } from '../../../const/ApiConst'; |
||||||
|
import axios from "../../../const/interceptorApi"; |
||||||
|
import { |
||||||
|
NotificationContainer, |
||||||
|
NotificationManager |
||||||
|
} from "react-notifications"; |
||||||
|
import { array } from 'prop-types'; |
||||||
|
import DialogFormBoard from './DialogFormBoard'; |
||||||
|
import DialogFormActivity from './DialogFormActivity'; |
||||||
|
import DialogFormChild from './DialogFormChild'; |
||||||
|
import DialogFormReport from './DialogFormReport'; |
||||||
|
import SweetAlert from 'react-bootstrap-sweetalert'; |
||||||
|
import { useParams, useHistory } from "react-router-dom"; |
||||||
|
import moment from 'moment'; |
||||||
|
const Container = styled.div` |
||||||
|
display: flex; |
||||||
|
` |
||||||
|
|
||||||
|
const { Option } = Select; |
||||||
|
|
||||||
|
const finalSpaceCharacters = [ |
||||||
|
{ |
||||||
|
id: 'gary', |
||||||
|
name: 'Gary Goodspeed', |
||||||
|
thumb: '/images/gary.png' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 'garyd', |
||||||
|
name: 'Gary Goodspeedg', |
||||||
|
thumb: '/images/gary.png' |
||||||
|
}, |
||||||
|
] |
||||||
|
|
||||||
|
const initialData = { |
||||||
|
columns: [ |
||||||
|
|
||||||
|
], |
||||||
|
} |
||||||
|
|
||||||
|
let hierarchy = []; |
||||||
|
hierarchy.push(JSON.parse(localStorage.getItem("hierarchy"))); |
||||||
|
const role_id = localStorage.getItem("role_id"); |
||||||
|
|
||||||
|
const Kanban = ({ params, ...props }) => { |
||||||
|
let history = useHistory(); |
||||||
|
const token = localStorage.getItem("token"); |
||||||
|
const sessionLogin = localStorage.getItem("user_id"); |
||||||
|
|
||||||
|
const HEADER = { |
||||||
|
headers: { |
||||||
|
"Content-Type": "application/json", |
||||||
|
Authorization: `Bearer ${token}`, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
const { proyek_id, version_gantt_id } = useParams(); |
||||||
|
const [characters, updateCharacters] = useState(finalSpaceCharacters); |
||||||
|
const [stateKanban, setStateKanban] = useState(initialData); |
||||||
|
const [kanbanBoard, setKanbanBoard] = useState([]); |
||||||
|
const [kanbanCard, setKanbanCard] = useState([]); |
||||||
|
const [alertDelete, setAlertDelete] = useState(false) |
||||||
|
const [alertDeleteCard, setAlertDeleteCard] = useState(false) |
||||||
|
const [idDelete, setIdDelete] = useState(0) |
||||||
|
const [idDeleteCard, setIdDeleteCard] = useState(0) |
||||||
|
const [project, setProject] = useState(!proyek_id ? '' : proyek_id) |
||||||
|
const [versionGantt, setVersionGantt] = useState(!version_gantt_id ? 0 : version_gantt_id) |
||||||
|
//
|
||||||
|
const [openDialogBoard, setOpenDialogBoard] = useState(false) |
||||||
|
const [typeDialogBoard, setTypeDialogBoard] = useState('') |
||||||
|
const [clickOpenModalBoard, setClickOpenModalBoard] = useState(false) |
||||||
|
const [openDialogActivity, setOpenDialogActivity] = useState(false) |
||||||
|
const [openDialogReport, setOpenDialogReport] = useState(false) |
||||||
|
const [typeDialogActivity, setTypeDialogActivity] = useState('Save') |
||||||
|
// report
|
||||||
|
|
||||||
|
const [typeDialogReport, setTypeDialogReport] = useState('Save') |
||||||
|
const [clickOpenModalActivity, setClickOpenModalActivity] = useState(false) |
||||||
|
const [openDialogChild, setOpenDialogChild] = useState(false) |
||||||
|
const [typeDialogChild, setTypeDialogChild] = useState('Save') |
||||||
|
const [clickOpenModalChild, setClickOpenModalChild] = useState(false) |
||||||
|
const [open, setOpen] = useState(false); |
||||||
|
const [dataEditBoard, setDataEditBoard] = useState([]) |
||||||
|
const [dataEditCard, setDataEditCard] = useState([]) |
||||||
|
const [idBoard, setIdBoard] = useState(0) |
||||||
|
const [loadingCard, setLoadingCard] = useState(false) |
||||||
|
const [dataHr, setDataHr] = useState([]); |
||||||
|
const [dataProyek, setDataProyek] = useState([]) |
||||||
|
const [dataVersionGantt, setDataVersionGantt] = useState([]) |
||||||
|
const [optionProyek, setOptionProyek] = useState([]) |
||||||
|
const [optionGantt, setOptionGantt] = useState([]) |
||||||
|
const [activityProject, setActivityProject] = useState(null) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
handleGetDataHr() |
||||||
|
}, [project]) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
getDataProyek() |
||||||
|
if (project && versionGantt) { |
||||||
|
getDataGantt(parseInt(project)) |
||||||
|
getActivityProject() |
||||||
|
getDataKanbanBoard() |
||||||
|
} |
||||||
|
}, [project, versionGantt]) |
||||||
|
|
||||||
|
const getActivityProject = async () => { |
||||||
|
const url = `${BASE_SIMPRO_LUMEN}/activity/${versionGantt}/${project}/get` |
||||||
|
const result = await axios |
||||||
|
.get(url, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response) |
||||||
|
|
||||||
|
if (result && result.data.data.length > 0) { |
||||||
|
result.data.data.map((item) => { |
||||||
|
if (item.type_activity == "project") { |
||||||
|
setActivityProject(item.id) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const getDataKanbanBoard = async () => { |
||||||
|
const url = `${KANBAN_BOARD_LIST}?start=0&length=-1&orderby=id&asc=true&column=version_gantt_id&value=${versionGantt}&logic==`; |
||||||
|
const result = await axios |
||||||
|
.get(url, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (!result || result.data.data.length == 0) { |
||||||
|
|
||||||
|
const data = [ |
||||||
|
{ |
||||||
|
name_board: 'TODO LIST', |
||||||
|
status_progress: 'open', |
||||||
|
header_color: "#9EE5FF", |
||||||
|
body_color: "#112A46", |
||||||
|
proyek_id: project, |
||||||
|
version_gantt_id: versionGantt |
||||||
|
}, |
||||||
|
{ |
||||||
|
name_board: 'DOING', |
||||||
|
status_progress: 'on-progress', |
||||||
|
header_color: "#D9D4FD", |
||||||
|
body_color: "#112A46", |
||||||
|
proyek_id: project, |
||||||
|
version_gantt_id: versionGantt |
||||||
|
}, |
||||||
|
{ |
||||||
|
name_board: 'TESTING', |
||||||
|
status_progress: 'none', |
||||||
|
header_color: "#FAD4FC", |
||||||
|
body_color: "#112A46", |
||||||
|
proyek_id: project, |
||||||
|
version_gantt_id: versionGantt |
||||||
|
}, |
||||||
|
{ |
||||||
|
name_board: 'DONE', |
||||||
|
status_progress: 'done', |
||||||
|
header_color: "#ADE7BF", |
||||||
|
body_color: "#112A46", |
||||||
|
proyek_id: project, |
||||||
|
version_gantt_id: versionGantt |
||||||
|
} |
||||||
|
]; |
||||||
|
for (let i = 0; i < data.length; i++) { |
||||||
|
const formData = data[i]; |
||||||
|
const result = await axios.post(KANBAN_BOARD_ADD, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataKanbanBoard() |
||||||
|
NotificationManager.success(`Data berhasil ditambah`, 'Success!!'); |
||||||
|
} else { |
||||||
|
NotificationManager.error(`${result.data.message}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (result && result.data && result.data.code == 200) { |
||||||
|
let countColumns = 0; |
||||||
|
const results = result.data.data; |
||||||
|
for (let i = results.length - 1; i >= 0; i--) { |
||||||
|
const res = results[i]; |
||||||
|
res.key = res.id.toString() |
||||||
|
res.tasks = [] |
||||||
|
await getDataKanbanCard(res.id).then(function (task) { |
||||||
|
if (task !== false) { |
||||||
|
task.map((e) => { |
||||||
|
e.id = e.id.toString() |
||||||
|
e.persentase_progress = e.persentase_progress ? e.persentase_progress : 0; |
||||||
|
res.tasks.push(e); |
||||||
|
}); |
||||||
|
} |
||||||
|
}) |
||||||
|
countColumns += 1; |
||||||
|
|
||||||
|
if (result.data.data.length === countColumns) { |
||||||
|
let newState = { |
||||||
|
...stateKanban, |
||||||
|
columns: [ |
||||||
|
...result.data.data, |
||||||
|
] |
||||||
|
} |
||||||
|
|
||||||
|
setStateKanban(newState) |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
setLoadingCard(false) |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
} else { |
||||||
|
NotificationManager.error('Gagal Mengambil Data!!', 'Failed'); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
const getDataProyek = async () => { |
||||||
|
let start = 0; |
||||||
|
|
||||||
|
const payload = { |
||||||
|
columns: [ |
||||||
|
{ |
||||||
|
name: "created_by", |
||||||
|
logic_operator: "IN", |
||||||
|
value: hierarchy, |
||||||
|
operator: "AND" |
||||||
|
} |
||||||
|
], |
||||||
|
joins: [ |
||||||
|
{ |
||||||
|
name: "m_users", |
||||||
|
column_join: "pm_id", |
||||||
|
column_results: ["name", "username"], |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "m_type_proyek", |
||||||
|
column_join: "type_proyek_id", |
||||||
|
column_results: ["name", "description"], |
||||||
|
}, |
||||||
|
], |
||||||
|
orders: { columns: ["id"], ascending: false }, |
||||||
|
}; |
||||||
|
|
||||||
|
if (parseInt(role_id) !== 1) { |
||||||
|
payload["columns"] = [ |
||||||
|
{ name: "id", logic_operator: "=", value: project, operator: "AND" }, |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
const result = await axios |
||||||
|
.post(PROYEK_SEARCH, payload, HEADER) |
||||||
|
.then((res) => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code == 200) { |
||||||
|
let dataRes = result.data.data || []; |
||||||
|
let dataTemp = [] |
||||||
|
dataRes.map(n => { |
||||||
|
if (n.id > 0 && n.nama.trim() !== "") { |
||||||
|
let obj = { |
||||||
|
key: n.id, |
||||||
|
value: n.id, |
||||||
|
label: n.nama.trim() |
||||||
|
} |
||||||
|
dataTemp.push(obj) |
||||||
|
} |
||||||
|
}) |
||||||
|
setOptionProyek(dataTemp); |
||||||
|
setDataProyek(dataRes); |
||||||
|
} else { |
||||||
|
NotificationManager.error("Gagal Mengambil Data!!", "Failed"); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const getDataGantt = async (id) => { |
||||||
|
const payload = { |
||||||
|
columns: [ |
||||||
|
{ |
||||||
|
name: "proyek_id", |
||||||
|
logic_operator: "=", |
||||||
|
value: id, |
||||||
|
operator: "AND", |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
const result = await axios |
||||||
|
.post(VERSION_GANTT_SEARCH, payload, HEADER) |
||||||
|
.then((res) => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.status == 200) { |
||||||
|
let dataRes = result.data.data || []; |
||||||
|
let dataTemp = [] |
||||||
|
dataRes.map(n => { |
||||||
|
if (n.id > 0 && n.name_version.trim() !== "") { |
||||||
|
let obj = { |
||||||
|
key: n.id, |
||||||
|
value: n.id, |
||||||
|
label: n.name_version |
||||||
|
} |
||||||
|
dataTemp.push(obj) |
||||||
|
} |
||||||
|
}) |
||||||
|
setOptionGantt(dataTemp); |
||||||
|
setDataVersionGantt(dataRes); |
||||||
|
|
||||||
|
} else { |
||||||
|
NotificationManager.error( |
||||||
|
`Data gantt project gagal terload silahkan coba lagi!`, |
||||||
|
"Failed!!" |
||||||
|
); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const getDataKanbanCard = async (id) => { |
||||||
|
const url = `${KANBAN_CARD_LIST}/${project}/${versionGantt}/${id}?session=${sessionLogin}`; |
||||||
|
const result = await axios |
||||||
|
.get(url, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
|
||||||
|
if (result.data.status === "empty") { |
||||||
|
return false |
||||||
|
} else { |
||||||
|
return result.data.data |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function handleOnDragEnd(result) { |
||||||
|
if (!result.destination) return; |
||||||
|
|
||||||
|
const items = Array.from(characters); |
||||||
|
const [reorderedItem] = items.splice(result.source.index, 1); |
||||||
|
items.splice(result.destination.index, 0, reorderedItem); |
||||||
|
|
||||||
|
updateCharacters(items); |
||||||
|
} |
||||||
|
|
||||||
|
const onChangeProject = (val) => { |
||||||
|
setProject(val); |
||||||
|
getDataGantt(val); |
||||||
|
setVersionGantt(''); |
||||||
|
}; |
||||||
|
|
||||||
|
const onChangeGantt = async (val) => { |
||||||
|
setVersionGantt(val); |
||||||
|
if (project) { |
||||||
|
history.push(`/kanban/${project}/${val}`); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
function onDragEnd(result) { |
||||||
|
const { destination, source, draggableId } = result |
||||||
|
|
||||||
|
|
||||||
|
if (!destination) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if ( |
||||||
|
destination.droppableId === source.droppableId && |
||||||
|
destination.index === source.index |
||||||
|
) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const start = source.droppableId; |
||||||
|
const finish = destination.droppableId; |
||||||
|
|
||||||
|
if (start != finish) { |
||||||
|
|
||||||
|
const data = { |
||||||
|
"kanban_board_id": destination.droppableId, |
||||||
|
} |
||||||
|
|
||||||
|
setLoadingCard(true) |
||||||
|
|
||||||
|
editActivity(data, draggableId) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
const saveBoard = async (data) => { |
||||||
|
const formData = data |
||||||
|
|
||||||
|
const result = await axios.post(KANBAN_BOARD_ADD, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
NotificationManager.success(`Data berhasil ditambah`, 'Success!!'); |
||||||
|
getDataKanbanBoard() |
||||||
|
} else { |
||||||
|
NotificationManager.error('Status Open Progress Done Hanya 1', 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const editBoard = async (data) => { |
||||||
|
let urlEdit = KANBAN_BOARD_EDIT(data.id) |
||||||
|
|
||||||
|
const formData = data |
||||||
|
const result = await axios.put(urlEdit, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataKanbanBoard() |
||||||
|
NotificationManager.success(`Data berhasil diedit`, 'Success!!'); |
||||||
|
} else { |
||||||
|
NotificationManager.error(`Data gagal di edit`, `Failed!!`); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Board
|
||||||
|
|
||||||
|
const handleCloseDialogBoard = (type, data) => { |
||||||
|
if (type === "save") { |
||||||
|
saveBoard(data); |
||||||
|
} else if (type === "edit") { |
||||||
|
editBoard(data); |
||||||
|
} |
||||||
|
setOpenDialogBoard(false) |
||||||
|
} |
||||||
|
|
||||||
|
const toggleDialogBoard = () => { |
||||||
|
setOpenDialogBoard(!openDialogBoard) |
||||||
|
} |
||||||
|
|
||||||
|
const handleOpenDialogBoard = (type) => { |
||||||
|
setOpenDialogBoard(true) |
||||||
|
setTypeDialogBoard(type) |
||||||
|
} |
||||||
|
|
||||||
|
const saveReport = async (data, dataHrSelect) => { |
||||||
|
setLoadingCard(true) |
||||||
|
var formData = new FormData(); |
||||||
|
formData.set('report_date', moment(data.report_date).format("YYYY-MM-DD")); |
||||||
|
formData.set('job_count_report', data.jumlah_pekerjaan); |
||||||
|
formData.set('user_id', dataHrSelect.id); |
||||||
|
formData.set('gantt', true); |
||||||
|
formData.set('activity_id', data.activity_id); |
||||||
|
formData.set('description', data.description); |
||||||
|
const result = await axios |
||||||
|
.post(`${BASE_SIMPRO_LUMEN}/report-activity/add`, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataKanbanBoard() |
||||||
|
NotificationManager.success(`Data berhasil ditambah`, 'Success!!'); |
||||||
|
} else { |
||||||
|
setLoadingCard(false) |
||||||
|
NotificationManager.error(`${result.data.message}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const saveCard = async (data, dataHrSelect) => { |
||||||
|
setLoadingCard(true) |
||||||
|
|
||||||
|
const formData = data |
||||||
|
const result = await axios.post(KANBAN_CARD_ADD, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
dataHrSelect.map((item) => { |
||||||
|
let dataSaveHr = { |
||||||
|
"user_id": item.id, |
||||||
|
"role_proyek_id": item.proyek_role, |
||||||
|
"version_gantt_id": version_gantt_id, |
||||||
|
"proyek_id": proyek_id, |
||||||
|
"activity_id": result.data.tid |
||||||
|
} |
||||||
|
userToActivityAdd(dataSaveHr) |
||||||
|
}) |
||||||
|
NotificationManager.success(`Data berhasil ditambah`, 'Success!!'); |
||||||
|
} else { |
||||||
|
setLoadingCard(false) |
||||||
|
NotificationManager.error(`${result.data.message}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const editCard = async (data, id) => { |
||||||
|
setLoadingCard(true) |
||||||
|
const url = `${KANBAN_CARD_ADD}/${id}` |
||||||
|
const formData = data |
||||||
|
const result = await axios.put(url, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataKanbanBoard() |
||||||
|
NotificationManager.success(`Data berhasil diubah`, 'Success!!'); |
||||||
|
} else { |
||||||
|
NotificationManager.error(`${result.data.message}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const userToActivityAdd = async (data) => { |
||||||
|
setLoadingCard(true) |
||||||
|
|
||||||
|
const formData = data |
||||||
|
const result = await axios.post(USER_TO_ACTIVITY_ADD, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataKanbanBoard() |
||||||
|
NotificationManager.success(`Data berhasil ditambah`, 'Success!!'); |
||||||
|
} else { |
||||||
|
setLoadingCard(false) |
||||||
|
NotificationManager.error(`${result.data.message}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const userToActivityDelete = async (id) => { |
||||||
|
setLoadingCard(true) |
||||||
|
|
||||||
|
const url = USER_TO_ACTIVITY_DELETE(id) |
||||||
|
const result = await axios.delete(url, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataKanbanBoard() |
||||||
|
NotificationManager.success(`Data berhasil dihapus`, 'Success!!'); |
||||||
|
} else { |
||||||
|
setLoadingCard(false) |
||||||
|
NotificationManager.error(`${result.data.message}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
// Activity
|
||||||
|
|
||||||
|
const handleCloseDialogActivity = (type, data, dataHrSelect, id) => { |
||||||
|
if (type === "save") { |
||||||
|
saveCard(data, dataHrSelect) |
||||||
|
} else if (type == "edit") { |
||||||
|
editCard(data, id) |
||||||
|
} |
||||||
|
setOpenDialogActivity(false) |
||||||
|
} |
||||||
|
|
||||||
|
const toggleAddDialogActivity = () => { |
||||||
|
setOpenDialogActivity(!openDialogActivity) |
||||||
|
} |
||||||
|
|
||||||
|
const handleOpenDialogActivity = (type, idBoard) => { |
||||||
|
setOpenDialogActivity(true) |
||||||
|
setTypeDialogActivity(type) |
||||||
|
setIdBoard(idBoard) |
||||||
|
} |
||||||
|
|
||||||
|
// Report
|
||||||
|
|
||||||
|
const handleCloseDialogReport = (type, data, dataHrSelect) => { |
||||||
|
if (type === "Save") { |
||||||
|
saveReport(data, dataHrSelect) |
||||||
|
} else if(type === "Delete") { |
||||||
|
setLoadingCard(true); |
||||||
|
getDataKanbanBoard(); |
||||||
|
} else { |
||||||
|
setOpenDialogReport(false) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const handleOpenDialogReport = (type) => { |
||||||
|
setOpenDialogReport(true) |
||||||
|
setTypeDialogReport(type) |
||||||
|
} |
||||||
|
|
||||||
|
const editActivity = async (data, id) => { |
||||||
|
let urlEdit = KANBAN_CARD_EDIT(id) |
||||||
|
|
||||||
|
const formData = data |
||||||
|
const result = await axios.put(urlEdit, formData, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataKanbanBoard() |
||||||
|
NotificationManager.success(`Data berhasil diedit`, 'Success!!'); |
||||||
|
} else { |
||||||
|
NotificationManager.error(`Data gagal di edit`, `Failed!!`); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Child
|
||||||
|
|
||||||
|
const handleCloseDialogChild = (type, data) => { |
||||||
|
if (type === "save") { |
||||||
|
// saveItem(data);
|
||||||
|
} |
||||||
|
setOpenDialogChild(false) |
||||||
|
} |
||||||
|
|
||||||
|
const toggleAddDialogChild = () => { |
||||||
|
setOpenDialogChild(!openDialogChild) |
||||||
|
} |
||||||
|
|
||||||
|
const handleOpenDialogChild = (type) => { |
||||||
|
setOpenDialogChild(true) |
||||||
|
setTypeDialogChild(type) |
||||||
|
} |
||||||
|
|
||||||
|
const onConfirmDelete = async () => { |
||||||
|
let url = KANBAN_BOARD_DELETE(idDelete); |
||||||
|
|
||||||
|
const result = await axios.delete(url, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
getDataKanbanBoard() |
||||||
|
setIdDelete(0) |
||||||
|
setAlertDelete(false) |
||||||
|
NotificationManager.success(`Data berhasil dihapus!`, 'Success!!'); |
||||||
|
} else { |
||||||
|
setIdDelete(0) |
||||||
|
setAlertDelete(false) |
||||||
|
NotificationManager.error(`Data gagal dihapus!}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const cancelDelete = () => { |
||||||
|
setAlertDelete(false) |
||||||
|
} |
||||||
|
|
||||||
|
const handleDelete = async (id) => { |
||||||
|
await setAlertDelete(true) |
||||||
|
setIdDelete(id) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
const handleEditBoard = (data) => { |
||||||
|
setDataEditBoard(data) |
||||||
|
handleOpenDialogBoard('Edit'); |
||||||
|
} |
||||||
|
|
||||||
|
const handleGetDataHr = async () => { |
||||||
|
let urlList = `${HUMAN_RESOURCE_LIST}/select?idProyek=${project}&sessionLogin=${sessionLogin}` |
||||||
|
const result = await axios |
||||||
|
.get(urlList, HEADER) |
||||||
|
.then((res) => res) |
||||||
|
.catch((err) => err.response); |
||||||
|
|
||||||
|
|
||||||
|
if (result.status === 200) { |
||||||
|
setDataHr(result.data) |
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
const handleDeleteCard = async (id) => { |
||||||
|
await setAlertDeleteCard(true) |
||||||
|
setIdDeleteCard(id) |
||||||
|
} |
||||||
|
|
||||||
|
const onConfirmDeleteCard = async () => { |
||||||
|
setAlertDeleteCard(false) |
||||||
|
setLoadingCard(true) |
||||||
|
|
||||||
|
const url = `${KANBAN_CARD_ADD}/${idDeleteCard}` |
||||||
|
|
||||||
|
const result = await axios.delete(url, HEADER) |
||||||
|
.then(res => res) |
||||||
|
.catch((error) => error.response); |
||||||
|
|
||||||
|
if (result && result.data && result.data.code === 200) { |
||||||
|
setIdDeleteCard(0) |
||||||
|
getDataKanbanBoard() |
||||||
|
NotificationManager.success(`Data berhasil dihapus!`, 'Success!!'); |
||||||
|
} else { |
||||||
|
setIdDeleteCard(0) |
||||||
|
NotificationManager.error(`Data gagal dihapus!}`, 'Failed!!'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const cancelDeleteCard = () => { |
||||||
|
setAlertDeleteCard(false) |
||||||
|
} |
||||||
|
|
||||||
|
const handleEditCard = (data) => { |
||||||
|
setDataEditCard(data) |
||||||
|
handleOpenDialogActivity('Edit'); |
||||||
|
} |
||||||
|
const setupSelectVersionGantt = () => { |
||||||
|
return ( |
||||||
|
<> |
||||||
|
{dataVersionGantt.map((val, index) => { |
||||||
|
return ( |
||||||
|
<Option key={index} value={val.id}>{val.name_version}</Option> |
||||||
|
) |
||||||
|
})} |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const setupSelectDataProyek = () => { |
||||||
|
return ( |
||||||
|
<> |
||||||
|
{dataProyek.map((val, index) => { |
||||||
|
return ( |
||||||
|
<Option key={index} value={val.id}>{val.nama}</Option> |
||||||
|
) |
||||||
|
})} |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const RenderStateKanban = useMemo(() => { |
||||||
|
return (<> |
||||||
|
{ |
||||||
|
stateKanban.columns.map((column) => { |
||||||
|
|
||||||
|
return <Column |
||||||
|
key={column.id} |
||||||
|
column={column} |
||||||
|
tasks={column.tasks} |
||||||
|
handleOpenDialogBoard={handleOpenDialogBoard} |
||||||
|
handleOpenDialogActivity={handleOpenDialogActivity} |
||||||
|
handleOpenDialogChild={handleOpenDialogChild} |
||||||
|
handleDelete={handleDelete} |
||||||
|
handleDeleteCard={handleDeleteCard} |
||||||
|
handleEditBoard={handleEditBoard} |
||||||
|
loadingCard={loadingCard} |
||||||
|
handleEditCard={handleEditCard} |
||||||
|
/> |
||||||
|
}) |
||||||
|
} |
||||||
|
</>) |
||||||
|
}, [stateKanban, loadingCard]) |
||||||
|
|
||||||
|
const RenderDialogFormActivity = useMemo( |
||||||
|
() => ( |
||||||
|
<DialogFormActivity |
||||||
|
activityProject={activityProject} |
||||||
|
openDialogActivity={openDialogActivity} |
||||||
|
closeDialogActivity={handleCloseDialogActivity} |
||||||
|
handleOpenDialogReport={handleOpenDialogReport} |
||||||
|
toggleDialogActivity={() => toggleAddDialogActivity} |
||||||
|
typeDialogActivity={typeDialogActivity} |
||||||
|
clickOpenModalActivity={clickOpenModalActivity} |
||||||
|
proyek_id={project} |
||||||
|
version_gantt_id={versionGantt} |
||||||
|
idBoard={idBoard} |
||||||
|
dataHr={dataHr} |
||||||
|
dataEditCard={dataEditCard} |
||||||
|
userToActivityAdd={userToActivityAdd} |
||||||
|
userToActivityDelete={userToActivityDelete} |
||||||
|
/> |
||||||
|
), |
||||||
|
[openDialogActivity] |
||||||
|
); |
||||||
|
const RenderDialogFormReport = useMemo( |
||||||
|
() => ( |
||||||
|
<DialogFormReport |
||||||
|
activityProject={activityProject} |
||||||
|
openDialogReport={openDialogReport} |
||||||
|
closeDialogReport={handleCloseDialogReport} |
||||||
|
typeDialogReport={typeDialogReport} |
||||||
|
clickOpenModalReport={clickOpenModalActivity} |
||||||
|
proyek_id={proyek_id} |
||||||
|
version_gantt_id={version_gantt_id} |
||||||
|
idBoard={idBoard} |
||||||
|
dataHr={dataHr} |
||||||
|
dataEditCard={dataEditCard} |
||||||
|
userToActivityAdd={userToActivityAdd} |
||||||
|
userToActivityDelete={userToActivityDelete} |
||||||
|
/> |
||||||
|
), |
||||||
|
[openDialogReport] |
||||||
|
); |
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<NotificationContainer /> |
||||||
|
<SweetAlert |
||||||
|
show={alertDelete} |
||||||
|
warning |
||||||
|
showCancel |
||||||
|
confirmBtnText="Delete" |
||||||
|
confirmBtnBsStyle="danger" |
||||||
|
title={`Are you sure?`} |
||||||
|
onConfirm={onConfirmDelete} |
||||||
|
onCancel={() => cancelDelete()} |
||||||
|
focusCancelBtn |
||||||
|
> |
||||||
|
Delete this data |
||||||
|
</SweetAlert> |
||||||
|
<SweetAlert |
||||||
|
show={alertDeleteCard} |
||||||
|
warning |
||||||
|
showCancel |
||||||
|
confirmBtnText="Delete" |
||||||
|
confirmBtnBsStyle="danger" |
||||||
|
title={`Are you sure?`} |
||||||
|
onConfirm={onConfirmDeleteCard} |
||||||
|
onCancel={() => cancelDeleteCard()} |
||||||
|
focusCancelBtn |
||||||
|
> |
||||||
|
Delete this data |
||||||
|
</SweetAlert> |
||||||
|
<DialogFormBoard |
||||||
|
openDialogBoard={openDialogBoard} |
||||||
|
closeDialogBoard={handleCloseDialogBoard} |
||||||
|
toggleDialogBoard={() => toggleDialogBoard} |
||||||
|
typeDialogBoard={typeDialogBoard} |
||||||
|
clickOpenModalBoard={clickOpenModalBoard} |
||||||
|
dataEditBoard={dataEditBoard} |
||||||
|
proyek_id={project} |
||||||
|
version_gantt_id={versionGantt} |
||||||
|
/> |
||||||
|
{RenderDialogFormActivity} |
||||||
|
{RenderDialogFormReport} |
||||||
|
<DialogFormChild |
||||||
|
openDialogChild={openDialogChild} |
||||||
|
closeDialogChild={handleCloseDialogChild} |
||||||
|
toggleDialogChild={() => toggleAddDialogChild} |
||||||
|
typeDialogChild={typeDialogChild} |
||||||
|
clickOpenModalChild={clickOpenModalChild} |
||||||
|
/> |
||||||
|
<div> |
||||||
|
<Card> |
||||||
|
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}> |
||||||
|
<h4 className="capitalize">Kanban</h4> |
||||||
|
<Row> |
||||||
|
<Col> |
||||||
|
<Select |
||||||
|
showSearch |
||||||
|
filterOption={(input, option) => ( |
||||||
|
option?.children ?? '').toLowerCase().includes(input.toLowerCase() |
||||||
|
)} |
||||||
|
defaultValue={proyek_id ? parseInt(proyek_id) : 'Pilih Project'} |
||||||
|
onChange={onChangeProject} |
||||||
|
style={{ |
||||||
|
width: 200, |
||||||
|
marginRight: 10 |
||||||
|
}} |
||||||
|
// options={optionProyek}
|
||||||
|
> |
||||||
|
{setupSelectDataProyek()} |
||||||
|
</Select> |
||||||
|
<Select |
||||||
|
showSearch |
||||||
|
filterOption={(input, option) => ( |
||||||
|
option?.children ?? '').toLowerCase().includes(input.toLowerCase() |
||||||
|
)} |
||||||
|
defaultValue={version_gantt_id ? parseInt(version_gantt_id) : 'Pilih Gantt'} |
||||||
|
onChange={onChangeGantt} |
||||||
|
style={{ |
||||||
|
width: 200, |
||||||
|
marginRight: 10 |
||||||
|
}} |
||||||
|
// option={optionGantt}
|
||||||
|
> |
||||||
|
{setupSelectVersionGantt()} |
||||||
|
</Select> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</CardHeader> |
||||||
|
</Card> |
||||||
|
{project != "" && versionGantt != 0 ? ( |
||||||
|
<> |
||||||
|
<Row gutter={16}> |
||||||
|
<Col className="gutter-row" span={6}> |
||||||
|
<div className='board-add' onClick={() => handleOpenDialogBoard("Save")} > |
||||||
|
<div className='title-board-add'> |
||||||
|
<div> |
||||||
|
+ Add Board |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
<Row gutter={16} className='body'> |
||||||
|
<DragDropContext onDragEnd={onDragEnd}> |
||||||
|
{RenderStateKanban} |
||||||
|
</DragDropContext> |
||||||
|
</Row> |
||||||
|
</> |
||||||
|
) : ( |
||||||
|
<p style={{ textAlign: 'center' }}>Please select Project and Gantt Option</p> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
</Fragment> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export default Kanban; |
@ -1,46 +0,0 @@ |
|||||||
import React, { Component } from 'react'; |
|
||||||
import { Card, CardBody, CardHeader, Col, Row, Table } from 'reactstrap'; |
|
||||||
|
|
||||||
import usersData from './UsersData' |
|
||||||
|
|
||||||
class User extends Component { |
|
||||||
|
|
||||||
render() { |
|
||||||
|
|
||||||
const user = usersData.find(user => user.id.toString() === this.props.match.params.id) |
|
||||||
|
|
||||||
const userDetails = user ? Object.entries(user) : [['id', (<span><i className="text-muted icon-ban"></i> Not found</span>)]] |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className="animated fadeIn"> |
|
||||||
<Row> |
|
||||||
<Col lg={6}> |
|
||||||
<Card> |
|
||||||
<CardHeader> |
|
||||||
<strong><i className="icon-info pr-1"></i>User id: {this.props.match.params.id}</strong> |
|
||||||
</CardHeader> |
|
||||||
<CardBody> |
|
||||||
<Table responsive striped hover> |
|
||||||
<tbody> |
|
||||||
{ |
|
||||||
userDetails.map(([key, value]) => { |
|
||||||
return ( |
|
||||||
<tr key={key}> |
|
||||||
<td>{`${key}:`}</td> |
|
||||||
<td><strong>{value}</strong></td> |
|
||||||
</tr> |
|
||||||
) |
|
||||||
}) |
|
||||||
} |
|
||||||
</tbody> |
|
||||||
</Table> |
|
||||||
</CardBody> |
|
||||||
</Card> |
|
||||||
</Col> |
|
||||||
</Row> |
|
||||||
</div> |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default User; |
|
@ -1,15 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import {MemoryRouter} from 'react-router-dom'; |
|
||||||
import { mount } from 'enzyme' |
|
||||||
import User from './User'; |
|
||||||
|
|
||||||
|
|
||||||
it('renders without crashing', () => { |
|
||||||
const wrapper = mount( |
|
||||||
<MemoryRouter> |
|
||||||
<User match={{params: {id: "1"}, isExact: true, path: "/users/:id", name: "User details"}}/> |
|
||||||
</MemoryRouter> |
|
||||||
); |
|
||||||
expect(wrapper.containsMatchingElement(<strong>Samppa Nori</strong>)).toEqual(true) |
|
||||||
wrapper.unmount() |
|
||||||
}); |
|
@ -1,78 +0,0 @@ |
|||||||
import React, { Component } from 'react' |
|
||||||
import DataTable from '../../components/DataTableEditDialog' |
|
||||||
import { API_LIST_DATA_USERS, API_INSERT_DATA_USERS, API_UPDATE_DATA_USERS, API_DELETE_DATA_USERS } from '../../const/ApiConst' |
|
||||||
|
|
||||||
const columns = [{ |
|
||||||
dataField: 'id', |
|
||||||
alias: "Id", |
|
||||||
showInput: false, |
|
||||||
type: "number", |
|
||||||
state: 0 |
|
||||||
}, { |
|
||||||
dataField: 'fullname', |
|
||||||
alias: "Fullname", |
|
||||||
showInput: true, |
|
||||||
type: "text", |
|
||||||
state: "" |
|
||||||
}, { |
|
||||||
dataField: 'username', |
|
||||||
alias: "Username", |
|
||||||
showInput: true, |
|
||||||
type: "text", |
|
||||||
state: "" |
|
||||||
}, { |
|
||||||
dataField: 'password', |
|
||||||
alias: "Password", |
|
||||||
showInput: true, |
|
||||||
type: "password", |
|
||||||
state: "" |
|
||||||
}, { |
|
||||||
dataField: 'created_time', |
|
||||||
alias: "Created Time", |
|
||||||
showInput: false, |
|
||||||
type: "text", |
|
||||||
state: "" |
|
||||||
}, { |
|
||||||
dataField: 'modified_time', |
|
||||||
alias: "Modified Time", |
|
||||||
showInput: false, |
|
||||||
type: "text", |
|
||||||
state: "" |
|
||||||
}, { |
|
||||||
dataField: 'created_by', |
|
||||||
alias: "Created By", |
|
||||||
showInput: false, |
|
||||||
type: "text", |
|
||||||
state: "admin" |
|
||||||
}]; |
|
||||||
|
|
||||||
class Users extends Component { |
|
||||||
constructor(props) { |
|
||||||
super(props) |
|
||||||
this.state = { |
|
||||||
columns: null, |
|
||||||
dataTable: [] |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
componentDidMount() { |
|
||||||
} |
|
||||||
|
|
||||||
render() { |
|
||||||
let dataTable = this.state.dataTable |
|
||||||
return ( |
|
||||||
<div> |
|
||||||
<DataTable |
|
||||||
title="User" |
|
||||||
columns={columns} |
|
||||||
urlParamGet={API_LIST_DATA_USERS} |
|
||||||
urlParamInsert={API_INSERT_DATA_USERS} |
|
||||||
urlParamUpdate={API_UPDATE_DATA_USERS} |
|
||||||
urlParamDelete={API_DELETE_DATA_USERS} |
|
||||||
/> |
|
||||||
</div> |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default Users; |
|
@ -1,10 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import ReactDOM from 'react-dom'; |
|
||||||
import { MemoryRouter } from 'react-router-dom'; |
|
||||||
import Users from './Users'; |
|
||||||
|
|
||||||
it('renders without crashing', () => { |
|
||||||
const div = document.createElement('div'); |
|
||||||
ReactDOM.render(<MemoryRouter><Users /></MemoryRouter>, div); |
|
||||||
ReactDOM.unmountComponentAtNode(div); |
|
||||||
}); |
|
@ -1,31 +0,0 @@ |
|||||||
const usersData = [ |
|
||||||
{id: 0, name: 'John Doe', registered: '2018/01/01', role: 'Guest', status: 'Pending'}, |
|
||||||
{id: 1, name: 'Samppa Nori', registered: '2018/01/01', role: 'Member', status: 'Active'}, |
|
||||||
{id: 2, name: 'Estavan Lykos', registered: '2018/02/01', role: 'Staff', status: 'Banned'}, |
|
||||||
{id: 3, name: 'Chetan Mohamed', registered: '2018/02/01', role: 'Admin', status: 'Inactive'}, |
|
||||||
{id: 4, name: 'Derick Maximinus', registered: '2018/03/01', role: 'Member', status: 'Pending'}, |
|
||||||
{id: 5, name: 'Friderik Dávid', registered: '2018/01/21', role: 'Staff', status: 'Active'}, |
|
||||||
{id: 6, name: 'Yiorgos Avraamu', registered: '2018/01/01', role: 'Member', status: 'Active'}, |
|
||||||
{id: 7, name: 'Avram Tarasios', registered: '2018/02/01', role: 'Staff', status: 'Banned'}, |
|
||||||
{id: 8, name: 'Quintin Ed', registered: '2018/02/01', role: 'Admin', status: 'Inactive'}, |
|
||||||
{id: 9, name: 'Enéas Kwadwo', registered: '2018/03/01', role: 'Member', status: 'Pending'}, |
|
||||||
{id: 10, name: 'Agapetus Tadeáš', registered: '2018/01/21', role: 'Staff', status: 'Active'}, |
|
||||||
{id: 11, name: 'Carwyn Fachtna', registered: '2018/01/01', role: 'Member', status: 'Active'}, |
|
||||||
{id: 12, name: 'Nehemiah Tatius', registered: '2018/02/01', role: 'Staff', status: 'Banned'}, |
|
||||||
{id: 13, name: 'Ebbe Gemariah', registered: '2018/02/01', role: 'Admin', status: 'Inactive'}, |
|
||||||
{id: 14, name: 'Eustorgios Amulius', registered: '2018/03/01', role: 'Member', status: 'Pending'}, |
|
||||||
{id: 15, name: 'Leopold Gáspár', registered: '2018/01/21', role: 'Staff', status: 'Active'}, |
|
||||||
{id: 16, name: 'Pompeius René', registered: '2018/01/01', role: 'Member', status: 'Active'}, |
|
||||||
{id: 17, name: 'Paĉjo Jadon', registered: '2018/02/01', role: 'Staff', status: 'Banned'}, |
|
||||||
{id: 18, name: 'Micheal Mercurius', registered: '2018/02/01', role: 'Admin', status: 'Inactive'}, |
|
||||||
{id: 19, name: 'Ganesha Dubhghall', registered: '2018/03/01', role: 'Member', status: 'Pending'}, |
|
||||||
{id: 20, name: 'Hiroto Šimun', registered: '2018/01/21', role: 'Staff', status: 'Active'}, |
|
||||||
{id: 21, name: 'Vishnu Serghei', registered: '2018/01/01', role: 'Member', status: 'Active'}, |
|
||||||
{id: 22, name: 'Zbyněk Phoibos', registered: '2018/02/01', role: 'Staff', status: 'Banned'}, |
|
||||||
{id: 23, name: 'Einar Randall', registered: '2018/02/01', role: 'Admin', status: 'Inactive'}, |
|
||||||
{id: 24, name: 'Félix Troels', registered: '2018/03/21', role: 'Staff', status: 'Active'}, |
|
||||||
{id: 25, name: 'Aulus Agmundr', registered: '2018/01/01', role: 'Member', status: 'Pending'}, |
|
||||||
{id: 42, name: 'Ford Prefex', registered: '2001/05/21', role: 'Alien', status: 'Don\'t panic!'} |
|
||||||
] |
|
||||||
|
|
||||||
export default usersData |
|
Loading…
Reference in new issue