diff --git a/package.json b/package.json index c698e3b..f958efc 100644 --- a/package.json +++ b/package.json @@ -1,142 +1,142 @@ -{ - "name": "simpro-web", - "version": "0.0.1", - "description": "Sistem Informasi Manajemen Proyek", - "author": "Ardhi", - "homepage": ".", - "copyright": "Copyright Integrasia Utama", - "license": "MIT", - "private": true, - "repository": { - "type": "http", - "url": "https://git.oslog.id/iu/simpro-website.git" - }, - "dependencies": { - "@ant-design/plots": "^1.1.1", - "@ckeditor/ckeditor5-build-classic": "^39.0.2", - "@ckeditor/ckeditor5-react": "^6.1.0", - "@coreui/coreui": "^2.1.12", - "@coreui/icons": "0.3.0", - "@coreui/react": "^2.5.1", - "@dabeng/react-orgchart": "^1.0.0", - "@develoka/angka-rupiah-js": "^1.0.3", - "@faker-js/faker": "^7.3.0", - "@iconify/icons-ant-design": "^1.0.6", - "@iconify/icons-fa-solid": "^1.0.6", - "@iconify/icons-fe": "^1.0.3", - "@iconify/icons-geo": "^1.0.3", - "@iconify/icons-ion": "^1.0.7", - "@iconify/icons-mdi": "^1.0.57", - "@iconify/icons-uil": "^1.0.6", - "@iconify/react": "^1.1.1", - "@nicholasadamou/react-iframe": "^1.0.3", - "@reduxjs/toolkit": "^1.9.2", - "@terrestris/ol-util": "^7.2.0", - "@terrestris/react-geo": "^12.0.0", - "alasql": "^1.7.3", - "antd": "^4.16.13", - "axios": "^0.21.1", - "bootstrap": "^4.3.1", - "chart.js": "^3.9.1", - "chartjs-plugin-datalabels": "^2.1.0", - "chartjs-plugin-zoom": "^0.7.7", - "classnames": "^2.2.6", - "core-js": "^3.1.4", - "dhtmlx-gantt": "^7.1.7", - "dom-to-image": "^2.6.0", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.14.0", - "flag-icon-css": "^3.3.0", - "font-awesome": "^4.7.0", - "i18next": "^22.4.9", - "interactjs": "^1.10.11", - "jspdf": "^2.5.1", - "jspdf-autotable": "^3.5.25", - "leaflet": "^1.8.0", - "leaflet-control-geocoder": "^2.4.0", - "leaflet-draw": "^1.0.4", - "leaflet.markercluster": "^1.5.3", - "moment": "^2.24.0", - "node-sass": "^4.12.0", - "numeral": "^2.0.6", - "ol": "^5.3.3", - "prop-types": "^15.7.2", - "rc-color-picker": "^1.2.6", - "re-resizable": "^6.9.9", - "react": "^16.14.0", - "react-app-polyfill": "^1.0.1", - "react-awesome-query-builder": "^4.3.0", - "react-bootstrap-sweetalert": "^5.1.9", - "react-bootstrap-table-next": "^3.3.3", - "react-bootstrap-table2-editor": "^1.4.0", - "react-bootstrap-table2-paginator": "^2.1.0", - "react-bootstrap-table2-toolkit": "^2.1.1", - "react-calendar-timeline": "^0.27.0", - "react-chartjs-2": "^4.3.1", - "react-color": "^2.17.3", - "react-content-loader": "^6.0.3", - "react-dom": "^16.14.0", - "react-excel-renderer": "^1.1.0", - "react-grid-layout": "^1.2.5", - "react-highlight-words": "^0.18.0", - "react-i18next": "^12.1.5", - "react-leaflet": "^3.2.0", - "react-leaflet-draw": "^0.19.8", - "react-loader-spinner": "^3.1.5", - "react-notifications": "^1.7.2", - "react-redux": "^8.0.5", - "react-router-dom": "^5.0.1", - "react-select": "^4.3.1", - "react-slick": "^0.28.1", - "react-tiny-fab": "^4.0.4", - "react-toastify": "^5.5.0", - "reactstrap": "^8.0.0", - "redux": "^4.2.1", - "redux-persist": "^6.0.0", - "redux-thunk": "^2.4.2", - "simple-line-icons": "^2.4.1", - "slick-carousel": "^1.8.1", - "underscore": "^1.13.1", - "xlsx": "^0.17.0" - }, - "devDependencies": { - "@babel/core": "^7.14.5", - "babel-plugin-module-resolver": "^4.1.0", - "clean-webpack-plugin": "^3.0.0", - "cypress": "^12.17.2", - "react-scripts": "^3.0.1", - "webpack-sources": "1.0.1" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts --max_old_space_size=8096 build", - "test": "react-scripts test", - "test:cov": "npm test -- --coverage --watchAll=false", - "test:debug": "react-scripts --inspect-brk test --runInBand", - "eject": "react-scripts eject" - }, - "bugs": { - "url": "https://git.oslog.id/iu/simpro-website/issues" - }, - "eslintConfig": { - "extends": "react-app" - }, - "browserslist": [ - ">0.2%", - "not dead", - "not ie <= 9", - "not op_mini all" - ], - "jest": { - "collectCoverageFrom": [ - "src/**/*.{js,jsx}", - "!**/*index.js", - "!src/serviceWorker.js", - "!src/polyfill.js" - ] - }, - "engines": { - "node": ">=8.10", - "npm": ">=6" - } -} +{ + "name": "simpro-web", + "version": "0.0.1", + "description": "Sistem Informasi Manajemen Proyek", + "author": "Ardhi", + "homepage": ".", + "copyright": "Copyright Integrasia Utama", + "license": "MIT", + "private": true, + "repository": { + "type": "http", + "url": "https://git.oslog.id/iu/simpro-website.git" + }, + "dependencies": { + "@ant-design/plots": "^1.1.1", + "@ckeditor/ckeditor5-build-classic": "^39.0.2", + "@ckeditor/ckeditor5-react": "^6.1.0", + "@coreui/coreui": "^2.1.12", + "@coreui/icons": "0.3.0", + "@coreui/react": "^2.5.1", + "@dabeng/react-orgchart": "^1.0.0", + "@develoka/angka-rupiah-js": "^1.0.3", + "@faker-js/faker": "^7.3.0", + "@iconify/icons-ant-design": "^1.0.6", + "@iconify/icons-fa-solid": "^1.0.6", + "@iconify/icons-fe": "^1.0.3", + "@iconify/icons-geo": "^1.0.3", + "@iconify/icons-ion": "^1.0.7", + "@iconify/icons-mdi": "^1.0.57", + "@iconify/icons-uil": "^1.0.6", + "@iconify/react": "^1.1.1", + "@nicholasadamou/react-iframe": "^1.0.3", + "@reduxjs/toolkit": "^1.9.2", + "@terrestris/ol-util": "^7.2.0", + "@terrestris/react-geo": "^12.0.0", + "alasql": "^1.7.3", + "antd": "^4.16.13", + "axios": "^0.21.1", + "bootstrap": "^4.3.1", + "chart.js": "^3.9.1", + "chartjs-plugin-datalabels": "^2.1.0", + "chartjs-plugin-zoom": "^0.7.7", + "classnames": "^2.2.6", + "core-js": "^3.1.4", + "dhtmlx-gantt": "^7.1.7", + "dom-to-image": "^2.6.0", + "enzyme": "^3.10.0", + "enzyme-adapter-react-16": "^1.14.0", + "flag-icon-css": "^3.3.0", + "font-awesome": "^4.7.0", + "i18next": "^22.4.9", + "interactjs": "^1.10.11", + "jspdf": "^2.5.1", + "jspdf-autotable": "^3.5.25", + "leaflet": "^1.8.0", + "leaflet-control-geocoder": "^2.4.0", + "leaflet-draw": "^1.0.4", + "leaflet.markercluster": "^1.5.3", + "moment": "^2.24.0", + "node-sass": "^4.12.0", + "numeral": "^2.0.6", + "ol": "^5.3.3", + "prop-types": "^15.7.2", + "rc-color-picker": "^1.2.6", + "re-resizable": "^6.9.9", + "react": "^16.14.0", + "react-app-polyfill": "^1.0.1", + "react-awesome-query-builder": "^4.3.0", + "react-bootstrap-sweetalert": "^5.1.9", + "react-bootstrap-table-next": "^3.3.3", + "react-bootstrap-table2-editor": "^1.4.0", + "react-bootstrap-table2-paginator": "^2.1.0", + "react-bootstrap-table2-toolkit": "^2.1.1", + "react-calendar-timeline": "^0.27.0", + "react-chartjs-2": "^4.3.1", + "react-color": "^2.17.3", + "react-content-loader": "^6.0.3", + "react-dom": "^16.14.0", + "react-excel-renderer": "^1.1.0", + "react-grid-layout": "^1.2.5", + "react-highlight-words": "^0.18.0", + "react-i18next": "^12.1.5", + "react-leaflet": "^3.2.0", + "react-leaflet-draw": "^0.19.8", + "react-loader-spinner": "^3.1.5", + "react-notifications": "^1.7.2", + "react-redux": "^8.0.5", + "react-router-dom": "^5.0.1", + "react-select": "^4.3.1", + "react-slick": "^0.28.1", + "react-tiny-fab": "^4.0.4", + "react-toastify": "^5.5.0", + "reactstrap": "^8.0.0", + "redux": "^4.2.1", + "redux-persist": "^6.0.0", + "redux-thunk": "^2.4.2", + "simple-line-icons": "^2.4.1", + "slick-carousel": "^1.8.1", + "underscore": "^1.13.1", + "xlsx": "^0.17.0" + }, + "devDependencies": { + "@babel/core": "^7.14.5", + "babel-plugin-module-resolver": "^4.1.0", + "clean-webpack-plugin": "^3.0.0", + "cypress": "^12.17.2", + "react-scripts": "^3.0.1", + "webpack-sources": "1.0.1" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts --max_old_space_size=8096 build", + "test": "react-scripts test", + "test:cov": "npm test -- --coverage --watchAll=false", + "test:debug": "react-scripts --inspect-brk test --runInBand", + "eject": "react-scripts eject" + }, + "bugs": { + "url": "https://git.oslog.id/iu/simpro-website/issues" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 9", + "not op_mini all" + ], + "jest": { + "collectCoverageFrom": [ + "src/**/*.{js,jsx}", + "!**/*index.js", + "!src/serviceWorker.js", + "!src/polyfill.js" + ] + }, + "engines": { + "node": ">=8.10", + "npm": ">=6" + } +} diff --git a/src/const/ApiConst.js b/src/const/ApiConst.js index 7e9365c..4241749 100644 --- a/src/const/ApiConst.js +++ b/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_SEARCH = `${BASE_SIMPRO_LUMEN}/role/search`; +export const ROLE_LIST = `${BASE_SIMPRO_LUMEN}/role/list`; export const ROLE_EDIT = (id) => { return `${BASE_SIMPRO_LUMEN}/role/update/${id}`; }; @@ -340,6 +341,7 @@ export const MENU_MANAGEMENT = (id) => { return `${BASE_SIMPRO_LUMEN}/menu/management/${id}`; }; export const MENU_SEARCH = `${BASE_SIMPRO_LUMEN}/menu/search`; +export const MENU_LIST = `${BASE_SIMPRO_LUMEN}/menu/list`; export const MENU_EDIT = (id) => { return `${BASE_SIMPRO_LUMEN}/menu/update/${id}`; }; diff --git a/src/views/Dashboard/DashboardBOD.js b/src/views/Dashboard/DashboardBOD.js index fff92ef..87625f3 100644 --- a/src/views/Dashboard/DashboardBOD.js +++ b/src/views/Dashboard/DashboardBOD.js @@ -244,8 +244,10 @@ const DashboardBOD = () => { return; } - if (result.status == 200 && result.data.data) { - SET_PROJECT_PER_DIVISION(result.data.data); + if (result.status == 200 && 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); } @@ -311,7 +313,7 @@ const DashboardBOD = () => { 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] } - + selisihProgress = planningProgress - actualProgress if (selisihProgress > 0 && selisihProgress <= 5) { @@ -611,8 +613,8 @@ const DashboardBOD = () => { label: "", // data: [7, 2, 4, 3], data: PROJECT_PER_DIVISION ? PROJECT_PER_DIVISION.map((item, idx) => item.total) : [], - borderColor: ["#023E8A", "#C851B7", "#FD7034", "#3A0CA3", "#A36A16"], - backgroundColor: ["#023E8A", "#C851B7", "#FD7034", "#3A0CA3", "#A36A16"], + borderColor: PROJECT_PER_DIVISION ? PROJECT_PER_DIVISION.map((item, idx) => item.color) : [], + backgroundColor: PROJECT_PER_DIVISION ? PROJECT_PER_DIVISION.map((item, idx) => item.color) : [], borderWidth: 2, borderSkipped: false }, diff --git a/src/views/Master/MasterBroadcast/DialogDetail.js b/src/views/Master/MasterBroadcast/DialogDetail.js index b4b96cc..b269bf8 100644 --- a/src/views/Master/MasterBroadcast/DialogDetail.js +++ b/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 Select from 'react-select'; 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 { withTranslation } from 'react-i18next'; const token = window.localStorage.getItem('token'); @@ -43,6 +43,7 @@ class DialogDetail extends Component { }, () => { this.getDataDetail(); this.getDataUsers(); + this.getDataRoles(); 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 () => { countError++; let url = BASE_SIMPRO_LUMEN + `/broadcast/search`; @@ -85,6 +98,7 @@ class DialogDetail extends Component { if (countError < 6) { this.getDataDetail(); this.getDataUsers(); + this.getDataRoles(); } } } @@ -97,7 +111,10 @@ class DialogDetail extends Component { this.props.closeDialog() } render() { + const dataListDetail = this.state.dataListDetail || []; const dataUser = this.state.dataUser || []; + const dataRoles = this.state.dataRoles || []; + return ( {this.props.t('broadcastDetail')} @@ -114,14 +131,42 @@ class DialogDetail extends Component { - {this.state.dataListDetail.map((val, index) => { - const matchedUser = dataUser.find(item => item.id == val.send_to_id); + {dataListDetail.map((val, index) => { + 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 ?
{"- " + matchedUser.name}
: 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 ?
{matchedUser.name}
: 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 ?
Role {matchedRole.name}
: null; + } + return ( {val.status_send === "" ? "-" : val.status_send} - {val.created_at === "" ? "-" : moment(val.created_date).format("DD-MM-YYYY HH:mm:ss")} + {val.created_at === "" ? "-" : moment(val.created_at).format("DD-MM-YYYY HH:mm:ss")} {val.description === "" ? "-" : val.description} - { matchedUser ? matchedUser.name : "-" } + + {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] : ""} + {val.title_notif === "" ? "-" : val.title_notif} {val.message_notif === "" ? "-" : val.message_notif} diff --git a/src/views/Master/MasterBroadcast/index.js b/src/views/Master/MasterBroadcast/index.js index 9cadec4..dfc989a 100644 --- a/src/views/Master/MasterBroadcast/index.js +++ b/src/views/Master/MasterBroadcast/index.js @@ -5,7 +5,7 @@ import React, { Component } from 'react'; import SweetAlert from 'react-bootstrap-sweetalert'; import axios from 'axios'; 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 { DatePicker, Pagination } from 'antd'; import { NotificationContainer, NotificationManager } from 'react-notifications'; @@ -92,8 +92,30 @@ class index extends Component { console.log('Get Data User', result) 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) { this.setState({ dataTable: result.data.data, totalPage: result.data.totalRecord }); this.getDataUsers() + this.getDataRoles() } else { NotificationManager.error('Failed retreiving data!!', 'Failed'); } @@ -326,18 +349,47 @@ class index extends Component { handleExportExcel = async () => { const dataExcel = this.state.dataTable || []; const dataUser = this.state.dataUser || []; + const dataRoles = this.state.dataRoles || []; + const dataExport = []; 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 ?
{"- " + matchedUser.name}
: 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 ?
{matchedUser.name}
: 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 ?
{matchedRole.name}
: null; + } + let row = { "Tanggal Broadcast": moment(val.created_at).format("YYYY-MM-DD HH:mm:ss"), "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, "Deskripsi": val.description, "Status": val.status_send - } + }; dataExport.push(row); + }); const fileName = "Broadcast.xlsx"; const ws = XLSX.utils.json_to_sheet(dataExport); @@ -399,14 +451,37 @@ class index extends Component { ] const dataTable2 = this.state.dataTable || []; const dataUser = this.state.dataUser || []; - + const dataRoles = this.state.dataRoles || []; return ( - {dataTable2.length !== 0 ? dataTable2.map((n) => { - const matchedUser = dataUser.find(item => item.id == n.send_to_id); - return ( - - + {dataTable2.length !== 0 ? dataTable2.map((n, index) => { + const matchedUserNames = []; + const matchedUserNamesNotKoma = []; + const matchRolesName = []; + + 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 ?
{"- " + matchedUser.name}
: 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 ?
{matchedUser.name}
: 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 ?
Role {matchedRole.name}
: null; + } + + return ( + + {n.status_send === 'completed' || n.status_send === 'failed' || n.status_send === 'send' || n.status_send === 'resend' ? this.renderBtnResend(n.id) : @@ -418,15 +493,21 @@ class index extends Component { Detail - - {n.title_notif} - {n.message_notif !== "" ? n.message_notif : "-"} - {n.description !== "" ? n.description : "-"} - { matchedUser ? matchedUser.name : "-" } - {n.status_send !== "" ? n.status_send : "-"} - {n.created_at !== "" ? moment.utc(n.created_at).format("DD-MM-YYYY HH:mm:ss") : "-"} - - ); + + + {n.title_notif} + {n.message_notif !== "" ? n.message_notif : "-"} + {n.description !== "" ? n.description : "-"} + + {n.send_to_type === "all" ? "All User" : ""} + {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] : ""} + + {n.status_send !== "" ? n.status_send : "-"} + {n.created_at !== "" ? moment(n.created_at).format("DD-MM-YYYY HH:mm:ss") : "-"} + + ); }) : {this.props.t('noData')} diff --git a/src/views/Master/MasterMenu/index.js b/src/views/Master/MasterMenu/index.js index 3c78402..7c0e9bc 100644 --- a/src/views/Master/MasterMenu/index.js +++ b/src/views/Master/MasterMenu/index.js @@ -5,7 +5,7 @@ import SweetAlert from 'react-bootstrap-sweetalert'; import axios from 'axios'; import { Button } 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 { Pagination, Tooltip, Table } from 'antd'; import { useTranslation } from 'react-i18next'; @@ -67,23 +67,21 @@ const Index = ({ params }) => { }; 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 - .post(MENU_SEARCH, payload, config) - .then(res => res) - .catch((error) => error.response); + .get(MENU_LIST, config) + .then(res => res) + .catch((error) => error.response); if (result && result.data && result.data.code == 200) { - setAllDataMenu(result.data.data); - } else { - } + let arr = [] + 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 () => { @@ -123,6 +121,7 @@ const Index = ({ params }) => { const handleOpenDialog = async (type) => { await setTypeDialog(type) + getDataAllMenu(); setOpenDialog(true) } diff --git a/src/views/SimproV2/CreatedProyek/AsignCustProject.js b/src/views/SimproV2/CreatedProyek/AsignCustProject.js index 1b9a70c..dca803a 100644 --- a/src/views/SimproV2/CreatedProyek/AsignCustProject.js +++ b/src/views/SimproV2/CreatedProyek/AsignCustProject.js @@ -32,11 +32,6 @@ const AssignCustProject = ({ openDialog, closeDialog, toggleDialog, idTask, proy } }, [openDialog]); - useEffect(() => { - if (openDialog) { - } - }, [dataUserToProject]) - const getDataAssignHr = async () => { const payload = { "paging": { @@ -45,7 +40,8 @@ const AssignCustProject = ({ openDialog, closeDialog, toggleDialog, idTask, proy }, "columns": [ { "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": [ { "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) => { - if (type === "add") getDataAssignHr(); + if (type === "add") { + getDataAssignHr() + } if (type === "success") { NotificationManager.success( `Assign Customer Project berhasil disimpan!`, diff --git a/src/views/SimproV2/CreatedProyek/AsignHrProject.js b/src/views/SimproV2/CreatedProyek/AsignHrProject.js index 4abb8a7..ff990b1 100644 --- a/src/views/SimproV2/CreatedProyek/AsignHrProject.js +++ b/src/views/SimproV2/CreatedProyek/AsignHrProject.js @@ -1,304 +1,305 @@ -import React, { useEffect, useState, useMemo } from 'react' -import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; -import { Button, Form } from 'reactstrap'; -import { Table, Tooltip } from 'antd'; -import 'antd/dist/antd.css'; -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 axios from "../../../const/interceptorApi" -import { NotificationContainer, NotificationManager } from 'react-notifications'; -import SweetAlert from 'react-bootstrap-sweetalert'; -import FormAsignHr from './FormAsignHr'; -import { formatThousand } from '../../../const/CustomFunc'; - -const AssignHrProject = ({ openDialog, closeDialog, toggleDialog, idTask, toolsResource, proyekName }) => { - const token = localStorage.getItem("token") - const HEADER = { - headers: { - "Content-Type": "application/json", - "Authorization": `Bearer ${token}` - } - } - const [dataUserToProject, setdataUserToProject] = useState([]) - const [alertDelete, setAlertDelete] = useState(false) - const [idDelete, setIdDelete] = useState(0) - const [openDialogFormTools, setOpenDialogFormTools] = useState(false) - const [dataEdit, setDataEdit] = useState(null) - const [listUser, setListUser] = useState([]) - const [listRole, setListRole] = useState([]) - - useEffect(() => { - if (idTask > 0) { - getDataAssignHr(); - } - }, [openDialog]); - - useEffect(() => { - if (openDialog) { - getDataProjectRole(); - getDataUser(); - } - }, [dataUserToProject]) - - const getDataAssignHr = async () => { - const payload = { - "paging": { - "start": 0, - "length": -1 - }, - "columns": [ - { "name": "name", "logic_operator": "ilike", "value": "", "table_name": "m_users" }, - { "name": "proyek_id", "logic_operator": "=", "value": idTask } - ], - "joins": [ - { "name": "m_users", "column_join": "user_id", "column_results": ["name"] }, - { "name": "m_role_proyek", "column_join": "project_role", "column_results": ["name"] }, - ], - "orders": { - "columns": [ - "id" - ], - "ascending": false - } - } - const URL = ASSIGN_HR_PROJECT_SEARCH - const result = await axios - .post(URL, payload, HEADER) - .then(res => res) - .catch((error) => error.response); - - if (result && result.data && result.data.code == 200) { - let dataRes = result.data.data || [] - - setdataUserToProject(dataRes); - } else { - NotificationManager.error('Gagal Mengambil Data!!', 'Failed'); - } - } - - const getDataUser = async () => { - const HEADER_ADW = { - headers: { - "Authorization": `${TOKEN_ADW}` - } - } - const result = await axios - // .get(`${API_ADW}employees`, HEADER_ADW) - .get(USER_LIST, HEADER) - .then(res => res) - .catch((error) => error.response); - if (result && result.data && result.data.data.length != 0) { - let dataRes = result.data.data - setListUser(dataRes) - } - } - - const getDataProjectRole = async () => { - const payload = { - "paging": { - "start": 0, - "length": -1 - }, - "columns": [ - { "name": "created_by", "logic_operator": "ilike", "value": "" }, - ], - "joins": [], - "orders": { - "columns": [ - "id" - ], - "ascending": false - } - } - - const result = await axios - .post(PROJECT_ROLE_SEARCH, payload, HEADER) - .then(res => res) - .catch((error) => error.response); - - if (result && result.data && result.data.code == 200) { - let dataRes = result.data.data || [] - setListRole(dataRes); - } else { - } - } - - const handleDelete = (id) => { - setIdDelete(id) - setAlertDelete(true) - } - - const cancelDelete = () => { - setAlertDelete(false) - setIdDelete(0) - } - - const onConfirmDelete = async () => { - let urlDel = ASSIGN_HR_PROJECT_DELETE(idDelete) - const result = await axios.delete(urlDel, HEADER) - .then(res => res) - .catch((error) => error.response); - - if (result && result.data && result.data.code === 200) { - getDataAssignHr() - setIdDelete(0) - setAlertDelete(false) - NotificationManager.success(`Data assign human resource berhasil dihapus`, 'Success!!'); - } else { - setIdDelete(0) - setAlertDelete(false) - NotificationManager.error(`Data assign human resource gagal dihapus`, 'Failed!!'); - } - } - - const handleEdit = async (data) => { - await setDataEdit(data) - setOpenDialogFormTools(true) - } - - const handleOpenDialogFormTools = () => { - setOpenDialogFormTools(true) - } - - const handleCancel = () => { - closeDialog('cancel', 'none') - } - - - const RenderTable = useMemo(() => { - const columns = [ - { - title: 'Action', - dataIndex: '', - key: 'x', - className: "nowrap", - render: (text, record) => <> - - {" "} - - , - }, - { 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: 'Percentage Available User', dataIndex: 'max_used', key: 'max_used', className: "nowrap", render: (text, record) => record.max_used ? formatThousand(record.max_used) : '-' }, - { title: 'Standard Rate', dataIndex: 'standart_rate', key: 'standart_rate', className: "nowrap", render: (text, record) => record.standart_rate ? formatThousand(record.standart_rate) : '-' }, - { title: 'UOM Standard Rate', dataIndex: 'uom_standart_rate', key: 'uom_standart_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 ( - - ) - }, [dataUserToProject]) - - const renderForm = () => { - return ( -
- {RenderTable} -
- ) - } - - const handleCloseDialogFormTools = (type, data) => { - if(type=="add"){ - addDataAssignHr(data); - }else if(type=="edit"){ - editDataAssignHr(data); - }else{ - setDataEdit(null) - setOpenDialogFormTools(false) - } - } - - const addDataAssignHr = async (payload) => { - const result = await axios - .post(ASSIGN_HR_PROJECT_ADD, payload, HEADER) - .then(res => res) - .catch((error) => error.response); - - if (result && result.data && result.data.code == 200) { - getDataAssignHr(); - NotificationManager.success('assign human resource berhasil!!', 'Success'); - setDataEdit(null) - setOpenDialogFormTools(false) - } else { - NotificationManager.error('assign human resource gagal!!', 'Failed'); - } - } - - const editDataAssignHr = async (payload) => { - let url = ASSIGN_HR_PROJECT_EDIT(payload.id) - const result = await axios - .put(url, payload, HEADER) - .then(res => res) - .catch((error) => error.response); - - if (result && result.data && result.data.code == 200) { - getDataAssignHr(); - NotificationManager.success('assign human resource berhasil diedit!!', 'Success'); - setDataEdit(null) - setOpenDialogFormTools(false) - } else { - NotificationManager.error('assign human resource gagal diedit!!', 'Failed'); - } - } - - const toogleDialogFormTools = () => { - if (openDialogFormTools) { - setDataEdit(null) - } - setOpenDialogFormTools(!openDialogFormTools) - } - - - return ( - <> - - cancelDelete()} - focusCancelBtn - > - Delete this data - - - - -
Assign Human Resource - {proyekName}
-
- - {renderForm()} - - {/* - - */} -
- - - ) - -} - -export default AssignHrProject; +import React, { useEffect, useState, useMemo } from 'react' +import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +import { Button, Form } from 'reactstrap'; +import { Table, Tooltip } from 'antd'; +import 'antd/dist/antd.css'; +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 axios from "../../../const/interceptorApi" +import { NotificationContainer, NotificationManager } from 'react-notifications'; +import SweetAlert from 'react-bootstrap-sweetalert'; +import FormAsignHr from './FormAsignHr'; +import { formatThousand } from '../../../const/CustomFunc'; + +const AssignHrProject = ({ openDialog, closeDialog, toggleDialog, idTask, toolsResource, proyekName }) => { + const token = localStorage.getItem("token") + const HEADER = { + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}` + } + } + const [dataUserToProject, setdataUserToProject] = useState([]) + const [alertDelete, setAlertDelete] = useState(false) + const [idDelete, setIdDelete] = useState(0) + const [openDialogFormTools, setOpenDialogFormTools] = useState(false) + const [dataEdit, setDataEdit] = useState(null) + const [listUser, setListUser] = useState([]) + const [listRole, setListRole] = useState([]) + + useEffect(() => { + if (idTask > 0) { + getDataAssignHr(); + } + }, [openDialog]); + + useEffect(() => { + if (openDialog) { + getDataProjectRole(); + getDataUser(); + } + }, [dataUserToProject]) + + const getDataAssignHr = async () => { + const payload = { + "paging": { + "start": 0, + "length": -1 + }, + "columns": [ + { "name": "name", "logic_operator": "ilike", "value": "", "table_name": "m_users" }, + { "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"] }, + { "name": "m_role_proyek", "column_join": "project_role", "column_results": ["name"] }, + ], + "orders": { + "columns": [ + "id" + ], + "ascending": false + } + } + const URL = ASSIGN_HR_PROJECT_SEARCH + const result = await axios + .post(URL, payload, HEADER) + .then(res => res) + .catch((error) => error.response); + + if (result && result.data && result.data.code == 200) { + let dataRes = result.data.data || [] + + setdataUserToProject(dataRes); + } else { + NotificationManager.error('Gagal Mengambil Data!!', 'Failed'); + } + } + + const getDataUser = async () => { + const HEADER_ADW = { + headers: { + "Authorization": `${TOKEN_ADW}` + } + } + const result = await axios + // .get(`${API_ADW}employees`, HEADER_ADW) + .get(USER_LIST, HEADER) + .then(res => res) + .catch((error) => error.response); + if (result && result.data && result.data.data.length != 0) { + let dataRes = result.data.data + setListUser(dataRes) + } + } + + const getDataProjectRole = async () => { + const payload = { + "paging": { + "start": 0, + "length": -1 + }, + "columns": [ + { "name": "created_by", "logic_operator": "ilike", "value": "" }, + ], + "joins": [], + "orders": { + "columns": [ + "id" + ], + "ascending": false + } + } + + const result = await axios + .post(PROJECT_ROLE_SEARCH, payload, HEADER) + .then(res => res) + .catch((error) => error.response); + + if (result && result.data && result.data.code == 200) { + let dataRes = result.data.data || [] + setListRole(dataRes); + } else { + } + } + + const handleDelete = (id) => { + setIdDelete(id) + setAlertDelete(true) + } + + const cancelDelete = () => { + setAlertDelete(false) + setIdDelete(0) + } + + const onConfirmDelete = async () => { + let urlDel = ASSIGN_HR_PROJECT_DELETE(idDelete) + const result = await axios.delete(urlDel, HEADER) + .then(res => res) + .catch((error) => error.response); + + if (result && result.data && result.data.code === 200) { + getDataAssignHr() + setIdDelete(0) + setAlertDelete(false) + NotificationManager.success(`Data assign human resource berhasil dihapus`, 'Success!!'); + } else { + setIdDelete(0) + setAlertDelete(false) + NotificationManager.error(`Data assign human resource gagal dihapus`, 'Failed!!'); + } + } + + const handleEdit = async (data) => { + await setDataEdit(data) + setOpenDialogFormTools(true) + } + + const handleOpenDialogFormTools = () => { + setOpenDialogFormTools(true) + } + + const handleCancel = () => { + closeDialog('cancel', 'none') + } + + + const RenderTable = useMemo(() => { + const columns = [ + { + title: 'Action', + dataIndex: '', + key: 'x', + className: "nowrap", + render: (text, record) => <> + + {" "} + + , + }, + { 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: 'Percentage Available User', dataIndex: 'max_used', key: 'max_used', className: "nowrap", render: (text, record) => record.max_used ? formatThousand(record.max_used) : '-' }, + { title: 'Standard Rate', dataIndex: 'standart_rate', key: 'standart_rate', className: "nowrap", render: (text, record) => record.standart_rate ? formatThousand(record.standart_rate) : '-' }, + { title: 'UOM Standard Rate', dataIndex: 'uom_standart_rate', key: 'uom_standart_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 ( +
+ ) + }, [dataUserToProject]) + + const renderForm = () => { + return ( +
+ {RenderTable} +
+ ) + } + + const handleCloseDialogFormTools = (type, data) => { + if(type=="add"){ + addDataAssignHr(data); + }else if(type=="edit"){ + editDataAssignHr(data); + }else{ + setDataEdit(null) + setOpenDialogFormTools(false) + } + } + + const addDataAssignHr = async (payload) => { + const result = await axios + .post(ASSIGN_HR_PROJECT_ADD, payload, HEADER) + .then(res => res) + .catch((error) => error.response); + + if (result && result.data && result.data.code == 200) { + getDataAssignHr(); + NotificationManager.success('assign human resource berhasil!!', 'Success'); + setDataEdit(null) + setOpenDialogFormTools(false) + } else { + NotificationManager.error('assign human resource gagal!!', 'Failed'); + } + } + + const editDataAssignHr = async (payload) => { + let url = ASSIGN_HR_PROJECT_EDIT(payload.id) + const result = await axios + .put(url, payload, HEADER) + .then(res => res) + .catch((error) => error.response); + + if (result && result.data && result.data.code == 200) { + getDataAssignHr(); + NotificationManager.success('assign human resource berhasil diedit!!', 'Success'); + setDataEdit(null) + setOpenDialogFormTools(false) + } else { + NotificationManager.error('assign human resource gagal diedit!!', 'Failed'); + } + } + + const toogleDialogFormTools = () => { + if (openDialogFormTools) { + setDataEdit(null) + } + setOpenDialogFormTools(!openDialogFormTools) + } + + + return ( + <> + + cancelDelete()} + focusCancelBtn + > + Delete this data + + + + +
Assign Human Resource - {proyekName}
+
+ + {renderForm()} + + {/* + + */} +
+ + + ) + +} + +export default AssignHrProject; diff --git a/src/views/SimproV2/CreatedProyek/DialogAssignCust.js b/src/views/SimproV2/CreatedProyek/DialogAssignCust.js index 940250c..c680615 100644 --- a/src/views/SimproV2/CreatedProyek/DialogAssignCust.js +++ b/src/views/SimproV2/CreatedProyek/DialogAssignCust.js @@ -3,7 +3,7 @@ import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; import { Button, Form } from 'reactstrap'; import axios from "../../../const/interceptorApi"; import { - USER_LIST, + USER_SEARCH, ASSIGN_HR_PROJECT_SEARCH, ASSIGN_HR_PROJECT_ADD_MULTIPLE } from '../../../const/ApiConst'; @@ -40,8 +40,29 @@ const DialogAssignCust = ({ openDialog, closeDialog, toggleDialog, idTask }) => 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 - .get(USER_LIST, HEADER) + .post(URL, payload, HEADER) .then(res => res) .catch((error) => error.response); @@ -99,6 +120,12 @@ const DialogAssignCust = ({ openDialog, closeDialog, toggleDialog, idTask }) => const getCustProject = async () => { const payload = { + "select": [ + "id", + "user_id", + "proyek_id", + "is_customer" + ], "columns": [ { "name": "proyek_id", "logic_operator": "=", "value": idTask }, {"name": "is_customer", "logic_operator": "=", "value": "true"} diff --git a/src/views/SimproV2/CreatedProyek/DialogFormProyek.js b/src/views/SimproV2/CreatedProyek/DialogFormProyek.js index 6547f98..e09fd47 100644 --- a/src/views/SimproV2/CreatedProyek/DialogFormProyek.js +++ b/src/views/SimproV2/CreatedProyek/DialogFormProyek.js @@ -200,6 +200,7 @@ const DialogFormProyek = ({ setFinance(""); setWorkArea(""); setProjectDuration(""); + setDivisiProject(null); setProjectStructureOrg(null); setCompany(""); setCurrency(""); @@ -331,18 +332,35 @@ const DialogFormProyek = ({ setHealthBudget(val); }; - const onChangePm = (val) => { - let data = [...dataPM]; - var item = data.find((item) => item.id === val); - participants.push({ - id: lastIdxParticipants + 1, - title: "PM", - name: item.name, - }); - setParticipants(participants); - setLastIdxParticipants(lastIdxParticipants + 1); - setPic(val); - }; + const onChangePm = (val) => { + const item = dataPM.find((item) => item.id === val); + const existingParticipant = participants.find((participant) => participant.tittle === "PM"); + if (existingParticipant) { + setParticipants((prevParticipants) => { + return prevParticipants.map((participant) => { + if (participant.tittle === "PM") { + return { + ...participant, + name: item.name, + }; + } + return participant; + }); + }); + } else { + setParticipants((prevParticipants) => [ + ...prevParticipants, + { + id: item.id, + tittle: "PM", + name: item.name, + }, + ]); + setLastIdxParticipants(lastIdxParticipants + 1); + } + + setPic(val); + }; const onChangeCurrency = (val) => { let curr = val.split("|"); // code|symbol|name @@ -398,7 +416,7 @@ const DialogFormProyek = ({ const addParticipant = () => { participants.push({ id: lastIdxParticipants + 1, - title: "", + tittle: "", name: "", }); setParticipants(participants); @@ -437,7 +455,24 @@ const DialogFormProyek = ({ }; 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]; newParticipants[index][name] = value; setParticipants(newParticipants); @@ -565,7 +600,7 @@ const DialogFormProyek = ({ const addApproval = () => { approval.push({ id: lastIdxApproval + 1, - title: "", + tittle: "", name: "", date: moment(), }); @@ -611,7 +646,7 @@ const DialogFormProyek = ({
- - + - - - - + - + - - + - + - + - + - + - + - + - + - Item +

Item

- Availability +

Availability

- Action +

Action

@@ -877,16 +918,16 @@ const DialogFormProyek = ({ - + - Issu Level +

Issue Level

- Description +

Description

- Action +

Action

@@ -909,7 +950,7 @@ const DialogFormProyek = ({ - +
- -
- Project Objectives - - - - setObjectives(e.target.value)} - /> - - - - - - Project is considered successful when - - - - - setProjectIsConsideredSuccessful(e.target.value) - } - placeholder={`List of indicators`} - rows={5} - /> - - - - - - Project Participants - - - - - Title - - - Name - - - Action - - - - - - - -
{RenderParticipants()}
- - - - - Testing Environment - - - - setTestingEnv(e.target.value)} - rows={5} - /> - - - - - - Milestones - - - - - Status - - - Deadline - - - Action - - - - - - - -
{RenderMilestones()}
- - - + + + Project Objectives + + + { + const data = editor.getData(); + setObjectives(data); + } } + /> + + + + + Project is considered successful when + + + { + const data = editor.getData(); + setProjectIsConsideredSuccessful(data); + } } + /> + + + + + Project Participants + + + + +

Title

+ + +

Name

+ + +

Action

+ + + + + + + +
{RenderParticipants()}
+ + + + + Testing Environment + + + { + const data = editor.getData(); + setTestingEnv(data); + } } + /> + + + + + Milestones + + + + +

Status

+ + +

Deadline

+ + +

Action

+ + + + + + + +
{RenderMilestones()}
+ + + Potential Risk - Risk Level +

Risk Level

- Description +

Description

- Prevention +

Prevention

- Action +

Action

@@ -1089,35 +1131,35 @@ const DialogFormProyek = ({
{RenderRisk()}
- -
- Approval - - - - - Title - - - Name - - - Date - - - Action - - - - - - - -
{RenderApproval()}
- - + + + Approval + + + + +

Title

+ + +

Name

+ + +

Date

+ + +

Action

+ + + + + + + +
{RenderApproval()}
+ + ) @@ -1313,8 +1355,8 @@ const DialogFormProyek = ({ handleInputChangeParticipants(e, index)} /> @@ -1413,7 +1455,7 @@ const DialogFormProyek = ({ handleInputChangeApproval(e, index)} /> diff --git a/src/views/SimproV2/CreatedProyek/DialogGantt.js b/src/views/SimproV2/CreatedProyek/DialogGantt.js index fdce115..439f084 100644 --- a/src/views/SimproV2/CreatedProyek/DialogGantt.js +++ b/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"], "columns": [ { "name": "hierarchy_ftth_id", "logic_operator": "=", "value": hierarchyId, "operator": "AND" } - ] + ], + "orders": { "columns": ["name_version"], "ascending": true } } } else { payload = { "select": ["id", "name_version", "calculation_type", "description", "created_at", "progress"], "columns": [ { "name": "proyek_id", "logic_operator": "=", "value": idTask, "operator": "AND" } - ] + ], + "orders": { "columns": ["name_version"], "ascending": true }, } } const result = await axios diff --git a/src/views/SimproV2/CreatedProyek/DialogHierarchy.js b/src/views/SimproV2/CreatedProyek/DialogHierarchy.js index 7c1f99a..a6ac1b1 100644 --- a/src/views/SimproV2/CreatedProyek/DialogHierarchy.js +++ b/src/views/SimproV2/CreatedProyek/DialogHierarchy.js @@ -16,6 +16,7 @@ import { useTranslation } from 'react-i18next'; import { async } from '@dabeng/react-orgchart'; import { Link } from 'react-router-dom'; import { use } from 'i18next'; +import _ from 'lodash'; const DialogHierarchy = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName }) => { const token = localStorage.getItem("token") const HEADER = { @@ -154,7 +155,8 @@ const DialogHierarchy = ({ openDialog, closeDialog, toggleDialog, idTask, proyek .catch((error) => error.response); if (result && result.status == 200) { - setDataHierarchy(result.data.data); + const sortedData = _.orderBy(result.data.data, ['name'], ['asc']); + setDataHierarchy(sortedData); } else { 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; diff --git a/src/views/SimproV2/CreatedProyek/FormAsignHr.js b/src/views/SimproV2/CreatedProyek/FormAsignHr.js index a080fa0..0c7927f 100644 --- a/src/views/SimproV2/CreatedProyek/FormAsignHr.js +++ b/src/views/SimproV2/CreatedProyek/FormAsignHr.js @@ -22,7 +22,6 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, const [accrue, setAccrue] = useState("") const [baseCalender, setBaseCalender] = useState("") const [listHr, setListHr] = useState([]) - const [isCustomer, setIsCustomer] = useState(false) const handleClearData = () => { setUser(null) @@ -30,7 +29,6 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, setProjectRole(null) setGroupR("") setMaxUsed("") - setIsCustomer(false) setStandartRate("") setUomStandartRate(null) setOverTimeRate("") @@ -69,7 +67,6 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, setProjectRole(dataEdit.project_role) setGroupR(dataEdit.group_r) setMaxUsed(dataEdit.max_used ? formatNumber(dataEdit.max_used.toString()) : '') - setIsCustomer(dataEdit.is_customer) setStandartRate(dataEdit.standart_rate ? formatNumber(dataEdit.standart_rate.toString()) : '') setUomStandartRate(dataEdit.uom_standart_rate) setOverTimeRate(dataEdit.overtime_rate ? formatNumber(dataEdit.overtime_rate.toString()) : '') @@ -94,7 +91,7 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, proyek_id: idTask, user_id:user, project_role:projectRole, - is_customer: isCustomer, + is_customer: false, max_used:maxUsed.replaceAll(".", ""), standart_rate:standartRate.replaceAll(".", ""), uom_standart_rate:uomStandartRate, @@ -108,7 +105,7 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, proyek_id: idTask, user_id:user, project_role:projectRole, - is_customer: isCustomer, + is_customer: false, max_used:maxUsed.replaceAll(".", ""), standart_rate:standartRate.replaceAll(".", ""), uom_standart_rate:uomStandartRate, @@ -162,33 +159,6 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, - - - - -
-
- - + + ) }) ) }else{ - return () + return ( + + + + ); } } @@ -201,10 +236,10 @@ const createMarkup = (element) => { const ChecklistNumber = number[index]; return( - - - + + @@ -213,7 +248,12 @@ const createMarkup = (element) => { }) ) }else{ - return () + return ( + + + + + ); } } @@ -224,17 +264,21 @@ const createMarkup = (element) => { return( - + ) }) ) }else{ - return () + return ( + + + + ) } } @@ -245,18 +289,23 @@ const createMarkup = (element) => { return( - - + + ) }) ) }else{ - return () + return ( + + + + + ) } } @@ -267,20 +316,25 @@ const createMarkup = (element) => { return( ) }) ) }else{ - return () + return ( + + + + + ) } } @@ -298,20 +352,28 @@ const createMarkup = (element) => { return ( ); }) ); } else { - return (); + return ( + + + + + ); } } @@ -329,7 +391,10 @@ const createMarkup = (element) => { }) ) }else{ - return () + return ( + + + ) } } @@ -353,26 +418,24 @@ const createMarkup = (element) => { marginLeft: '5pt', marginTop: '2pt', marginBottom: '2pt', - fontFamily: 'Arial', fontSize: '10pt', fontWeight: 'bold', }; - const italicStyle = { - fontStyle: 'italic' - }; - const boldStyle = { - fontWeight: 'bold', - fontVariant: 'small-caps', - }; - const emptyCellStyle = { padding: '0', }; + const paddingTable = { + paddingTop:"20px", + paddingLeft: "30px", + paddingRight: "30px" + } + const renderForm = () => { return ( -
+
+

Project Charter

{ K3Number }

{val.checklist_k3_name ? val.checklist_k3_name : "-"}

{ K3Number }

{val.checklist_k3_name ? val.checklist_k3_name : "-"}



--

{ ChecklistNumber }

{val.item ? val.item : "-"}

-

+

{ ChecklistNumber }

{val.item ?? "-"}

+

{val.status_exist === true ? "Tersedia" : "Tidak tersedia"}



---
-

+

{val.level_issue ? val.level_issue : "-"}

{val.description ? val.description : "-"}

{val.description ? val.description : "-"}



--
-

- {val.level_risk ? val.level_risk : "-"} +

+ {val.level_risk ?? "-"}

{val.description ? val.description : "-"}

{val.preventive_risk ? val.preventive_risk : "-"}

{val.description ?? "-"}

{val.preventive_risk ?? "-"}



---
-

{val.join_first_name ? val.join_first_name : val.join_first_name}

+

{val.join_first_name ? val.join_first_name : "-"}

-

{val.join_second_name ? val.join_second_name : val.join_second_name}

+

{val.join_second_name ? val.join_second_name : "-"}

-

{val.join_second_description ? val.join_second_description : val.join_second_description}

+

{val.join_second_description ? val.join_second_description : "-"}



---
-

{milestoneLetter}

+

{milestoneLetter}

-

{val.status}

+

{val.status ?? "-"}

-

 {moment(val.deadline).format(formatDate)}

+

+ +  {moment(val.deadline).format(formatDate)} +



---


 -
@@ -385,7 +448,7 @@ const createMarkup = (element) => {

Nama Proyek

@@ -393,7 +456,7 @@ const createMarkup = (element) => {

Project description

@@ -409,7 +472,7 @@ const createMarkup = (element) => {

Lokasi Proyek

@@ -441,7 +504,7 @@ const createMarkup = (element) => {

Anggaran Proyek

@@ -462,7 +525,7 @@ const createMarkup = (element) => {

Project Manager

@@ -480,12 +543,18 @@ const createMarkup = (element) => { @@ -495,13 +564,17 @@ const createMarkup = (element) => { @@ -512,7 +585,7 @@ const createMarkup = (element) => { @@ -534,14 +607,14 @@ const createMarkup = (element) => { @@ -577,7 +650,7 @@ const createMarkup = (element) => { @@ -591,13 +664,13 @@ const createMarkup = (element) => {
-

{proyekName ?? '-'}

+

{proyekName ?? '-'}

-

{description ?? '-'}

+

{description != "" ? description : '-'}

-

 {lokasi ?? '-' }

+

 {lokasi != "" ? lokasi :'-' }

-

{currency}. {formatThousand(budget)}

+

{currency}. {formatThousand(budget)}

-

 {PM}

+

 {PM ?? "-"}

-

2.0 OBJEKTIF PROYEK (TUJUAN)

+

2.0 OBJEKTIF PROYEK (TUJUAN)

-

{objectives ?? '-'}

+

+ {objectives ? ( + + ) : ( + '-' + )} +

-

3.0 RUANG LINGKUP PROYEK

+

3.0 RUANG LINGKUP PROYEK

    -
  • { scoupeProyek ?? '-' }
  • + {scoupeProyek ? ( +
  • { scoupeProyek ?? '-' }
  • + ) : ( + "-" + )}
-

4.0 ANGGOTA PROYEK

+

4.0 ANGGOTA PROYEK

-

5.0 STRUKTUR ORGANISASI

+

5.0 STRUKTUR ORGANISASI

  {image ? ( - + ) : ( '-' )} @@ -555,7 +628,7 @@ const createMarkup = (element) => {

-

6.0 TARGET UTAMA & MILESTONE PENCAPAIAN

+

6.0 TARGET UTAMA & MILESTONE PENCAPAIAN

-

7.0 ISU & HAMBATAN UTAMA

+

7.0 ISU & HAMBATAN UTAMA

-

*Skala 1 ke 7 (1 = kecil, 7 = besar)

+

*Skala 1 ke 7 (1 = kecil, 7 = besar)

 

@@ -614,7 +687,7 @@ const createMarkup = (element) => {
-

8.0 RESIKO

+

8.0 RESIKO

-

*Skala 1 ke 7 (1 = kecil, 7 = besar)

+

*Skala 1 ke 7 (1 = kecil, 7 = besar)

 

@@ -624,7 +697,13 @@ const createMarkup = (element) => { -

+

+ {lateProyek ? ( + + ) : ( + "-" + )} +

@@ -638,7 +717,13 @@ const createMarkup = (element) => { -

{projectSuccess ?? '-'}

+

+ {projectSuccess ? ( + + ) : ( + '-' + )} +

@@ -653,7 +738,13 @@ const createMarkup = (element) => { -

+

+ {assumtionProyek ? ( + + ) : ( + '-' + )} +

@@ -719,9 +810,17 @@ const createMarkup = (element) => { return ( <> - Project + +
+ + + +
+
- {renderForm()} +
+ {renderForm()} +
diff --git a/src/views/SimproV2/CreatedProyek/index.js b/src/views/SimproV2/CreatedProyek/index.js index 485b32c..9a08500 100644 --- a/src/views/SimproV2/CreatedProyek/index.js +++ b/src/views/SimproV2/CreatedProyek/index.js @@ -248,7 +248,9 @@ const CreatedProyek = ({ params, ...props }) => { .then((res) => res) .catch((err) => err.response); 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"] } ], - orders: { columns: ["id"], ascending: false }, + orders: { columns: ["nama"], ascending: true }, paging: { start: start, length: rowsPerPage }, }; @@ -609,8 +611,8 @@ const CreatedProyek = ({ params, ...props }) => { .catch((error) => error.response); 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 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 {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 = {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); } else { NotificationManager.error("Gagal Mengambil Data!!", "Failed"); @@ -965,7 +967,7 @@ const CreatedProyek = ({ params, ...props }) => { const request = data.map((res) => { const payload = { proyek_id: parseInt(id), - tittle: res.title, + tittle: res.tittle, name: res.name, }; 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"] } ], - orders: { columns: ["id"], ascending: false }, + orders: { columns: ["nama"], ascending: true }, }; const result = await axios @@ -1899,6 +1901,7 @@ const CreatedProyek = ({ params, ...props }) => { projectK3={projectK3Search} assignHR={projectAssignHR} projectImage={image} + idTask={idTask} /> ), [openDialogViewDetail] @@ -1996,7 +1999,7 @@ const CreatedProyek = ({ params, ...props }) => { )} - + Close} title="Export" diff --git a/src/views/SimproV2/Divisi/DialogForm.js b/src/views/SimproV2/Divisi/DialogForm.js index c32e621..62ce6c2 100644 --- a/src/views/SimproV2/Divisi/DialogForm.js +++ b/src/views/SimproV2/Divisi/DialogForm.js @@ -6,12 +6,16 @@ import { import { Select } from 'antd'; import 'antd/dist/antd.css'; import { useTranslation } from 'react-i18next'; +import InputColor from "./InputColor"; +import "./styles.css"; +import "rc-color-picker/assets/index.css"; const { Option } = Select const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdit, dataDivisions }) => { const [id, setId] = useState(0) const [name, setName] = useState('') const [parent, setParent] = useState(null) const [description, setDescription] = useState('') + const [color, setColor] = useState('') const { t } = useTranslation() const onChangeParent = (val) => { @@ -23,9 +27,11 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi setId(dataEdit.id) setDescription(dataEdit.description) setName(dataEdit.name) - setParent(dataEdit.parent) + setParent(dataEdit.parent) + setColor(dataEdit.color) } else { setId(0) + setColor('') } }, [dataEdit, openDialog]) @@ -42,30 +48,35 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi if (!err) { if (typeDialog === "Save") { data = { - name: name, + name, description, - parent + parent, + color } closeDialog('save', data); } else { data = { id, - name: name, + name, description, - parent + parent, + color } closeDialog('edit', data); } setId(0) setDescription('') setName('') + setParent(null) + setColor('') } } const handleCancel = () => { closeDialog('cancel', 'none') setId(0) setDescription('') - setName('') + setName('') + setParent(null) } const renderForm = () => { @@ -89,22 +100,22 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi - - - - - - - + + + + + + + @@ -112,6 +123,14 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi + + + + + setColor(e.color)} /> + + + ) } diff --git a/src/views/SimproV2/Divisi/InputColor.js b/src/views/SimproV2/Divisi/InputColor.js new file mode 100644 index 0000000..ff2f865 --- /dev/null +++ b/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 = ( +
+ +
+ ); + + return ( + <> + setInternalColor(e.target.value)} + suffix={ + + + + } + /> + + ); +} + diff --git a/src/views/SimproV2/Divisi/index.js b/src/views/SimproV2/Divisi/index.js index 9ab06d3..17e576a 100644 --- a/src/views/SimproV2/Divisi/index.js +++ b/src/views/SimproV2/Divisi/index.js @@ -25,6 +25,7 @@ const config = { const column = [ { name: "Nama" }, { name: "Deskripsi" }, + { name: "Color" }, ] const ProjectType = ({ params }) => { @@ -72,8 +73,10 @@ const ProjectType = ({ params }) => { if (listDivions && listDivions.data && listDivions.data.code == 200) { let arr = [] - for (const v in listDivions.data.data) { - arr.push(listDivions.data.data[v]) + let dataRes = listDivions.data.data; + const filteredData = dataRes.filter(item => item.parent === null); + for (const v in filteredData) { + arr.push(filteredData[v]) } setDataDivisions(arr); } else { @@ -97,7 +100,7 @@ const ProjectType = ({ params }) => { "orders": { "ascending": true, "columns": [ - 'id' + 'name' ] }, "paging": { @@ -183,7 +186,8 @@ const ProjectType = ({ params }) => { }; const handleOpenDialog = (type) => { - setOpenDialog(true) + setOpenDialog(true) + getListDivision(); setTypeDialog(type) } @@ -348,7 +352,16 @@ const ProjectType = ({ params }) => {
{n.name} - {n.description} + {n.description ?? '-'} + {n.color != null ? ( + + + + + + ): ( + No color set + )} ) })} diff --git a/src/views/SimproV2/Divisi/styles.css b/src/views/SimproV2/Divisi/styles.css new file mode 100644 index 0000000..d48cce6 --- /dev/null +++ b/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; +} +