Browse Source

Merge branch 'staging' of https://git.oslog.id/ordo/adw-frontend into dev-wahyu

pull/2/head
wahyu 1 year ago
parent
commit
b88599938c
  1. 284
      package.json
  2. 2
      src/const/ApiConst.js
  3. 12
      src/views/Dashboard/DashboardBOD.js
  4. 55
      src/views/Master/MasterBroadcast/DialogDetail.js
  5. 123
      src/views/Master/MasterBroadcast/index.js
  6. 29
      src/views/Master/MasterMenu/index.js
  7. 12
      src/views/SimproV2/CreatedProyek/AsignCustProject.js
  8. 609
      src/views/SimproV2/CreatedProyek/AsignHrProject.js
  9. 31
      src/views/SimproV2/CreatedProyek/DialogAssignCust.js
  10. 414
      src/views/SimproV2/CreatedProyek/DialogFormProyek.js
  11. 6
      src/views/SimproV2/CreatedProyek/DialogGantt.js
  12. 6
      src/views/SimproV2/CreatedProyek/DialogHierarchy.js
  13. 34
      src/views/SimproV2/CreatedProyek/FormAsignHr.js
  14. 223
      src/views/SimproV2/CreatedProyek/ViewProject.js
  15. 17
      src/views/SimproV2/CreatedProyek/index.js
  16. 63
      src/views/SimproV2/Divisi/DialogForm.js
  17. 46
      src/views/SimproV2/Divisi/InputColor.js
  18. 23
      src/views/SimproV2/Divisi/index.js
  19. 41
      src/views/SimproV2/Divisi/styles.css

284
package.json

@ -1,142 +1,142 @@
{ {
"name": "simpro-web", "name": "simpro-web",
"version": "0.0.1", "version": "0.0.1",
"description": "Sistem Informasi Manajemen Proyek", "description": "Sistem Informasi Manajemen Proyek",
"author": "Ardhi", "author": "Ardhi",
"homepage": ".", "homepage": ".",
"copyright": "Copyright Integrasia Utama", "copyright": "Copyright Integrasia Utama",
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"repository": { "repository": {
"type": "http", "type": "http",
"url": "https://git.oslog.id/iu/simpro-website.git" "url": "https://git.oslog.id/iu/simpro-website.git"
}, },
"dependencies": { "dependencies": {
"@ant-design/plots": "^1.1.1", "@ant-design/plots": "^1.1.1",
"@ckeditor/ckeditor5-build-classic": "^39.0.2", "@ckeditor/ckeditor5-build-classic": "^39.0.2",
"@ckeditor/ckeditor5-react": "^6.1.0", "@ckeditor/ckeditor5-react": "^6.1.0",
"@coreui/coreui": "^2.1.12", "@coreui/coreui": "^2.1.12",
"@coreui/icons": "0.3.0", "@coreui/icons": "0.3.0",
"@coreui/react": "^2.5.1", "@coreui/react": "^2.5.1",
"@dabeng/react-orgchart": "^1.0.0", "@dabeng/react-orgchart": "^1.0.0",
"@develoka/angka-rupiah-js": "^1.0.3", "@develoka/angka-rupiah-js": "^1.0.3",
"@faker-js/faker": "^7.3.0", "@faker-js/faker": "^7.3.0",
"@iconify/icons-ant-design": "^1.0.6", "@iconify/icons-ant-design": "^1.0.6",
"@iconify/icons-fa-solid": "^1.0.6", "@iconify/icons-fa-solid": "^1.0.6",
"@iconify/icons-fe": "^1.0.3", "@iconify/icons-fe": "^1.0.3",
"@iconify/icons-geo": "^1.0.3", "@iconify/icons-geo": "^1.0.3",
"@iconify/icons-ion": "^1.0.7", "@iconify/icons-ion": "^1.0.7",
"@iconify/icons-mdi": "^1.0.57", "@iconify/icons-mdi": "^1.0.57",
"@iconify/icons-uil": "^1.0.6", "@iconify/icons-uil": "^1.0.6",
"@iconify/react": "^1.1.1", "@iconify/react": "^1.1.1",
"@nicholasadamou/react-iframe": "^1.0.3", "@nicholasadamou/react-iframe": "^1.0.3",
"@reduxjs/toolkit": "^1.9.2", "@reduxjs/toolkit": "^1.9.2",
"@terrestris/ol-util": "^7.2.0", "@terrestris/ol-util": "^7.2.0",
"@terrestris/react-geo": "^12.0.0", "@terrestris/react-geo": "^12.0.0",
"alasql": "^1.7.3", "alasql": "^1.7.3",
"antd": "^4.16.13", "antd": "^4.16.13",
"axios": "^0.21.1", "axios": "^0.21.1",
"bootstrap": "^4.3.1", "bootstrap": "^4.3.1",
"chart.js": "^3.9.1", "chart.js": "^3.9.1",
"chartjs-plugin-datalabels": "^2.1.0", "chartjs-plugin-datalabels": "^2.1.0",
"chartjs-plugin-zoom": "^0.7.7", "chartjs-plugin-zoom": "^0.7.7",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"core-js": "^3.1.4", "core-js": "^3.1.4",
"dhtmlx-gantt": "^7.1.7", "dhtmlx-gantt": "^7.1.7",
"dom-to-image": "^2.6.0", "dom-to-image": "^2.6.0",
"enzyme": "^3.10.0", "enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0", "enzyme-adapter-react-16": "^1.14.0",
"flag-icon-css": "^3.3.0", "flag-icon-css": "^3.3.0",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"i18next": "^22.4.9", "i18next": "^22.4.9",
"interactjs": "^1.10.11", "interactjs": "^1.10.11",
"jspdf": "^2.5.1", "jspdf": "^2.5.1",
"jspdf-autotable": "^3.5.25", "jspdf-autotable": "^3.5.25",
"leaflet": "^1.8.0", "leaflet": "^1.8.0",
"leaflet-control-geocoder": "^2.4.0", "leaflet-control-geocoder": "^2.4.0",
"leaflet-draw": "^1.0.4", "leaflet-draw": "^1.0.4",
"leaflet.markercluster": "^1.5.3", "leaflet.markercluster": "^1.5.3",
"moment": "^2.24.0", "moment": "^2.24.0",
"node-sass": "^4.12.0", "node-sass": "^4.12.0",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"ol": "^5.3.3", "ol": "^5.3.3",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"rc-color-picker": "^1.2.6", "rc-color-picker": "^1.2.6",
"re-resizable": "^6.9.9", "re-resizable": "^6.9.9",
"react": "^16.14.0", "react": "^16.14.0",
"react-app-polyfill": "^1.0.1", "react-app-polyfill": "^1.0.1",
"react-awesome-query-builder": "^4.3.0", "react-awesome-query-builder": "^4.3.0",
"react-bootstrap-sweetalert": "^5.1.9", "react-bootstrap-sweetalert": "^5.1.9",
"react-bootstrap-table-next": "^3.3.3", "react-bootstrap-table-next": "^3.3.3",
"react-bootstrap-table2-editor": "^1.4.0", "react-bootstrap-table2-editor": "^1.4.0",
"react-bootstrap-table2-paginator": "^2.1.0", "react-bootstrap-table2-paginator": "^2.1.0",
"react-bootstrap-table2-toolkit": "^2.1.1", "react-bootstrap-table2-toolkit": "^2.1.1",
"react-calendar-timeline": "^0.27.0", "react-calendar-timeline": "^0.27.0",
"react-chartjs-2": "^4.3.1", "react-chartjs-2": "^4.3.1",
"react-color": "^2.17.3", "react-color": "^2.17.3",
"react-content-loader": "^6.0.3", "react-content-loader": "^6.0.3",
"react-dom": "^16.14.0", "react-dom": "^16.14.0",
"react-excel-renderer": "^1.1.0", "react-excel-renderer": "^1.1.0",
"react-grid-layout": "^1.2.5", "react-grid-layout": "^1.2.5",
"react-highlight-words": "^0.18.0", "react-highlight-words": "^0.18.0",
"react-i18next": "^12.1.5", "react-i18next": "^12.1.5",
"react-leaflet": "^3.2.0", "react-leaflet": "^3.2.0",
"react-leaflet-draw": "^0.19.8", "react-leaflet-draw": "^0.19.8",
"react-loader-spinner": "^3.1.5", "react-loader-spinner": "^3.1.5",
"react-notifications": "^1.7.2", "react-notifications": "^1.7.2",
"react-redux": "^8.0.5", "react-redux": "^8.0.5",
"react-router-dom": "^5.0.1", "react-router-dom": "^5.0.1",
"react-select": "^4.3.1", "react-select": "^4.3.1",
"react-slick": "^0.28.1", "react-slick": "^0.28.1",
"react-tiny-fab": "^4.0.4", "react-tiny-fab": "^4.0.4",
"react-toastify": "^5.5.0", "react-toastify": "^5.5.0",
"reactstrap": "^8.0.0", "reactstrap": "^8.0.0",
"redux": "^4.2.1", "redux": "^4.2.1",
"redux-persist": "^6.0.0", "redux-persist": "^6.0.0",
"redux-thunk": "^2.4.2", "redux-thunk": "^2.4.2",
"simple-line-icons": "^2.4.1", "simple-line-icons": "^2.4.1",
"slick-carousel": "^1.8.1", "slick-carousel": "^1.8.1",
"underscore": "^1.13.1", "underscore": "^1.13.1",
"xlsx": "^0.17.0" "xlsx": "^0.17.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.14.5", "@babel/core": "^7.14.5",
"babel-plugin-module-resolver": "^4.1.0", "babel-plugin-module-resolver": "^4.1.0",
"clean-webpack-plugin": "^3.0.0", "clean-webpack-plugin": "^3.0.0",
"cypress": "^12.17.2", "cypress": "^12.17.2",
"react-scripts": "^3.0.1", "react-scripts": "^3.0.1",
"webpack-sources": "1.0.1" "webpack-sources": "1.0.1"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",
"build": "react-scripts --max_old_space_size=8096 build", "build": "react-scripts --max_old_space_size=8096 build",
"test": "react-scripts test", "test": "react-scripts test",
"test:cov": "npm test -- --coverage --watchAll=false", "test:cov": "npm test -- --coverage --watchAll=false",
"test:debug": "react-scripts --inspect-brk test --runInBand", "test:debug": "react-scripts --inspect-brk test --runInBand",
"eject": "react-scripts eject" "eject": "react-scripts eject"
}, },
"bugs": { "bugs": {
"url": "https://git.oslog.id/iu/simpro-website/issues" "url": "https://git.oslog.id/iu/simpro-website/issues"
}, },
"eslintConfig": { "eslintConfig": {
"extends": "react-app" "extends": "react-app"
}, },
"browserslist": [ "browserslist": [
">0.2%", ">0.2%",
"not dead", "not dead",
"not ie <= 9", "not ie <= 9",
"not op_mini all" "not op_mini all"
], ],
"jest": { "jest": {
"collectCoverageFrom": [ "collectCoverageFrom": [
"src/**/*.{js,jsx}", "src/**/*.{js,jsx}",
"!**/*index.js", "!**/*index.js",
"!src/serviceWorker.js", "!src/serviceWorker.js",
"!src/polyfill.js" "!src/polyfill.js"
] ]
}, },
"engines": { "engines": {
"node": ">=8.10", "node": ">=8.10",
"npm": ">=6" "npm": ">=6"
} }
} }

2
src/const/ApiConst.js

@ -316,6 +316,7 @@ export const DOCUMENT_DOWNLOAD = (id) => {
export const ROLE_ADD = `${BASE_SIMPRO_LUMEN}/role/add`; export const ROLE_ADD = `${BASE_SIMPRO_LUMEN}/role/add`;
export const ROLE_SEARCH = `${BASE_SIMPRO_LUMEN}/role/search`; export const ROLE_SEARCH = `${BASE_SIMPRO_LUMEN}/role/search`;
export const ROLE_LIST = `${BASE_SIMPRO_LUMEN}/role/list`;
export const ROLE_EDIT = (id) => { export const ROLE_EDIT = (id) => {
return `${BASE_SIMPRO_LUMEN}/role/update/${id}`; return `${BASE_SIMPRO_LUMEN}/role/update/${id}`;
}; };
@ -340,6 +341,7 @@ export const MENU_MANAGEMENT = (id) => {
return `${BASE_SIMPRO_LUMEN}/menu/management/${id}`; return `${BASE_SIMPRO_LUMEN}/menu/management/${id}`;
}; };
export const MENU_SEARCH = `${BASE_SIMPRO_LUMEN}/menu/search`; export const MENU_SEARCH = `${BASE_SIMPRO_LUMEN}/menu/search`;
export const MENU_LIST = `${BASE_SIMPRO_LUMEN}/menu/list`;
export const MENU_EDIT = (id) => { export const MENU_EDIT = (id) => {
return `${BASE_SIMPRO_LUMEN}/menu/update/${id}`; return `${BASE_SIMPRO_LUMEN}/menu/update/${id}`;
}; };

12
src/views/Dashboard/DashboardBOD.js

@ -244,8 +244,10 @@ const DashboardBOD = () => {
return; return;
} }
if (result.status == 200 && result.data.data) { if (result.status == 200 && result.data.data) {
SET_PROJECT_PER_DIVISION(result.data.data); let dataRes = result.data.data;
const filteredData = dataRes.filter(item => item.parent === null);
SET_PROJECT_PER_DIVISION(filteredData);
} }
SET_READY_PROJECT_PER_DIVISION(true); SET_READY_PROJECT_PER_DIVISION(true);
} }
@ -311,7 +313,7 @@ const DashboardBOD = () => {
planningProgress = item.scurve[0].data.percentagePlan[item.scurve[0].data.percentagePlan.length - 1] planningProgress = item.scurve[0].data.percentagePlan[item.scurve[0].data.percentagePlan.length - 1]
actualProgress = item.scurve[0].data.percentageReal[item.scurve[0].data.percentageReal.length - 1] actualProgress = item.scurve[0].data.percentageReal[item.scurve[0].data.percentageReal.length - 1]
} }
selisihProgress = planningProgress - actualProgress selisihProgress = planningProgress - actualProgress
if (selisihProgress > 0 && selisihProgress <= 5) { if (selisihProgress > 0 && selisihProgress <= 5) {
@ -611,8 +613,8 @@ const DashboardBOD = () => {
label: "", label: "",
// data: [7, 2, 4, 3], // data: [7, 2, 4, 3],
data: PROJECT_PER_DIVISION ? PROJECT_PER_DIVISION.map((item, idx) => item.total) : [], data: PROJECT_PER_DIVISION ? PROJECT_PER_DIVISION.map((item, idx) => item.total) : [],
borderColor: ["#023E8A", "#C851B7", "#FD7034", "#3A0CA3", "#A36A16"], borderColor: PROJECT_PER_DIVISION ? PROJECT_PER_DIVISION.map((item, idx) => item.color) : [],
backgroundColor: ["#023E8A", "#C851B7", "#FD7034", "#3A0CA3", "#A36A16"], backgroundColor: PROJECT_PER_DIVISION ? PROJECT_PER_DIVISION.map((item, idx) => item.color) : [],
borderWidth: 2, borderWidth: 2,
borderSkipped: false borderSkipped: false
}, },

55
src/views/Master/MasterBroadcast/DialogDetail.js

@ -4,7 +4,7 @@ import moment from 'moment';
import { Button, Table, FormFeedback, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { Button, Table, FormFeedback, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
import Select from 'react-select'; import Select from 'react-select';
import axios from 'axios'; import axios from 'axios';
import { BASE_SIMPRO_LUMEN, USER_LIST } from '../../../const/ApiConst'; import { BASE_SIMPRO_LUMEN, USER_LIST, ROLE_LIST } from '../../../const/ApiConst';
import { Transfer } from 'antd'; import { Transfer } from 'antd';
import { withTranslation } from 'react-i18next'; import { withTranslation } from 'react-i18next';
const token = window.localStorage.getItem('token'); const token = window.localStorage.getItem('token');
@ -43,6 +43,7 @@ class DialogDetail extends Component {
}, () => { }, () => {
this.getDataDetail(); this.getDataDetail();
this.getDataUsers(); this.getDataUsers();
this.getDataRoles();
this.setState({ isParentClick: false }); this.setState({ isParentClick: false });
}); });
} }
@ -61,6 +62,18 @@ class DialogDetail extends Component {
} }
} }
getDataRoles = async () => {
const result = await axios
.get(ROLE_LIST, config)
.then(res => res)
.catch((error) => error.response);
console.log('Get Data Roles', result)
if (result && result.data && result.status == 200) {
this.setState({ dataRoles: result.data.data });
}
}
getDataDetail = async () => { getDataDetail = async () => {
countError++; countError++;
let url = BASE_SIMPRO_LUMEN + `/broadcast/search`; let url = BASE_SIMPRO_LUMEN + `/broadcast/search`;
@ -85,6 +98,7 @@ class DialogDetail extends Component {
if (countError < 6) { if (countError < 6) {
this.getDataDetail(); this.getDataDetail();
this.getDataUsers(); this.getDataUsers();
this.getDataRoles();
} }
} }
} }
@ -97,7 +111,10 @@ class DialogDetail extends Component {
this.props.closeDialog() this.props.closeDialog()
} }
render() { render() {
const dataListDetail = this.state.dataListDetail || [];
const dataUser = this.state.dataUser || []; const dataUser = this.state.dataUser || [];
const dataRoles = this.state.dataRoles || [];
return ( return (
<Modal size="xl" isOpen={this.props.openDialog} toggle={this.props.toggleDialog}> <Modal size="xl" isOpen={this.props.openDialog} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.handleCloseDialog}>{this.props.t('broadcastDetail')}</ModalHeader> <ModalHeader toggle={this.handleCloseDialog}>{this.props.t('broadcastDetail')}</ModalHeader>
@ -114,14 +131,42 @@ class DialogDetail extends Component {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{this.state.dataListDetail.map((val, index) => { {dataListDetail.map((val, index) => {
const matchedUser = dataUser.find(item => item.id == val.send_to_id); const matchedUserNames = [];
const matchedUserNamesNotKoma = [];
const matchRolesName = [];
if (typeof val.send_to_id === 'string' && val.send_to_id.includes(',')) {
const sendToIds = val.send_to_id.split(',').map(id => parseInt(id, 10));
matchedUserNames[index] = sendToIds.map(id => {
const matchedUser = dataUser.find(item => item.id === id);
return matchedUser ? <div>{"- " + matchedUser.name}</div> : null;
});
}
if (typeof val.send_to_id === 'string' && val.send_to_id.indexOf(',') === -1) {
const id = parseInt(val.send_to_id, 10);
const matchedUser = dataUser.find(item => item.id === id);
matchedUserNamesNotKoma[index] = matchedUser ? <div>{matchedUser.name}</div> : null;
}
if (val.send_to_type === 'roles') {
const id = parseInt(val.send_to_id, 10);
const matchedRole = dataRoles.find(item => item.id === id);
matchRolesName[index] = matchedRole ? <div><b>Role </b>{matchedRole.name}</div> : null;
}
return ( return (
<tr key={index}> <tr key={index}>
<td>{val.status_send === "" ? "-" : val.status_send}</td> <td>{val.status_send === "" ? "-" : val.status_send}</td>
<td>{val.created_at === "" ? "-" : moment(val.created_date).format("DD-MM-YYYY HH:mm:ss")}</td> <td>{val.created_at === "" ? "-" : moment(val.created_at).format("DD-MM-YYYY HH:mm:ss")}</td>
<td>{val.description === "" ? "-" : val.description}</td> <td>{val.description === "" ? "-" : val.description}</td>
<td>{ matchedUser ? matchedUser.name : "-" }</td> <td>
{val.send_to_type === "all" ? "All User" : ""}
{val.send_to_type === "roles" ? matchRolesName[index] : ""}
{typeof val.send_to_id === 'string' && val.send_to_id.indexOf(',') === -1 ? matchedUserNamesNotKoma[index] : ""}
{typeof val.send_to_id === 'string' && val.send_to_id.includes(',') ? matchedUserNames[index] : ""}
</td>
<td>{val.title_notif === "" ? "-" : val.title_notif}</td> <td>{val.title_notif === "" ? "-" : val.title_notif}</td>
<td>{val.message_notif === "" ? "-" : val.message_notif}</td> <td>{val.message_notif === "" ? "-" : val.message_notif}</td>
</tr> </tr>

123
src/views/Master/MasterBroadcast/index.js

@ -5,7 +5,7 @@ import React, { Component } from 'react';
import SweetAlert from 'react-bootstrap-sweetalert'; import SweetAlert from 'react-bootstrap-sweetalert';
import axios from 'axios'; import axios from 'axios';
import moment from 'moment'; import moment from 'moment';
import { USER_LIST, BASE_SIMPRO_LUMEN } from '../../../const/ApiConst'; import { USER_LIST, BASE_SIMPRO_LUMEN, ROLE_LIST } from '../../../const/ApiConst';
import { Button, Card, CardBody, CardHeader, DropdownItem, DropdownMenu, DropdownToggle, Input, InputGroup, InputGroupButtonDropdown, Table, Row, Col } from 'reactstrap'; import { Button, Card, CardBody, CardHeader, DropdownItem, DropdownMenu, DropdownToggle, Input, InputGroup, InputGroupButtonDropdown, Table, Row, Col } from 'reactstrap';
import { DatePicker, Pagination } from 'antd'; import { DatePicker, Pagination } from 'antd';
import { NotificationContainer, NotificationManager } from 'react-notifications'; import { NotificationContainer, NotificationManager } from 'react-notifications';
@ -92,8 +92,30 @@ class index extends Component {
console.log('Get Data User', result) console.log('Get Data User', result)
if (result && result.data && result.status == 200) { if (result && result.data && result.status == 200) {
this.setState({ dataUser: result.data.data }, () => { const dataRes = result.data.data;
}); const finalData = [];
if (dataRes.length > 0) {
dataRes.map((val, index) => {
let data = {
id: val.id,
name: val.name,
};
finalData.push(data);
});
}
this.setState({ dataUser: finalData });
}
}
getDataRoles = async () => {
const result = await axios
.get(ROLE_LIST, config)
.then(res => res)
.catch((error) => error.response);
console.log('Get Data Roles', result)
if (result && result.data && result.status == 200) {
this.setState({ dataRoles: result.data.data });
} }
} }
@ -147,6 +169,7 @@ class index extends Component {
if (result.data.code === 200) { if (result.data.code === 200) {
this.setState({ dataTable: result.data.data, totalPage: result.data.totalRecord }); this.setState({ dataTable: result.data.data, totalPage: result.data.totalRecord });
this.getDataUsers() this.getDataUsers()
this.getDataRoles()
} else { } else {
NotificationManager.error('Failed retreiving data!!', 'Failed'); NotificationManager.error('Failed retreiving data!!', 'Failed');
} }
@ -326,18 +349,47 @@ class index extends Component {
handleExportExcel = async () => { handleExportExcel = async () => {
const dataExcel = this.state.dataTable || []; const dataExcel = this.state.dataTable || [];
const dataUser = this.state.dataUser || []; const dataUser = this.state.dataUser || [];
const dataRoles = this.state.dataRoles || [];
const dataExport = []; const dataExport = [];
dataExcel.map((val) => { dataExcel.map((val) => {
const matchedUser = dataUser.find(item => item.id == val.send_to_id); const matchedUserNames = [];
const matchedUserNamesNotKoma = [];
const matchRolesName = [];
if (typeof val.send_to_id === 'string' && val.send_to_id.includes(',')) {
const sendToIds = val.send_to_id.split(',').map(id => parseInt(id, 10));
matchedUserNames[index] = sendToIds.map(id => {
const matchedUser = dataUser.find(item => item.id === id);
return matchedUser ? <div>{"- " + matchedUser.name}</div> : null;
});
}
if (typeof val.send_to_id === 'string' && val.send_to_id.indexOf(',') === -1) {
const id = parseInt(val.send_to_id, 10);
const matchedUser = dataUser.find(item => item.id === id);
matchedUserNamesNotKoma[index] = matchedUser ? <div>{matchedUser.name}</div> : null;
}
if (val.send_to_type === 'roles') {
const id = parseInt(val.send_to_id, 10);
const matchedRole = dataRoles.find(item => item.id === id);
matchRolesName[index] = matchedRole ? <div>{matchedRole.name}</div> : null;
}
let row = { let row = {
"Tanggal Broadcast": moment(val.created_at).format("YYYY-MM-DD HH:mm:ss"), "Tanggal Broadcast": moment(val.created_at).format("YYYY-MM-DD HH:mm:ss"),
"Judul": val.title_notif, "Judul": val.title_notif,
"Penerima": matchedUser ? matchedUser.name : "-", "Penerima": (val.send_to_type === "all" ? "All User" : "") +
(val.send_to_type === "roles" ? (matchRolesName[index] ? 'Role: ' + matchRolesName[index].props.children : "") : "") +
(typeof val.send_to_id === 'string' && val.send_to_id.indexOf(',') === -1 ? (matchedUserNamesNotKoma[index] ? matchedUserNamesNotKoma[index].props.children : "") : "") +
(typeof val.send_to_id === 'string' && val.send_to_id.includes(',') ? (matchedUserNames[index] ? matchedUserNames[index].map(item => item.props.children).join("") : "") : ""),
"Pesan": val.message_notif, "Pesan": val.message_notif,
"Deskripsi": val.description, "Deskripsi": val.description,
"Status": val.status_send "Status": val.status_send
} };
dataExport.push(row); dataExport.push(row);
}); });
const fileName = "Broadcast.xlsx"; const fileName = "Broadcast.xlsx";
const ws = XLSX.utils.json_to_sheet(dataExport); const ws = XLSX.utils.json_to_sheet(dataExport);
@ -399,14 +451,37 @@ class index extends Component {
] ]
const dataTable2 = this.state.dataTable || []; const dataTable2 = this.state.dataTable || [];
const dataUser = this.state.dataUser || []; const dataUser = this.state.dataUser || [];
const dataRoles = this.state.dataRoles || [];
return ( return (
<tbody> <tbody>
{dataTable2.length !== 0 ? dataTable2.map((n) => { {dataTable2.length !== 0 ? dataTable2.map((n, index) => {
const matchedUser = dataUser.find(item => item.id == n.send_to_id); const matchedUserNames = [];
return ( const matchedUserNamesNotKoma = [];
<tr key={n.id}> const matchRolesName = [];
<td width={93}>
if (typeof n.send_to_id === 'string' && n.send_to_id.includes(',')) {
const sendToIds = n.send_to_id.split(',').map(id => parseInt(id, 10));
matchedUserNames[index] = sendToIds.map(id => {
const matchedUser = dataUser.find(item => item.id === id);
return matchedUser ? <div>{"- " + matchedUser.name}</div> : null;
});
}
if (typeof n.send_to_id === 'string' && n.send_to_id.indexOf(',') === -1) {
const id = parseInt(n.send_to_id, 10);
const matchedUser = dataUser.find(item => item.id === id);
matchedUserNamesNotKoma[index] = matchedUser ? <div>{matchedUser.name}</div> : null;
}
if (n.send_to_type === 'roles') {
const id = parseInt(n.send_to_id, 10);
const matchedRole = dataRoles.find(item => item.id === id);
matchRolesName[index] = matchedRole ? <div><b>Role </b>{matchedRole.name}</div> : null;
}
return (
<tr key={n.id}>
<td width={93}>
<Row> <Row>
{n.status_send === 'completed' || n.status_send === 'failed' || n.status_send === 'send' || n.status_send === 'resend' ? {n.status_send === 'completed' || n.status_send === 'failed' || n.status_send === 'send' || n.status_send === 'resend' ?
this.renderBtnResend(n.id) : this.renderBtnResend(n.id) :
@ -418,15 +493,21 @@ class index extends Component {
Detail Detail
</Tooltip> </Tooltip>
</Col> </Col>
</Row> </td> </Row>
<td>{n.title_notif}</td> </td>
<td>{n.message_notif !== "" ? n.message_notif : "-"}</td> <td>{n.title_notif}</td>
<td>{n.description !== "" ? n.description : "-"}</td> <td>{n.message_notif !== "" ? n.message_notif : "-"}</td>
<td>{ matchedUser ? matchedUser.name : "-" }</td> <td>{n.description !== "" ? n.description : "-"}</td>
<td>{n.status_send !== "" ? n.status_send : "-"}</td> <td>
<td>{n.created_at !== "" ? moment.utc(n.created_at).format("DD-MM-YYYY HH:mm:ss") : "-"}</td> {n.send_to_type === "all" ? "All User" : ""}
</tr> {n.send_to_type === "roles" ? matchRolesName[index] : ""}
); {typeof n.send_to_id === 'string' && n.send_to_id.indexOf(',') === -1 ? matchedUserNamesNotKoma[index] : ""}
{typeof n.send_to_id === 'string' && n.send_to_id.includes(',') ? matchedUserNames[index] : ""}
</td>
<td>{n.status_send !== "" ? n.status_send : "-"}</td>
<td>{n.created_at !== "" ? moment(n.created_at).format("DD-MM-YYYY HH:mm:ss") : "-"}</td>
</tr>
);
}) : <tr> }) : <tr>
<td colSpan={column.length} align="center">{this.props.t('noData')}</td> <td colSpan={column.length} align="center">{this.props.t('noData')}</td>
</tr> </tr>

29
src/views/Master/MasterMenu/index.js

@ -5,7 +5,7 @@ import SweetAlert from 'react-bootstrap-sweetalert';
import axios from 'axios'; import axios from 'axios';
import { Button } from 'reactstrap'; import { Button } from 'reactstrap';
import { Card, CardBody, CardHeader, Col, Row, Input } from 'reactstrap'; import { Card, CardBody, CardHeader, Col, Row, Input } from 'reactstrap';
import { MENU_ADD, MENU_SEARCH, MENU_EDIT, MENU_DELETE } from '../../../const/ApiConst.js'; import { MENU_ADD, MENU_SEARCH, MENU_EDIT, MENU_DELETE, MENU_LIST } from '../../../const/ApiConst.js';
import { NotificationContainer, NotificationManager } from 'react-notifications'; import { NotificationContainer, NotificationManager } from 'react-notifications';
import { Pagination, Tooltip, Table } from 'antd'; import { Pagination, Tooltip, Table } from 'antd';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -67,23 +67,21 @@ const Index = ({ params }) => {
}; };
const getDataAllMenu = async () => { const getDataAllMenu = async () => {
const payload = {
"paging": { "start": 0, "length": -1 },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": "", "operator": "AND" }
],
"joins": [],
"orders": { "columns": ["id"], "ascending": false }
}
const result = await axios const result = await axios
.post(MENU_SEARCH, payload, config) .get(MENU_LIST, config)
.then(res => res) .then(res => res)
.catch((error) => error.response); .catch((error) => error.response);
if (result && result.data && result.data.code == 200) { if (result && result.data && result.data.code == 200) {
setAllDataMenu(result.data.data); let arr = []
} else { let dataRes = result.data.data;
} for (const v in dataRes) {
arr.push(dataRes[v])
}
setAllDataMenu(arr);
}else {
NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
}
} }
const getDataMenu = async () => { const getDataMenu = async () => {
@ -123,6 +121,7 @@ const Index = ({ params }) => {
const handleOpenDialog = async (type) => { const handleOpenDialog = async (type) => {
await setTypeDialog(type) await setTypeDialog(type)
getDataAllMenu();
setOpenDialog(true) setOpenDialog(true)
} }

12
src/views/SimproV2/CreatedProyek/AsignCustProject.js

@ -32,11 +32,6 @@ const AssignCustProject = ({ openDialog, closeDialog, toggleDialog, idTask, proy
} }
}, [openDialog]); }, [openDialog]);
useEffect(() => {
if (openDialog) {
}
}, [dataUserToProject])
const getDataAssignHr = async () => { const getDataAssignHr = async () => {
const payload = { const payload = {
"paging": { "paging": {
@ -45,7 +40,8 @@ const AssignCustProject = ({ openDialog, closeDialog, toggleDialog, idTask, proy
}, },
"columns": [ "columns": [
{ "name": "name", "logic_operator": "ilike", "value": "", "table_name": "m_users" }, { "name": "name", "logic_operator": "ilike", "value": "", "table_name": "m_users" },
{ "name": "proyek_id", "logic_operator": "=", "value": idTask } { "name": "proyek_id", "logic_operator": "=", "value": idTask },
{ "name": "is_customer", "logic_operator": "=", "value": "true" }
], ],
"joins": [ "joins": [
{ "name": "m_users", "column_join": "user_id", "column_results": ["name"] }, { "name": "m_users", "column_join": "user_id", "column_results": ["name"] },
@ -144,7 +140,9 @@ const AssignCustProject = ({ openDialog, closeDialog, toggleDialog, idTask, proy
} }
const handleCloseDialogFormTools = (type, data) => { const handleCloseDialogFormTools = (type, data) => {
if (type === "add") getDataAssignHr(); if (type === "add") {
getDataAssignHr()
}
if (type === "success") { if (type === "success") {
NotificationManager.success( NotificationManager.success(
`Assign Customer Project berhasil disimpan!`, `Assign Customer Project berhasil disimpan!`,

609
src/views/SimproV2/CreatedProyek/AsignHrProject.js

@ -1,304 +1,305 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Button, Form } from 'reactstrap'; import { Button, Form } from 'reactstrap';
import { Table, Tooltip } from 'antd'; import { Table, Tooltip } from 'antd';
import 'antd/dist/antd.css'; import 'antd/dist/antd.css';
import moment from 'moment'; import moment from 'moment';
import { API_ADW, TOKEN_ADW, ASSIGN_HR_PROJECT_SEARCH, ASSIGN_HR_PROJECT_DELETE, USER_LIST, PROJECT_ROLE_SEARCH, ASSIGN_HR_PROJECT_ADD, ASSIGN_HR_PROJECT_EDIT } from '../../../const/ApiConst'; import { API_ADW, TOKEN_ADW, ASSIGN_HR_PROJECT_SEARCH, ASSIGN_HR_PROJECT_DELETE, USER_LIST, PROJECT_ROLE_SEARCH, ASSIGN_HR_PROJECT_ADD, ASSIGN_HR_PROJECT_EDIT } from '../../../const/ApiConst';
import axios from "../../../const/interceptorApi" import axios from "../../../const/interceptorApi"
import { NotificationContainer, NotificationManager } from 'react-notifications'; import { NotificationContainer, NotificationManager } from 'react-notifications';
import SweetAlert from 'react-bootstrap-sweetalert'; import SweetAlert from 'react-bootstrap-sweetalert';
import FormAsignHr from './FormAsignHr'; import FormAsignHr from './FormAsignHr';
import { formatThousand } from '../../../const/CustomFunc'; import { formatThousand } from '../../../const/CustomFunc';
const AssignHrProject = ({ openDialog, closeDialog, toggleDialog, idTask, toolsResource, proyekName }) => { const AssignHrProject = ({ openDialog, closeDialog, toggleDialog, idTask, toolsResource, proyekName }) => {
const token = localStorage.getItem("token") const token = localStorage.getItem("token")
const HEADER = { const HEADER = {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": `Bearer ${token}` "Authorization": `Bearer ${token}`
} }
} }
const [dataUserToProject, setdataUserToProject] = useState([]) const [dataUserToProject, setdataUserToProject] = useState([])
const [alertDelete, setAlertDelete] = useState(false) const [alertDelete, setAlertDelete] = useState(false)
const [idDelete, setIdDelete] = useState(0) const [idDelete, setIdDelete] = useState(0)
const [openDialogFormTools, setOpenDialogFormTools] = useState(false) const [openDialogFormTools, setOpenDialogFormTools] = useState(false)
const [dataEdit, setDataEdit] = useState(null) const [dataEdit, setDataEdit] = useState(null)
const [listUser, setListUser] = useState([]) const [listUser, setListUser] = useState([])
const [listRole, setListRole] = useState([]) const [listRole, setListRole] = useState([])
useEffect(() => { useEffect(() => {
if (idTask > 0) { if (idTask > 0) {
getDataAssignHr(); getDataAssignHr();
} }
}, [openDialog]); }, [openDialog]);
useEffect(() => { useEffect(() => {
if (openDialog) { if (openDialog) {
getDataProjectRole(); getDataProjectRole();
getDataUser(); getDataUser();
} }
}, [dataUserToProject]) }, [dataUserToProject])
const getDataAssignHr = async () => { const getDataAssignHr = async () => {
const payload = { const payload = {
"paging": { "paging": {
"start": 0, "start": 0,
"length": -1 "length": -1
}, },
"columns": [ "columns": [
{ "name": "name", "logic_operator": "ilike", "value": "", "table_name": "m_users" }, { "name": "name", "logic_operator": "ilike", "value": "", "table_name": "m_users" },
{ "name": "proyek_id", "logic_operator": "=", "value": idTask } { "name": "proyek_id", "logic_operator": "=", "value": idTask },
], { "name": "is_customer", "logic_operator": "=", "value": "false" }
"joins": [ ],
{ "name": "m_users", "column_join": "user_id", "column_results": ["name"] }, "joins": [
{ "name": "m_role_proyek", "column_join": "project_role", "column_results": ["name"] }, { "name": "m_users", "column_join": "user_id", "column_results": ["name"] },
], { "name": "m_role_proyek", "column_join": "project_role", "column_results": ["name"] },
"orders": { ],
"columns": [ "orders": {
"id" "columns": [
], "id"
"ascending": false ],
} "ascending": false
} }
const URL = ASSIGN_HR_PROJECT_SEARCH }
const result = await axios const URL = ASSIGN_HR_PROJECT_SEARCH
.post(URL, payload, HEADER) const result = await axios
.then(res => res) .post(URL, payload, HEADER)
.catch((error) => error.response); .then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
let dataRes = result.data.data || [] if (result && result.data && result.data.code == 200) {
let dataRes = result.data.data || []
setdataUserToProject(dataRes);
} else { setdataUserToProject(dataRes);
NotificationManager.error('Gagal Mengambil Data!!', 'Failed'); } else {
} NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
} }
}
const getDataUser = async () => {
const HEADER_ADW = { const getDataUser = async () => {
headers: { const HEADER_ADW = {
"Authorization": `${TOKEN_ADW}` headers: {
} "Authorization": `${TOKEN_ADW}`
} }
const result = await axios }
// .get(`${API_ADW}employees`, HEADER_ADW) const result = await axios
.get(USER_LIST, HEADER) // .get(`${API_ADW}employees`, HEADER_ADW)
.then(res => res) .get(USER_LIST, HEADER)
.catch((error) => error.response); .then(res => res)
if (result && result.data && result.data.data.length != 0) { .catch((error) => error.response);
let dataRes = result.data.data if (result && result.data && result.data.data.length != 0) {
setListUser(dataRes) let dataRes = result.data.data
} setListUser(dataRes)
} }
}
const getDataProjectRole = async () => {
const payload = { const getDataProjectRole = async () => {
"paging": { const payload = {
"start": 0, "paging": {
"length": -1 "start": 0,
}, "length": -1
"columns": [ },
{ "name": "created_by", "logic_operator": "ilike", "value": "" }, "columns": [
], { "name": "created_by", "logic_operator": "ilike", "value": "" },
"joins": [], ],
"orders": { "joins": [],
"columns": [ "orders": {
"id" "columns": [
], "id"
"ascending": false ],
} "ascending": false
} }
}
const result = await axios
.post(PROJECT_ROLE_SEARCH, payload, HEADER) const result = await axios
.then(res => res) .post(PROJECT_ROLE_SEARCH, payload, HEADER)
.catch((error) => error.response); .then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
let dataRes = result.data.data || [] if (result && result.data && result.data.code == 200) {
setListRole(dataRes); let dataRes = result.data.data || []
} else { setListRole(dataRes);
} } else {
} }
}
const handleDelete = (id) => {
setIdDelete(id) const handleDelete = (id) => {
setAlertDelete(true) setIdDelete(id)
} setAlertDelete(true)
}
const cancelDelete = () => {
setAlertDelete(false) const cancelDelete = () => {
setIdDelete(0) setAlertDelete(false)
} setIdDelete(0)
}
const onConfirmDelete = async () => {
let urlDel = ASSIGN_HR_PROJECT_DELETE(idDelete) const onConfirmDelete = async () => {
const result = await axios.delete(urlDel, HEADER) let urlDel = ASSIGN_HR_PROJECT_DELETE(idDelete)
.then(res => res) const result = await axios.delete(urlDel, HEADER)
.catch((error) => error.response); .then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
getDataAssignHr() if (result && result.data && result.data.code === 200) {
setIdDelete(0) getDataAssignHr()
setAlertDelete(false) setIdDelete(0)
NotificationManager.success(`Data assign human resource berhasil dihapus`, 'Success!!'); setAlertDelete(false)
} else { NotificationManager.success(`Data assign human resource berhasil dihapus`, 'Success!!');
setIdDelete(0) } else {
setAlertDelete(false) setIdDelete(0)
NotificationManager.error(`Data assign human resource gagal dihapus`, 'Failed!!'); setAlertDelete(false)
} NotificationManager.error(`Data assign human resource gagal dihapus`, 'Failed!!');
} }
}
const handleEdit = async (data) => {
await setDataEdit(data) const handleEdit = async (data) => {
setOpenDialogFormTools(true) await setDataEdit(data)
} setOpenDialogFormTools(true)
}
const handleOpenDialogFormTools = () => {
setOpenDialogFormTools(true) const handleOpenDialogFormTools = () => {
} setOpenDialogFormTools(true)
}
const handleCancel = () => {
closeDialog('cancel', 'none') const handleCancel = () => {
} closeDialog('cancel', 'none')
}
const RenderTable = useMemo(() => {
const columns = [ const RenderTable = useMemo(() => {
{ const columns = [
title: 'Action', {
dataIndex: '', title: 'Action',
key: 'x', dataIndex: '',
className: "nowrap", key: 'x',
render: (text, record) => <><Tooltip title="Delete Request Resource"> className: "nowrap",
<Button size={"sm"} color='danger' onClick={() => handleDelete(text.id)}><i className="fa fa-trash"></i></Button> render: (text, record) => <><Tooltip title="Delete Request Resource">
</Tooltip>{" "}<Tooltip title="Edit Request Resource"> <Button size={"sm"} color='danger' onClick={() => handleDelete(text.id)}><i className="fa fa-trash"></i></Button>
<Button size={"sm"} color='primary' onClick={() => handleEdit(text)}><i className="fa fa-edit"></i></Button> </Tooltip>{" "}<Tooltip title="Edit Request Resource">
</Tooltip></>, <Button size={"sm"} color='primary' onClick={() => handleEdit(text)}><i className="fa fa-edit"></i></Button>
}, </Tooltip></>,
{ title: 'Name Human Resource', dataIndex: 'join_first_name', key: 'join_first_name', className: "nowrap" }, },
{ title: 'Role Human Resource', dataIndex: 'join_second_name', key: 'join_second_name', className: "nowrap" }, { title: 'Name Human Resource', dataIndex: 'join_first_name', key: 'join_first_name', className: "nowrap" },
{ title: 'Percentage Available User', dataIndex: 'max_used', key: 'max_used', className: "nowrap", render: (text, record) => record.max_used ? formatThousand(record.max_used) : '-' }, { title: 'Role Human Resource', dataIndex: 'join_second_name', key: 'join_second_name', className: "nowrap" },
{ title: 'Standard Rate', dataIndex: 'standart_rate', key: 'standart_rate', className: "nowrap", render: (text, record) => record.standart_rate ? formatThousand(record.standart_rate) : '-' }, { title: 'Percentage Available User', dataIndex: 'max_used', key: 'max_used', className: "nowrap", render: (text, record) => record.max_used ? formatThousand(record.max_used) : '-' },
{ title: 'UOM Standard Rate', dataIndex: 'uom_standart_rate', key: 'uom_standart_rate', className: "nowrap" }, { title: 'Standard Rate', dataIndex: 'standart_rate', key: 'standart_rate', className: "nowrap", render: (text, record) => record.standart_rate ? formatThousand(record.standart_rate) : '-' },
{ title: 'Overtime Rate', dataIndex: 'overtime_rate', key: 'overtime_rate', className: "nowrap", render: (text, record) => record.overtime_rate ? formatThousand(record.overtime_rate) : '-' }, { title: 'UOM Standard Rate', dataIndex: 'uom_standart_rate', key: 'uom_standart_rate', className: "nowrap" },
{ title: 'UOM Overtime Rate', dataIndex: 'uom_overtime_rate', key: 'uom_overtime_rate', className: "nowrap" }, { title: 'Overtime Rate', dataIndex: 'overtime_rate', key: 'overtime_rate', className: "nowrap", render: (text, record) => record.overtime_rate ? formatThousand(record.overtime_rate) : '-' },
{ title: 'UOM Overtime Rate', dataIndex: 'uom_overtime_rate', key: 'uom_overtime_rate', className: "nowrap" },
];
];
return (
<Table return (
size="small" <Table
columns={columns} size="small"
dataSource={dataUserToProject} columns={columns}
pagination={{ position: ["bottomLeft"] }} dataSource={dataUserToProject}
/> pagination={{ position: ["bottomLeft"] }}
) />
}, [dataUserToProject]) )
}, [dataUserToProject])
const renderForm = () => {
return ( const renderForm = () => {
<div style={{"overflowX":"scroll"}}> return (
{RenderTable} <div style={{"overflowX":"scroll"}}>
</div> {RenderTable}
) </div>
} )
}
const handleCloseDialogFormTools = (type, data) => {
if(type=="add"){ const handleCloseDialogFormTools = (type, data) => {
addDataAssignHr(data); if(type=="add"){
}else if(type=="edit"){ addDataAssignHr(data);
editDataAssignHr(data); }else if(type=="edit"){
}else{ editDataAssignHr(data);
setDataEdit(null) }else{
setOpenDialogFormTools(false) setDataEdit(null)
} setOpenDialogFormTools(false)
} }
}
const addDataAssignHr = async (payload) => {
const result = await axios const addDataAssignHr = async (payload) => {
.post(ASSIGN_HR_PROJECT_ADD, payload, HEADER) const result = await axios
.then(res => res) .post(ASSIGN_HR_PROJECT_ADD, payload, HEADER)
.catch((error) => error.response); .then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
getDataAssignHr(); if (result && result.data && result.data.code == 200) {
NotificationManager.success('assign human resource berhasil!!', 'Success'); getDataAssignHr();
setDataEdit(null) NotificationManager.success('assign human resource berhasil!!', 'Success');
setOpenDialogFormTools(false) setDataEdit(null)
} else { setOpenDialogFormTools(false)
NotificationManager.error('assign human resource gagal!!', 'Failed'); } else {
} NotificationManager.error('assign human resource gagal!!', 'Failed');
} }
}
const editDataAssignHr = async (payload) => {
let url = ASSIGN_HR_PROJECT_EDIT(payload.id) const editDataAssignHr = async (payload) => {
const result = await axios let url = ASSIGN_HR_PROJECT_EDIT(payload.id)
.put(url, payload, HEADER) const result = await axios
.then(res => res) .put(url, payload, HEADER)
.catch((error) => error.response); .then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
getDataAssignHr(); if (result && result.data && result.data.code == 200) {
NotificationManager.success('assign human resource berhasil diedit!!', 'Success'); getDataAssignHr();
setDataEdit(null) NotificationManager.success('assign human resource berhasil diedit!!', 'Success');
setOpenDialogFormTools(false) setDataEdit(null)
} else { setOpenDialogFormTools(false)
NotificationManager.error('assign human resource gagal diedit!!', 'Failed'); } else {
} NotificationManager.error('assign human resource gagal diedit!!', 'Failed');
} }
}
const toogleDialogFormTools = () => {
if (openDialogFormTools) { const toogleDialogFormTools = () => {
setDataEdit(null) if (openDialogFormTools) {
} setDataEdit(null)
setOpenDialogFormTools(!openDialogFormTools) }
} setOpenDialogFormTools(!openDialogFormTools)
}
return (
<> return (
<NotificationContainer /> <>
<SweetAlert <NotificationContainer />
show={alertDelete} <SweetAlert
warning show={alertDelete}
showCancel warning
confirmBtnText="Delete" showCancel
confirmBtnBsStyle="danger" confirmBtnText="Delete"
title={`Are you sure?`} confirmBtnBsStyle="danger"
onConfirm={onConfirmDelete} title={`Are you sure?`}
onCancel={() => cancelDelete()} onConfirm={onConfirmDelete}
focusCancelBtn onCancel={() => cancelDelete()}
> focusCancelBtn
Delete this data >
</SweetAlert> Delete this data
<Modal size="xl" isOpen={openDialog} toggle={toggleDialog}> </SweetAlert>
<ModalHeader className="capitalize withBtn" toggle={closeDialog}> <Modal size="xl" isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize withBtn" toggle={closeDialog}>
<div>Assign Human Resource - {proyekName}</div> <Button onClick={handleOpenDialogFormTools} size='sm' color="primary"><i className='fa fa-plus'></i></Button>
</ModalHeader> <div>Assign Human Resource - {proyekName}</div> <Button onClick={handleOpenDialogFormTools} size='sm' color="primary"><i className='fa fa-plus'></i></Button>
<ModalBody> </ModalHeader>
{renderForm()} <ModalBody>
</ModalBody> {renderForm()}
{/* <ModalFooter> </ModalBody>
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Close</Button> {/* <ModalFooter>
</ModalFooter> */} <Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Close</Button>
</Modal> </ModalFooter> */}
<FormAsignHr </Modal>
openDialog={openDialogFormTools} <FormAsignHr
closeDialog={handleCloseDialogFormTools} openDialog={openDialogFormTools}
toggleDialog={toogleDialogFormTools} closeDialog={handleCloseDialogFormTools}
idTask={idTask} toggleDialog={toogleDialogFormTools}
dataEdit={dataEdit} idTask={idTask}
dataHr={listUser} dataEdit={dataEdit}
dataRole={listRole} dataHr={listUser}
dataCurrentHr={dataUserToProject} dataRole={listRole}
/> dataCurrentHr={dataUserToProject}
</> />
) </>
)
}
}
export default AssignHrProject;
export default AssignHrProject;

31
src/views/SimproV2/CreatedProyek/DialogAssignCust.js

@ -3,7 +3,7 @@ import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Button, Form } from 'reactstrap'; import { Button, Form } from 'reactstrap';
import axios from "../../../const/interceptorApi"; import axios from "../../../const/interceptorApi";
import { import {
USER_LIST, USER_SEARCH,
ASSIGN_HR_PROJECT_SEARCH, ASSIGN_HR_PROJECT_SEARCH,
ASSIGN_HR_PROJECT_ADD_MULTIPLE ASSIGN_HR_PROJECT_ADD_MULTIPLE
} from '../../../const/ApiConst'; } from '../../../const/ApiConst';
@ -40,8 +40,29 @@ const DialogAssignCust = ({ openDialog, closeDialog, toggleDialog, idTask }) =>
const getDataAssignCustomer = async () => { const getDataAssignCustomer = async () => {
const payload = {
"select": [
"id",
"name",
"role_id"
],
"paging": {
"start": 0,
"length": -1
},
"columns": [
{ "name": "role_id", "logic_operator": "=", "value": 44 }
],
"orders": {
"columns": [
"id"
],
"ascending": false
}
}
const URL = USER_SEARCH;
const result = await axios const result = await axios
.get(USER_LIST, HEADER) .post(URL, payload, HEADER)
.then(res => res) .then(res => res)
.catch((error) => error.response); .catch((error) => error.response);
@ -99,6 +120,12 @@ const DialogAssignCust = ({ openDialog, closeDialog, toggleDialog, idTask }) =>
const getCustProject = async () => { const getCustProject = async () => {
const payload = { const payload = {
"select": [
"id",
"user_id",
"proyek_id",
"is_customer"
],
"columns": [ "columns": [
{ "name": "proyek_id", "logic_operator": "=", "value": idTask }, { "name": "proyek_id", "logic_operator": "=", "value": idTask },
{"name": "is_customer", "logic_operator": "=", "value": "true"} {"name": "is_customer", "logic_operator": "=", "value": "true"}

414
src/views/SimproV2/CreatedProyek/DialogFormProyek.js

@ -200,6 +200,7 @@ const DialogFormProyek = ({
setFinance(""); setFinance("");
setWorkArea(""); setWorkArea("");
setProjectDuration(""); setProjectDuration("");
setDivisiProject(null);
setProjectStructureOrg(null); setProjectStructureOrg(null);
setCompany(""); setCompany("");
setCurrency(""); setCurrency("");
@ -331,18 +332,35 @@ const DialogFormProyek = ({
setHealthBudget(val); setHealthBudget(val);
}; };
const onChangePm = (val) => { const onChangePm = (val) => {
let data = [...dataPM]; const item = dataPM.find((item) => item.id === val);
var item = data.find((item) => item.id === val); const existingParticipant = participants.find((participant) => participant.tittle === "PM");
participants.push({ if (existingParticipant) {
id: lastIdxParticipants + 1, setParticipants((prevParticipants) => {
title: "PM", return prevParticipants.map((participant) => {
name: item.name, if (participant.tittle === "PM") {
}); return {
setParticipants(participants); ...participant,
setLastIdxParticipants(lastIdxParticipants + 1); name: item.name,
setPic(val); };
}; }
return participant;
});
});
} else {
setParticipants((prevParticipants) => [
...prevParticipants,
{
id: item.id,
tittle: "PM",
name: item.name,
},
]);
setLastIdxParticipants(lastIdxParticipants + 1);
}
setPic(val);
};
const onChangeCurrency = (val) => { const onChangeCurrency = (val) => {
let curr = val.split("|"); // code|symbol|name let curr = val.split("|"); // code|symbol|name
@ -398,7 +416,7 @@ const DialogFormProyek = ({
const addParticipant = () => { const addParticipant = () => {
participants.push({ participants.push({
id: lastIdxParticipants + 1, id: lastIdxParticipants + 1,
title: "", tittle: "",
name: "", name: "",
}); });
setParticipants(participants); setParticipants(participants);
@ -437,7 +455,24 @@ const DialogFormProyek = ({
}; };
const handleInputChangeParticipants = (e, index) => { const handleInputChangeParticipants = (e, index) => {
const { name, value } = e.target; const { name, value } = e.target;
const existingParticipant = participants.find((participant) => participant.tittle === "PM");
if(value.toLowerCase() === "pm" && name === "tittle" && existingParticipant)
{
alert('PM is already exist!');
setParticipants((prevParticipants) =>
prevParticipants.map((participant, i) => {
if (i === index) {
return {
...participant,
tittle: "",
};
}
return participant;
})
);
return false;
}
const newParticipants = [...participants]; const newParticipants = [...participants];
newParticipants[index][name] = value; newParticipants[index][name] = value;
setParticipants(newParticipants); setParticipants(newParticipants);
@ -565,7 +600,7 @@ const DialogFormProyek = ({
const addApproval = () => { const addApproval = () => {
approval.push({ approval.push({
id: lastIdxApproval + 1, id: lastIdxApproval + 1,
title: "", tittle: "",
name: "", name: "",
date: moment(), date: moment(),
}); });
@ -611,7 +646,7 @@ const DialogFormProyek = ({
<Row> <Row>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize"> <Label className="capitalize" style={{ fontWeight: "bold" }}>
Project Name<span style={{ color: "red" }}>*</span> Project Name<span style={{ color: "red" }}>*</span>
</Label> </Label>
<Input <Input
@ -623,7 +658,7 @@ const DialogFormProyek = ({
</Col> </Col>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">Code / Short Name<span style={{ color: "red" }}>*</span></Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Code / Short Name<span style={{ color: "red" }}>*</span></Label>
<Input <Input
type="text" type="text"
value={shortName} value={shortName}
@ -635,7 +670,7 @@ const DialogFormProyek = ({
<Row> <Row>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize"> <Label className="capitalize" style={{ fontWeight: "bold" }}>
Project Type<span style={{ color: "red" }}>*</span> Project Type<span style={{ color: "red" }}>*</span>
</Label> </Label>
<Select <Select
@ -658,7 +693,7 @@ const DialogFormProyek = ({
</Col> </Col>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">PM</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>PM</Label>
<Select <Select
showSearch showSearch
filterOption={(inputValue, option) => filterOption={(inputValue, option) =>
@ -681,7 +716,7 @@ const DialogFormProyek = ({
<Row> <Row>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize"> <Label className="capitalize" style={{ fontWeight: "bold" }}>
Start Date<span style={{ color: "red" }}>*</span> Start Date<span style={{ color: "red" }}>*</span>
</Label> </Label>
<DatePicker <DatePicker
@ -694,7 +729,7 @@ const DialogFormProyek = ({
</Col> </Col>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize"> <Label className="capitalize" style={{ fontWeight: "bold" }}>
End Date<span style={{ color: "red" }}>*</span> End Date<span style={{ color: "red" }}>*</span>
</Label> </Label>
<DatePicker <DatePicker
@ -716,7 +751,7 @@ const DialogFormProyek = ({
<Row> <Row>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">Work Area</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Work Area</Label>
<Input <Input
type="text" type="text"
value={workArea} value={workArea}
@ -726,7 +761,7 @@ const DialogFormProyek = ({
</Col> </Col>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">Company</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Company</Label>
<Input <Input
type="text" type="text"
value={company} value={company}
@ -738,7 +773,7 @@ const DialogFormProyek = ({
<Row> <Row>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize"> <Label className="capitalize" style={{ fontWeight: "bold" }}>
Budget<span style={{ color: "red" }}>*</span> Budget<span style={{ color: "red" }}>*</span>
</Label> </Label>
<Row> <Row>
@ -768,8 +803,14 @@ const DialogFormProyek = ({
<Row> <Row>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label>Handled By Division</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>
Handled By Division<span style={{ color: "red" }}>*</span>
</Label>
<Select <Select
showSearch
filterOption={(inputValue, option) =>
option.children.toLowerCase().includes(inputValue.toLowerCase())
}
value={divisiProject} value={divisiProject}
defaultValue={divisiProject} defaultValue={divisiProject}
onChange={onChangeDivisiProject} onChange={onChangeDivisiProject}
@ -785,7 +826,7 @@ const DialogFormProyek = ({
</Col> </Col>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">Project Duration</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Project Duration</Label>
<Input <Input
type="number" type="number"
min="1" min="1"
@ -798,7 +839,7 @@ const DialogFormProyek = ({
<Row> <Row>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">Organizational Structure</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Organizational Structure</Label>
<Input <Input
type="file" type="file"
accept="image/*" accept="image/*"
@ -809,7 +850,7 @@ const DialogFormProyek = ({
</Col> </Col>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">Description</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Description</Label>
<Input <Input
type="textarea" type="textarea"
value={description} value={description}
@ -820,7 +861,7 @@ const DialogFormProyek = ({
</Row> </Row>
<Row> <Row>
<Col md={12}> <Col md={12}>
<Label className="capitalize">Late Consequence</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Late Consequence</Label>
<CKEditor <CKEditor
editor={ ClassicEditor } editor={ ClassicEditor }
data={ late } data={ late }
@ -832,9 +873,9 @@ const DialogFormProyek = ({
/> />
</Col> </Col>
</Row> </Row>
<Row> <Row style={{ marginTop: "20px"}}>
<Col md={12}> <Col md={12}>
<Label className="capitalize">Assumtion</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Assumtion</Label>
<CKEditor <CKEditor
editor={ClassicEditor} editor={ClassicEditor}
data={assumtion} data={assumtion}
@ -846,18 +887,18 @@ const DialogFormProyek = ({
/> />
</Col> </Col>
</Row> </Row>
<Row> <Row style={{ marginTop: "20px"}}>
<Col md={12}> <Col md={12}>
<Label className="capitalize">Project Checklist</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Project Checklist</Label>
<Row> <Row>
<Col md={5}> <Col md={5}>
<b>Item</b> <p>Item</p>
</Col> </Col>
<Col md={4}> <Col md={4}>
<b>Availability</b> <p>Availability</p>
</Col> </Col>
<Col md={2}> <Col md={2}>
<b>Action</b> <p>Action</p>
</Col> </Col>
<Col md={1}> <Col md={1}>
<Tooltip title="Add row"> <Tooltip title="Add row">
@ -877,16 +918,16 @@ const DialogFormProyek = ({
<Divider orientation="left" plain></Divider> <Divider orientation="left" plain></Divider>
<Row> <Row>
<Col md={12}> <Col md={12}>
<Label className="capitalize">Issues & Obstacles</Label> <Label className="capitalize" style={{ fontWeight: "bold" }}>Issues & Obstacles</Label>
<Row> <Row>
<Col md={5}> <Col md={5}>
<b>Issu Level</b> <p>Issue Level</p>
</Col> </Col>
<Col md={4}> <Col md={4}>
<b>Description</b> <p>Description</p>
</Col> </Col>
<Col md={2}> <Col md={2}>
<b>Action</b> <p>Action</p>
</Col> </Col>
<Col md={1}> <Col md={1}>
<Tooltip title="Add row"> <Tooltip title="Add row">
@ -909,7 +950,7 @@ const DialogFormProyek = ({
<Row> <Row>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label>Phase</Label> <Label style={{ fontWeight: "bold" }}>Phase</Label>
<Select <Select
value={phaseProject} value={phaseProject}
defaultValue={phaseProject} defaultValue={phaseProject}
@ -926,7 +967,7 @@ const DialogFormProyek = ({
</Col> </Col>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label>Cost Health</Label> <Label style={{ fontWeight: "bold" }}>Cost Health</Label>
<Select <Select
value={budgetHealth} value={budgetHealth}
defaultValue={budgetHealth} defaultValue={budgetHealth}
@ -949,130 +990,131 @@ const DialogFormProyek = ({
</Form> </Form>
<Form style={{ display: step === 2 ? 'block' : 'none' }}> <Form style={{ display: step === 2 ? 'block' : 'none' }}>
<Row> <Row >
<Col md={3}> <Col md={3}>
<b>Project Objectives</b> <b>Project Objectives</b>
</Col> </Col>
<Col md={9}> <Col md={9}>
<FormGroup> <CKEditor
<Input editor={ClassicEditor}
type="textarea" data={objectives}
value={objectives} config={editorConfig}
onChange={(e) => setObjectives(e.target.value)} onChange={ ( event, editor ) => {
/> const data = editor.getData();
</FormGroup> setObjectives(data);
</Col> } }
</Row> />
<Row> </Col>
<Col md={3}> </Row>
<b>Project is considered successful when</b> <Row style={{ marginTop: "20px" }}>
</Col> <Col md={3}>
<Col md={9}> <b>Project is considered successful when</b>
<FormGroup> </Col>
<Input <Col md={9}>
type="textarea" <CKEditor
value={projectIsConsideredSuccessful} editor={ClassicEditor}
onChange={(e) => data={projectIsConsideredSuccessful}
setProjectIsConsideredSuccessful(e.target.value) config={editorConfig}
} onChange={ ( event, editor ) => {
placeholder={`List of indicators`} const data = editor.getData();
rows={5} setProjectIsConsideredSuccessful(data);
/> } }
</FormGroup> />
</Col> </Col>
</Row> </Row>
<Row> <Row style={{ marginTop:"20px" }}>
<Col md={3}> <Col md={3}>
<b>Project Participants</b> <b>Project Participants</b>
</Col> </Col>
<Col md={9}> <Col md={9}>
<Row> <Row>
<Col md={5}> <Col md={5}>
<b>Title</b> <p>Title</p>
</Col> </Col>
<Col md={4}> <Col md={4}>
<b>Name</b> <p>Name</p>
</Col> </Col>
<Col md={2}> <Col md={2}>
<b>Action</b> <p>Action</p>
</Col> </Col>
<Col md={1}> <Col md={1}>
<Tooltip title="Add row"> <Tooltip title="Add row">
<Button <Button
size="sm" size="sm"
color="primary" color="primary"
onClick={() => addParticipant()} onClick={() => addParticipant()}
> >
<i className="fa fa-plus"></i> <i className="fa fa-plus"></i>
</Button> </Button>
</Tooltip> </Tooltip>
</Col> </Col>
</Row> </Row>
<div style={{ marginBottom: 50 }}>{RenderParticipants()}</div> <div style={{ marginBottom: 50 }}>{RenderParticipants()}</div>
</Col> </Col>
</Row> </Row>
<Row> <Row style={{ marginTop:"20px" }}>
<Col md={3}> <Col md={3}>
<b>Testing Environment</b> <b>Testing Environment</b>
</Col> </Col>
<Col md={9}> <Col md={9}>
<FormGroup> <CKEditor
<Input editor={ClassicEditor}
type="textarea" data={testingEnv}
value={testingEnv} config={editorConfig}
onChange={(e) => setTestingEnv(e.target.value)} onChange={ ( event, editor ) => {
rows={5} const data = editor.getData();
/> setTestingEnv(data);
</FormGroup> } }
</Col> />
</Row> </Col>
<Row> </Row>
<Col md={3}> <Row style={{ marginTop:"20px" }}>
<b>Milestones</b> <Col md={3}>
</Col> <b>Milestones</b>
<Col md={9}> </Col>
<Row> <Col md={9}>
<Col md={4}> <Row>
<b>Status</b> <Col md={4}>
</Col> <p>Status</p>
<Col md={4}> </Col>
<b>Deadline</b> <Col md={4}>
</Col> <p>Deadline</p>
<Col md={3}> </Col>
<b>Action</b> <Col md={3}>
</Col> <p>Action</p>
<Col md={1}> </Col>
<Tooltip title="Add row"> <Col md={1}>
<Button <Tooltip title="Add row">
size="sm" <Button
color="primary" size="sm"
onClick={() => addMilestone()} color="primary"
> onClick={() => addMilestone()}
<i className="fa fa-plus"></i> >
</Button> <i className="fa fa-plus"></i>
</Tooltip> </Button>
</Col> </Tooltip>
</Row> </Col>
<div style={{ marginBottom: 50 }}>{RenderMilestones()}</div> </Row>
</Col> <div style={{ marginBottom: 50 }}>{RenderMilestones()}</div>
</Row> </Col>
<Row> </Row>
<Row style={{ marginTop:"20px" }}>
<Col md={3}> <Col md={3}>
<b>Potential Risk</b> <b>Potential Risk</b>
</Col> </Col>
<Col md={9}> <Col md={9}>
<Row> <Row>
<Col md={3}> <Col md={3}>
<b>Risk Level</b> <p>Risk Level</p>
</Col> </Col>
<Col md={3}> <Col md={3}>
<b>Description</b> <p>Description</p>
</Col> </Col>
<Col md={3}> <Col md={3}>
<b>Prevention</b> <p>Prevention</p>
</Col> </Col>
<Col md={2}> <Col md={2}>
<b>Action</b> <p>Action</p>
</Col> </Col>
<Col md={1}> <Col md={1}>
<Tooltip title="Add row"> <Tooltip title="Add row">
@ -1089,35 +1131,35 @@ const DialogFormProyek = ({
<div style={{ marginBottom: 50 }}>{RenderRisk()}</div> <div style={{ marginBottom: 50 }}>{RenderRisk()}</div>
</Col> </Col>
</Row> </Row>
<Row> <Row style={{ marginTop:"20px" }}>
<Col md={3}> <Col md={3}>
<b>Approval</b> <b>Approval</b>
</Col> </Col>
<Col md={9}> <Col md={9}>
<Row> <Row>
<Col md={3}> <Col md={3}>
<b>Title</b> <p>Title</p>
</Col> </Col>
<Col md={3}> <Col md={3}>
<b>Name</b> <p>Name</p>
</Col> </Col>
<Col md={3}> <Col md={3}>
<b>Date</b> <p>Date</p>
</Col> </Col>
<Col md={2}> <Col md={2}>
<b>Action</b> <p>Action</p>
</Col> </Col>
<Tooltip title="Add row"> <Tooltip title="Add row">
<Col md={1}> <Col md={1}>
<Button size="sm" color="primary" onClick={() => addApproval()}> <Button size="sm" color="primary" onClick={() => addApproval()}>
<i className="fa fa-plus"></i> <i className="fa fa-plus"></i>
</Button> </Button>
</Col> </Col>
</Tooltip> </Tooltip>
</Row> </Row>
<div style={{ marginBottom: 50 }}>{RenderApproval()}</div> <div style={{ marginBottom: 50 }}>{RenderApproval()}</div>
</Col> </Col>
</Row> </Row>
</Form> </Form>
</> </>
) )
@ -1313,8 +1355,8 @@ const DialogFormProyek = ({
<Col md={4}> <Col md={4}>
<Input <Input
type="text" type="text"
value={item.tittle ? item.tittle : "-"} value={item.tittle}
name="title" name="tittle"
onChange={(e) => handleInputChangeParticipants(e, index)} onChange={(e) => handleInputChangeParticipants(e, index)}
/> />
</Col> </Col>
@ -1413,7 +1455,7 @@ const DialogFormProyek = ({
<Col md={3}> <Col md={3}>
<Input <Input
type="text" type="text"
value={item.tittle ? item.tittle : item.title} value={item.tittle ? item.tittle : item.tittle}
name="title" name="title"
onChange={(e) => handleInputChangeApproval(e, index)} onChange={(e) => handleInputChangeApproval(e, index)}
/> />

6
src/views/SimproV2/CreatedProyek/DialogGantt.js

@ -74,14 +74,16 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName
"select": ["id", "name_version", "calculation_type", "description", "created_at", "progress"], "select": ["id", "name_version", "calculation_type", "description", "created_at", "progress"],
"columns": [ "columns": [
{ "name": "hierarchy_ftth_id", "logic_operator": "=", "value": hierarchyId, "operator": "AND" } { "name": "hierarchy_ftth_id", "logic_operator": "=", "value": hierarchyId, "operator": "AND" }
] ],
"orders": { "columns": ["name_version"], "ascending": true }
} }
} else { } else {
payload = { payload = {
"select": ["id", "name_version", "calculation_type", "description", "created_at", "progress"], "select": ["id", "name_version", "calculation_type", "description", "created_at", "progress"],
"columns": [ "columns": [
{ "name": "proyek_id", "logic_operator": "=", "value": idTask, "operator": "AND" } { "name": "proyek_id", "logic_operator": "=", "value": idTask, "operator": "AND" }
] ],
"orders": { "columns": ["name_version"], "ascending": true },
} }
} }
const result = await axios const result = await axios

6
src/views/SimproV2/CreatedProyek/DialogHierarchy.js

@ -16,6 +16,7 @@ import { useTranslation } from 'react-i18next';
import { async } from '@dabeng/react-orgchart'; import { async } from '@dabeng/react-orgchart';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { use } from 'i18next'; import { use } from 'i18next';
import _ from 'lodash';
const DialogHierarchy = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName }) => { const DialogHierarchy = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName }) => {
const token = localStorage.getItem("token") const token = localStorage.getItem("token")
const HEADER = { const HEADER = {
@ -154,7 +155,8 @@ const DialogHierarchy = ({ openDialog, closeDialog, toggleDialog, idTask, proyek
.catch((error) => error.response); .catch((error) => error.response);
if (result && result.status == 200) { if (result && result.status == 200) {
setDataHierarchy(result.data.data); const sortedData = _.orderBy(result.data.data, ['name'], ['asc']);
setDataHierarchy(sortedData);
} else { } else {
NotificationManager.error(`Data gantt project gagal terload silahkan coba lagi!`, 'Failed!!'); NotificationManager.error(`Data gantt project gagal terload silahkan coba lagi!`, 'Failed!!');
} }
@ -340,4 +342,4 @@ const DialogHierarchy = ({ openDialog, closeDialog, toggleDialog, idTask, proyek
} }
export default DialogHierarchy; export default DialogHierarchy;

34
src/views/SimproV2/CreatedProyek/FormAsignHr.js

@ -22,7 +22,6 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit,
const [accrue, setAccrue] = useState("") const [accrue, setAccrue] = useState("")
const [baseCalender, setBaseCalender] = useState("") const [baseCalender, setBaseCalender] = useState("")
const [listHr, setListHr] = useState([]) const [listHr, setListHr] = useState([])
const [isCustomer, setIsCustomer] = useState(false)
const handleClearData = () => { const handleClearData = () => {
setUser(null) setUser(null)
@ -30,7 +29,6 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit,
setProjectRole(null) setProjectRole(null)
setGroupR("") setGroupR("")
setMaxUsed("") setMaxUsed("")
setIsCustomer(false)
setStandartRate("") setStandartRate("")
setUomStandartRate(null) setUomStandartRate(null)
setOverTimeRate("") setOverTimeRate("")
@ -69,7 +67,6 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit,
setProjectRole(dataEdit.project_role) setProjectRole(dataEdit.project_role)
setGroupR(dataEdit.group_r) setGroupR(dataEdit.group_r)
setMaxUsed(dataEdit.max_used ? formatNumber(dataEdit.max_used.toString()) : '') setMaxUsed(dataEdit.max_used ? formatNumber(dataEdit.max_used.toString()) : '')
setIsCustomer(dataEdit.is_customer)
setStandartRate(dataEdit.standart_rate ? formatNumber(dataEdit.standart_rate.toString()) : '') setStandartRate(dataEdit.standart_rate ? formatNumber(dataEdit.standart_rate.toString()) : '')
setUomStandartRate(dataEdit.uom_standart_rate) setUomStandartRate(dataEdit.uom_standart_rate)
setOverTimeRate(dataEdit.overtime_rate ? formatNumber(dataEdit.overtime_rate.toString()) : '') setOverTimeRate(dataEdit.overtime_rate ? formatNumber(dataEdit.overtime_rate.toString()) : '')
@ -94,7 +91,7 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit,
proyek_id: idTask, proyek_id: idTask,
user_id:user, user_id:user,
project_role:projectRole, project_role:projectRole,
is_customer: isCustomer, is_customer: false,
max_used:maxUsed.replaceAll(".", ""), max_used:maxUsed.replaceAll(".", ""),
standart_rate:standartRate.replaceAll(".", ""), standart_rate:standartRate.replaceAll(".", ""),
uom_standart_rate:uomStandartRate, uom_standart_rate:uomStandartRate,
@ -108,7 +105,7 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit,
proyek_id: idTask, proyek_id: idTask,
user_id:user, user_id:user,
project_role:projectRole, project_role:projectRole,
is_customer: isCustomer, is_customer: false,
max_used:maxUsed.replaceAll(".", ""), max_used:maxUsed.replaceAll(".", ""),
standart_rate:standartRate.replaceAll(".", ""), standart_rate:standartRate.replaceAll(".", ""),
uom_standart_rate:uomStandartRate, uom_standart_rate:uomStandartRate,
@ -162,33 +159,6 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit,
</FormGroup> </FormGroup>
</Col> </Col>
</Row> </Row>
<Row>
<Col>
<FormGroup>
<Label>Customer</Label>
<div>
<Select
value={isCustomer}
defaultValue={false}
style={{
width: 235,
}}
onChange={(val) => setIsCustomer(val)}
options={[
{
value: true,
label: 'Yes',
},
{
value: false,
label: 'No',
}
]}
/>
</div>
</FormGroup>
</Col>
</Row>
<div style={{widht:"100%",display:"flex",flexDirection:"row",justifyContent:"space-between",alignItems:"center"}}> <div style={{widht:"100%",display:"flex",flexDirection:"row",justifyContent:"space-between",alignItems:"center"}}>
<FormGroup style={{flexBasis:"49%"}}> <FormGroup style={{flexBasis:"49%"}}>
<Label>Standart Rate</Label> <Label>Standart Rate</Label>

223
src/views/SimproV2/CreatedProyek/ViewProject.js

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState, useRef } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Button } from 'reactstrap'; import { Button } from 'reactstrap';
import moment from 'moment'; import moment from 'moment';
@ -6,13 +6,18 @@ import 'antd/dist/antd.css';
import _ from 'underscore' import _ from 'underscore'
import './style.css' import './style.css'
import { formatThousand, sortBy } from '../../../const/CustomFunc'; import { formatThousand, sortBy } from '../../../const/CustomFunc';
import { BASE_OSPRO } from "../../../const/ApiConst"; import { BASE_OSPRO, PROYEK_SEARCH} from "../../../const/ApiConst";
import { Tooltip, Spin } from 'antd';
import { useTranslation } from 'react-i18next';
import axios from "../../../const/interceptorApi"
import autoTable from "jspdf-autotable";
import jsPDF from "jspdf";
const createMarkup = (element) => { const createMarkup = (element) => {
return {__html: element}; return {__html: element};
} }
const ViewProject = ({ openDialog, closeDialog, toggleDialog, projectCharter, projectParticipant, projectChecklist, projectIssue, projectRisk, projectMilestone, projectApproval, projectManager, projectK3, assignHR, projectImage }) => { const ViewProject = ({ idTask, openDialog, closeDialog, toggleDialog, projectCharter, projectParticipant, projectChecklist, projectIssue, projectRisk, projectMilestone, projectApproval, projectManager, projectK3, assignHR, projectImage }) => {
const [proyekName, setProyekName] = useState("") const [proyekName, setProyekName] = useState("")
const [description, setDescription] = useState("") const [description, setDescription] = useState("")
const [shortname, setKodeShortname] = useState("") const [shortname, setKodeShortname] = useState("")
@ -41,6 +46,18 @@ const createMarkup = (element) => {
const [K3Search, setDataK3Search] = useState("") const [K3Search, setDataK3Search] = useState("")
const [HR, setAssignHR] = useState("") const [HR, setAssignHR] = useState("")
const formatDate = "DD-MM-YYYY"; const formatDate = "DD-MM-YYYY";
const reportTemplateRef = useRef(null);
const [loading, setLoading] = useState(true);
const { t } = useTranslation();
const token = localStorage.getItem("token");
const HEADER = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
};
useEffect(() => { useEffect(() => {
if(!openDialog){ if(!openDialog){
setProyekName("") setProyekName("")
@ -69,15 +86,16 @@ const createMarkup = (element) => {
setMilestone([]) setMilestone([])
setPotentialRisks("") setPotentialRisks("")
setApproval([]) setApproval([])
setLoading(false)
} }
}, [openDialog]); }, [openDialog]);
useEffect(() => { useEffect(() => {
if(projectCharter && projectCharter!={}){ if (projectCharter && projectCharter != {}) {
setProyekName(projectCharter.nama); setProyekName(projectCharter.nama);
setDescription(projectCharter.keterangan); setDescription(projectCharter.keterangan);
setKodeShortname(projectCharter.kode_sortname); setKodeShortname(projectCharter.kode_sortname);
setLokasiKantor(projectCharter.lokasi_kantor); setLokasiKantor(projectCharter.area_kerja);
setDurasiProyek(projectCharter.durasi_proyek); setDurasiProyek(projectCharter.durasi_proyek);
setMulaiProyek(projectCharter.mulai_proyek); setMulaiProyek(projectCharter.mulai_proyek);
setValueProyek(projectCharter.value_proyek); setValueProyek(projectCharter.value_proyek);
@ -155,6 +173,19 @@ const createMarkup = (element) => {
setAssignHR(assignHR) setAssignHR(assignHR)
} }
}, [assignHR]); }, [assignHR]);
const handleExportPdf = async () => {
const doc = new jsPDF({
orientation: 'landscape',
unit: 'px',
format: [1106, 1000]
});
doc.html(reportTemplateRef.current, {
async callback(doc) {
await doc.save('Project Charter');
},
});
};
const RenderParticipant = () => { const RenderParticipant = () => {
if(participants && participants.length > 0){ if(participants && participants.length > 0){
@ -182,14 +213,18 @@ const createMarkup = (element) => {
const K3Number = number[index]; const K3Number = number[index];
return( return(
<tr key={index}> <tr key={index}>
<td style={{...tdStyle, width:50, textAlign:'center' }}><p style={pStyle}>{ K3Number }</p></td> <td style={{...tdStyle, width:50, textAlign:'center' }}><p style={{ ...pStyle, fontWeight:'normal' }}>{ K3Number }</p></td>
<td style={tdStyle} className='plr-10'><p style={pStyle}>{val.checklist_k3_name ? val.checklist_k3_name : "-"}</p></td> <td style={ tdStyle } className='plr-10'><p style={{ ...pStyle, fontWeight:'normal' }}>{val.checklist_k3_name ? val.checklist_k3_name : "-"}</p></td>
</tr> </tr>
) )
}) })
) )
}else{ }else{
return (<tr><td><br></br></td></tr>) return (
<tr>
<td style={{ ...tdStyle, textAlign: "center" }}>-</td>
<td style={{ ...tdStyle, textAlign: "center" }}>-</td>
</tr>);
} }
} }
@ -201,10 +236,10 @@ const createMarkup = (element) => {
const ChecklistNumber = number[index]; const ChecklistNumber = number[index];
return( return(
<tr key={index}> <tr key={index}>
<td style={{...tdStyle, width:50, textAlign:'center' }}><p style={pStyle}>{ ChecklistNumber }</p></td> <td style={{...tdStyle, width:50, textAlign:'center' }}><p style={{ ...pStyle, fontWeight:'normal' }}>{ ChecklistNumber }</p></td>
<td style={tdStyle} className='plr-10'><p style={pStyle}>{val.item ? val.item : "-"}</p></td> <td style={ tdStyle } className='plr-10'><p style={{ ...pStyle, fontWeight:'normal' }}>{val.item ?? "-"}</p></td>
<td style={tdStyle} className='plr-10'> <td style={ tdStyle } className='plr-10'>
<p style={pStyle}> <p style={{ ...pStyle, fontWeight:'normal' }}>
{val.status_exist === true ? "Tersedia" : "Tidak tersedia"} {val.status_exist === true ? "Tersedia" : "Tidak tersedia"}
</p> </p>
</td> </td>
@ -213,7 +248,12 @@ const createMarkup = (element) => {
}) })
) )
}else{ }else{
return (<tr><td><br></br></td></tr>) return (
<tr>
<td style={{ ...tdStyle, textAlign: "center" }}>-</td>
<td style={{ ...tdStyle, textAlign: "center" }}>-</td>
<td style={{ ...tdStyle, textAlign: "center" }}>-</td>
</tr>);
} }
} }
@ -224,17 +264,21 @@ const createMarkup = (element) => {
return( return(
<tr key={index}> <tr key={index}>
<td style={{ ...tdStyle, width:50, textAlign:'center' }} className='plr-10'> <td style={{ ...tdStyle, width:50, textAlign:'center' }} className='plr-10'>
<p style={pStyle}> <p style={{ ...pStyle, fontWeight:'normal' }}>
{val.level_issue ? val.level_issue : "-"} {val.level_issue ? val.level_issue : "-"}
</p> </p>
</td> </td>
<td style={tdStyle} className='plr-10'><p style={pStyle}>{val.description ? val.description : "-"}</p></td> <td style={ tdStyle } className='plr-10'><p style={{ ...pStyle, fontWeight:'normal' }}>{val.description ? val.description : "-"}</p></td>
</tr> </tr>
) )
}) })
) )
}else{ }else{
return (<tr><td><br></br></td></tr>) return (
<tr>
<td style={{ ...tdStyle, textAlign:"center" }}>-</td>
<td style={{ ...tdStyle, textAlign:"center" }}>-</td>
</tr>)
} }
} }
@ -245,18 +289,23 @@ const createMarkup = (element) => {
return( return(
<tr key={index}> <tr key={index}>
<td style={{ ...tdStyle, width:50, textAlign:'center' }} className='plr-10'> <td style={{ ...tdStyle, width:50, textAlign:'center' }} className='plr-10'>
<p style={pStyle}> <p style={{ ...pStyle, fontWeight:'normal' }}>
{val.level_risk ? val.level_risk : "-"} {val.level_risk ?? "-"}
</p> </p>
</td> </td>
<td style={tdStyle} className='plr-10'><p style={pStyle}>{val.description ? val.description : "-"}</p></td> <td style={ tdStyle } className='plr-10'><p style={{ ...pStyle, fontWeight:'normal' }}>{val.description ?? "-"}</p></td>
<td style={tdStyle} className='plr-10'><p style={pStyle}>{val.preventive_risk ? val.preventive_risk : "-"}</p></td> <td style={ tdStyle } className='plr-10'><p style={{ ...pStyle, fontWeight:'normal' }}>{val.preventive_risk ?? "-"}</p></td>
</tr> </tr>
) )
}) })
) )
}else{ }else{
return (<tr><td><br></br></td></tr>) return (
<tr>
<td style={{ ...tdStyle, textAlign:"center" }}>-</td>
<td style={{ ...tdStyle, textAlign:"center" }}>-</td>
<td style={{ ...tdStyle, textAlign:"center" }}>-</td>
</tr>)
} }
} }
@ -267,20 +316,25 @@ const createMarkup = (element) => {
return( return(
<tr key={index}> <tr key={index}>
<td style={tdStyle} className='plr-10'> <td style={tdStyle} className='plr-10'>
<p>{val.join_first_name ? val.join_first_name : val.join_first_name}</p> <p>{val.join_first_name ? val.join_first_name : "-"}</p>
</td> </td>
<td style={tdStyle} className='plr-10'> <td style={tdStyle} className='plr-10'>
<p>{val.join_second_name ? val.join_second_name : val.join_second_name}</p> <p>{val.join_second_name ? val.join_second_name : "-"}</p>
</td> </td>
<td style={tdStyle} className='plr-10'> <td style={tdStyle} className='plr-10'>
<p>{val.join_second_description ? val.join_second_description : val.join_second_description}</p> <p>{val.join_second_description ? val.join_second_description : "-"}</p>
</td> </td>
</tr> </tr>
) )
}) })
) )
}else{ }else{
return (<tr><td><br></br></td></tr>) return (
<tr>
<td style={{ ...tdStyle, textAlign:"center" }}>-</td>
<td style={{ ...tdStyle, textAlign:"center" }}>-</td>
<td style={{ ...tdStyle, textAlign:"center" }}>-</td>
</tr>)
} }
} }
@ -298,20 +352,28 @@ const createMarkup = (element) => {
return ( return (
<tr key={index}> <tr key={index}>
<td style={tdStyle}> <td style={tdStyle}>
<p style={{ ...pStyle, textAlign:'center' }}>{milestoneLetter}</p> <p style={{ ...pStyle, fontWeight:'normal', textAlign:'center' }}>{milestoneLetter}</p>
</td> </td>
<td className='plr-10' style={tdStyle}> <td className='plr-10' style={tdStyle}>
<p style={{ ...pStyle, color: '#000000' }}>{val.status}</p> <p style={{ ...pStyle, fontWeight:'normal', color: '#000000' }}>{val.status ?? "-"}</p>
</td> </td>
<td className='plr-10' style={{ ...tdStyle, textAlign:'center' }}> <td className='plr-10' style={{ ...tdStyle, textAlign:'center' }}>
<p>&nbsp;{moment(val.deadline).format(formatDate)}</p> <p style={{ ...pStyle, fontWeight: 'normal', color: '#000000' }}>
&nbsp;{moment(val.deadline).format(formatDate)}
</p>
</td> </td>
</tr> </tr>
); );
}) })
); );
} else { } else {
return (<tr><td><br></br></td></tr>); return (
<tr>
<td style={{ ...tdStyle, textAlign: "center" }}>-</td>
<td style={{ ...tdStyle, textAlign: "center" }}>-</td>
<td style={{ ...tdStyle, textAlign: "center" }}>-</td>
</tr>);
} }
} }
@ -329,7 +391,10 @@ const createMarkup = (element) => {
}) })
) )
}else{ }else{
return (<tr><td><br></br></td></tr>) return (
<tr>
<td style={{ textAlign:"center" }}>&nbsp;-</td>
</tr>)
} }
} }
@ -353,26 +418,24 @@ const createMarkup = (element) => {
marginLeft: '5pt', marginLeft: '5pt',
marginTop: '2pt', marginTop: '2pt',
marginBottom: '2pt', marginBottom: '2pt',
fontFamily: 'Arial',
fontSize: '10pt', fontSize: '10pt',
fontWeight: 'bold', fontWeight: 'bold',
}; };
const italicStyle = {
fontStyle: 'italic'
};
const boldStyle = {
fontWeight: 'bold',
fontVariant: 'small-caps',
};
const emptyCellStyle = { const emptyCellStyle = {
padding: '0', padding: '0',
}; };
const paddingTable = {
paddingTop:"20px",
paddingLeft: "30px",
paddingRight: "30px"
}
const renderForm = () => { const renderForm = () => {
return ( return (
<div> <div id="pdf-content" style={ paddingTable }>
<h3>Project Charter</h3>
<table style={tableStyle} className="a"> <table style={tableStyle} className="a">
<tbody> <tbody>
<tr> <tr>
@ -385,7 +448,7 @@ const createMarkup = (element) => {
<p style={ pStyle }>Nama Proyek</p> <p style={ pStyle }>Nama Proyek</p>
</td> </td>
<td colSpan="2" style={tdStyle}> <td colSpan="2" style={tdStyle}>
<p style={{ ...pStyle, fontWeight: 'normal', fontStyle: 'italic' }}>{proyekName ?? '-'}</p> <p className="capitalize" style={{ ...pStyle, fontWeight: 'normal' }}>{proyekName ?? '-'}</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -393,7 +456,7 @@ const createMarkup = (element) => {
<p style={ pStyle }>Project description</p> <p style={ pStyle }>Project description</p>
</td> </td>
<td colSpan="2" style={tdStyle}> <td colSpan="2" style={tdStyle}>
<p style={{ ...pStyle, fontWeight: 'normal', fontStyle: 'italic' }}>{description ?? '-'}</p> <p style={{ ...pStyle, fontWeight: 'normal' }}>{description != "" ? description : '-'}</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -409,7 +472,7 @@ const createMarkup = (element) => {
<p style={ pStyle }>Lokasi Proyek</p> <p style={ pStyle }>Lokasi Proyek</p>
</td> </td>
<td colSpan="2" style={tdStyle}> <td colSpan="2" style={tdStyle}>
<p>&nbsp;{lokasi ?? '-' }</p> <p>&nbsp;{lokasi != "" ? lokasi :'-' }</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -441,7 +504,7 @@ const createMarkup = (element) => {
<p style={ pStyle }>Anggaran Proyek</p> <p style={ pStyle }>Anggaran Proyek</p>
</td> </td>
<td colSpan="2" style={tdStyle}> <td colSpan="2" style={tdStyle}>
<p style={{ ...pStyle, fontWeight: 'normal', fontStyle: 'italic' }}>{currency}. {formatThousand(budget)}</p> <p style={{ ...pStyle, fontWeight: 'normal' }}>{currency}. {formatThousand(budget)}</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -462,7 +525,7 @@ const createMarkup = (element) => {
<p style={ pStyle }>Project Manager</p> <p style={ pStyle }>Project Manager</p>
</td> </td>
<td colSpan="2" style={tdStyle}> <td colSpan="2" style={tdStyle}>
<p>&nbsp;{PM}</p> <p>&nbsp;{PM ?? "-"}</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -480,12 +543,18 @@ const createMarkup = (element) => {
<tbody> <tbody>
<tr> <tr>
<td bgcolor="#F2F2F2" style={tdStyle}> <td bgcolor="#F2F2F2" style={tdStyle}>
<p style={{ ...pStyle, fontVariant: 'small-caps' }}>2.0 OBJEKTIF PROYEK (TUJUAN)</p> <p style={ pStyle }>2.0 OBJEKTIF PROYEK (TUJUAN)</p>
</td> </td>
</tr> </tr>
<tr> <tr>
<td style={tdStyle}> <td style={tdStyle}>
<p style={italicStyle}>{objectives ?? '-'}</p> <p style={{ ...pStyle, fontWeight: 'normal' }}>
{objectives ? (
<span dangerouslySetInnerHTML={createMarkup(objectives)} />
) : (
'-'
)}
</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -495,13 +564,17 @@ const createMarkup = (element) => {
<tbody> <tbody>
<tr> <tr>
<th style={thStyle}> <th style={thStyle}>
<p style={{ ...pStyle, ...boldStyle }}>3.0 RUANG LINGKUP PROYEK</p> <p style={ pStyle }>3.0 RUANG LINGKUP PROYEK</p>
</th> </th>
</tr> </tr>
<tr> <tr>
<td style={tdStyle}> <td style={tdStyle}>
<ul> <ul>
<li style={pStyle}>{ scoupeProyek ?? '-' }</li> {scoupeProyek ? (
<li style={pStyle}>{ scoupeProyek ?? '-' }</li>
) : (
"-"
)}
</ul> </ul>
</td> </td>
</tr> </tr>
@ -512,7 +585,7 @@ const createMarkup = (element) => {
<tbody> <tbody>
<tr> <tr>
<td colSpan="3" style={thStyle}> <td colSpan="3" style={thStyle}>
<p style={{ ...pStyle, fontVariant: 'small-caps' }}>4.0 ANGGOTA PROYEK</p> <p style={ pStyle }>4.0 ANGGOTA PROYEK</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -534,14 +607,14 @@ const createMarkup = (element) => {
<tbody> <tbody>
<tr> <tr>
<th style={thStyle}> <th style={thStyle}>
<p style={{ ...pStyle, fontVariant: 'small-caps' }}>5.0 STRUKTUR ORGANISASI</p> <p style={ pStyle }>5.0 STRUKTUR ORGANISASI</p>
</th> </th>
</tr> </tr>
<tr> <tr>
<th style={emptyCellStyle}> <th style={emptyCellStyle}>
<p>&nbsp; <p>&nbsp;
{image ? ( {image ? (
<img src={`${BASE_OSPRO}/assets/image/` + image} style={{ width: "50px" }}></img> <img src={`${BASE_OSPRO}/assets/image/` + image} style={{ maxWidth: "100%" }}></img>
) : ( ) : (
'-' '-'
)} )}
@ -555,7 +628,7 @@ const createMarkup = (element) => {
<tbody> <tbody>
<tr> <tr>
<th colSpan="3" style={thStyle}> <th colSpan="3" style={thStyle}>
<p style={{ ...pStyle, fontVariant: 'small-caps' }}>6.0 TARGET UTAMA &amp; MILESTONE PENCAPAIAN</p> <p style={ pStyle }>6.0 TARGET UTAMA &amp; MILESTONE PENCAPAIAN</p>
</th> </th>
</tr> </tr>
<tr> <tr>
@ -577,7 +650,7 @@ const createMarkup = (element) => {
<tbody> <tbody>
<tr> <tr>
<td colSpan="2" style={thStyle}> <td colSpan="2" style={thStyle}>
<p style={{ ...pStyle, fontVariant: 'small-caps' }}>7.0 ISU &amp; HAMBATAN UTAMA</p> <p style={ pStyle }>7.0 ISU &amp; HAMBATAN UTAMA</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -591,13 +664,13 @@ const createMarkup = (element) => {
<RenderIssueProject/> <RenderIssueProject/>
</tbody> </tbody>
</table> </table>
<p style={{ ...pStyle, fontSize: '10pt', fontStyle: 'italic' }}>*Skala 1 ke 7 (1 = kecil, 7 = besar)</p> <p style={{ ...pStyle, fontSize: '10pt', fontWeight: 'normal', fontStyle: 'italic' }}>*Skala 1 ke 7 (1 = kecil, 7 = besar)</p>
<p>&nbsp;</p> <p>&nbsp;</p>
<table style={tableStyle} className="a6"> <table style={tableStyle} className="a6">
<tbody> <tbody>
<tr> <tr>
<td colSpan="3" style={thStyle}> <td colSpan="3" style={thStyle}>
<p style={{ ...pStyle, fontVariant: 'small-caps' }}>8.0 RESIKO</p> <p style={ pStyle }>8.0 RESIKO</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -614,7 +687,7 @@ const createMarkup = (element) => {
<RenderRiskProject/> <RenderRiskProject/>
</tbody> </tbody>
</table> </table>
<p style={{ ...pStyle, fontSize: '10pt', fontStyle: 'italic' }}>*Skala 1 ke 7 (1 = kecil, 7 = besar)</p> <p style={{ ...pStyle, fontSize: '10pt', fontWeight: 'normal', fontStyle: 'italic' }}>*Skala 1 ke 7 (1 = kecil, 7 = besar)</p>
<p>&nbsp;</p> <p>&nbsp;</p>
<table style={tableStyle} className="a7"> <table style={tableStyle} className="a7">
<tbody> <tbody>
@ -624,7 +697,13 @@ const createMarkup = (element) => {
</th> </th>
</tr> </tr>
<tr> <tr>
<p dangerouslySetInnerHTML={createMarkup(lateProyek ?? '-')}></p> <p style={{ ...pStyle, fontWeight: 'normal' }}>
{lateProyek ? (
<span dangerouslySetInnerHTML={createMarkup(lateProyek)} />
) : (
"-"
)}
</p>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -638,7 +717,13 @@ const createMarkup = (element) => {
</tr> </tr>
<tr> <tr>
<th> <th>
<p style={pStyle}>{projectSuccess ?? '-'}</p> <p style={{ ...pStyle, fontWeight: 'normal' }}>
{projectSuccess ? (
<span dangerouslySetInnerHTML={createMarkup(projectSuccess)} />
) : (
'-'
)}
</p>
</th> </th>
</tr> </tr>
</tbody> </tbody>
@ -653,7 +738,13 @@ const createMarkup = (element) => {
</tr> </tr>
<tr> <tr>
<td> <td>
<p dangerouslySetInnerHTML={createMarkup(assumtionProyek ?? '-')}></p> <p style={{ ...pStyle, fontWeight: 'normal' }}>
{assumtionProyek ? (
<span dangerouslySetInnerHTML={createMarkup(assumtionProyek)} />
) : (
'-'
)}
</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -719,9 +810,17 @@ const createMarkup = (element) => {
return ( return (
<> <>
<Modal size="xl" isOpen={openDialog} toggle={toggleDialog}> <Modal size="xl" isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={closeDialog}>Project</ModalHeader> <ModalHeader className="capitalize" toggle={closeDialog}>
<div>
<Tooltip title={t('Export PDF')}>
<Button style={{ marginLeft: "5px" }} onClick={(e) => handleExportPdf()}><i className="fa fa-print"></i> Export PDF</Button>
</Tooltip>
</div>
</ModalHeader>
<ModalBody> <ModalBody>
{renderForm()} <div ref={reportTemplateRef}>
{renderForm()}
</div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button color="primary" onClick={closeDialog}>Close</Button> <Button color="primary" onClick={closeDialog}>Close</Button>

17
src/views/SimproV2/CreatedProyek/index.js

@ -248,7 +248,9 @@ const CreatedProyek = ({ params, ...props }) => {
.then((res) => res) .then((res) => res)
.catch((err) => err.response); .catch((err) => err.response);
if (result && result.data && result.data.code === 200) { if (result && result.data && result.data.code === 200) {
setDataDivisions(result.data.data); const dataRes = result.data.data;
const filteredData = dataRes.filter(item => item.parent === null);
setDataDivisions(filteredData);
} }
}; };
@ -326,7 +328,7 @@ const CreatedProyek = ({ params, ...props }) => {
}, },
// { "name": "subproyeks.m_subproyek", "column_join": "parent_id", "column_results": ["nama", "biaya", "color_progress", "jumlah_pekerja", "pic", "mulai_proyek", "akhir_proyek", "biaya_actual", "persentase_progress_plan", "persentase_progress_actual"] } // { "name": "subproyeks.m_subproyek", "column_join": "parent_id", "column_results": ["nama", "biaya", "color_progress", "jumlah_pekerja", "pic", "mulai_proyek", "akhir_proyek", "biaya_actual", "persentase_progress_plan", "persentase_progress_actual"] }
], ],
orders: { columns: ["id"], ascending: false }, orders: { columns: ["nama"], ascending: true },
paging: { start: start, length: rowsPerPage }, paging: { start: start, length: rowsPerPage },
}; };
@ -609,8 +611,8 @@ const CreatedProyek = ({ params, ...props }) => {
.catch((error) => error.response); .catch((error) => error.response);
if (result && result.data && result.data.code == 200) { if (result && result.data && result.data.code == 200) {
const {kode_sortname,nama,mulai_proyek,rencana_biaya,keterangan,durasi_proyek,project_objectives,potential_risk,currency_symbol, nama_divisi, late_consequence, assumtion, considered_success_when} = result.data.data; const {value_proyek,area_kerja,scoupe_of_work, kode_sortname,nama,mulai_proyek,rencana_biaya,keterangan,durasi_proyek,project_objectives,potential_risk,currency_symbol, nama_divisi, late_consequence, assumtion, considered_success_when} = result.data.data;
const dataToSend = { kode_sortname, nama, mulai_proyek, rencana_biaya, keterangan, durasi_proyek, project_objectives, potential_risk, currency_symbol, nama_divisi, late_consequence, assumtion, considered_success_when}; const dataToSend = {value_proyek,area_kerja,scoupe_of_work, kode_sortname, nama, mulai_proyek, rencana_biaya, keterangan, durasi_proyek, project_objectives, potential_risk, currency_symbol, nama_divisi, late_consequence, assumtion, considered_success_when};
setProjectCharter(dataToSend); setProjectCharter(dataToSend);
} else { } else {
NotificationManager.error("Gagal Mengambil Data!!", "Failed"); NotificationManager.error("Gagal Mengambil Data!!", "Failed");
@ -965,7 +967,7 @@ const CreatedProyek = ({ params, ...props }) => {
const request = data.map((res) => { const request = data.map((res) => {
const payload = { const payload = {
proyek_id: parseInt(id), proyek_id: parseInt(id),
tittle: res.title, tittle: res.tittle,
name: res.name, name: res.name,
}; };
return axios.post(PROJECT_PARTICIPANT_ADD, payload, HEADER); return axios.post(PROJECT_PARTICIPANT_ADD, payload, HEADER);
@ -1365,7 +1367,7 @@ const CreatedProyek = ({ params, ...props }) => {
}, },
// { "name": "subproyeks.m_subproyek", "column_join": "parent_id", "column_results": ["nama", "biaya", "color_progress", "jumlah_pekerja", "pic", "mulai_proyek", "akhir_proyek", "biaya_actual", "persentase_progress_plan", "persentase_progress_actual"] } // { "name": "subproyeks.m_subproyek", "column_join": "parent_id", "column_results": ["nama", "biaya", "color_progress", "jumlah_pekerja", "pic", "mulai_proyek", "akhir_proyek", "biaya_actual", "persentase_progress_plan", "persentase_progress_actual"] }
], ],
orders: { columns: ["id"], ascending: false }, orders: { columns: ["nama"], ascending: true },
}; };
const result = await axios const result = await axios
@ -1899,6 +1901,7 @@ const CreatedProyek = ({ params, ...props }) => {
projectK3={projectK3Search} projectK3={projectK3Search}
assignHR={projectAssignHR} assignHR={projectAssignHR}
projectImage={image} projectImage={image}
idTask={idTask}
/> />
), ),
[openDialogViewDetail] [openDialogViewDetail]
@ -1996,7 +1999,7 @@ const CreatedProyek = ({ params, ...props }) => {
</Button> </Button>
</Tooltip> </Tooltip>
)} )}
<Tooltip title="Export Excel"> <Tooltip title="Export">
<Popover <Popover
// content={<a onClick={hide}>Close</a>} // content={<a onClick={hide}>Close</a>}
title="Export" title="Export"

63
src/views/SimproV2/Divisi/DialogForm.js

@ -6,12 +6,16 @@ import {
import { Select } from 'antd'; import { Select } from 'antd';
import 'antd/dist/antd.css'; import 'antd/dist/antd.css';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import InputColor from "./InputColor";
import "./styles.css";
import "rc-color-picker/assets/index.css";
const { Option } = Select const { Option } = Select
const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdit, dataDivisions }) => { const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdit, dataDivisions }) => {
const [id, setId] = useState(0) const [id, setId] = useState(0)
const [name, setName] = useState('') const [name, setName] = useState('')
const [parent, setParent] = useState(null) const [parent, setParent] = useState(null)
const [description, setDescription] = useState('') const [description, setDescription] = useState('')
const [color, setColor] = useState('')
const { t } = useTranslation() const { t } = useTranslation()
const onChangeParent = (val) => { const onChangeParent = (val) => {
@ -23,9 +27,11 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi
setId(dataEdit.id) setId(dataEdit.id)
setDescription(dataEdit.description) setDescription(dataEdit.description)
setName(dataEdit.name) setName(dataEdit.name)
setParent(dataEdit.parent) setParent(dataEdit.parent)
setColor(dataEdit.color)
} else { } else {
setId(0) setId(0)
setColor('')
} }
}, [dataEdit, openDialog]) }, [dataEdit, openDialog])
@ -42,30 +48,35 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi
if (!err) { if (!err) {
if (typeDialog === "Save") { if (typeDialog === "Save") {
data = { data = {
name: name, name,
description, description,
parent parent,
color
} }
closeDialog('save', data); closeDialog('save', data);
} else { } else {
data = { data = {
id, id,
name: name, name,
description, description,
parent parent,
color
} }
closeDialog('edit', data); closeDialog('edit', data);
} }
setId(0) setId(0)
setDescription('') setDescription('')
setName('') setName('')
setParent(null)
setColor('')
} }
} }
const handleCancel = () => { const handleCancel = () => {
closeDialog('cancel', 'none') closeDialog('cancel', 'none')
setId(0) setId(0)
setDescription('') setDescription('')
setName('') setName('')
setParent(null)
} }
const renderForm = () => { const renderForm = () => {
@ -89,22 +100,22 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi
</FormGroup> </FormGroup>
</Col> </Col>
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">{t('nameDivision')}</Label> <Label className="capitalize">{t('Parent Division')}</Label>
<Select showSearch <Select showSearch
value={parent} value={parent}
onChange={onChangeParent} onChange={onChangeParent}
style={{ width: '100%' }} style={{ width: '100%' }}
filterOption={(input, option) => option.children.toLowerCase().includes(input.toLowerCase())} filterOption={(input, option) => option.children.toLowerCase().includes(input.toLowerCase())}
> >
{dataDivisions.map((res, idx) => ( {dataDivisions.map((res, idx) => (
<Option key={res['id']} value={res['id']}>{res['displayName']}</Option> <Option key={res['id']} value={res['id']}>{res['displayName']}</Option>
))} ))}
</Select> </Select>
</FormGroup> </FormGroup>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Col md={12}> <Col md={12}>
<FormGroup> <FormGroup>
<Label className="capitalize">{t('description')}</Label> <Label className="capitalize">{t('description')}</Label>
@ -112,6 +123,14 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi
</FormGroup> </FormGroup>
</Col> </Col>
</Row> </Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">{t('color')}</Label>
<InputColor value={color} color={color} onChange={(e) => setColor(e.color)} />
</FormGroup>
</Col>
</Row>
</Form> </Form>
) )
} }

46
src/views/SimproV2/Divisi/InputColor.js

@ -0,0 +1,46 @@
import React from "react";
import Input from "antd/lib/input";
import Button from "antd/lib/button";
import Dropdown from "antd/lib/dropdown";
import { Panel } from 'rc-color-picker'
import "antd/dist/antd.css";
import "./styles.css";
export default function InputColor(props) {
const { color, onChange } = props;
const [internalColor, setInternalColor] = React.useState(color);
const handleChange = (color) => {
setInternalColor(color.color);
if (onChange) {
onChange(color);
}
};
const overlay = (
<div>
<Panel
color={internalColor}
enableAlpha={false}
onChange={handleChange}
/>
</div>
);
return (
<>
<Input
value={internalColor || ""}
onChange={(e) => setInternalColor(e.target.value)}
suffix={
<Dropdown trigger={["click"]} overlay={overlay}>
<Button style={{ background: internalColor }}> </Button>
</Dropdown>
}
/>
</>
);
}

23
src/views/SimproV2/Divisi/index.js

@ -25,6 +25,7 @@ const config = {
const column = [ const column = [
{ name: "Nama" }, { name: "Nama" },
{ name: "Deskripsi" }, { name: "Deskripsi" },
{ name: "Color" },
] ]
const ProjectType = ({ params }) => { const ProjectType = ({ params }) => {
@ -72,8 +73,10 @@ const ProjectType = ({ params }) => {
if (listDivions && listDivions.data && listDivions.data.code == 200) { if (listDivions && listDivions.data && listDivions.data.code == 200) {
let arr = [] let arr = []
for (const v in listDivions.data.data) { let dataRes = listDivions.data.data;
arr.push(listDivions.data.data[v]) const filteredData = dataRes.filter(item => item.parent === null);
for (const v in filteredData) {
arr.push(filteredData[v])
} }
setDataDivisions(arr); setDataDivisions(arr);
} else { } else {
@ -97,7 +100,7 @@ const ProjectType = ({ params }) => {
"orders": { "orders": {
"ascending": true, "ascending": true,
"columns": [ "columns": [
'id' 'name'
] ]
}, },
"paging": { "paging": {
@ -183,7 +186,8 @@ const ProjectType = ({ params }) => {
}; };
const handleOpenDialog = (type) => { const handleOpenDialog = (type) => {
setOpenDialog(true) setOpenDialog(true)
getListDivision();
setTypeDialog(type) setTypeDialog(type)
} }
@ -348,7 +352,16 @@ const ProjectType = ({ params }) => {
</Tooltip> </Tooltip>
</td> </td>
<td>{n.name}</td> <td>{n.name}</td>
<td>{n.description}</td> <td>{n.description ?? '-'}</td>
{n.color != null ? (
<td>
<Tooltip title={n.color}>
<span className="fa fa-square" style={{ color: n.color }}></span>
</Tooltip>
</td>
): (
<td><small style={{ color:"grey",fontStyle:"italic" }}>No color set</small></td>
)}
</tr> </tr>
) )
})} })}

41
src/views/SimproV2/Divisi/styles.css

@ -0,0 +1,41 @@
.App {
font-family: sans-serif;
padding: 20px;
}
h2 {
margin-top: 40px;
}
.rc-color-picker-panel {
border: 1px solid #ccc;
}
.rc-color-picker-panel-inner {
border: none;
box-shadow: none;
}
.rc-color-picker-panel-board-hsv {
border-radius: 12px;
outline: none;
}
.rc-color-picker-panel-board-value {
border: none;
border-radius: 12px;
}
.rc-color-picker-panel-board-saturation {
border: none;
border-radius: 12px;
}
.rc-color-picker-panel-ribbon {
border-radius: 12px;
}
.rc-color-picker-panel-wrap-preview {
border-radius: 12px;
}
.rc-color-picker-panel-preview span {
border-radius: 12px;
}
.rc-color-picker-panel-preview input {
border-radius: 12px;
}
Loading…
Cancel
Save